diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 7bfb0ab611cf39710e5c934f5b89411c7173ba21..09e13f9a39a82aa7f50bff6cb5f608a154262274 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1084,6 +1084,9 @@ set(PHY_SRC
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/prach.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pmch.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pch.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/slss.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sldch.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/slsch.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/group_hopping.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/srs_modulation.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/drs_modulation.c
@@ -1176,6 +1179,9 @@ set(PHY_SRC_UE
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/prach.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pmch.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pch.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/slss.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sldch.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/slsch.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/group_hopping.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/srs_modulation.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/drs_modulation.c
@@ -1351,6 +1357,7 @@ set(L2_SRC_UE
   )
 
 set (MAC_SRC
+  #${PHY_INTERFACE_DIR}/phy_stub_UE.c
   ${PHY_INTERFACE_DIR}/IF_Module.c
   ${MAC_DIR}/main.c
   ${MAC_DIR}/main_ue.c
@@ -1373,6 +1380,7 @@ set (MAC_SRC
  )
 
 set (MAC_SRC_UE
+  ${PHY_INTERFACE_DIR}/phy_stub_UE.c
   ${MAC_DIR}/main_ue.c
   ${MAC_DIR}/ue_procedures.c
   ${MAC_DIR}/ra_procedures.c
@@ -1398,7 +1406,6 @@ add_library(L2_UE
   ${MAC_SRC_UE}
 )
 
-
 include_directories(${NFAPI_USER_DIR})
 
 # L3 Libs
@@ -1968,6 +1975,8 @@ add_executable(lte-softmodem
   ${OPENAIR_TARGETS}/COMMON/create_tasks.c
   ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
   ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c
   ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
   ${OPENAIR_DIR}/common/utils/utils.c
   ${OPENAIR_DIR}/common/utils/system.c
@@ -2009,6 +2018,8 @@ add_executable(lte-softmodem-nos1
   ${OPENAIR2_DIR}/RRC/NAS/nas_config.c
   ${OPENAIR2_DIR}/RRC/NAS/rb_config.c
   ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c
   ${OPENAIR_DIR}/common/utils/system.c
   ${XFORMS_SOURCE}
   ${XFORMS_SOURCE_SOFTMODEM}
@@ -2024,7 +2035,7 @@ target_link_libraries (lte-softmodem-nos1
   -Wl,--end-group z dl )
 
 target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES})
-target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp  ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
+target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
 target_link_libraries (lte-softmodem-nos1  ${LIB_LMS_LIBRARIES})
 target_link_libraries (lte-softmodem-nos1 ${T_LIB})
 
@@ -2043,6 +2054,8 @@ add_executable(lte-uesoftmodem
   ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
   ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
   ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c
   ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
   ${OPENAIR_DIR}/common/utils/utils.c
   ${OPENAIR_DIR}/common/utils/system.c
@@ -2057,6 +2070,7 @@ target_link_libraries (lte-uesoftmodem
   -Wl,--start-group
   RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_UE_LIB PHY_UE LFDS L2_UE 
   ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7
+  NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
   -Wl,--end-group z dl)
 
 target_link_libraries (lte-uesoftmodem ${LIBXML2_LIBRARIES})
@@ -2064,7 +2078,7 @@ target_link_libraries (lte-uesoftmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${
 target_link_libraries (lte-uesoftmodem ${LIB_LMS_LIBRARIES})
 target_link_libraries (lte-uesoftmodem ${T_LIB})
 
-# lte-softmodem-nos1 is both eNB and UE implementation
+# lte-uesoftmodem-nos1 is UE implementation
 ###################################################
 add_executable(lte-uesoftmodem-nos1
   ${rrc_h}
@@ -2080,6 +2094,9 @@ add_executable(lte-uesoftmodem-nos1
   ${OPENAIR2_DIR}/RRC/NAS/nas_config.c
   ${OPENAIR2_DIR}/RRC/NAS/rb_config.c
   ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c
+  ${OPENAIR_DIR}/common/utils/utils.c
   ${OPENAIR_DIR}/common/utils/system.c
   ${XFORMS_SOURCE}
   ${XFORMS_SOURCE_SOFTMODEM}
@@ -2087,10 +2104,12 @@ add_executable(lte-uesoftmodem-nos1
   ${CONFIG_SOURCES}
   ${SHLIB_LOADER_SOURCES}
   )
+
 target_link_libraries (lte-uesoftmodem-nos1
   -Wl,--start-group
   RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_UE_LIB PHY_UE LFDS L2_UE ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} 
   ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7
+  NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
   -Wl,--end-group z dl )
 
 target_link_libraries (lte-uesoftmodem-nos1 ${LIBXML2_LIBRARIES})
diff --git a/d2d_emulator_setup.txt b/d2d_emulator_setup.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ef904066bc28d55eb345f9957e8751498c31e95e
--- /dev/null
+++ b/d2d_emulator_setup.txt
@@ -0,0 +1,107 @@
+Scenario 1 : Off-network UE2UE link
+SynchREF UE (UE1)
+
+UE1(eth0 - 10.10.10.1)--------UE2(eno1 - 10.10.10.2)
+
+Here's an example of /etc/network/interfaces configuration for UE1
+auto eth0
+   iface eth0 inet static
+   address 10.10.10.1
+   netmask 255.255.255.0
+   gateway 10.10.10.1
+
+Prepare the environment:
+ - git clone https://gitlab.eurecom.fr/matzakos/LTE-D2D.git  #branch: master
+This branch contains all the current development for DDPS
+ - UE MAC<-> UE MAC for Scenario 1
+ - eNB MAC<->UE MAC (NFAPI Transport)
+ - RRC Extensions for “on-network” cases
+ 
+NFAPI configuration (required even for Scenario 1 target)
+ - git clone https://github.com/cisco/open-nFAPI.git
+ - cd open-nfapi
+ - patch -p1 --dry-run < $OPENAIR_HOME/open-nfapi.oai.patch
+Validate that there are no errors
+ - patch -p1 < $OPENAIR_HOME/open-nfapi.oai.patch
+ 
+OAI build/execute
+ - export NFAPI_DIR=XXX (place where NFAPI was installed)
+ - cd cmake_targets
+ - ./build_oai --UE
+ (if necessary, use ./build_oai -I --UE to install required packages)
+ - cd lte_build_oai/build/
+ - cp ../../../targets/bin/.ue* .
+ - cp ../../../targets/bin/.usim* .
+ - sudo insmod ../../../targets/bin/ue_ip.ko
+
+UE1: 
+ - sudo ifconfig oip0 10.0.0.1
+ - sudo iptables -A POSTROUTING  -t mangle -o oip0 -d 224.0.0.3 -j MARK --set-mark 3
+ - (if necessary) sudo route add default gw 10.10.10.1 eth0
+UE2:
+ - sudo ifconfig oip0 10.0.0.2
+ - sudo iptables -A POSTROUTING  -t mangle -o oip0 -d 224.0.0.3 -j MARK --set-mark 3
+ - (if necessary) sudo route add default gw 10.10.10.1 eno1
+
+UE1 and UE2: Get and build vencore_app from d2d-l3-stub (branch: l3_stub)
+ - gcc -I . vencore_app.c -o vencore_app -lpthread
+ 
+--------------------------------
+TEST ONE-TO-MANY
+Run UE1 then UE2, for example:
+UE1: sudo ./lte-softmodem-stub -U --emul-iface eth0
+UE2: sudo ./lte-softmodem-stub -U --emul-iface eno1
+
+Test with Ping
+- Sender - UE1: ping -I oip0 224.0.0.3
+- Receiver - UE2: using wireshark
+
+Test with Iperf
+- Sender - UE1: iperf -c 224.0.0.3 -u -b 0.1M --bind 10.0.0.1 -t 100
+- Receiver - UE2: sudo ./mcreceive 224.0.0.3 5001 
+
+Filter the incomming packets according to GroupL2Id: receiver (one-to-many) can discard the packets if it doesn't belong to this group. 
+For the moment, both sender and receiver use the same set of Ids (hardcoded)  
+
+UE1 (sender)
+ - sudo ./lte-softmodem-stub -U --emul-iface eth0
+ - ./vencore_app  #send the sourceL2Id, groupL2Id to OAI
+ - ping -I oip0 224.0.0.3
+ UE2(receiver)
+  - sudo ./lte-softmodem-stub -U --emul-iface eno1 
+  #we can see the incomming packets from OAI log, however, cannot see from Wireshark -> they are discarded at MAC layer
+  - ./vencore_app  #we can see the packets appearing in Wireshark
+ 
+ --------------------------------------
+TEST PC5-S (UE1 -sender, UE2 - receiver) and PC5-U for ONE-TO-ONE scenario
+Configure UE1/UE2
+UE1: 
+ - sudo ifconfig oip0 10.0.0.1
+ - sudo iptables -A POSTROUTING  -t mangle -o oip0 -d 10.0.0.2 -j MARK --set-mark 3
+ - sudo route add default gw 10.10.10.1 eth0
+UE2:
+ - sudo ifconfig oip0 10.0.0.2
+ - sudo iptables -A POSTROUTING  -t mangle -o oip0 -d 10.0.0.1 -j MARK --set-mark 3
+ - sudo route add default gw 10.10.10.1 eno1
+ 
+step 1:
+- UE1: sudo ./lte-softmodem-stub -U --emul-iface eth0
+step 2:
+- UE2: sudo ./lte-softmodem-stub -U --emul-iface eno1
+- UE2: ./vencore_app -r #listen to incomming message from PC5-S 
+step 3: 
+- UE1: ./vencore_app -s #send a message via PC5-S (e.g., DirectCommunicationRequest)
+
+Generate unicast traffic
+UE1: ping -I oip0 10.0.0.2
+ 
+ 
+  --------------------------------------
+TEST PC5-D
+step 1:
+- UE1: sudo ./lte-softmodem-stub -U --emul-iface eth0
+- UE1: ./vencore_app -d #send a PC5-Discovery-Announcement via PC5D
+step 2:
+- UE2: sudo ./lte-softmodem-stub -U --emul-iface eno1
+- UE2: ./vencore_app -d #send a PC5-Discovery-Announcement via PC5D
+
diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c
index c63d504e43d569f2cf9c3045aa2dca1c3b7056d8..2a6fc334f439cc6eb1a801c6bf71a2fcb05da977 100644
--- a/nfapi/oai_integration/nfapi_pnf.c
+++ b/nfapi/oai_integration/nfapi_pnf.c
@@ -32,6 +32,7 @@
 #include "nfapi.h"
 #include "nfapi_pnf.h"
 #include "common/ran_context.h"
+#include "openair2/PHY_INTERFACE/phy_stub_UE.h"
 //#include "openair1/PHY/vars.h"
 extern RAN_CONTEXT_t RC;
 
@@ -61,8 +62,10 @@ extern pthread_mutex_t nfapi_sync_mutex;
 extern int nfapi_sync_var;
 
 extern int sync_var;
+char uecap_xer_in;
 
 extern void init_eNB_afterRU(void);
+extern void init_UE_stub(int nb_inst,int,int);
 extern void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB *eNB, int frame, int subframe, eNB_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu);
 extern void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, nfapi_ul_config_request_pdu_t *ul_config_pdu, uint16_t frame,uint8_t subframe,uint8_t srs_present);
 extern void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, eNB_rxtx_proc_t *proc,  nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t codeword_index, uint8_t *sdu);
@@ -508,9 +511,31 @@ int config_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfap
 
   pnf_info* pnf = (pnf_info*)(config->user_data);
   uint8_t num_tlv = 0;
-  struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
-  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
+  //struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
+
+  // Panos: In the case of nfapi_mode = 3 (UE = PNF) we should not have dependency on any eNB var. So we aim
+  // to keep only the necessary just to keep the nfapi FSM rolling by sending a dummy response.
+  LTE_DL_FRAME_PARMS *fp;
+  if (nfapi_mode!=3) {
+	  struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
+	  fp = &eNB->frame_parms;
+  }
+  else{
+	  fp = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS));
+  }
 
+
+#if 0
+  //DJP
+  auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
+      { return item.id == req->header.phy_id; });
+
+  if(found != pnf->phys.end())
+  {
+    phy_info& phy_info = (*found);
+  }
+#endif
+  //DJP 
   phy_info* phy_info = pnf->phys;
 
   if(req->nfapi_config.timing_window.tl.tag == NFAPI_NFAPI_TIMING_WINDOW_TAG) {
@@ -667,6 +692,7 @@ int config_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfap
     num_tlv++;
   }
 
+  if(nfapi_mode!=3) {
   printf("[PNF] CONFIG_REQUEST[num_tlv:%d] TLVs processed:%d\n", req->num_tlv, num_tlv);
 
   printf("[PNF] Simulating PHY CONFIG - DJP\n");
@@ -678,6 +704,7 @@ int config_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfap
   phy_config_request(&phy_config);
 
   dump_frame_parms(fp);
+  }
 
   phy_info->remote_port = req->nfapi_config.p7_vnf_port.value;
 
@@ -695,6 +722,8 @@ int config_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfap
   nfapi_resp.error_code = 0; // DJP - some value resp->error_code;
   nfapi_pnf_config_resp(config, &nfapi_resp);
   printf("[PNF] Sent NFAPI_CONFIG_RESPONSE phy_id:%d\n", phy_info->id);
+  if(nfapi_mode ==3)
+	  free(fp);
 
   return 0;
 }
@@ -1081,6 +1110,7 @@ int start_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi
   }
 
   if(phy_info->timing_info_mode & 0x2) {
+	  //printf("Panos-D: start_request () Enabling timing_info_mode_aperiodic \n");
     p7_config->timing_info_mode_aperiodic = 1;
   }
 
@@ -1090,77 +1120,110 @@ int start_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi
   p7_config->tx_req = &pnf_phy_tx_req;
   p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req;
 
-  memset(&dummy_dl_config_req, 0, sizeof(dummy_dl_config_req));
-  dummy_dl_config_req.dl_config_request_body.tl.tag=NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
-  dummy_dl_config_req.dl_config_request_body.number_pdcch_ofdm_symbols=1;
-  dummy_dl_config_req.dl_config_request_body.number_dci=0;
-  dummy_dl_config_req.dl_config_request_body.number_pdu=0;
-  dummy_dl_config_req.dl_config_request_body.number_pdsch_rnti=0;
-  dummy_dl_config_req.dl_config_request_body.transmission_power_pcfich=6000;
-  dummy_dl_config_req.dl_config_request_body.dl_config_pdu_list=0;
+    if (nfapi_mode==3) {
+    	p7_config->dl_config_req = &memcpy_dl_config_req;
+    	p7_config->ul_config_req = &memcpy_ul_config_req;
+    	p7_config->hi_dci0_req = &memcpy_hi_dci0_req;
+    	p7_config->tx_req = &memcpy_tx_req;
+    }
+    else {
+    	p7_config->dl_config_req = &pnf_phy_dl_config_req;
+    	p7_config->ul_config_req = &pnf_phy_ul_config_req;
+    	p7_config->hi_dci0_req = &pnf_phy_hi_dci0_req;
+    	p7_config->tx_req = &pnf_phy_tx_req;
+    }
+    p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req;
 
-  memset(&dummy_tx_req, 0, sizeof(dummy_tx_req));
-  dummy_tx_req.tx_request_body.number_of_pdus=0;
-  dummy_tx_req.tx_request_body.tl.tag=NFAPI_TX_REQUEST_BODY_TAG;
+    memset(&dummy_dl_config_req, 0, sizeof(dummy_dl_config_req));
+    dummy_dl_config_req.dl_config_request_body.tl.tag=NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
+    dummy_dl_config_req.dl_config_request_body.number_pdcch_ofdm_symbols=1;
+    dummy_dl_config_req.dl_config_request_body.number_dci=0;
+    dummy_dl_config_req.dl_config_request_body.number_pdu=0;
+    dummy_dl_config_req.dl_config_request_body.number_pdsch_rnti=0;
+    dummy_dl_config_req.dl_config_request_body.transmission_power_pcfich=6000;
+    dummy_dl_config_req.dl_config_request_body.dl_config_pdu_list=0;
 
-  dummy_subframe.dl_config_req = &dummy_dl_config_req;
-  dummy_subframe.tx_req = 0;//&dummy_tx_req;
+    memset(&dummy_tx_req, 0, sizeof(dummy_tx_req));
+    dummy_tx_req.tx_request_body.number_of_pdus=0;
+    dummy_tx_req.tx_request_body.tl.tag=NFAPI_TX_REQUEST_BODY_TAG;
 
-  dummy_subframe.ul_config_req=0;
-  dummy_subframe.hi_dci0_req=0;
-  dummy_subframe.lbt_dl_config_req=0;
+    dummy_subframe.dl_config_req = &dummy_dl_config_req;
+    dummy_subframe.tx_req = 0;//&dummy_tx_req;
 
-  p7_config->dummy_subframe = dummy_subframe;
+    dummy_subframe.ul_config_req=0;
+    dummy_subframe.hi_dci0_req=0;
+    dummy_subframe.lbt_dl_config_req=0;
 
-  p7_config->vendor_ext = &pnf_phy_vendor_ext;
+    p7_config->dummy_subframe = dummy_subframe;
 
-  p7_config->allocate_p7_vendor_ext = &pnf_phy_allocate_p7_vendor_ext;
-  p7_config->deallocate_p7_vendor_ext = &pnf_phy_deallocate_p7_vendor_ext;
+    p7_config->vendor_ext = &pnf_phy_vendor_ext;
 
-  p7_config->codec_config.unpack_p7_vendor_extension = &pnf_phy_unpack_p7_vendor_extension;
-  p7_config->codec_config.pack_p7_vendor_extension = &pnf_phy_pack_p7_vendor_extension;
-  p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_phy_unpack_vendor_extension_tlv;
-  p7_config->codec_config.pack_vendor_extension_tlv = &pnf_phy_pack_vendor_extention_tlv;
+    p7_config->allocate_p7_vendor_ext = &pnf_phy_allocate_p7_vendor_ext;
+    p7_config->deallocate_p7_vendor_ext = &pnf_phy_deallocate_p7_vendor_ext;
 
-  NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__);
-  pthread_t p7_thread;
-  pthread_create(&p7_thread, NULL, &pnf_p7_thread_start, p7_config);
+    p7_config->codec_config.unpack_p7_vendor_extension = &pnf_phy_unpack_p7_vendor_extension;
+    p7_config->codec_config.pack_p7_vendor_extension = &pnf_phy_pack_p7_vendor_extension;
+    p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_phy_unpack_vendor_extension_tlv;
+    p7_config->codec_config.pack_vendor_extension_tlv = &pnf_phy_pack_vendor_extention_tlv;
 
-  //((pnf_phy_user_data_t*)(phy_info->fapi->user_data))->p7_config = p7_config;
+    NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__);
+    pthread_t p7_thread;
+    pthread_create(&p7_thread, NULL, &pnf_p7_thread_start, p7_config);
 
-  NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Calling l1_north_init_eNB() %s\n", __FUNCTION__);
-  l1_north_init_eNB();
+    //((pnf_phy_user_data_t*)(phy_info->fapi->user_data))->p7_config = p7_config;
 
-  NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] DJP - HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__);
-  p7_config_g = p7_config;
+    NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Calling l1_north_init_eNB() %s\n", __FUNCTION__);
+    l1_north_init_eNB();
 
-  // Need to wait for main thread to create RU structures
-  while(config_sync_var<0) {
-    usleep(5000000);
-    printf("[PNF] waiting for OAI to be configured (eNB/RU)\n");
-  }
-  printf("[PNF] OAI eNB/RU configured\n");
+    NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] DJP - HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__);
+    p7_config_g = p7_config;
 
-  printf("[PNF] About to call init_eNB_afterRU()\n");
-  init_eNB_afterRU();
+    //NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Panos-D: start_request, BUFFER SIZE: %d", p7_config_g->subframe_buffer_size);
+    //printf("Panos-D: start_request, bUFFER SIZE: %d", p7_config_g->subframe_buffer_size);
 
-  // Signal to main thread that it can carry on - otherwise RU will startup too quickly and it is not initialised
-  pthread_mutex_lock(&nfapi_sync_mutex);
-  nfapi_sync_var=0;
-  pthread_cond_broadcast(&nfapi_sync_cond);
-  pthread_mutex_unlock(&nfapi_sync_mutex);
+    // Need to wait for main thread to create RU structures
+    while(config_sync_var<0)
+    {
+      usleep(5000000);
+      printf("[PNF] waiting for OAI to be configured (eNB/RU)\n");
+    }
+    printf("[PNF] OAI eNB/RU configured\n");
 
-  while(sync_var<0) {
-    usleep(5000000);
-    printf("[PNF] waiting for OAI to be started\n");
-  }
+    //printf("[PNF] About to call phy_init_RU() for RC.ru[0]:%p\n", RC.ru[0]);
+    //phy_init_RU(RC.ru[0]);
+
+    printf("[PNF] About to call init_eNB_afterRU()\n");
+
+    // Panos: Instead
+    /*if (nfapi_mode == 3) {
+    	init_UE_stub(1,0,uecap_xer_in);
+    }*/
+    //else{
+    if (nfapi_mode != 3) {
+    	// Panos
+    	init_eNB_afterRU();
+    }
+
+    // Signal to main thread that it can carry on - otherwise RU will startup too quickly and it is not initialised
+    {
+      pthread_mutex_lock(&nfapi_sync_mutex);
+      nfapi_sync_var=0;
+      pthread_cond_broadcast(&nfapi_sync_cond);
+      pthread_mutex_unlock(&nfapi_sync_mutex);
+    }
+
+    while(sync_var<0)
+    {
+      usleep(5000000);
+      printf("[PNF] waiting for OAI to be started\n");
+    }
 
-  printf("[PNF] Sending PNF_START_RESP\n");
-  nfapi_send_pnf_start_resp(config, p7_config->phy_id);
+    printf("[PNF] Sending PNF_START_RESP\n");
+    nfapi_send_pnf_start_resp(config, p7_config->phy_id);
 
-  printf("[PNF] Sending first P7 subframe ind\n");
-  nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // DJP - SFN_SF set to zero - correct???
-  printf("[PNF] Sent first P7 subframe ind\n");
+    printf("[PNF] Sending first P7 subframe ind\n");
+    nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // DJP - SFN_SF set to zero - correct???
+    printf("[PNF] Sent first P7 subframe ind\n");
 
   return 0;
 }
@@ -1464,7 +1527,9 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr,
 
   printf("%s() PNF\n\n\n\n\n\n", __FUNCTION__);
 
+  if(nfapi_mode!=3) {
   nfapi_mode = 1;  // PNF!
+  }
 
   nfapi_pnf_config_t* config = nfapi_pnf_config_create();
 
diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c
index 13041767522935fb74a90cfe9748517d303588dd..3c469c942bc028c81f8cbbf1492850891be06604 100644
--- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c
+++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c
@@ -1247,9 +1247,14 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
           int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf);
 
           //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PNF:SFN/SF:%d VNF:SFN/SF:%d deltaSFNSF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind.last_sfn_sf), NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), vnf_pnf_sfnsf_delta);
-          if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1)
+
+          // Panos: Careful here!!!
+          //if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1)
+          if (vnf_pnf_sfnsf_delta>0 || vnf_pnf_sfnsf_delta < 0)
           {
             NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnsf_delta, NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), NFAPI_SFNSF2DEC(ind.last_sfn_sf));
+            // Panos: Careful here!!!
+            vnf_p7->p7_connections[0].sfn_sf = ind.last_sfn_sf;
           }
         }
 }
diff --git a/openair1/PHY/INIT/lte_init_ue.c b/openair1/PHY/INIT/lte_init_ue.c
index 16274d687841098c06042d9c471f2add19900fcb..84b045d9608b6837e8f2b7d627545a9dd0757be8 100644
--- a/openair1/PHY/INIT/lte_init_ue.c
+++ b/openair1/PHY/INIT/lte_init_ue.c
@@ -34,6 +34,7 @@
 
 
 uint8_t dmrs1_tab_ue[8] = {0,2,3,4,6,8,9,10};
+extern uint8_t nfapi_mode;
 
 void phy_config_sib1_ue(uint8_t Mod_id,int CC_id,
                         uint8_t eNB_id,
@@ -563,14 +564,17 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
   	phy_vars_ue->decode_SIB = 0;
   	phy_vars_ue->decode_MIB = 0;
   }
-  //phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti;
-  if(phy_vars_ue->pdcch_vars[0][eNB_id]->crnti == 0x1234)
-      phy_vars_ue->pdcch_vars[0][eNB_id]->crnti = phy_vars_ue->pdcch_vars[1][eNB_id]->crnti;
-  else
-      phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti;
 
-  LOG_I(PHY,"C-RNTI %x %x \n", phy_vars_ue->pdcch_vars[0][eNB_id]->crnti,
-                               phy_vars_ue->pdcch_vars[1][eNB_id]->crnti);
+  if(nfapi_mode!=3){
+    //phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti;
+    if(phy_vars_ue->pdcch_vars[0][eNB_id]->crnti == 0x1234)
+        phy_vars_ue->pdcch_vars[0][eNB_id]->crnti = phy_vars_ue->pdcch_vars[1][eNB_id]->crnti;
+    else
+        phy_vars_ue->pdcch_vars[1][eNB_id]->crnti = phy_vars_ue->pdcch_vars[0][eNB_id]->crnti;
+
+    LOG_I(PHY,"C-RNTI %x %x \n", phy_vars_ue->pdcch_vars[0][eNB_id]->crnti,
+                                 phy_vars_ue->pdcch_vars[1][eNB_id]->crnti);
+  }
 
 
 }
diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h
index f1f4be3072c86b166168fc906a061b599aa0cfc5..e4d9b47986f7ad1edf4f34bc9f6e230688f33f24 100644
--- a/openair1/PHY/LTE_TRANSPORT/defs.h
+++ b/openair1/PHY/LTE_TRANSPORT/defs.h
@@ -252,7 +252,7 @@ typedef struct {
 
   // decode phich
   uint8_t decode_phich;
-} LTE_UL_UE_HARQ_t; 
+} LTE_UL_UE_HARQ_t;
 
 #ifdef Rel14
 typedef enum {
@@ -265,7 +265,7 @@ typedef struct {
   /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding)
   int32_t *txdataF[8];
   /// beamforming weights for UE-spec transmission (antenna ports 5 or 7..14), for each codeword, maximum 4 layers?
-  int32_t **ue_spec_bf_weights[4]; 
+  int32_t **ue_spec_bf_weights[4];
   /// dl channel estimates (estimated from ul channel estimates)
   int32_t **calib_dl_ch_estimates;
   /// Allocated RNTI (0 means DLSCH_t is not currently used)
@@ -413,7 +413,7 @@ typedef struct {
   /// is done after a new scheduling
   uint16_t previous_first_rb;
   /// Current Number of RBs
-  uint16_t nb_rb; 
+  uint16_t nb_rb;
   /// Current Modulation order
   uint8_t Qm;
   /// Transport block size
@@ -531,7 +531,7 @@ typedef enum {
   HARQ_SR,
   HARQ_CQI,
   SR_CQI,
-  HARQ_SR_CQI  
+  HARQ_SR_CQI
 } UCI_type_t;
 
 #ifdef Rel14
@@ -556,7 +556,7 @@ typedef struct {
   uint8_t     srs_active;
   /// PUCCH format to use
   PUCCH_FMT_t pucch_fmt;
-  /// number of PUCCH antenna ports 
+  /// number of PUCCH antenna ports
   uint8_t     num_antenna_ports;
   /// number of PUCCH resources
   uint8_t     num_pucch_resources;
@@ -864,11 +864,105 @@ typedef enum {
 } RX_type_t;
 
 
+#ifdef Rel14
 typedef enum {
   DCI_COMMON_SPACE,
   DCI_UE_SPACE
 } dci_space_t;
 
 
+typedef struct {
+  uint16_t slss_id;
+  uint8_t *slmib;
+} SLSS_t;
+
+typedef struct {
+  // SL Configuration
+  /// Number of SL resource blocks (1-100)
+  uint32_t N_SL_RB;
+  /// prb-start (0-99)
+  uint32_t prb_Start;
+  /// prb-End (0-99)
+  uint32_t prb_End;
+  /// SL-OffsetIndicator (0-10239)
+  uint32_t SL_OffsetIndicator;
+  /// PSCCH subframe bitmap, first 64-bits (up to 40 bits for Rel 12)
+  uint64_t bitmap1;
+  /// PSCCH subframe bitmap, 2nd 64-bits (up to 100 bits for Rel 14)
+  uint64_t bitmap2;
+
+  // SCI parameters
+  /// npscch resource index
+  uint32_t n_pscch;
+  /// format of SCI (0,1)
+  uint32_t format;
+  /// SCI0 frequency hopping flag
+  uint32_t freq_hopping_flag;
+  /// SCI0 Resource Block Coding
+  uint32_t resource_block_coding;
+  /// SCI0 Time Resource Pattern for SLSCH
+  uint32_t time_resource_pattern;
+  /// SCI0 MCS for SLSCH
+  uint32_t mcs;
+  /// SCI0 Timing advance indication for SLSCH
+  uint32_t timing_advance_indication;
+  /// SCI0 Group Destination ID for SLSCH
+  uint32_t group_destination_id;
+
+  // SLSCH Parameters
+  /// Number of Subbands (36.213 14.1.1.2)
+  uint32_t Nsb;
+  /// N_RB_HO (36.213 14.1.1.2)
+  uint32_t N_RB_HO;
+  /// n_ss_PSSCH (36.211 9.2.4)
+  uint32_t n_ss_PSSCH;
+  /// n_ssf_PSSCH
+  uint32_t n_ssf_PSSCH;
+  /// cinit (36.331 hoppingParameter-r12)
+  uint32_t cinit;
+  /// redundancy version
+  uint32_t rvidx;
+  /// n_prime_VRB (36.213 14.1.1.2.1)
+  uint32_t n_prime_VRB;
+  /// M_RB_PSSCH_RP (36.213 14.1.3
+  uint32_t M_RB_PSSCH_RP;
+  /// n_prime_PRB (36.213 14.1.1.4
+  uint32_t n_prime_PRB;
+  /// m_nprime_PRB_PSSCH (36.213 14.1.3)
+  uint32_t m_nprime_PRB_PSCCH;
+  /// payload length
+  int payload_length;
+  /// pointer to payload
+  uint8_t *payload;
+} SLSCH_t;
+
+typedef struct {
+  /// payload length
+  int payload_length;
+	uint8_t payload[100];
+} SLDCH_t;
+
+#define TTI_SYNC 0
+#define SLSS 1
+#define SLDCH 2
+#define SLSCH 3
+
+typedef struct UE_tport_header_s {
+  int packet_type;
+  uint16_t absSF;
+} UE_tport_header_t;
+
+typedef struct UE_tport_s {
+  UE_tport_header_t header;
+  union {
+    SLSS_t slss;
+    SLDCH_t sldch;
+    SLSCH_t slsch;
+  };
+  uint8_t payload[1500];
+} UE_tport_t;
+
+#endif
+
 /**@}*/
 #endif
diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h
index e706bbbaeb2658fba754ce367e9f248d09f0e490..91806667d268b26a0d6da09e3de431079ec30b5e 100644
--- a/openair1/PHY/LTE_TRANSPORT/proto.h
+++ b/openair1/PHY/LTE_TRANSPORT/proto.h
@@ -1504,6 +1504,29 @@ uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB,
                               DCI_ALLOC_t *dci_alloc,
                               uint8_t subframe);
 
+/*! \brief Top-level generation route for Sidelink BCH,PSS and SSS
+  \param ue pointer to UE descriptor
+  \param slss pointer to SLSS configuration and payload
+  \param frame_tx Frame number
+  \param subframe_tx subframe number
+*/
+void generate_slss(PHY_VARS_UE *ue,SLSS_t *slss,int frame_tx,int subframe_tx);
+
+/*! \brief Top-level generation route for Sidelink Discovery Channel
+  \param ue pointer to UE descriptor
+  \param sldch pointer to SLDCH configuration and payload
+  \param frame_tx Frame number
+  \param subframe_tx subframe number
+*/
+void generate_sldch(PHY_VARS_UE *ue,SLDCH_t *sldch,int frame_tx,int subframe_tx);
+
+/*! \brief Top-level generation route for Sidelink Shared Channel
+  \param ue pointer to UE descriptor
+  \param slsch pointer to SLSCH configuration and payload
+  \param frame_tx Frame number
+  \param subframe_tx subframe number
+*/
+void generate_slsch(PHY_VARS_UE *ue,SLSCH_t *slss,int frame_tx,int subframe_tx);
 
 void generate_64qam_table(void);
 void generate_16qam_table(void);
diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c
index 9a19b0ddaf3dee79997ca3af075bd9448b74d43b..bb0ae8e11cee2ee59987b62b80d12945abbe40ba 100644
--- a/openair1/PHY/LTE_TRANSPORT/pucch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pucch.c
@@ -1278,7 +1278,7 @@ uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX
     int32_t         IP_CsData_allsfavg[NB_ANTENNAS_RX][14][4][2];
     int32_t         IP_allavg[D_NPUCCH_SF5];
     //int16_t         temp_ch[2];
-	int16_t         m[NUMBER_OF_UE_MAX], m_self, same_m_number;
+	int16_t         m[NUMBER_OF_UE_MAX], m_self=0, same_m_number;
 	uint16_t        n3_pucch_sameRB[NUMBER_OF_UE_MAX];
 	int16_t         n_oc0[NUMBER_OF_UE_MAX];
 	int16_t         n_oc1[NUMBER_OF_UE_MAX];
diff --git a/openair1/PHY/LTE_TRANSPORT/sldch.c b/openair1/PHY/LTE_TRANSPORT/sldch.c
new file mode 100644
index 0000000000000000000000000000000000000000..64d13c46890bc1f55184fd34e79e30969ea2208b
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/sldch.c
@@ -0,0 +1,66 @@
+/*
+ * 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
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * 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
+ */
+
+/*! \file PHY/LTE_TRANSPORT/slss.c
+ * \brief Functions to Generate and Receive PSDCH
+ * \author R. Knopp
+ * \date 2017
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr
+ * \note
+ * \warning
+ */
+#ifndef __LTE_TRANSPORT_SLSS__C__
+#define __LTE_TRANSPORT_SLSS__C__
+#include "PHY/defs.h"
+
+extern int multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP);
+
+void generate_sldch(PHY_VARS_UE *ue,SLDCH_t *sldch,int frame_tx,int subframe_tx) {
+
+  UE_tport_t pdu;
+  size_t sldch_header_len = sizeof(UE_tport_header_t);
+
+  pdu.header.packet_type = SLDCH;
+  pdu.header.absSF = (frame_tx*10)+subframe_tx;
+
+
+  AssertFatal(sldch->payload_length <=1500-sldch_header_len - sizeof(SLDCH_t) + sizeof(uint8_t*),
+                "SLDCH payload length > %d\n",
+                1500-sldch_header_len - sizeof(SLDCH_t) + sizeof(uint8_t*));
+  memcpy((void*)&pdu.sldch,
+         (void*)sldch,
+         sizeof(SLDCH_t));
+
+  LOG_I(PHY,"SLDCH configuration %d bytes, TBS payload %d bytes => %d bytes\n",
+        sizeof(SLDCH_t)-sizeof(uint8_t*),
+        sldch->payload_length,
+        sldch_header_len+sizeof(SLDCH_t)-sizeof(uint8_t*)+sldch->payload_length);
+
+  multicast_link_write_sock(0,
+                            &pdu,
+                            sldch_header_len+sizeof(SLDCH_t));
+
+}
+
+
+#endif
diff --git a/openair1/PHY/LTE_TRANSPORT/slsch.c b/openair1/PHY/LTE_TRANSPORT/slsch.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c199456e22f3c8d1a7e6a42c20895a55fa06f91
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/slsch.c
@@ -0,0 +1,70 @@
+/*
+ * 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
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * 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
+ */
+
+/*! \file PHY/LTE_TRANSPORT/slss.c
+ * \brief Functions to Generate and Receive PSSCH
+ * \author R. Knopp
+ * \date 2017
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr
+ * \note
+ * \warning
+ */
+#ifndef __LTE_TRANSPORT_SLSS__C__
+#define __LTE_TRANSPORT_SLSS__C__
+#include "PHY/defs.h"
+
+extern int
+multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP);
+
+
+void generate_slsch(PHY_VARS_UE *ue,SLSCH_t *slsch,int frame_tx,int subframe_tx) {
+
+  UE_tport_t pdu;
+  size_t slsch_header_len = sizeof(UE_tport_header_t);
+
+  if (slsch->rvidx==0) {
+    pdu.header.packet_type = SLSCH;
+    pdu.header.absSF = (frame_tx*10)+subframe_tx;
+    
+    memcpy((void*)&pdu.slsch,(void*)slsch,sizeof(SLSCH_t)-sizeof(uint8_t*));
+    
+    AssertFatal(slsch->payload_length <=1500-slsch_header_len - sizeof(SLSCH_t) + sizeof(uint8_t*),
+		"SLSCH payload length > %d\n",
+		1500-slsch_header_len - sizeof(SLSCH_t) + sizeof(uint8_t*));
+    memcpy((void*)&pdu.payload[0],
+	   (void*)slsch->payload,
+	   slsch->payload_length);
+    
+    LOG_I(PHY,"SLSCH configuration %d bytes, TBS payload %d bytes => %d bytes\n",
+	  sizeof(SLSCH_t)-sizeof(uint8_t*),
+	  slsch->payload_length,
+	  slsch_header_len+sizeof(SLSCH_t)-sizeof(uint8_t*)+slsch->payload_length);
+    
+    multicast_link_write_sock(0, 
+			      &pdu, 
+			      slsch_header_len+sizeof(SLSCH_t)-sizeof(uint8_t*)+slsch->payload_length);
+    
+  }
+}
+
+#endif
diff --git a/openair1/PHY/LTE_TRANSPORT/slss.c b/openair1/PHY/LTE_TRANSPORT/slss.c
new file mode 100644
index 0000000000000000000000000000000000000000..a8c9b75ae03e7065dfc88be9cc54c8ea43c9bf1d
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/slss.c
@@ -0,0 +1,43 @@
+/*
+ * 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
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * 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
+ */
+
+/*! \file PHY/LTE_TRANSPORT/slss.c
+ * \brief Functions to Generate and Received Sidelink PSS,SSS and PSBCH
+ * \author R. Knopp
+ * \date 2017
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr
+ * \note
+ * \warning
+ */
+#ifndef __LTE_TRANSPORT_SLSS__C__
+#define __LTE_TRANSPORT_SLSS__C__
+#include "PHY/defs.h"
+
+
+void generate_slss(PHY_VARS_UE *ue,SLSS_t *slss,int frame_tx,int subframe_tx) {
+
+  AssertFatal(1==0,"Should get here yet for UE %d\n",ue->Mod_id);
+
+}
+
+#endif
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 1d2b622e7e748db1610f3bf96a30f26177df7c8c..55425596d748ba1e0643e65a7c138f1c0ae5500e 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -58,6 +58,7 @@
 #include "msc.h"
 
 #include "openair2/PHY_INTERFACE/IF_Module.h"
+//#include "openair2/PHY_INTERFACE/IF_Module_UE.h"
 
 //#include <complex.h>
 #include "assertions.h"
@@ -142,6 +143,8 @@ static inline void* malloc16_clear( size_t size )
 #include "targets/ARCH/COMMON/common_lib.h"
 #include "targets/COMMON/openairinterface5g_limits.h"
 
+#include "openair2/LAYER2/MAC/defs.h"
+
 #if defined(EXMIMO) || defined(OAI_USRP)
 //#define NUMBER_OF_eNB_MAX 1
 //#define NUMBER_OF_UE_MAX 16
@@ -695,6 +698,22 @@ typedef struct {
   UE_rxtx_proc_t proc_rxtx[RX_NB_TH];
 } UE_proc_t;
 
+
+/// Panos: Structure holding timer_thread related elements (phy_stub_UE mode)
+typedef struct{
+	pthread_t pthread_timer;
+	/// Panos: mutex for waiting SF ticking
+	pthread_mutex_t mutex_ticking;
+	/// Panos: \brief ticking var for ticking thread.
+	/// \internal This variable is protected by \ref mutex_ticking.
+	int ticking_var;
+	/// condition variable for timer_thread;
+	pthread_cond_t cond_ticking;
+	//time_stats_t timer_stats;
+}SF_ticking;
+
+
+
 typedef enum {
   LOCAL_RF        =0,
   REMOTE_IF5      =1,
@@ -1497,6 +1516,11 @@ typedef struct {
   time_stats_t dlsch_tc_intl1_stats;
   time_stats_t dlsch_tc_intl2_stats;
   time_stats_t tx_prach;
+  time_stats_t timer_stats;
+
+  pthread_mutex_t timer_mutex;
+  pthread_cond_t timer_cond;
+  int instance_cnt_timer;
 
   /// RF and Interface devices per CC
 
@@ -1666,6 +1690,25 @@ static inline void wait_sync(char *thread_name) {
 
 }
 
+static inline int wakeup_thread(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
+
+  if (pthread_mutex_lock(mutex) != 0) {
+    LOG_E( PHY, "error locking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  *instance_cnt = *instance_cnt + 1;
+  // the thread can now be woken up
+  if (pthread_cond_signal(cond) != 0) {
+    LOG_E( PHY, "ERROR pthread_cond_signal\n");
+    exit_fun( "ERROR pthread_cond_signal" );
+    return(-1);
+  }
+  
+  pthread_mutex_unlock(mutex);
+  return(0);
+}
+
 static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
   if (pthread_mutex_lock(mutex) != 0) {
     LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
@@ -1717,6 +1760,8 @@ static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *
     return(-1);
   }
 
+  //LOG_D(PHY, "%s() name:%s instance_cnt:%u - about to decrement\n", __FUNCTION__, name, *instance_cnt);
+
   *instance_cnt=*instance_cnt-1;
 
   if (pthread_mutex_unlock(mutex) != 0) {
diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h
index 2697dc55789078aadc22ed4d701156381ef15a55..c3ab134d87ff88579df89773b26509cc6d239710 100644
--- a/openair1/PHY/impl_defs_top.h
+++ b/openair1/PHY/impl_defs_top.h
@@ -272,7 +272,7 @@ typedef struct {
 
 /// Measurement Variables
 
-#define NUMBER_OF_SUBBANDS_MAX 13
+//#define NUMBER_OF_SUBBANDS_MAX 13
 #define NUMBER_OF_HARQ_PID_MAX 8
 
 #define MAX_FRAME_NUMBER 0x400
diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h
index 3c232a82b755bc001c59f50d4de5a6433f47db3d..5c8840f84a8b1eb8e8c5e9d9fee355d2f9fedae6 100644
--- a/openair1/SCHED/defs.h
+++ b/openair1/SCHED/defs.h
@@ -140,6 +140,19 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t
   @param phy_vars_rn pointer to RN variables
 */
 int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn);
+
+/*! \brief Scheduling for UE Sidelink RX procedures in normal subframes.
+  @param ue Pointer to UE variables on which to act
+  @param proc Pointer to RXn_TXnp4 proc information
+*/
+void phy_procedures_UE_SL_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc);
+
+/*! \brief Scheduling for UE Sidelink TX procedures in normal subframes.
+  @param ue Pointer to UE variables on which to act
+  @param proc Pointer to RXn_TXnp4 proc information
+*/
+void phy_procedures_UE_SL_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc);
+
 int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,
                                               uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode,
                                               relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn);
diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c
index df01fad13622307d0c14c65fbd302744d23453e2..ea891aad770f414ca796157b96dd8e5c5c6e4712 100644
--- a/openair1/SCHED/fapi_l1.c
+++ b/openair1/SCHED/fapi_l1.c
@@ -35,6 +35,7 @@
 #include "SCHED/defs.h"
 #include "SCHED/extern.h"
 #include "nfapi_interface.h"
+#include "nfapi_pnf_interface.h"
 #include "fapi_l1.h"
 
 int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req);
@@ -844,3 +845,25 @@ void schedule_response(Sched_Rsp_t *Sched_INFO)
     }
   }
 }
+
+/*Dummy functions*/
+
+int memcpy_dl_config_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_dl_config_request_t* req)
+{
+	return 0;
+}
+
+int memcpy_ul_config_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req)
+{
+	return 0;
+}
+
+int memcpy_hi_dci0_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_hi_dci0_request_t* req)
+{
+	return 0;
+}
+
+int memcpy_tx_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_tx_request_t* req)
+{
+	return 0;
+}
diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c
index 151a74f6200c2ddb8c3180de9952988ba5283a3a..6f9aebbc1b5a2660dd663556c3f6bbc0160073ee 100644
--- a/openair1/SCHED/phy_procedures_lte_ue.c
+++ b/openair1/SCHED/phy_procedures_lte_ue.c
@@ -506,6 +506,7 @@ void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id
                   {
                       int Mod_id = ue->Mod_id;
                       int CC_id = ue->CC_id;
+                      // Panos: Substitute call to ue_get_SR() with the filled ue_SR_config->SR_payload (0, or 1).
                       SR_payload = ue_get_SR(Mod_id,
 					     CC_id,
 					     frame_tx,
@@ -1454,8 +1455,6 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 	  ue->tx_power_dBm[subframe_tx],
 	  dB_fixed(prach_power),
 	  ue->prach_vars[eNB_id]->amp);
-   
-
 
     if (ue->mac_enabled==1){
       Msg1_transmitted(ue->Mod_id,
@@ -1754,6 +1753,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
 	if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round==0) {
 	  //if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) {
 	  access_mode=SCHEDULED_ACCESS;
+
 	  ue_get_sdu(Mod_id,
 		     CC_id,
 		     frame_tx,
@@ -2333,6 +2333,27 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 
 }
 
+void phy_procedures_UE_SL_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc) {
+
+  int subframe_tx = proc->subframe_tx;
+  int frame_tx = proc->frame_tx;
+  SLSS_t *slss;
+  SLDCH_t *sldch;
+  SLSCH_t *slsch;
+
+  LOG_D(PHY,"****** start Sidelink TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, subframe_tx);
+
+  // check for SLBCH/SLSS
+  if ((slss = ue_get_slss(ue->Mod_id,ue->CC_id,frame_tx,subframe_tx)) != NULL) generate_slss(ue,slss,frame_tx,subframe_tx);
+
+  // check for SLDCH
+  if ((sldch = ue_get_sldch(ue->Mod_id,ue->CC_id,frame_tx,subframe_tx)) != NULL) generate_sldch(ue,sldch,frame_tx,subframe_tx);
+
+  // check for SLSCH
+  if ((slsch = ue_get_slsch(ue->Mod_id,ue->CC_id,frame_tx,subframe_tx)) != NULL) generate_slsch(ue,slsch,frame_tx,subframe_tx);
+
+}
+
 void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type) {
 
 
@@ -2727,6 +2748,7 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uin
     ue->pbch_vars[eNB_id]->pdu_errors_conseq++;
     ue->pbch_vars[eNB_id]->pdu_errors++;
 
+		// Panos: Substitute call to rrc_out_of_sync_ind() with fill_bch_incication(sync=0).
     if (ue->mac_enabled == 1) rrc_out_of_sync_ind(ue->Mod_id,frame_rx,eNB_id);
     else AssertFatal(ue->pbch_vars[eNB_id]->pdu_errors_conseq<100,
 		     "More that 100 consecutive PBCH errors! Exiting!\n");
@@ -2747,6 +2769,8 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uin
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT);
 }
 
+
+
 int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t abstraction_flag)
 {
 
@@ -3397,6 +3421,7 @@ void process_rar(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, runmode_t mo
 	    subframe_rx,
 	    ue->prach_resources[eNB_id]->ra_PreambleIndex);
       
+      // Panos: Substitute call to ue_process_rar() with call to fill_dlsch_rar_indication()
       timing_advance = ue_process_rar(ue->Mod_id,
 				      ue->CC_id,
 				      frame_rx,
@@ -3727,6 +3752,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
 	
 	switch (pdsch) {
 	case PDSCH:
+		// Panos: Substitute call to ue_send_sdu() with call to fill_dlsch_indication()
 	  ue_send_sdu(ue->Mod_id,
 		      CC_id,
 		      frame_rx,
@@ -3736,6 +3762,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
 		      eNB_id);
 	  break;
 	case SI_PDSCH:
+		// Panos: Substitute call with call to fill_dlsch_indication()
 	  ue_decode_si(ue->Mod_id,
 		       CC_id,
 		       frame_rx,
@@ -3744,7 +3771,8 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
 		       ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3);
 	  break;
 	case P_PDSCH:
-	  ue_decode_p(ue->Mod_id,
+		// Panos: Substitute call with call to fill_dlsch_indication()
+		ue_decode_p(ue->Mod_id,
 		      CC_id,
 		      frame_rx,
 		      eNB_id,
@@ -3752,6 +3780,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
 		      ue->dlsch_SI[eNB_id]->harq_processes[0]->TBS>>3);
 	  break;
 	case RA_PDSCH:
+		// Panos: Substitute with call to fill_dlsch_rar_indication()
 	  process_rar(ue,proc,eNB_id,mode,abstraction_flag);
 	  break;
 	case PDSCH1:
@@ -4654,6 +4683,11 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
 #endif
 
 
+void phy_procedures_UE_SL_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc) {
+
+
+}
+
 int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,
 			 uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode,
 			 relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn) {
diff --git a/openair1/SCHED/pusch_pc.c b/openair1/SCHED/pusch_pc.c
index caef13162726849dd38948a8079adaca4982bcc9..a631839bf581e128ed644b4313b018ac97cae485 100644
--- a/openair1/SCHED/pusch_pc.c
+++ b/openair1/SCHED/pusch_pc.c
@@ -35,6 +35,8 @@
 #include "PHY/LTE_TRANSPORT/proto.h"
 #include "PHY/extern.h"
 
+extern uint8_t  nfapi_mode;
+
 // This is the formula from Section 5.1.1.1 in 36.213 100*10*log10((2^(MPR*Ks)-1)), where MPR is in the range [0,6] and Ks=1.25
 int16_t hundred_times_delta_TF[100] = {-32768,-1268,-956,-768,-631,-523,-431,-352,-282,-219,-161,-107,-57,-9,36,79,120,159,197,234,269,304,337,370,402,434,465,495,525,555,583,612,640,668,696,723,750,777,803,829,856,881,907,933,958,983,1008,1033,1058,1083,1108,1132,1157,1181,1205,1229,1254,1278,1302,1325,1349,1373,1397,1421,1444,1468,1491,1515,1538,1562,1585,1609,1632,1655,1679,1702,1725,1748,1772,1795,1818,1841,1864,1887,1910,1933,1956,1980,2003,2026,2049,2072,2095,2118,2141,2164,2186,2209,2232,2255};
 uint16_t hundred_times_log10_NPRB[100] = {0,301,477,602,698,778,845,903,954,1000,1041,1079,1113,1146,1176,1204,1230,1255,1278,1301,1322,1342,1361,1380,1397,1414,1431,1447,1462,1477,1491,1505,1518,1531,1544,1556,1568,1579,1591,1602,1612,1623,1633,1643,1653,1662,1672,1681,1690,1698,1707,1716,1724,1732,1740,1748,1755,1763,1770,1778,1785,1792,1799,1806,1812,1819,1826,1832,1838,1845,1851,1857,1863,1869,1875,1880,1886,1892,1897,1903,1908,1913,1919,1924,1929,1934,1939,1944,1949,1954,1959,1963,1968,1973,1977,1982,1986,1991,1995,2000};
@@ -201,7 +203,10 @@ void pusch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_
 int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id,uint8_t eNB_index)
 {
 
-  return PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->PHR;
+	if(nfapi_mode!=3)
+		return PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->PHR;
+	else
+		return 40; // For nfapi_mode=3 consider ideal conditions
 }
 
 // uint8_t eNB_id,uint8_t harq_pid, uint8_t UE_id,
diff --git a/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c b/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c
index 1ba724976fabdd87b82c623ee50ea9b43cb8cbfb..8cf9e13212244ec7e1ab7350c1228deff9b1d5e0 100644
--- a/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c
+++ b/openair1/SIMULATION/ETH_TRANSPORT/multicast_link.c
@@ -113,7 +113,7 @@ multicast_link_init(void)
 
     if (multicast_if != NULL) {
       if (setsockopt(group_list[group].socket, SOL_SOCKET,SO_BINDTODEVICE,
-                     multicast_if, 4) < 0) {
+                     multicast_if, strlen(multicast_if)) < 0) {
         LOG_E(EMU,
               "[MULTICAST] ERROR : setsockopt:SO_BINDTODEVICE on interface %s, exiting ...\n",
               multicast_if);
diff --git a/openair2/COMMON/mac_rrc_primitives.h b/openair2/COMMON/mac_rrc_primitives.h
index 3a73000e505aa5452bd53543669bf3bec0e0ec8e..6efa4e4d94b3ae9a02718354e53aa278796e6853 100644
--- a/openair2/COMMON/mac_rrc_primitives.h
+++ b/openair2/COMMON/mac_rrc_primitives.h
@@ -364,10 +364,20 @@ typedef struct {
                             struct PMCH_InfoList_r9 *pmch_InfoList
 #endif
                            );
-  unsigned int (*mac_rlc_data_req)(module_id_t, unsigned int, const unsigned int,char*);
+  unsigned int (*mac_rlc_data_req)(module_id_t, unsigned int, const unsigned int,char*
+#ifdef Rel14
+                                  ,uint32_t
+                                  ,uint32_t
+#endif
+                                   );
   void (*mac_rlc_data_ind)(module_id_t, logical_chan_id_t, char*, tb_size_t, num_tb_t, crc_t* );
   mac_rlc_status_resp_t (*mac_rlc_status_ind)     (module_id_t enb_mod_idP, module_id_t ue_mod_idP, frame_t frameP, sub_frame_t subframeP, eNB_flag_t eNB_flagP, MBMS_flag_t MBMS_flagP,
-      logical_chan_id_t channel_idP, tb_size_t tb_sizeP);
+      logical_chan_id_t channel_idP, tb_size_t tb_sizeP
+#ifdef Rel14
+      ,uint32_t sourceL2Id
+      ,uint32_t destinationL2Id
+#endif
+      );
   signed int (*rrc_rlc_data_req)(module_id_t, rb_id_t, mui_t, confirm_t, sdu_size_t, char *);
   void (*rrc_rlc_register_rrc) (void (*rrc_data_indP)(module_id_t , rb_id_t , sdu_size_t , char* ),
                                 void  (*rrc_data_confP) (module_id_t , rb_id_t , mui_t ) ) ;
diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h
index 0ab8d9670145ceab059356b9d6675e94b786b2b7..bb8fa7bb1c2ed9f5a3224f3906e3544fcd4dd760 100644
--- a/openair2/COMMON/platform_types.h
+++ b/openair2/COMMON/platform_types.h
@@ -88,6 +88,10 @@ typedef boolean_t             srb_flag_t;
 #define  SRB_FLAG_NO          FALSE
 #define  SRB_FLAG_YES         TRUE
 
+typedef boolean_t             sl_discovery_flag_t;
+#define  SL_DISCOVERY_FLAG_NO          FALSE
+#define  SL_DISCOVERY_FLAG_YES         TRUE
+
 typedef enum link_direction_e {
   UNKNOWN_DIR          = 0,
   DIR_UPLINK           = 1,
@@ -164,7 +168,9 @@ typedef enum  ip_traffic_type_e {
   TRAFFIC_IPV4_TYPE_UNICAST    =  5,
   TRAFFIC_IPV4_TYPE_MULTICAST  =  6,
   TRAFFIC_IPV4_TYPE_BROADCAST  =  7,
-  TRAFFIC_IPV4_TYPE_UNKNOWN    =  8
+  TRAFFIC_IPV4_TYPE_UNKNOWN    =  8,
+  TRAFFIC_PC5S_SIGNALLING      =  9,
+  TRAFFIC_PC5S_SESSION_INIT    =  10
 } ip_traffic_type_t;
 
 //-----------------------------------------------------------------------------
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index 9bd25d3b3aa52075eaf3acf5f5c51b0f9f7581b5..76794580066f5eeeb363c62c8455222720dab318 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -37,6 +37,12 @@
 #else
 #include "RRC/LITE/MESSAGES/SystemInformationBlockType2.h"
 #endif
+#include "SL-OffsetIndicator-r12.h"
+#include "SubframeBitmapSL-r12.h"
+#include "SL-CP-Len-r12.h"
+#include "SL-PeriodComm-r12.h"
+#include "SL-DiscResourcePool-r12.h"
+
 
 //-------------------------------------------------------------------------------------------//
 // Messages for RRC logging
@@ -168,6 +174,56 @@ typedef struct RrcConfigurationReq_s {
   long                    ue_TimersAndConstants_n310[MAX_NUM_CCs];
   long                    ue_TimersAndConstants_n311[MAX_NUM_CCs];
   long                    ue_TransmissionMode[MAX_NUM_CCs];
+
+  //TTN - for D2D
+  //SIB18
+  e_SL_CP_Len_r12                rxPool_sc_CP_Len[MAX_NUM_CCs];
+  e_SL_PeriodComm_r12            rxPool_sc_Period[MAX_NUM_CCs];
+  e_SL_CP_Len_r12                rxPool_data_CP_Len[MAX_NUM_CCs];
+  long                           rxPool_ResourceConfig_prb_Num[MAX_NUM_CCs];
+  long                           rxPool_ResourceConfig_prb_Start[MAX_NUM_CCs];
+  long                           rxPool_ResourceConfig_prb_End[MAX_NUM_CCs];
+  SL_OffsetIndicator_r12_PR      rxPool_ResourceConfig_offsetIndicator_present[MAX_NUM_CCs];
+  long                           rxPool_ResourceConfig_offsetIndicator_choice[MAX_NUM_CCs];
+  SubframeBitmapSL_r12_PR        rxPool_ResourceConfig_subframeBitmap_present[MAX_NUM_CCs];
+  char*                          rxPool_ResourceConfig_subframeBitmap_choice_bs_buf[MAX_NUM_CCs];
+  long                           rxPool_ResourceConfig_subframeBitmap_choice_bs_size[MAX_NUM_CCs];
+  long                           rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[MAX_NUM_CCs];
+
+  //SIB19
+  //for discRxPool
+  SL_CP_Len_r12_t                discRxPool_cp_Len[MAX_NUM_CCs];
+  e_SL_DiscResourcePool_r12__discPeriod_r12                   discRxPool_discPeriod[MAX_NUM_CCs];
+  long                           discRxPool_numRetx[MAX_NUM_CCs];
+  long                           discRxPool_numRepetition[MAX_NUM_CCs];
+  long                           discRxPool_ResourceConfig_prb_Num[MAX_NUM_CCs];
+  long                           discRxPool_ResourceConfig_prb_Start[MAX_NUM_CCs];
+  long                           discRxPool_ResourceConfig_prb_End[MAX_NUM_CCs];
+  SL_OffsetIndicator_r12_PR      discRxPool_ResourceConfig_offsetIndicator_present[MAX_NUM_CCs];
+  long                           discRxPool_ResourceConfig_offsetIndicator_choice[MAX_NUM_CCs];
+  SubframeBitmapSL_r12_PR        discRxPool_ResourceConfig_subframeBitmap_present[MAX_NUM_CCs];
+  char*                          discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf[MAX_NUM_CCs];
+  long                           discRxPool_ResourceConfig_subframeBitmap_choice_bs_size[MAX_NUM_CCs];
+  long                           discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[MAX_NUM_CCs];
+  //for discRxPoolPS
+  SL_CP_Len_r12_t                discRxPoolPS_cp_Len[MAX_NUM_CCs];
+  e_SL_DiscResourcePool_r12__discPeriod_r12                   discRxPoolPS_discPeriod[MAX_NUM_CCs];
+  long                           discRxPoolPS_numRetx[MAX_NUM_CCs];
+  long                           discRxPoolPS_numRepetition[MAX_NUM_CCs];
+  long                           discRxPoolPS_ResourceConfig_prb_Num[MAX_NUM_CCs];
+  long                           discRxPoolPS_ResourceConfig_prb_Start[MAX_NUM_CCs];
+  long                           discRxPoolPS_ResourceConfig_prb_End[MAX_NUM_CCs];
+  SL_OffsetIndicator_r12_PR      discRxPoolPS_ResourceConfig_offsetIndicator_present[MAX_NUM_CCs];
+  long                           discRxPoolPS_ResourceConfig_offsetIndicator_choice[MAX_NUM_CCs];
+  SubframeBitmapSL_r12_PR        discRxPoolPS_ResourceConfig_subframeBitmap_present[MAX_NUM_CCs];
+  char*                          discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[MAX_NUM_CCs];
+  long                           discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[MAX_NUM_CCs];
+  long                           discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[MAX_NUM_CCs];
+
+
+
+
+
 } RrcConfigurationReq;
 #define MAX_NUM_NBIOT_CELEVELS    3
 typedef struct NbIoTRrcConfigurationReq_s {
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 19c168503fbea71b190eb870de1ce7a4c7c2b5d1..fd6575f3045c3ef4a403d6b3c4ed5d9a5c2897f3 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -101,6 +101,52 @@ void RCconfig_flexran()
     ue_TimersAndConstants_n310, ue_TimersAndConstants_n311,
     ue_TransmissionMode;
 
+
+    e_SL_CP_Len_r12                rxPool_sc_CP_Len;
+    e_SL_PeriodComm_r12            rxPool_sc_Period;
+    e_SL_CP_Len_r12                rxPool_data_CP_Len;
+    long                           rxPool_ResourceConfig_prb_Num;
+    long                           rxPool_ResourceConfig_prb_Start;
+    long                           rxPool_ResourceConfig_prb_End;
+    SL_OffsetIndicator_r12_PR      rxPool_ResourceConfig_offsetIndicator_present;
+    long                           rxPool_ResourceConfig_offsetIndicator_choice;
+    SubframeBitmapSL_r12_PR        rxPool_ResourceConfig_subframeBitmap_present;
+    char*                          rxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
+    long                           rxPool_ResourceConfig_subframeBitmap_choice_bs_size;
+    long                           rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
+
+    //SIB19
+    //for discRxPool
+    SL_CP_Len_r12_t                discRxPool_cp_Len;
+    e_SL_DiscResourcePool_r12__discPeriod_r12                   discRxPool_discPeriod;
+    long                           discRxPool_numRetx;
+    long                           discRxPool_numRepetition;
+    long                           discRxPool_ResourceConfig_prb_Num;
+    long                           discRxPool_ResourceConfig_prb_Start;
+    long                           discRxPool_ResourceConfig_prb_End;
+    SL_OffsetIndicator_r12_PR      discRxPool_ResourceConfig_offsetIndicator_present;
+    long                           discRxPool_ResourceConfig_offsetIndicator_choice;
+    SubframeBitmapSL_r12_PR        discRxPool_ResourceConfig_subframeBitmap_present;
+    char*                          discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
+    long                           discRxPool_ResourceConfig_subframeBitmap_choice_bs_size;
+    long                           discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
+    //for discRxPoolPS
+    SL_CP_Len_r12_t                discRxPoolPS_cp_Len;
+    e_SL_DiscResourcePool_r12__discPeriod_r12                   discRxPoolPS_discPeriod;
+    long                           discRxPoolPS_numRetx;
+    long                           discRxPoolPS_numRepetition;
+    long                           discRxPoolPS_ResourceConfig_prb_Num;
+    long                           discRxPoolPS_ResourceConfig_prb_Start;
+    long                           discRxPoolPS_ResourceConfig_prb_End;
+    SL_OffsetIndicator_r12_PR      discRxPoolPS_ResourceConfig_offsetIndicator_present;
+    long                           discRxPoolPS_ResourceConfig_offsetIndicator_choice;
+    SubframeBitmapSL_r12_PR        discRxPoolPS_ResourceConfig_subframeBitmap_present;
+    char*                          discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf;
+    long                           discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size;
+    long                           discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
+
+
+
   /* get number of eNBs */
   paramdef_t ENBSParams[] = ENBSPARAMS_DESC;
   config_get(ENBSParams, sizeof(ENBSParams)/sizeof(paramdef_t), NULL);
@@ -181,6 +227,48 @@ void RCconfig_flexran()
   }
 }
 
+
+/*void UE_config_stub_pnf(void) {
+  int               j;
+  paramdef_t L1_Params[] = L1PARAMS_DESC;
+  paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST,NULL,0};
+
+  config_getlist( &L1_ParamList,L1_Params,sizeof(L1_Params)/sizeof(paramdef_t), NULL);
+  if (L1_ParamList.numelt > 0) {
+	  for (j=0; j<L1_ParamList.numelt; j++){
+		  //nb_L1_CC = *(L1_ParamList.paramarray[j][L1_CC_IDX].uptr); // Number of component carriers is of no use for the
+	                                                            // phy_stub mode UE pnf. Maybe we can completely skip it.
+
+		  if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
+			  sf_ahead = 4; // Need 4 subframe gap between RX and TX
+			  }
+		  // Panos: Right now that we have only one UE (thread) it is ok to put the eth_params in the UE_mac_inst.
+		  // Later I think we have to change that to attribute eth_params to a global element for all the UEs.
+		  else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
+			  stub_eth_params.local_if_name            = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_IF_NAME_IDX].strptr));
+			  stub_eth_params.my_addr                  = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr));
+			  stub_eth_params.remote_addr              = strdup(*(L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr));
+			  stub_eth_params.my_portc                 = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr);
+			  stub_eth_params.remote_portc             = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr);
+			  stub_eth_params.my_portd                 = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr);
+			  stub_eth_params.remote_portd             = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr);
+			  stub_eth_params.transp_preference        = ETH_UDP_MODE;
+
+
+			  sf_ahead = 2; // Cannot cope with 4 subframes betweem RX and TX - set it to 2
+			  //configure_nfapi_pnf(UE_mac_inst[0].eth_params_n.remote_addr, UE_mac_inst[0].eth_params_n.remote_portc, UE_mac_inst[0].eth_params_n.my_addr, UE_mac_inst[0].eth_params_n.my_portd, UE_mac_inst[0].eth_params_n.remote_portd);
+			  configure_nfapi_pnf(stub_eth_params.remote_addr, stub_eth_params.remote_portc, stub_eth_params.my_addr, stub_eth_params.my_portd, stub_eth_params.remote_portd);
+		  }
+		  else { // other midhaul
+		  }
+	  }
+  }
+  else {
+
+  }
+}*/
+
+
 void RCconfig_L1(void) {
   int               i,j;
   paramdef_t L1_Params[] = L1PARAMS_DESC;
@@ -196,7 +284,6 @@ void RCconfig_L1(void) {
 
   config_getlist( &L1_ParamList,L1_Params,sizeof(L1_Params)/sizeof(paramdef_t), NULL);
   if (L1_ParamList.numelt > 0) {
-
     for (j = 0; j < RC.nb_L1_inst; j++) {
       RC.nb_L1_CC[j] = *(L1_ParamList.paramarray[j][L1_CC_IDX].uptr);
 
@@ -249,6 +336,7 @@ void RCconfig_L1(void) {
         configure_nfapi_pnf(RC.eNB[j][0]->eth_params_n.remote_addr, RC.eNB[j][0]->eth_params_n.remote_portc, RC.eNB[j][0]->eth_params_n.my_addr, RC.eNB[j][0]->eth_params_n.my_portd, RC.eNB[j][0]->eth_params_n     .remote_portd);
       }
       else { // other midhaul
+        //printf("Panos-D: RCconfig_L1 12 \n");
       }	
     }// j=0..num_inst
     printf("Initializing northbound interface for L1\n");
@@ -430,6 +518,52 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) {
   int32_t     ue_TimersAndConstants_n311    = 0;
   int32_t     ue_TransmissionMode           = 0;
 
+  //TTN - for D2D
+  //SIB18
+  const char*       rxPool_sc_CP_Len                                        = NULL;
+  const char*       rxPool_sc_Period                                        = NULL;
+  const char*       rxPool_data_CP_Len                                      = NULL;
+  libconfig_int     rxPool_ResourceConfig_prb_Num                           = 0;
+  libconfig_int     rxPool_ResourceConfig_prb_Start                         = 0;
+  libconfig_int     rxPool_ResourceConfig_prb_End                           = 0;
+  const char*       rxPool_ResourceConfig_offsetIndicator_present           = NULL;
+  libconfig_int     rxPool_ResourceConfig_offsetIndicator_choice            = 0;
+  const char*       rxPool_ResourceConfig_subframeBitmap_present            = NULL;
+  const char*       rxPool_ResourceConfig_subframeBitmap_choice_bs_buf      = NULL;
+  libconfig_int     rxPool_ResourceConfig_subframeBitmap_choice_bs_size     = 0;
+  libconfig_int     rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused     = 0;
+  //SIB19
+  //For discRxPool
+  const char*       discRxPool_cp_Len                                              = NULL;
+  const char*       discRxPool_discPeriod                                          = NULL;
+  libconfig_int     discRxPool_numRetx                                             = 0;
+  libconfig_int     discRxPool_numRepetition                                       = 0;
+
+  libconfig_int     discRxPool_ResourceConfig_prb_Num                              = 0;
+  libconfig_int     discRxPool_ResourceConfig_prb_Start                            = 0;
+  libconfig_int     discRxPool_ResourceConfig_prb_End                              = 0;
+  const char*       discRxPool_ResourceConfig_offsetIndicator_present              = NULL;
+  libconfig_int     discRxPool_ResourceConfig_offsetIndicator_choice               = 0;
+  const char*       discRxPool_ResourceConfig_subframeBitmap_present               = NULL;
+  const char*       discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf         = NULL;
+  libconfig_int     discRxPool_ResourceConfig_subframeBitmap_choice_bs_size        = 0;
+  libconfig_int     discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0;
+  //For discRxPoolPS
+  const char*       discRxPoolPS_cp_Len                                              = NULL;
+  const char*       discRxPoolPS_discPeriod                                          = NULL;
+  libconfig_int     discRxPoolPS_numRetx                                             = 0;
+  libconfig_int     discRxPoolPS_numRepetition                                       = 0;
+
+  libconfig_int     discRxPoolPS_ResourceConfig_prb_Num                              = 0;
+  libconfig_int     discRxPoolPS_ResourceConfig_prb_Start                            = 0;
+  libconfig_int     discRxPoolPS_ResourceConfig_prb_End                              = 0;
+  const char*       discRxPoolPS_ResourceConfig_offsetIndicator_present              = NULL;
+  libconfig_int     discRxPoolPS_ResourceConfig_offsetIndicator_choice               = 0;
+  const char*       discRxPoolPS_ResourceConfig_subframeBitmap_present               = NULL;
+  const char*       discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf         = NULL;
+  libconfig_int     discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size        = 0;
+  libconfig_int     discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0;
+
 
   int32_t     srb1_timer_poll_retransmit    = 0;
   int32_t     srb1_timer_reordering         = 0;
@@ -609,6 +743,7 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) {
 	    for (j = 0; j < CCsParamList.numelt ;j++) { 
 
 	      sprintf(ccspath,"%s.%s.[%i]",enbpath,ENB_CONFIG_STRING_COMPONENT_CARRIERS,j);
+	      LOG_I(RRC, "enb_config::RCconfig_RRC() parameter number: %d, total number of parameters: %d, ccspath: %s \n \n", j, sizeof(CCsParams)/sizeof(paramdef_t), ccspath);
 	      config_get( CCsParams,sizeof(CCsParams)/sizeof(paramdef_t),ccspath);	      
 
 
@@ -1439,6 +1574,267 @@ int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc) {
 			       RC.config_file_name, i, ue_TransmissionMode);
 		  break;
 		}
+
+		//TTN - for D2D
+		//SIB18
+		if (strcmp(rxPool_sc_CP_Len,"normal")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_CP_Len[j] = SL_CP_Len_r12_normal;
+		} else if (strcmp(rxPool_sc_CP_Len,"extended")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_CP_Len[j] = SL_CP_Len_r12_extended;
+		} else
+		   AssertFatal (0,
+		         "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for rxPool_sc_CP_Len choice: normal,extended!\n",
+		         RC.config_file_name, i, rxPool_sc_CP_Len);
+
+		if (strcmp(rxPool_sc_Period,"sf40")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf40;
+		} else if (strcmp(rxPool_sc_Period,"sf60")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf60;
+		} else if (strcmp(rxPool_sc_Period,"sf70")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf70;
+		} else if (strcmp(rxPool_sc_Period,"sf80")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf80;
+		} else if (strcmp(rxPool_sc_Period,"sf120")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf120;
+		} else if (strcmp(rxPool_sc_Period,"sf140")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf140;
+		} else if (strcmp(rxPool_sc_Period,"sf160")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf160;
+		} else if (strcmp(rxPool_sc_Period,"sf240")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf240;
+		} else if (strcmp(rxPool_sc_Period,"sf280")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf280;
+		} else if (strcmp(rxPool_sc_Period,"sf320")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_sf320;
+		} else if (strcmp(rxPool_sc_Period,"spare6")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_spare6;
+		} else if (strcmp(rxPool_sc_Period,"spare5")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_spare5;
+		} else if (strcmp(rxPool_sc_Period,"spare4")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_spare4;
+		} else if (strcmp(rxPool_sc_Period,"spare3")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_spare3;
+		} else if (strcmp(rxPool_sc_Period,"spare2")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_spare2;
+		} else if (strcmp(rxPool_sc_Period,"spare")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_sc_Period[j] = SL_PeriodComm_r12_spare;
+		} else
+		   AssertFatal (0,
+		         "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for rxPool_sc_Period choice: sf40,sf60,sf70,sf80,sf120,sf140,sf160,sf240,sf280,sf320,spare6,spare5,spare4,spare3,spare2,spare!\n",
+		         RC.config_file_name, i, rxPool_sc_Period);
+
+		if (strcmp(rxPool_data_CP_Len,"normal")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_data_CP_Len[j] = SL_CP_Len_r12_normal;
+		} else if (strcmp(rxPool_data_CP_Len,"extended")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_data_CP_Len[j] = SL_CP_Len_r12_extended;
+		} else
+		   AssertFatal (0,
+		         "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for rxPool_data_CP_Len choice: normal,extended!\n",
+		         RC.config_file_name, i, rxPool_data_CP_Len);
+
+		RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_prb_Num[j] = rxPool_ResourceConfig_prb_Num;
+		RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_prb_Start[j] = rxPool_ResourceConfig_prb_Start;
+		RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_prb_End[j] = rxPool_ResourceConfig_prb_End;
+
+		if (strcmp(rxPool_ResourceConfig_offsetIndicator_present,"prNothing")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_offsetIndicator_present[j] = SL_OffsetIndicator_r12_PR_NOTHING;
+		} else if (strcmp(rxPool_ResourceConfig_offsetIndicator_present,"prSmall")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_offsetIndicator_present[j] = SL_OffsetIndicator_r12_PR_small_r12;
+		} else if (strcmp(rxPool_ResourceConfig_offsetIndicator_present,"prLarge")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_offsetIndicator_present[j] = SL_OffsetIndicator_r12_PR_large_r12;
+		} else
+		   AssertFatal (0,
+		         "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for rxPool_ResourceConfig_offsetIndicator_present choice: prNothing,prSmal,prLarge!\n",
+		         RC.config_file_name, i, rxPool_ResourceConfig_offsetIndicator_present);
+
+		RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_offsetIndicator_choice[j] = rxPool_ResourceConfig_offsetIndicator_choice;
+
+		if (strcmp(rxPool_ResourceConfig_subframeBitmap_present,"prNothing")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_NOTHING;
+		} else if (strcmp(rxPool_ResourceConfig_subframeBitmap_present,"prBs4")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs4_r12;
+		} else if (strcmp(rxPool_ResourceConfig_subframeBitmap_present,"prBs8")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs8_r12;
+		} else if (strcmp(rxPool_ResourceConfig_subframeBitmap_present,"prBs12")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs12_r12;
+		} else if (strcmp(rxPool_ResourceConfig_subframeBitmap_present,"prBs16")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs16_r12;
+		} else if (strcmp(rxPool_ResourceConfig_subframeBitmap_present,"prBs30")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs30_r12;
+		} else if (strcmp(rxPool_ResourceConfig_subframeBitmap_present,"prBs40")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs40_r12;
+		} else if (strcmp(rxPool_ResourceConfig_subframeBitmap_present,"prBs42")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs42_r12;
+		} else
+		   AssertFatal (0,
+		         "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for rxPool_ResourceConfig_subframeBitmap_present choice: prNothing,prBs4,prBs8,prBs12,prBs16,prBs30,prBs40,prBs42!\n",
+		         RC.config_file_name, i, rxPool_ResourceConfig_subframeBitmap_present);
+
+		RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_choice_bs_buf[j] = rxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
+		RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_choice_bs_size[j] = rxPool_ResourceConfig_subframeBitmap_choice_bs_size;
+		RRC_CONFIGURATION_REQ (msg_p).rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[j] = rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
+
+		//SIB19 - for discRxPool
+		if (strcmp(discRxPool_cp_Len,"normal")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_cp_Len[j] = SL_CP_Len_r12_normal;
+		} else if (strcmp(discRxPool_cp_Len,"extended")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_cp_Len[j] = SL_CP_Len_r12_extended;
+		} else
+		   AssertFatal (0,
+		         "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for discRxPool_cp_Len choice: normal,extended!\n",
+		         RC.config_file_name, i, discRxPool_cp_Len);
+
+
+		if (strcmp(discRxPool_discPeriod,"rf32")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf32;
+		} else if (strcmp(discRxPool_discPeriod,"rf64")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf64;
+		} else if (strcmp(discRxPool_discPeriod,"rf128")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf128;
+		} else if (strcmp(discRxPool_discPeriod,"rf256")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf256;
+		} else if (strcmp(discRxPool_discPeriod,"rf512")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf512;
+		} else if (strcmp(discRxPool_discPeriod,"rf1024")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf1024;
+		} else if (strcmp(discRxPool_discPeriod,"rf16")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf16_v1310;
+		} else if (strcmp(discRxPool_discPeriod,"spare")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_spare;
+		} else
+		   AssertFatal (0,
+		         "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for discRxPool_discPeriod choice: rf32,rf64,rf128,rf512,rf1024,rf16,spare!\n",
+		         RC.config_file_name, i, discRxPool_discPeriod);
+
+
+
+		RRC_CONFIGURATION_REQ (msg_p).discRxPool_numRetx[j] = discRxPool_numRetx;
+		RRC_CONFIGURATION_REQ (msg_p).discRxPool_numRepetition[j] = discRxPool_numRepetition;
+
+
+		RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_prb_Num[j] = discRxPool_ResourceConfig_prb_Num;
+		RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_prb_Start[j] = discRxPool_ResourceConfig_prb_Start;
+		RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_prb_End[j] = discRxPool_ResourceConfig_prb_End;
+
+		if (strcmp(discRxPool_ResourceConfig_offsetIndicator_present,"prNothing")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_offsetIndicator_present[j] = SL_OffsetIndicator_r12_PR_NOTHING;
+		} else if (strcmp(discRxPool_ResourceConfig_offsetIndicator_present,"prSmall")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_offsetIndicator_present[j] = SL_OffsetIndicator_r12_PR_small_r12;
+		} else if (strcmp(discRxPool_ResourceConfig_offsetIndicator_present,"prLarge")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_offsetIndicator_present[j] = SL_OffsetIndicator_r12_PR_large_r12;
+		} else
+		   AssertFatal (0,
+		         "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for discRxPool_ResourceConfig_offsetIndicator_present choice: prNothing,prSmal,prLarge!\n",
+		         RC.config_file_name, i, discRxPool_ResourceConfig_offsetIndicator_present);
+
+		RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_offsetIndicator_choice[j] = discRxPool_ResourceConfig_offsetIndicator_choice;
+
+		if (strcmp(discRxPool_ResourceConfig_subframeBitmap_present,"prNothing")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_NOTHING;
+		} else if (strcmp(discRxPool_ResourceConfig_subframeBitmap_present,"prBs4")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs4_r12;
+		} else if (strcmp(discRxPool_ResourceConfig_subframeBitmap_present,"prBs8")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs8_r12;
+		} else if (strcmp(discRxPool_ResourceConfig_subframeBitmap_present,"prBs12")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs12_r12;
+		} else if (strcmp(discRxPool_ResourceConfig_subframeBitmap_present,"prBs16")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs16_r12;
+		} else if (strcmp(discRxPool_ResourceConfig_subframeBitmap_present,"prBs30")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs30_r12;
+		} else if (strcmp(discRxPool_ResourceConfig_subframeBitmap_present,"prBs40")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs40_r12;
+		} else if (strcmp(discRxPool_ResourceConfig_subframeBitmap_present,"prBs42")==0) {
+		   RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs42_r12;
+		} else
+		   AssertFatal (0,
+		         "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for discRxPool_ResourceConfig_subframeBitmap_present choice: prNothing,prBs4,prBs8,prBs12,prBs16,prBs30,prBs40,prBs42!\n",
+		         RC.config_file_name, i, discRxPool_ResourceConfig_subframeBitmap_present);
+
+		RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf[j] = discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
+		RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_choice_bs_size[j] = discRxPool_ResourceConfig_subframeBitmap_choice_bs_size;
+		RRC_CONFIGURATION_REQ (msg_p).discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[j] = discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
+
+		//SIB19 - For discRxPoolPS
+      if (strcmp(discRxPoolPS_cp_Len,"normal")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_cp_Len[j] = SL_CP_Len_r12_normal;
+      } else if (strcmp(discRxPoolPS_cp_Len,"extended")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_cp_Len[j] = SL_CP_Len_r12_extended;
+      } else
+         AssertFatal (0,
+               "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for discRxPoolPS_cp_Len choice: normal,extended!\n",
+               RC.config_file_name, i, discRxPoolPS_cp_Len);
+
+
+      if (strcmp(discRxPoolPS_discPeriod,"rf32")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf32;
+      } else if (strcmp(discRxPoolPS_discPeriod,"rf64")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf64;
+      } else if (strcmp(discRxPoolPS_discPeriod,"rf128")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf128;
+      } else if (strcmp(discRxPoolPS_discPeriod,"rf256")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf256;
+      } else if (strcmp(discRxPoolPS_discPeriod,"rf512")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf512;
+      } else if (strcmp(discRxPoolPS_discPeriod,"rf1024")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf1024;
+      } else if (strcmp(discRxPoolPS_discPeriod,"rf16")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_rf16_v1310;
+      } else if (strcmp(discRxPoolPS_discPeriod,"spare")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_discPeriod[j] = SL_DiscResourcePool_r12__discPeriod_r12_spare;
+      } else
+         AssertFatal (0,
+               "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for discRxPoolPS_discPeriod choice: rf32,rf64,rf128,rf512,rf1024,rf16,spare!\n",
+               RC.config_file_name, i, discRxPoolPS_discPeriod);
+
+
+
+      RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_numRetx[j] = discRxPoolPS_numRetx;
+      RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_numRepetition[j] = discRxPoolPS_numRepetition;
+
+
+      RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_prb_Num[j] = discRxPoolPS_ResourceConfig_prb_Num;
+      RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_prb_Start[j] = discRxPoolPS_ResourceConfig_prb_Start;
+      RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_prb_End[j] = discRxPoolPS_ResourceConfig_prb_End;
+
+      if (strcmp(discRxPoolPS_ResourceConfig_offsetIndicator_present,"prNothing")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_offsetIndicator_present[j] = SL_OffsetIndicator_r12_PR_NOTHING;
+      } else if (strcmp(discRxPoolPS_ResourceConfig_offsetIndicator_present,"prSmall")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_offsetIndicator_present[j] = SL_OffsetIndicator_r12_PR_small_r12;
+      } else if (strcmp(discRxPoolPS_ResourceConfig_offsetIndicator_present,"prLarge")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_offsetIndicator_present[j] = SL_OffsetIndicator_r12_PR_large_r12;
+      } else
+         AssertFatal (0,
+               "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for discRxPoolPS_ResourceConfig_offsetIndicator_present choice: prNothing,prSmal,prLarge!\n",
+               RC.config_file_name, i, discRxPoolPS_ResourceConfig_offsetIndicator_present);
+
+      RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_offsetIndicator_choice[j] = discRxPoolPS_ResourceConfig_offsetIndicator_choice;
+
+      if (strcmp(discRxPoolPS_ResourceConfig_subframeBitmap_present,"prNothing")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_NOTHING;
+      } else if (strcmp(discRxPoolPS_ResourceConfig_subframeBitmap_present,"prBs4")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs4_r12;
+      } else if (strcmp(discRxPoolPS_ResourceConfig_subframeBitmap_present,"prBs8")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs8_r12;
+      } else if (strcmp(discRxPoolPS_ResourceConfig_subframeBitmap_present,"prBs12")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs12_r12;
+      } else if (strcmp(discRxPoolPS_ResourceConfig_subframeBitmap_present,"prBs16")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs16_r12;
+      } else if (strcmp(discRxPoolPS_ResourceConfig_subframeBitmap_present,"prBs30")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs30_r12;
+      } else if (strcmp(discRxPoolPS_ResourceConfig_subframeBitmap_present,"prBs40")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs40_r12;
+      } else if (strcmp(discRxPoolPS_ResourceConfig_subframeBitmap_present,"prBs42")==0) {
+         RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_present[j] = SubframeBitmapSL_r12_PR_bs42_r12;
+      } else
+         AssertFatal (0,
+               "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for discRxPoolPS_ResourceConfig_subframeBitmap_present choice: prNothing,prBs4,prBs8,prBs12,prBs16,prBs30,prBs40,prBs42!\n",
+               RC.config_file_name, i, discRxPoolPS_ResourceConfig_subframeBitmap_present);
+
+      RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[j] = discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf;
+      RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[j] = discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size;
+      RRC_CONFIGURATION_REQ (msg_p).discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[j] = discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
+
+
 	      }
 	    }
 	    char srb1path[MAX_OPTNAME_SIZE*2 + 8];
diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h
index 42bef9c4e990c0746aeb027c950394d5faee0c0f..a7eb9f3cddfd414ae3073e035bd44d478b989924 100644
--- a/openair2/ENB_APP/enb_config.h
+++ b/openair2/ENB_APP/enb_config.h
@@ -97,6 +97,7 @@ extern void RCconfig_RU(void);
 extern void RCconfig_flexran(void);
 extern void RCconfig_L1(void);
 extern void RCconfig_macrlc(void);
+extern void UE_config_stub_pnf(void);
 extern int  RCconfig_gtpu(void );
 extern void RCConfig(void);
 
diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h
index fe2b5a8515c164681841375b1b00576255fcc59e..51014d45b026c86b8a4022cec7a3f4a4a092d5f1 100755
--- a/openair2/ENB_APP/enb_paramdef.h
+++ b/openair2/ENB_APP/enb_paramdef.h
@@ -35,11 +35,6 @@
 
 
 
-
-
-
-
-
 #define ENB_CONFIG_STRING_CC_NODE_FUNCTION                              "node_function"
 #define ENB_CONFIG_STRING_CC_NODE_TIMING                                "node_timing"   
 #define ENB_CONFIG_STRING_CC_NODE_SYNCH_REF                             "node_synch_ref"   
@@ -310,6 +305,54 @@ typedef enum {
 #define ENB_CONFIG_STRING_UETIMERS_N311                                 "ue_TimersAndConstants_n311"
 #define ENB_CONFIG_STRING_UE_TRANSMISSION_MODE                          "ue_TransmissionMode"
 
+//TTN - for D2D
+//SIB18
+#define ENB_CONFIG_STRING_RXPOOL_SC_CP_LEN                              "rxPool_sc_CP_Len"
+#define ENB_CONFIG_STRING_RXPOOL_SC_PRIOD                               "rxPool_sc_Period"
+#define ENB_CONFIG_STRING_RXPOOL_DATA_CP_LEN                            "rxPool_data_CP_Len"
+#define ENB_CONFIG_STRING_RXPOOL_RC_PRB_NUM                             "rxPool_ResourceConfig_prb_Num"
+#define ENB_CONFIG_STRING_RXPOOL_RC_PRB_START                           "rxPool_ResourceConfig_prb_Start"
+#define ENB_CONFIG_STRING_RXPOOL_RC_PRB_END                             "rxPool_ResourceConfig_prb_End"
+#define ENB_CONFIG_STRING_RXPOOL_RC_OFFSETIND_PRESENT                   "rxPool_ResourceConfig_offsetIndicator_present"
+#define ENB_CONFIG_STRING_RXPOOL_RC_OFFSETIND_CHOICE                    "rxPool_ResourceConfig_offsetIndicator_choice"
+#define ENB_CONFIG_STRING_RXPOOL_RC_SFBITMAP_PRESENT                    "rxPool_ResourceConfig_subframeBitmap_present"
+#define ENB_CONFIG_STRING_RXPOOL_RC_SFBITMAP_CHOICE_BS_BUF              "rxPool_ResourceConfig_subframeBitmap_choice_bs_buf"
+#define ENB_CONFIG_STRING_RXPOOL_RC_SFBITMAP_CHOICE_BS_SIZE             "rxPool_ResourceConfig_subframeBitmap_choice_bs_size"
+#define ENB_CONFIG_STRING_RXPOOL_RC_SFBITMAP_CHOICE_BS_ASN_BITS_UNUSED  "rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused"
+//SIB19 for DiscRxPool
+#define ENB_CONFIG_STRING_DISCRXPOOL_CP_LEN                                 "discRxPool_cp_Len"
+#define ENB_CONFIG_STRING_DISCRXPOOL_DISCPERIOD                             "discRxPool_discPeriod"
+#define ENB_CONFIG_STRING_DISCRXPOOL_NUMRETX                                "discRxPool_numRetx"
+#define ENB_CONFIG_STRING_DISCRXPOOL_NUMREPETITION                          "discRxPool_numRepetition"
+#define ENB_CONFIG_STRING_DISCRXPOOL_RC_PRB_NUM                             "discRxPool_ResourceConfig_prb_Num"
+#define ENB_CONFIG_STRING_DISCRXPOOL_RC_PRB_START                           "discRxPool_ResourceConfig_prb_Start"
+#define ENB_CONFIG_STRING_DISCRXPOOL_RC_PRB_END                             "discRxPool_ResourceConfig_prb_End"
+#define ENB_CONFIG_STRING_DISCRXPOOL_RC_OFFSETIND_PRESENT                   "discRxPool_ResourceConfig_offsetIndicator_present"
+#define ENB_CONFIG_STRING_DISCRXPOOL_RC_OFFSETIND_CHOICE                    "discRxPool_ResourceConfig_offsetIndicator_choice"
+#define ENB_CONFIG_STRING_DISCRXPOOL_RC_SFBITMAP_PRESENT                    "discRxPool_ResourceConfig_subframeBitmap_present"
+#define ENB_CONFIG_STRING_DISCRXPOOL_RC_SFBITMAP_CHOICE_BS_BUF              "discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf"
+#define ENB_CONFIG_STRING_DISCRXPOOL_RC_SFBITMAP_CHOICE_BS_SIZE             "discRxPool_ResourceConfig_subframeBitmap_choice_bs_size"
+#define ENB_CONFIG_STRING_DISCRXPOOL_RC_SFBITMAP_CHOICE_BS_ASN_BITS_UNUSED  "discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused"
+
+//SIB19 for DiscRxPoolPS
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_CP_LEN                                 "DISCRXPOOLPS_cp_Len"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_DISCPERIOD                             "DISCRXPOOLPS_discPeriod"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_NUMRETX                                "DISCRXPOOLPS_numRetx"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_NUMREPETITION                          "DISCRXPOOLPS_numRepetition"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_RC_PRB_NUM                             "DISCRXPOOLPS_ResourceConfig_prb_Num"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_RC_PRB_START                           "DISCRXPOOLPS_ResourceConfig_prb_Start"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_RC_PRB_END                             "DISCRXPOOLPS_ResourceConfig_prb_End"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_RC_OFFSETIND_PRESENT                   "DISCRXPOOLPS_ResourceConfig_offsetIndicator_present"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_RC_OFFSETIND_CHOICE                    "DISCRXPOOLPS_ResourceConfig_offsetIndicator_choice"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_RC_SFBITMAP_PRESENT                    "DISCRXPOOLPS_ResourceConfig_subframeBitmap_present"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_RC_SFBITMAP_CHOICE_BS_BUF              "DISCRXPOOLPS_ResourceConfig_subframeBitmap_choice_bs_buf"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_RC_SFBITMAP_CHOICE_BS_SIZE             "DISCRXPOOLPS_ResourceConfig_subframeBitmap_choice_bs_size"
+#define ENB_CONFIG_STRING_DISCRXPOOLPS_RC_SFBITMAP_CHOICE_BS_ASN_BITS_UNUSED  "DISCRXPOOLPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused"
+
+/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*                                     component carriers configuration parameters                                                                                                     */
+/*   optname                                                   helpstr   paramflags    XXXptr                                        defXXXval                    type         numelt  */
+/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
 /* init for checkedparam_t structure */
 
 #define CCPARAMS_CHECK                 {                                     \
@@ -381,11 +424,51 @@ typedef enum {
              { .s1a= { config_check_modify_integer, UETIMER_N310_OKVALUES, UETIMER_N310_MODVALUES,8}} , 					      \
              { .s1a= { config_check_modify_integer, UETIMER_N311_OKVALUES, UETIMER_N311_MODVALUES,8}} , 					      \
              { .s5= {NULL }} ,						     \
+             { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
+                          { .s5= {NULL }} ,						     \
 }
 /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
 /*                                     component carriers configuration parameters                                                                                                                   */
 /*   optname                                                   helpstr   paramflags    XXXptr                                        defXXXval                    type         numelt  checked_param */
 /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+
 #define CCPARAMS_DESC { \
 {ENB_CONFIG_STRING_FRAME_TYPE,                                   NULL,   0,           strptr:&frame_type,                             defstrval:"FDD",           TYPE_STRING,     0},  \
 {ENB_CONFIG_STRING_TDD_CONFIG,                                   NULL,   0,           iptr:&tdd_config,                               defintval:3,               TYPE_UINT,       0},  \
@@ -454,7 +537,45 @@ typedef enum {
 {ENB_CONFIG_STRING_UETIMERS_T311,                                NULL,   0,           iptr:&ue_TimersAndConstants_t311,               defintval:10000,           TYPE_UINT,       0},  \
 {ENB_CONFIG_STRING_UETIMERS_N310,                                NULL,   0,           iptr:&ue_TimersAndConstants_n310,               defintval:20,              TYPE_UINT,       0},  \
 {ENB_CONFIG_STRING_UETIMERS_N311,                                NULL,   0,           iptr:&ue_TimersAndConstants_n311,               defintval:1,               TYPE_UINT,       0},  \
-{ENB_CONFIG_STRING_UE_TRANSMISSION_MODE,                         NULL,   0,           iptr:&ue_TransmissionMode,                      defintval:1,               TYPE_UINT,       0}   \
+{ENB_CONFIG_STRING_UE_TRANSMISSION_MODE,                         NULL,   0,           iptr:&ue_TransmissionMode,                      defintval:1,               TYPE_UINT,       0},  \
+{ENB_CONFIG_STRING_RXPOOL_SC_CP_LEN,                             NULL,   0,   strptr:(char **)&rxPool_sc_CP_Len,          defstrval:"normal",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_RXPOOL_SC_PRIOD,                              NULL,   0,   strptr:(char **)&rxPool_sc_Period,          defstrval:"sf40",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_RXPOOL_DATA_CP_LEN,                           NULL,   0,   strptr:(char **)&rxPool_data_CP_Len,          defstrval:"normal",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_RXPOOL_RC_PRB_NUM,                            NULL,   0,   iptr:(int32_t *)&rxPool_ResourceConfig_prb_Num,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_RXPOOL_RC_PRB_START,                          NULL,   0,   iptr:(int32_t *)&rxPool_ResourceConfig_prb_Start,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_RXPOOL_RC_PRB_END,                            NULL,   0,   iptr:(int32_t *)&rxPool_ResourceConfig_prb_End,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_RXPOOL_RC_OFFSETIND_PRESENT,                  NULL,   0,   strptr:(char **)&rxPool_ResourceConfig_offsetIndicator_present,            defstrval:"prNothing",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_RXPOOL_RC_OFFSETIND_CHOICE,                   NULL,   0,   iptr:(int32_t *)&rxPool_ResourceConfig_offsetIndicator_choice,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_RXPOOL_RC_SFBITMAP_PRESENT,                   NULL,   0,   strptr:(char **)&rxPool_ResourceConfig_subframeBitmap_present,            defstrval:"prNothing",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_RXPOOL_RC_SFBITMAP_CHOICE_BS_BUF,             NULL,   0,   strptr:(char **)&rxPool_ResourceConfig_subframeBitmap_choice_bs_buf,            defstrval:"001001",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_RXPOOL_RC_SFBITMAP_CHOICE_BS_SIZE,            NULL,   0,   iptr:(int32_t *)&rxPool_ResourceConfig_subframeBitmap_choice_bs_size,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_RXPOOL_RC_SFBITMAP_CHOICE_BS_ASN_BITS_UNUSED, NULL,   0,   iptr:(int32_t *)&rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_CP_LEN,                            NULL,   0,   strptr:(char **)&discRxPool_cp_Len,          defstrval:"normal",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_DISCPERIOD,                        NULL,   0,   strptr:(char **)&discRxPool_discPeriod,          defstrval:"rf32",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_NUMRETX,                           NULL,   0,   iptr:(int32_t *)&discRxPool_numRetx,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_NUMREPETITION,                     NULL,   0,   iptr:(int32_t *)&discRxPool_numRepetition,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_RC_PRB_NUM,                        NULL,   0,   iptr:(int32_t *)&discRxPool_ResourceConfig_prb_Num,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_RC_PRB_START,                      NULL,   0,   iptr:(int32_t *)&discRxPool_ResourceConfig_prb_Start,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_RC_PRB_END,                        NULL,   0,   iptr:(int32_t *)&discRxPool_ResourceConfig_prb_End,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_RC_OFFSETIND_PRESENT,              NULL,   0,   strptr:(char **)&discRxPool_ResourceConfig_offsetIndicator_present,            defstrval:"prNothing",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_RC_OFFSETIND_CHOICE,               NULL,   0,   iptr:(int32_t *)&discRxPool_ResourceConfig_offsetIndicator_choice,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_RC_SFBITMAP_PRESENT,               NULL,   0,   strptr:(char **)&discRxPool_ResourceConfig_subframeBitmap_present,            defstrval:"prNothing",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_RC_SFBITMAP_CHOICE_BS_BUF,         NULL,   0,   strptr:(char **)&discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf,            defstrval:"001001",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_RC_SFBITMAP_CHOICE_BS_SIZE,        NULL,   0,   iptr:(int32_t *)&discRxPool_ResourceConfig_subframeBitmap_choice_bs_size,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOL_RC_SFBITMAP_CHOICE_BS_ASN_BITS_UNUSED,NULL,   0,   iptr:(int32_t *)&discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_CP_LEN,                            NULL,   0,   strptr:(char **)&discRxPoolPS_cp_Len,          defstrval:"normal",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_DISCPERIOD,                        NULL,   0,   strptr:(char **)&discRxPoolPS_discPeriod,          defstrval:"rf32",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_NUMRETX,                           NULL,   0,   iptr:(int32_t *)&discRxPoolPS_numRetx,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_NUMREPETITION,                     NULL,   0,   iptr:(int32_t *)&discRxPoolPS_numRepetition,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_RC_PRB_NUM,                        NULL,   0,   iptr:(int32_t *)&discRxPoolPS_ResourceConfig_prb_Num,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_RC_PRB_START,                      NULL,   0,   iptr:(int32_t *)&discRxPoolPS_ResourceConfig_prb_Start,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_RC_PRB_END,                        NULL,   0,   iptr:(int32_t *)&discRxPoolPS_ResourceConfig_prb_End,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_RC_OFFSETIND_PRESENT,              NULL,   0,   strptr:(char **)&discRxPoolPS_ResourceConfig_offsetIndicator_present,            defstrval:"prNothing",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_RC_OFFSETIND_CHOICE,               NULL,   0,   iptr:(int32_t *)&discRxPoolPS_ResourceConfig_offsetIndicator_choice,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_RC_SFBITMAP_PRESENT,               NULL,   0,   strptr:(char **)&discRxPoolPS_ResourceConfig_subframeBitmap_present,            defstrval:"prNothing",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_RC_SFBITMAP_CHOICE_BS_BUF,         NULL,   0,   strptr:(char **)&discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf,            defstrval:"001001",  TYPE_STRING,  0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_RC_SFBITMAP_CHOICE_BS_SIZE,        NULL,   0,   iptr:(int32_t *)&discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size,         defintval:1,       TYPE_UINT,    0}, \
+{ENB_CONFIG_STRING_DISCRXPOOLPS_RC_SFBITMAP_CHOICE_BS_ASN_BITS_UNUSED,NULL,   0,   iptr:(int32_t *)&discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused,         defintval:1,       TYPE_UINT,    0} \
 }
 
 #define ENB_CONFIG_FRAME_TYPE_IDX                            0  			     
diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c
index 3200f55f16fa1100e75140b87c98b6f257786701..9766d315a7fec8237738a47e93f20c1b20eb9560 100644
--- a/openair2/ENB_APP/flexran_agent_ran_api.c
+++ b/openair2/ENB_APP/flexran_agent_ran_api.c
@@ -140,7 +140,11 @@ rlc_buffer_occupancy_t flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logi
   rnti_t rnti = flexran_get_ue_crnti(mod_id, ue_id);
   frame_t frame = flexran_get_current_frame(mod_id);
   sub_frame_t subframe = flexran_get_current_subframe(mod_id);
-  mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0);
+  mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0
+#ifdef Rel14
+                                                    ,0, 0
+#endif
+                                                    );
   return rlc_status.bytes_in_buffer;
 }
 
@@ -149,7 +153,11 @@ rlc_buffer_occupancy_t flexran_get_num_pdus_buffer(mid_t mod_id, mid_t ue_id, lo
   rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
   frame_t frame = flexran_get_current_frame(mod_id);
   sub_frame_t subframe = flexran_get_current_subframe(mod_id);
-  mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0);
+  mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0
+#ifdef Rel14
+                                                    ,0, 0
+#endif
+                                                    );
   return rlc_status.pdus_in_buffer;
 }
 
@@ -158,7 +166,11 @@ frame_t flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t chann
   rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
   frame_t frame = flexran_get_current_frame(mod_id);
   sub_frame_t subframe = flexran_get_current_subframe(mod_id);
-  mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0);
+  mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0
+#ifdef Rel14
+                                                    ,0, 0
+#endif
+                                                    );
   return rlc_status.head_sdu_creation_time;
 }
 
diff --git a/openair2/LAYER2/MAC/config_ue.c b/openair2/LAYER2/MAC/config_ue.c
index 5ef18f5bdad0c2b4917d943824c9cae3f1c90430..d91792c567a2df8395879850c1f8f6dcb018aaae 100644
--- a/openair2/LAYER2/MAC/config_ue.c
+++ b/openair2/LAYER2/MAC/config_ue.c
@@ -60,6 +60,8 @@
 extern void mac_init_cell_params(int Mod_idP,int CC_idP);
 extern void phy_reset_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
 
+extern uint8_t  nfapi_mode;
+
 
 /* sec 5.9, 36.321: MAC Reset Procedure */
 void ue_mac_reset(module_id_t module_idP, uint8_t eNB_index)
@@ -134,6 +136,11 @@ rrc_mac_config_req_ue(module_id_t Mod_idP,
 #endif
 #ifdef CBA
 		      , uint8_t num_active_cba_groups, uint16_t cba_rnti
+#endif
+#if defined(Rel14)
+  ,config_action_t  config_action
+  ,const uint32_t * const sourceL2Id
+  ,const uint32_t * const destinationL2Id
 #endif
 		      )
 {
@@ -228,9 +235,10 @@ rrc_mac_config_req_ue(module_id_t Mod_idP,
 	  (uint16_t)
 	  MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
       }
-      phy_config_harq_ue(Mod_idP, 0, eNB_index,
-			 UE_mac_inst[Mod_idP].
-			 scheduling_info.maxHARQ_Tx);
+      if(nfapi_mode!=3)
+        phy_config_harq_ue(Mod_idP, 0, eNB_index,
+			   UE_mac_inst[Mod_idP].
+			   scheduling_info.maxHARQ_Tx);
 
       if (mac_MainConfig->ul_SCH_Config->retxBSR_Timer) {
 	UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer =
@@ -348,8 +356,9 @@ rrc_mac_config_req_ue(module_id_t Mod_idP,
 
 
   if (physicalConfigDedicated != NULL) {
-    phy_config_dedicated_ue(Mod_idP, 0, eNB_index,
-			    physicalConfigDedicated);
+    if(nfapi_mode!=3)
+      phy_config_dedicated_ue(Mod_idP, 0, eNB_index,
+			      physicalConfigDedicated);
     UE_mac_inst[Mod_idP].physicalConfigDedicated = physicalConfigDedicated;	// for SR proc
   }
 #if defined(Rel10) || defined(Rel14)
@@ -579,6 +588,34 @@ rrc_mac_config_req_ue(module_id_t Mod_idP,
 #endif
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
     (VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_OUT);
+  //for D2D
+  #if defined(Rel10) || defined(Rel14)
+    switch (config_action) {
+    case CONFIG_ACTION_ADD:
+       if (sourceL2Id){
+          UE_mac_inst[Mod_idP].sourceL2Id = *sourceL2Id;
+          LOG_I(MAC,"[UE %d] Configure source L2Id 0x%08x \n", Mod_idP, *sourceL2Id );
+       }
+       if (destinationL2Id) {
+          LOG_I(MAC,"[UE %d] Configure destination L2Id 0x%08x\n", Mod_idP, *destinationL2Id );
+          int j = 0;
+          int i = 0;
+          for (i=0; i< MAX_NUM_DEST; i++) {
+             if ((UE_mac_inst[Mod_idP].destinationList[i] == 0) && (j == 0)) j = i+1;
+             if (UE_mac_inst[Mod_idP].destinationList[i] == *destinationL2Id) break; //destination already exists!
+          }
+          if ((i == MAX_NUM_DEST) && (j > 0))  UE_mac_inst[Mod_idP].destinationList[j-1] = *destinationL2Id;
+          UE_mac_inst[Mod_idP].numCommFlows++;
+       }
+       break;
+    case CONFIG_ACTION_REMOVE:
+       //TODO
+       break;
+    default:
+       break;
+    }
+
+  #endif
 
   return (0);
 }
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index 107483b35a071e65a5a8118127b08b483ff78cf2..99f75175190a803d26e0f6a6c613a79e97cb7a32 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -63,8 +63,9 @@
 #endif
 #ifdef Rel14
 #include "SystemInformationBlockType1-v1310-IEs.h"
+#include "SystemInformationBlockType18-r12.h"
 #endif
-
+#include "RadioResourceConfigCommonSIB.h"
 #include "nfapi_interface.h"
 #include "PHY_INTERFACE/IF_Module.h"
 
@@ -79,6 +80,7 @@
 #define RAR_PAYLOAD_SIZE_MAX 128
 
 #define SCH_PAYLOAD_SIZE_MAX 4096
+#define DCH_PAYLOAD_SIZE_MAX 4096
 /// Logical channel ids from 36-311 (Note BCCH is not specified in 36-311, uses the same as first DRB)
 
 #if defined(Rel10) || defined(Rel14)
@@ -155,6 +157,7 @@
 /*!\brief maximum number of slices / groups */
 #define MAX_NUM_SLICES 4
 
+
 #define U_PLANE_INACTIVITY_VALUE 6000
 
 /*
@@ -233,6 +236,75 @@ typedef struct {
     uint8_t R:2;
 } __attribute__ ((__packed__)) SCH_SUBHEADER_FIXED;
 
+
+
+/*!\brief  MAC subheader long  with 24bit DST field */
+typedef struct {
+  uint8_t   R0:4;
+  uint8_t   V:4;//Version number: Possible values "0001", "0010", "0011" based on TS36.321 section 6.2.3.
+  uint8_t  SRC07; //Prose UE source ID. Size 24 bits.
+  uint8_t  SRC815; //Prose UE source ID. Size 24 bits.
+  uint8_t  SRC1623; //Prose UE source ID. Size 24 bits.
+  uint8_t  DST07; //Prose UE destination ID. Size 24 bits.
+  uint8_t  DST815; //Prose UE destination ID. Size 24 bits.
+  uint8_t  DST1623; //Prose UE destination ID. Size 24 bits.
+  uint8_t  LCID:5;
+  uint8_t  E:1;
+  uint8_t  R1:2;
+  uint8_t  L:7;	// Length field indicating the size of the corresponding SDU in bytes.
+  uint8_t  F:1;
+}__attribute__((__packed__))SLSCH_SUBHEADER_24_Bit_DST_SHORT;
+
+/*!\brief  MAC subheader long  with 24bit DST field */
+typedef struct {
+  uint8_t   R0:4;
+  uint8_t   V:4;//Version number: Possible values "0001", "0010", "0011" based on TS36.321 section 6.2.3.
+  uint8_t  SRC07; //Prose UE source ID. Size 24 bits.
+  uint8_t  SRC815; //Prose UE source ID. Size 24 bits.
+  uint8_t  SRC1623; //Prose UE source ID. Size 24 bits.
+  uint8_t  DST07; //Prose UE destination ID. Size 24 bits.
+  uint8_t  DST815; //Prose UE destination ID. Size 24 bits.
+  uint8_t  DST1623; //Prose UE destination ID. Size 24 bits.
+  uint8_t  LCID:5;
+  uint8_t  E:1;
+  uint8_t  R1:2;
+  uint8_t  L_MSB:7;	// Length field indicating the size of the corresponding SDU in bytes.
+  uint8_t  F:1;
+  uint8_t  L_LSB:8;
+}__attribute__((__packed__))SLSCH_SUBHEADER_24_Bit_DST_LONG;
+
+/*!\brief  MAC subheader long  with 24bit DST field */
+typedef struct {
+  uint8_t   R0:4;
+  uint8_t   V:4;//Version number: Possible values "0001", "0010", "0011" based on TS36.321 section 6.2.3.
+  uint8_t  SRC07; //Prose UE source ID. Size 24 bits.
+  uint8_t  SRC815; //Prose UE source ID. Size 24 bits.
+  uint8_t  DST07; //Prose UE destination ID. Size 16 bits.
+  uint8_t  DST815; //Prose UE destination ID. Size 16 bits.
+  uint8_t  LCID:5;
+  uint8_t  E:1;
+  uint8_t  R1:2;
+  uint8_t  L:7;	// Length field indicating the size of the corresponding SDU in bytes.
+  uint8_t  F:1;
+}__attribute__((__packed__))SLSCH_SUBHEADER_16_Bit_DST_SHORT;
+
+/*!\brief  MAC subheader long  with 24bit DST field */
+typedef struct {
+  uint8_t   R0:4;
+  uint8_t   V:4;//Version number: Possible values "0001", "0010", "0011" based on TS36.321 section 6.2.3.
+  uint8_t  SRC07; //Prose UE source ID. Size 24 bits.
+  uint8_t  SRC815; //Prose UE source ID. Size 24 bits.
+  uint8_t  SRC1623; //Prose UE source ID. Size 24 bits.
+  uint8_t  DST07; //Prose UE destination ID. Size 16 bits.
+  uint8_t  DST815; //Prose UE destination ID. Size 16 bits.
+  uint8_t  LCID:5;
+  uint8_t  E:1;
+  uint8_t  R1:2;
+  uint8_t  L_MSB:7;	// Length field indicating the size of the corresponding SDU in bytes.
+  uint8_t  F:1;
+  uint8_t  L_LSB:8;
+}__attribute__((__packed__))SLSCH_SUBHEADER_16_Bit_DST_LONG;
+
 /*!\brief  mac control element: short buffer status report for a specific logical channel group ID*/
 typedef struct {
     uint8_t Buffer_size:6;	// octet 1 LSB
@@ -248,6 +320,30 @@ typedef struct {
     uint8_t Buffer_size0:6;
 } __attribute__ ((__packed__)) BSR_LONG;
 
+// Panos:
+/*!\brief  mac control element: sidelink buffer status report */
+typedef struct {
+	uint8_t DST_1:4;
+	uint8_t LCGID_1: 2;
+	uint8_t Buffer_size_1:6;
+	uint8_t DST_2:4;
+	uint8_t LCGID_2: 2;
+	uint8_t Buffer_size_2:6;
+}__attribute__((__packed__))SL_BSR;
+
+/*!\brief  mac control element: truncated sidelink buffer status report */
+typedef struct {
+	uint8_t DST:4;
+	uint8_t LCGID: 2;
+	uint8_t Buffer_size:6;
+	uint8_t R1:1;
+	uint8_t R2:1;
+	uint8_t R3:1;
+	uint8_t R4:1;
+}__attribute__((__packed__))SL_BSR_Truncated;
+
+
+
 #define BSR_LONG_SIZE  (sizeof(BSR_LONG))
 /*!\brief  mac control element: timing advance  */
 typedef struct {
@@ -346,6 +442,9 @@ typedef struct {
 #define MCH_SCHDL_INFO 3
 /*!\brief LCID of Carrier component activation/deactivation */
 #define CC_ACT_DEACT 27
+//TTN (for D2D)
+#define SL_DISCOVERY 8 //LCID (fake)
+#define MAX_NUM_DEST 10
 #endif
 
 // ULSCH LCHAN IDs
@@ -392,6 +491,13 @@ typedef struct {
     uint16_t Pdu_size;
 } __attribute__ ((__packed__)) ULSCH_PDU;
 
+
+/*! \brief Uplink SCH PDU Structure */
+typedef struct {
+  int8_t payload[DCH_PAYLOAD_SIZE_MAX];         /*!< \brief SACH payload */
+  uint16_t Pdu_size;
+} __attribute__ ((__packed__)) ULDCH_PDU;
+
 #include "PHY/impl_defs_top.h"
 
 /*!\brief RA process state*/
@@ -522,7 +628,6 @@ typedef struct {
 } eNB_STATS;
 /*! \brief eNB statistics for the connected UEs*/
 typedef struct {
-
     /// CRNTI of UE
     rnti_t crnti;		///user id (rnti) of connected UEs
     // rrc status
@@ -938,7 +1043,7 @@ typedef struct {
 
 /*! \brief subband bitmap confguration (for ALU icic algo purpose), in test phase */
 typedef struct {
-    uint8_t sbmap[NUMBER_OF_SUBBANDS_MAX];	//13 = number of SB MAX for 100 PRB
+    uint8_t sbmap[13];	//13 = number of SB MAX for 100 PRB
     uint8_t periodicity;
     uint8_t first_subframe;
     uint8_t sb_size;
@@ -1242,82 +1347,116 @@ typedef struct {
     /// pointer to RRC PHY configuration
     struct PhysicalConfigDedicated *physicalConfigDedicated;
 #if defined(Rel10) || defined(Rel14)
-    /// pointer to RRC PHY configuration SCEll
-    struct PhysicalConfigDedicatedSCell_r10
-	*physicalConfigDedicatedSCell_r10;
+  /// pointer to RRC PHY configuration SCEll
+  struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10;
+  /// Preconfiguration for Sidelink
+  struct SL_Preconfiguration_r12 *SL_Preconfiguration;
+  /// RX Pool for Sidelink from SIB18
+  SL_CommRxPoolList_r12_t	 commRxPool_r12;
+  /// TX Pool Normal for Sidelink from SIB18
+  struct SL_CommTxPoolList_r12	*commTxPoolNormalCommon_r12;
+  /// TX Pool Exceptional for Sidelink from SIB18
+  struct SL_CommTxPoolList_r12	*commTxPoolExceptional_r12;
+  /// Common Sync Config for Sidelink from SIB18
+  struct SL_SyncConfigList_r12	*commSyncConfig_r12;
+  /// Dedicated Sync TX control for Sidelink
+  struct SL_SyncTxControl_r12 *sl_SyncTxControl_r12;
+  /// Dedicated Discovery TX control for Sidelink
+  struct SL_DiscConfig_r12	*sl_DiscConfig_r12;
+  /// Dedicated TX config for Sidelink
+  struct SL_CommConfig_r12	*sl_CommConfig_r12;
+  //SL sourceL2ID
+  uint32_t sourceL2Id;
+  //SL groupL2Id
+  uint32_t groupL2Id;
+  //SL destinationL2Id
+  uint32_t destinationL2Id;
+  //List of destinations
+  uint32_t destinationList[MAX_NUM_DEST];
+  uint8_t numCommFlows;
+  uint32_t  SL_LCID[MAX_NUM_LCID];
+
 #endif
-    /// pointer to TDD Configuration (NULL for FDD)
-    TDD_Config_t *tdd_Config;
-    /// Number of adjacent cells to measure
-    uint8_t n_adj_cells;
-    /// Array of adjacent physical cell ids
-    uint32_t adj_cell_id[6];
-    /// Pointer to RRC MAC configuration
-    MAC_MainConfig_t *macConfig;
-    /// Pointer to RRC Measurement gap configuration
-    MeasGapConfig_t *measGapConfig;
-    /// Pointers to LogicalChannelConfig indexed by LogicalChannelIdentity. Note NULL means LCHAN is inactive.
-    LogicalChannelConfig_t *logicalChannelConfig[MAX_NUM_LCID];
-    /// Scheduling Information
-    UE_SCHEDULING_INFO scheduling_info;
-    /// Outgoing CCCH pdu for PHY
-    CCCH_PDU CCCH_pdu;
-    /// Outgoing RAR pdu for PHY
-    RAR_PDU RAR_pdu;
-    /// Incoming DLSCH pdu for PHY
-    DLSCH_PDU DLSCH_pdu[NUMBER_OF_UE_MAX][2];
-    /// number of attempt for rach
-    uint8_t RA_attempt_number;
-    /// Random-access procedure flag
-    uint8_t RA_active;
-    /// Random-access window counter
-    int8_t RA_window_cnt;
-    /// Random-access Msg3 size in bytes
-    uint8_t RA_Msg3_size;
-    /// Random-access prachMaskIndex
-    uint8_t RA_prachMaskIndex;
-    /// Flag indicating Preamble set (A,B) used for first Msg3 transmission
-    uint8_t RA_usedGroupA;
-    /// Random-access Resources
-    PRACH_RESOURCES_t RA_prach_resources;
-    /// Random-access PREAMBLE_TRANSMISSION_COUNTER
-    uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER;
-    /// Random-access backoff counter
-    int16_t RA_backoff_cnt;
-    /// Random-access variable for window calculation (frame of last change in window counter)
-    uint32_t RA_tx_frame;
-    /// Random-access variable for window calculation (subframe of last change in window counter)
-    uint8_t RA_tx_subframe;
-    /// Random-access Group B maximum path-loss
-    /// Random-access variable for backoff (frame of last change in backoff counter)
-    uint32_t RA_backoff_frame;
-    /// Random-access variable for backoff (subframe of last change in backoff counter)
-    uint8_t RA_backoff_subframe;
-    /// Random-access Group B maximum path-loss
-    uint16_t RA_maxPL;
-    /// Random-access Contention Resolution Timer active flag
-    uint8_t RA_contention_resolution_timer_active;
-    /// Random-access Contention Resolution Timer count value
-    uint8_t RA_contention_resolution_cnt;
-    /// power headroom reporitng reconfigured
-    uint8_t PHR_reconfigured;
-    /// power headroom state as configured by the higher layers
-    uint8_t PHR_state;
-    /// power backoff due to power management (as allowed by P-MPRc) for this cell
-    uint8_t PHR_reporting_active;
-    /// power backoff due to power management (as allowed by P-MPRc) for this cell
-    uint8_t power_backoff_db[NUMBER_OF_eNB_MAX];
-    /// BSR report falg management
-    uint8_t BSR_reporting_active;
-    /// retxBSR-Timer expires flag
-    uint8_t retxBSRTimer_expires_flag;
-    /// periodBSR-Timer expires flag
-    uint8_t periodBSRTimer_expires_flag;
-
-    /// MBSFN_Subframe Configuration
-    struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8];	// FIXME replace 8 by MAX_MBSFN_AREA?
-    /// number of subframe allocation pattern available for MBSFN sync area
-    uint8_t num_sf_allocation_pattern;
+  /// pointer to TDD Configuration (NULL for FDD)
+  TDD_Config_t *tdd_Config;
+  /// Number of adjacent cells to measure
+  uint8_t  n_adj_cells;
+  /// Array of adjacent physical cell ids
+  uint32_t adj_cell_id[6];
+  /// Pointer to RRC MAC configuration
+  MAC_MainConfig_t *macConfig;
+  /// Pointer to RRC Measurement gap configuration
+  MeasGapConfig_t  *measGapConfig;
+  /// Pointers to LogicalChannelConfig indexed by LogicalChannelIdentity. Note NULL means LCHAN is inactive.
+  LogicalChannelConfig_t *logicalChannelConfig[MAX_NUM_LCID];
+
+  /// Scheduling Information
+  UE_SCHEDULING_INFO scheduling_info;
+  /// Outgoing CCCH pdu for PHY
+  CCCH_PDU CCCH_pdu;
+  /// Outgoing RAR pdu for PHY
+  RAR_PDU RAR_pdu;
+  /// Incoming DLSCH pdu for PHY
+  DLSCH_PDU DLSCH_pdu[NUMBER_OF_UE_MAX][2];
+#ifdef Rel14
+  int sltx_active;
+  SLSCH_t slsch;
+  SLDCH_t sldch;
+  ULSCH_PDU slsch_pdu;
+  int slsch_lcid;
+#endif
+  /// number of attempt for rach
+  uint8_t RA_attempt_number;
+  /// Random-access procedure flag
+  uint8_t RA_active;
+  /// Random-access window counter
+  int8_t RA_window_cnt;
+  /// Random-access Msg3 size in bytes
+  uint8_t RA_Msg3_size;
+  /// Random-access prachMaskIndex
+  uint8_t RA_prachMaskIndex;
+  /// Flag indicating Preamble set (A,B) used for first Msg3 transmission
+  uint8_t RA_usedGroupA;
+  /// Random-access Resources
+  PRACH_RESOURCES_t RA_prach_resources;
+  /// Random-access PREAMBLE_TRANSMISSION_COUNTER
+  uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER;
+  /// Random-access backoff counter
+  int16_t RA_backoff_cnt;
+  /// Random-access variable for window calculation (frame of last change in window counter)
+  uint32_t RA_tx_frame;
+  /// Random-access variable for window calculation (subframe of last change in window counter)
+  uint8_t RA_tx_subframe;
+  /// Random-access Group B maximum path-loss
+  /// Random-access variable for backoff (frame of last change in backoff counter)
+  uint32_t RA_backoff_frame;
+  /// Random-access variable for backoff (subframe of last change in backoff counter)
+  uint8_t RA_backoff_subframe;
+  /// Random-access Group B maximum path-loss
+  uint16_t RA_maxPL;
+  /// Random-access Contention Resolution Timer active flag
+  uint8_t RA_contention_resolution_timer_active;
+  /// Random-access Contention Resolution Timer count value
+  uint8_t RA_contention_resolution_cnt;
+  /// power headroom reporitng reconfigured
+  uint8_t PHR_reconfigured;
+  /// power headroom state as configured by the higher layers
+  uint8_t PHR_state;
+  /// power backoff due to power management (as allowed by P-MPRc) for this cell
+  uint8_t PHR_reporting_active;
+  /// power backoff due to power management (as allowed by P-MPRc) for this cell
+  uint8_t power_backoff_db[NUMBER_OF_eNB_MAX];
+  /// BSR report falg management
+  uint8_t BSR_reporting_active;
+  /// retxBSR-Timer expires flag
+  uint8_t retxBSRTimer_expires_flag;
+  /// periodBSR-Timer expires flag
+  uint8_t periodBSRTimer_expires_flag;
+
+  /// MBSFN_Subframe Configuration
+  struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA?
+  /// number of subframe allocation pattern available for MBSFN sync area
+  uint8_t num_sf_allocation_pattern;
 #if defined(Rel10) || defined(Rel14)
     /// number of active MBSFN area
     uint8_t num_active_mbsfn_area;
@@ -1330,26 +1469,41 @@ typedef struct {
     /// MSI status
     uint8_t msi_status;		// could be an array if there are >1 MCH in one MBSFN area
 #endif
-    //#ifdef CBA
-    /// CBA RNTI for each group
-    uint16_t cba_rnti[NUM_MAX_CBA_GROUP];
-    /// last SFN for CBA channel access
-    uint8_t cba_last_access[NUM_MAX_CBA_GROUP];
-    //#endif
-    /// total UE scheduler processing time
-    time_stats_t ue_scheduler;	// total
-    /// UE ULSCH tx  processing time inlcuding RLC interface (rlc_data_req) and mac header generation
-    time_stats_t tx_ulsch_sdu;
-    /// UE DLSCH rx  processing time inlcuding RLC interface (mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind) and mac header parser
-    time_stats_t rx_dlsch_sdu;
-    /// UE query for MCH subframe processing time
-    time_stats_t ue_query_mch;
-    /// UE MCH rx processing time
-    time_stats_t rx_mch_sdu;
-    /// UE BCCH rx processing time including RLC interface (mac_rrc_data_ind)
-    time_stats_t rx_si;
-    /// UE PCCH rx processing time including RLC interface (mac_rrc_data_ind)
-    time_stats_t rx_p;
+  //#ifdef CBA
+  /// CBA RNTI for each group
+  uint16_t cba_rnti[NUM_MAX_CBA_GROUP];
+  /// last SFN for CBA channel access
+  uint8_t cba_last_access[NUM_MAX_CBA_GROUP];
+  //#endif
+  /// total UE scheduler processing time
+  time_stats_t ue_scheduler; // total
+  /// UE ULSCH tx  processing time inlcuding RLC interface (rlc_data_req) and mac header generation
+  time_stats_t tx_ulsch_sdu;
+  /// UE DLSCH rx  processing time inlcuding RLC interface (mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind) and mac header parser
+  time_stats_t rx_dlsch_sdu ;
+  /// UE query for MCH subframe processing time
+  time_stats_t ue_query_mch;
+  /// UE MCH rx processing time
+  time_stats_t rx_mch_sdu;
+  /// UE BCCH rx processing time including RLC interface (mac_rrc_data_ind)
+  time_stats_t rx_si;
+  /// UE PCCH rx processing time including RLC interface (mac_rrc_data_ind)
+  time_stats_t rx_p;
+  /// Panos: Mutex for nfapi UL_INFO
+  pthread_mutex_t      UL_INFO_mutex;
+  /// Panos: UE_Mode variable should be used in the case of Phy_stub operation since we won't have access to PHY_VARS_UE
+  /// where the UE_mode originally is for the full stack operation mode. The transitions between the states of the UE_Mode
+  /// will be triggered within phy_stub_ue.c in this case
+  UE_MODE_t        UE_mode[NUMBER_OF_CONNECTED_eNB_MAX];
+  /// Panos: Phy_stub mode: Boolean variable to distinguish whether a Msg3 or a regular ULSCH data pdu should be generated
+  /// after the reception of NFAPI_UL_CONFIG_ULSCH_PDU_TYPE.
+  uint8_t first_ULSCH_Tx;
+  uint8_t SI_Decoded;
+  int ra_frame; 	// This variable keeps the frame in which the RA started for the specific UE. It is used in order
+                    // to make sure that different UEs RA starts within a number of frames difference.
+
+  eth_params_t         eth_params_n;
+
 } UE_MAC_INST;
 /*! \brief ID of the neighboring cells used for HO*/
 typedef struct {
@@ -1357,6 +1511,8 @@ typedef struct {
     uint8_t n_adj_cells;
 } neigh_cell_id_t;
 
+
+
 #include "proto.h"
 /*@}*/
 #endif /*__LAYER2_MAC_DEFS_H__ */
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index 874b63c6c8e21eabf4f9bd8c8510dd67fc23a65a..7dda39cce7fb4496b84337b19c3b252a6a57d85f 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -72,8 +72,6 @@ uint16_t pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 };
 void
 schedule_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 {
-
-
   eNB_MAC_INST *eNB = RC.mac[module_idP];
   UE_list_t *UE_list = &eNB->UE_list;
   nfapi_ul_config_request_body_t *ul_req;
@@ -92,150 +90,140 @@ schedule_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
   uint16_t srsPeriodicity, srsOffset;
   
   for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
-    soundingRS_UL_ConfigCommon = &cc[CC_id].radioResourceConfigCommon->soundingRS_UL_ConfigCommon;
-    // check if SRS is enabled in this frame/subframe
-    if (soundingRS_UL_ConfigCommon) {
-      srs_SubframeConfig = soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig;
-      if (cc[CC_id].tdd_Config == NULL) {	// FDD
-	deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
-	TSFC = deltaTSFCTabType1[srs_SubframeConfig][1];
-      } else {		// TDD
-	deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
-	TSFC = deltaTSFCTabType2[srs_SubframeConfig][1];
-      }
-      // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
-      uint16_t tmp = (subframeP % TSFC);
-      
-      if ((1 << tmp) & deltaTSFC) {
-	// This is an SRS subframe, loop over UEs
-	for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
-	  if (RC.mac[module_idP]->UE_list.active[UE_id] != TRUE)
-	    continue;
-	  ul_req = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body;
-	  // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
-	  if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) continue;
-	  
-	  AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL,
-		      "physicalConfigDedicated is null for UE %d\n",
-		      UE_id);
-	  
-	  if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) {
-	    if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
-	      get_srs_pos(&cc[CC_id],
-			  soundingRS_UL_ConfigDedicated->choice.
-			  setup.srs_ConfigIndex,
-			  &srsPeriodicity, &srsOffset);
-	      if (((10 * frameP + subframeP) % srsPeriodicity) == srsOffset) {
-		// Program SRS
-		ul_req->srs_present = 1;
-		nfapi_ul_config_request_pdu_t * ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
-		memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
-		ul_config_pdu->pdu_type =  NFAPI_UL_CONFIG_SRS_PDU_TYPE;
-		ul_config_pdu->pdu_size =  2 + (uint8_t) (2 + sizeof(nfapi_ul_config_srs_pdu));
-		ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG;
-		ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t)sizeof(nfapi_ul_config_srs_pdu);
-		ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti;
-		ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
-		ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
-		ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;;
-		ul_config_pdu->srs_pdu.srs_pdu_rel8.transmission_comb = soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
-		ul_config_pdu->srs_pdu.srs_pdu_rel8.i_srs = soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
-		ul_config_pdu->srs_pdu.srs_pdu_rel8.sounding_reference_cyclic_shift = soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;		//              ul_config_pdu->srs_pdu.srs_pdu_rel10.antenna_port                   = ;//
-		//              ul_config_pdu->srs_pdu.srs_pdu_rel13.number_of_combs                = ;//
-		RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
-		RC.mac[module_idP]->UL_req[CC_id].header.message_id = NFAPI_UL_CONFIG_REQUEST;
-		ul_req->number_of_pdus++;
-	      }	// if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset)
-	    }	// if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup)
-	  }		// if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL)
-	}		// for (UE_id ...
-      }			// if((1<<tmp) & deltaTSFC)
-      
-    }			// SRS config
-  }
+	  soundingRS_UL_ConfigCommon = &cc[CC_id].radioResourceConfigCommon->soundingRS_UL_ConfigCommon;
+	  // check if SRS is enabled in this frame/subframe
+	  if (soundingRS_UL_ConfigCommon) {
+		  srs_SubframeConfig = soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig;
+		  if (cc[CC_id].tdd_Config == NULL) {	// FDD
+			  deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
+			  TSFC = deltaTSFCTabType1[srs_SubframeConfig][1];
+		  } else {		// TDD
+			  deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
+			  TSFC = deltaTSFCTabType2[srs_SubframeConfig][1];
+		  }
+		  // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
+		  uint16_t tmp = (subframeP % TSFC);
+
+		  if ((1 << tmp) & deltaTSFC) {
+			  // This is an SRS subframe, loop over UEs
+			  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
+				  if (RC.mac[module_idP]->UE_list.active[UE_id] != TRUE)
+					  continue;
+				  ul_req = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body;
+				  // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
+				  if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) continue;
+				  AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL,
+						  "physicalConfigDedicated is null for UE %d\n", UE_id);
+
+				  if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) {
+					  if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
+						  get_srs_pos(&cc[CC_id],soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex,&srsPeriodicity, &srsOffset);
+
+						  if (((10 * frameP + subframeP) % srsPeriodicity) == srsOffset) {
+							  // Program SRS
+							  ul_req->srs_present = 1;
+							  nfapi_ul_config_request_pdu_t * ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
+							  memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
+							  ul_config_pdu->pdu_type =  NFAPI_UL_CONFIG_SRS_PDU_TYPE;
+							  ul_config_pdu->pdu_size =  2 + (uint8_t) (2 + sizeof(nfapi_ul_config_srs_pdu));
+							  ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG;
+							  ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t)sizeof(nfapi_ul_config_srs_pdu);
+							  ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti;
+							  ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
+							  ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
+							  ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;;
+							  ul_config_pdu->srs_pdu.srs_pdu_rel8.transmission_comb = soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
+							  ul_config_pdu->srs_pdu.srs_pdu_rel8.i_srs = soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
+							  ul_config_pdu->srs_pdu.srs_pdu_rel8.sounding_reference_cyclic_shift = soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;		//              ul_config_pdu->srs_pdu.srs_pdu_rel10.antenna_port                   = ;//
+							  //              ul_config_pdu->srs_pdu.srs_pdu_rel13.number_of_combs                = ;//
+							  RC.mac[module_idP]->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP;
+							  RC.mac[module_idP]->UL_req[CC_id].header.message_id = NFAPI_UL_CONFIG_REQUEST;
+							  ul_req->number_of_pdus++;
+						  }	// if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset)
+						  }	// if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup)
+					  }		// if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL)
+				  }		// for (UE_id ...
+			  }			// if((1<<tmp) & deltaTSFC)
+		  }			// SRS config
+	  }
 }
 
 void
 schedule_CSI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 {
-  eNB_MAC_INST                   *eNB = RC.mac[module_idP];
-  UE_list_t                      *UE_list = &eNB->UE_list;
-  COMMON_channels_t              *cc;
-  nfapi_ul_config_request_body_t *ul_req;
-  int                            CC_id, UE_id;
-  struct CQI_ReportPeriodic      *cqi_ReportPeriodic;
-  uint16_t                       Npd, N_OFFSET_CQI;
-  int                            H;
-
-  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
-
-    cc = &eNB->common_channels[CC_id];
-    for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
-      if (UE_list->active[UE_id] != TRUE)
-	continue;
-
-      ul_req = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body;
+	eNB_MAC_INST                   *eNB = RC.mac[module_idP];
+	UE_list_t                      *UE_list = &eNB->UE_list;
+	COMMON_channels_t              *cc;
+	nfapi_ul_config_request_body_t *ul_req;
+	int                            CC_id, UE_id;
+	struct CQI_ReportPeriodic      *cqi_ReportPeriodic;
+	uint16_t                       Npd, N_OFFSET_CQI;
+	int                            H;
+
+	for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
+		cc = &eNB->common_channels[CC_id];
+		for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
+			if (UE_list->active[UE_id] != TRUE)
+				continue;
+			ul_req = &RC.mac[module_idP]->UL_req[CC_id].ul_config_request_body;
+			// drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
+			if (mac_eNB_get_rrc_status(module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) continue;
+			AssertFatal(UE_list->
+					UE_template[CC_id][UE_id].physicalConfigDedicated
+					!= NULL,
+					"physicalConfigDedicated is null for UE %d\n",
+					UE_id);
+			if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig) {
+				if ((cqi_ReportPeriodic = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) != NULL
+						&& (cqi_ReportPeriodic->present != CQI_ReportPeriodic_PR_release)) {
+					//Rel8 Periodic CQI/PMI/RI reporting
+					get_csi_params(cc, cqi_ReportPeriodic, &Npd,
+							&N_OFFSET_CQI, &H);
+					if ((((frameP * 10) + subframeP) % Npd) == N_OFFSET_CQI) {	// CQI opportunity
+						UE_list->UE_sched_ctrl[UE_id].feedback_cnt[CC_id] = (((frameP * 10) + subframeP) / Npd) % H;
+						// Program CQI
+						nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
+						memset((void *) ul_config_pdu, 0,
+								sizeof(nfapi_ul_config_request_pdu_t));
+						ul_config_pdu->pdu_type                                                          = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
+						ul_config_pdu->pdu_size                                                          = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu));
+						ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
+						ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
+						ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
+						ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index      = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
+						ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size  = get_rel8_dl_cqi_pmi_size(&UE_list->UE_sched_ctrl[UE_id], CC_id, cc,get_tmode(module_idP, CC_id, UE_id),cqi_ReportPeriodic);
+						ul_req->number_of_pdus++;
+						ul_req->tl.tag                                                                   = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
+
+						#if defined(Rel10) || defined(Rel14)
+						// PUT rel10-13 UCI options here
+						#endif
+						} else
+							if ((cqi_ReportPeriodic->choice.setup.ri_ConfigIndex)
+									&& ((((frameP * 10) + subframeP) % ((H * Npd) << (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex / 161))) == N_OFFSET_CQI + (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex % 161))) {	// RI opportunity
+								// Program RI
+								nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
+								memset((void *) ul_config_pdu, 0,
+										sizeof(nfapi_ul_config_request_pdu_t));
+								ul_config_pdu->pdu_type                                                          = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
+								ul_config_pdu->pdu_size                                                          = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu));
+								ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
+								ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
+								ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
+								ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index      = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
+								ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size  = (cc->p_eNB == 2) ? 1 : 2;
+								RC.mac[module_idP]->UL_req[CC_id].sfn_sf                                         = (frameP << 4) + subframeP;
+								ul_req->number_of_pdus++;
+								ul_req->tl.tag                                                                   = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
+							}
+				}		// if ((cqi_ReportPeriodic = cqi_ReportConfig->cqi_ReportPeriodic)!=NULL) {
+
+			}			// if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig)
+
+		}			// for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
+
+	}				// for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
 
-      // drop the allocation if the UE hasn't send RRCConnectionSetupComplete yet
-      if (mac_eNB_get_rrc_status(module_idP, UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) continue;
-
-      AssertFatal(UE_list->
-		  UE_template[CC_id][UE_id].physicalConfigDedicated
-		  != NULL,
-		  "physicalConfigDedicated is null for UE %d\n",
-		  UE_id);
-
-      if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig) {
-	if ((cqi_ReportPeriodic = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) != NULL
-	    && (cqi_ReportPeriodic->present != CQI_ReportPeriodic_PR_release)) {
-	  //Rel8 Periodic CQI/PMI/RI reporting
-
-	  get_csi_params(cc, cqi_ReportPeriodic, &Npd,
-			 &N_OFFSET_CQI, &H);
-
-	  if ((((frameP * 10) + subframeP) % Npd) == N_OFFSET_CQI) {	// CQI opportunity
-	    UE_list->UE_sched_ctrl[UE_id].feedback_cnt[CC_id] = (((frameP * 10) + subframeP) / Npd) % H;
-	    // Program CQI
-	    nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
-	    memset((void *) ul_config_pdu, 0,
-		   sizeof(nfapi_ul_config_request_pdu_t));
-	    ul_config_pdu->pdu_type                                                          = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
-	    ul_config_pdu->pdu_size                                                          = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu));
-	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
-	    ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
-	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
-	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index      = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
-	    ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size  = get_rel8_dl_cqi_pmi_size(&UE_list->UE_sched_ctrl[UE_id], CC_id, cc,
-															get_tmode(module_idP, CC_id, UE_id),
-															cqi_ReportPeriodic);
-	    ul_req->number_of_pdus++;
-	    ul_req->tl.tag                                                                   = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
-
-#if defined(Rel10) || defined(Rel14)
-	    // PUT rel10-13 UCI options here
-#endif
-	  } else
-	    if ((cqi_ReportPeriodic->choice.setup.ri_ConfigIndex)
-		&& ((((frameP * 10) + subframeP) % ((H * Npd) << (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex / 161))) == N_OFFSET_CQI + (*cqi_ReportPeriodic->choice.setup.ri_ConfigIndex % 161))) {	// RI opportunity
-	      // Program RI
-	      nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
-	      memset((void *) ul_config_pdu, 0,
-		     sizeof(nfapi_ul_config_request_pdu_t));
-	      ul_config_pdu->pdu_type                                                          = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE;
-	      ul_config_pdu->pdu_size                                                          = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu));
-	      ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag             = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
-	      ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti               = UE_list->UE_template[CC_id][UE_id].rnti;
-	      ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag           = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG;
-	      ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index      = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
-	      ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size  = (cc->p_eNB == 2) ? 1 : 2;
-	      RC.mac[module_idP]->UL_req[CC_id].sfn_sf                                         = (frameP << 4) + subframeP;
-	      ul_req->number_of_pdus++;
-	      ul_req->tl.tag                                                                   = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
-	    }
-	}		// if ((cqi_ReportPeriodic = cqi_ReportConfig->cqi_ReportPeriodic)!=NULL) {
-      }			// if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig)
-    }			// for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
-  }				// for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
 }
 
 void
@@ -531,6 +519,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
     cc[CC_id].mcch_active        = 0;
 #endif
 
+
     clear_nfapi_information(RC.mac[module_idP], CC_id, frameP, subframeP);
   }
 
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
index 3005ecf464233f379d856c22441608f6ea1ca182..b71683cfb6c53ebe72ad46c45cbcf48e70e61cbb 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
@@ -174,9 +174,9 @@ add_msg3(module_id_t module_idP, int CC_id, RA_t * ra, frame_t frameP,
 	      ra->Msg3_subframe);
 
 	LOG_D(MAC,
-	      "Frame %d, Subframe %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d)\n",
+	      "Frame %d, Subframe %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d) for rnti: %d\n",
 	      frameP, subframeP, ra->Msg3_frame, ra->Msg3_subframe,
-	      ra->msg3_nb_rb, ra->msg3_first_rb, ra->msg3_round);
+	      ra->msg3_nb_rb, ra->msg3_first_rb, ra->msg3_round, ra->rnti);
 
 	ul_config_pdu = &ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus];
 
@@ -698,7 +698,7 @@ generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP,
     else
 	ra->harq_pid = ((frameP * 10) + subframeP) & 7;
 
-    // Get RRCConnectionSetup for Piggyback
+   /* // Get RRCConnectionSetup for Piggyback
     rrc_sdu_length = mac_rrc_data_req(module_idP, CC_idP, frameP, CCCH, 1,	// 1 transport block
 				      &cc[CC_idP].CCCH_pdu.payload[0], 0);	// not used in this case
 
@@ -708,7 +708,7 @@ generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP,
 
     LOG_D(MAC,
 	  "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, rrc_sdu_length %d\n",
-	  module_idP, CC_idP, frameP, subframeP, UE_id, rrc_sdu_length);
+	  module_idP, CC_idP, frameP, subframeP, UE_id, rrc_sdu_length);*/
 
 
 #ifdef Rel14
@@ -817,6 +817,20 @@ generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP,
 
 		// Program PDSCH
 
+	        // Get RRCConnectionSetup for Piggyback
+	        /*rrc_sdu_length = mac_rrc_data_req(module_idP, CC_idP, frameP, CCCH, 1,	// 1 transport block
+	    				      &cc[CC_idP].CCCH_pdu.payload[0], ENB_FLAG_YES, module_idP, 0);	// not used in this case*/
+
+	    	rrc_sdu_length = mac_rrc_data_req(module_idP, CC_idP, frameP, CCCH, 1,	// 1 transport block
+	    					      &cc[CC_idP].CCCH_pdu.payload[0], 0);	// not used in this case
+
+	        LOG_D(MAC,
+	        	  "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, rrc_sdu_length %d\n",
+	        	  module_idP, CC_idP, frameP, subframeP, UE_id, rrc_sdu_length);
+
+	        AssertFatal(rrc_sdu_length > 0,
+	    		"[MAC][eNB Scheduler] CCCH not allocated\n");
+
 		LOG_D(MAC,
 		      "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 BR with RRC Piggyback (ce_level %d RNTI %x)\n",
 		      module_idP, CC_idP, frameP, subframeP,
@@ -978,8 +992,27 @@ generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP,
     }				// rach_resource_type > 0 
     else
 #endif
-    {				// This is normal LTE case
-	if ((ra->Msg4_frame == frameP) && (ra->Msg4_subframe == subframeP)) {
+    {
+    // This is normal LTE case
+	LOG_D(MAC, "Panos-D: generate_Msg4 1 ra->Msg4_frame SFN/SF: %d.%d,  frameP SFN/SF: %d.%d FOR eNB_Mod: %d \n", ra->Msg4_frame, ra->Msg4_subframe, frameP, subframeP, module_idP);
+    	if ((ra->Msg4_frame == frameP) && (ra->Msg4_subframe == subframeP)) {
+
+    	    // Get RRCConnectionSetup for Piggyback
+    	    /*rrc_sdu_length = mac_rrc_data_req(module_idP, CC_idP, frameP, CCCH, 1,	// 1 transport block
+    					      &cc[CC_idP].CCCH_pdu.payload[0], ENB_FLAG_YES, module_idP, 0);	// not used in this case*/
+
+    		rrc_sdu_length = mac_rrc_data_req(module_idP, CC_idP, frameP, CCCH, 1,	// 1 transport block
+    						      &cc[CC_idP].CCCH_pdu.payload[0], 0);	// not used in this case
+
+    	    LOG_D(MAC,
+    	    	  "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, rrc_sdu_length %d\n",
+    	    	  module_idP, CC_idP, frameP, subframeP, UE_id, rrc_sdu_length);
+
+    	    AssertFatal(rrc_sdu_length > 0,
+    			"[MAC][eNB Scheduler] CCCH not allocated, rrc_sdu_length: %d\n", rrc_sdu_length);
+
+
+
 	    LOG_D(MAC,
 		  "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RNTI %x)\n",
 		  module_idP, CC_idP, frameP, subframeP, ra->rnti);
@@ -1233,8 +1266,8 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP,
     N_RB_DL = to_prb(cc[CC_idP].mib->message.dl_Bandwidth);
 
     LOG_D(MAC,
-	  "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 for harq_pid %d was acknowledged (round %d)\n",
-	  module_idP, CC_idP, frameP, subframeP, ra->harq_pid, round);
+	  "[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 for harq_pid %d was acknowledged (round %d), UE_id: %d \n",
+	  module_idP, CC_idP, frameP, subframeP, ra->harq_pid, round, UE_id);
 
     if (round != 8) {
 
@@ -1283,6 +1316,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP,
 			  ra->rnti, round, frameP, subframeP);
 		    // DLSCH Config
                     //DJP - fix this pdu_index = -1
+		    LOG_D(MAC, "Panos:D: check_Msg4_retransmission() before fill_nfapi_dlsch_config() with pdu_index = -1 \n");
 		    fill_nfapi_dlsch_config(mac, dl_req_body, ra->msg4_TBsize,
 					    -1
 					    /* retransmission, no pdu_index */
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
index f12702fbb8c554d75784e3aa7472f586dd6817af..b6253034fc9ad51d759fc7d8222c88ef52f5752d 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
@@ -84,7 +84,6 @@ schedule_SIB1_BR(module_id_t module_idP,
 		 frame_t frameP, sub_frame_t subframeP)
 //------------------------------------------------------------------------------
 {
-
     int8_t bcch_sdu_length;
     int CC_id;
     eNB_MAC_INST *eNB = RC.mac[module_idP];
@@ -509,7 +508,6 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP,
 void
 schedule_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 {
-
     eNB_MAC_INST *eNB = RC.mac[module_idP];
     COMMON_channels_t *cc;
     nfapi_dl_config_request_pdu_t *dl_config_pdu;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
index 0729073eba3cc5e6ca1351603329d83c095497bc..dcc41ce3eb3014e2aaad1b0ec5d7a1f01a7b7e61 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
@@ -1007,7 +1007,11 @@ schedule_ue_spec(module_id_t module_idP,slice_id_t slice_idP,
 	// RLC data on DCCH
 	if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) {
 	  rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH,
-                                          TBS - ta_len - header_length_total - sdu_length_total - 3);
+                                          TBS - ta_len - header_length_total - sdu_length_total - 3
+#ifdef Rel14
+                                                    ,0, 0
+#endif
+                          );
 
 	  sdu_lengths[0] = 0;
 
@@ -1018,7 +1022,11 @@ schedule_ue_spec(module_id_t module_idP,slice_id_t slice_idP,
 
 	    sdu_lengths[0] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH,
                                               TBS, //not used
-					      (char *)&dlsch_buffer[0]);
+					      (char *)&dlsch_buffer[0]
+#ifdef Rel14
+                          ,0, 0
+#endif
+                          );
 
 	    T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP),
 	      T_INT(CC_id), T_INT(rnti), T_INT(frameP),
@@ -1057,7 +1065,11 @@ schedule_ue_spec(module_id_t module_idP,slice_id_t slice_idP,
 	// RLC data on DCCH1
 	if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) {
 	  rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1,
-                                          TBS - ta_len - header_length_total - sdu_length_total - 3);
+                                          TBS - ta_len - header_length_total - sdu_length_total - 3
+#ifdef Rel14
+                                                    ,0, 0
+#endif
+                                         );
 
 	  // DCCH SDU
 	  sdu_lengths[num_sdus] = 0;
@@ -1069,7 +1081,11 @@ schedule_ue_spec(module_id_t module_idP,slice_id_t slice_idP,
 
 	    sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1,
                                                       TBS, //not used
-						      (char *)&dlsch_buffer[sdu_length_total]);
+						      (char *)&dlsch_buffer[sdu_length_total]
+#ifdef Rel14
+                          ,0, 0
+#endif
+	    );
 
 	    T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP),
 	      T_INT(CC_id), T_INT(rnti), T_INT(frameP),
@@ -1099,6 +1115,7 @@ schedule_ue_spec(module_id_t module_idP,slice_id_t slice_idP,
 
 	    LOG_T(MAC, "\n");
 #endif
+
 	  }
 	}
 
@@ -1119,7 +1136,11 @@ schedule_ue_spec(module_id_t module_idP,slice_id_t slice_idP,
 					    ENB_FLAG_YES,
 					    MBMS_FLAG_NO,
 					    lcid,
-					    TBS - ta_len - header_length_total - sdu_length_total - 3);
+					    TBS - ta_len - header_length_total - sdu_length_total - 3
+#ifdef Rel14
+                                                    ,0, 0
+#endif
+                                           );
 
 
 
@@ -1133,7 +1154,11 @@ schedule_ue_spec(module_id_t module_idP,slice_id_t slice_idP,
 
 	      sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid,
                                                        TBS, //not used
-						       (char *)&dlsch_buffer[sdu_length_total]);
+						       (char *)&dlsch_buffer[sdu_length_total]
+#ifdef Rel14
+                          ,0, 0
+#endif
+	      );
 
 	      T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP),
 		T_INT(CC_id), T_INT(rnti), T_INT(frameP),
@@ -1505,7 +1530,6 @@ schedule_ue_spec(module_id_t module_idP,slice_id_t slice_idP,
   }				// CC_id loop
 
 
-
   fill_DLSCH_dci(module_idP, frameP, subframeP, mbsfn_flag);
 
   stop_meas(&eNB->schedule_dlsch);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
index 37b13d2de71936b52dec051274b91e4c73bdd3fe..9e2deca20252a554446944cd7defdde471949f69 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
@@ -635,7 +635,12 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
 			       module_idP, ENB_FLAG_YES, MBMS_FLAG_YES,
 			       MTCH,
 			       TBS - header_len_mcch - header_len_msi -
-			       sdu_length_total - header_len_mtch);
+			       sdu_length_total - header_len_mtch
+#ifdef Rel14
+                                    ,0, 0
+#endif
+                                    );
+
 	LOG_D(MAC,
 	      "e-MBMS log channel %u frameP %d, subframeP %d,  rlc_status.bytes_in_buffer is %d\n",
 	      MTCH, frameP, subframeP, rlc_status.bytes_in_buffer);
@@ -649,8 +654,14 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
 
 	    sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES, MTCH, 0,	//not used
 						     (char *)
-						     &mch_buffer
-						     [sdu_length_total]);
+						     &mch_buffer[sdu_length_total]
+#ifdef Rel14
+                                ,0,
+                                 0
+#endif
+                                 );
+
+
 	    //sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO,  MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)), (char*)&mch_buffer[sdu_length_total]);
 	    LOG_I(MAC,
 		  "[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d\n",
diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c
index 2cdcfc7de857a8c4df4089881040907b731d21c4..245598cb549deb2204efab7771312d1bd20d12f1 100644
--- a/openair2/LAYER2/MAC/pre_processor.c
+++ b/openair2/LAYER2/MAC/pre_processor.c
@@ -128,13 +128,19 @@ store_dlsch_buffer(module_id_t Mod_id, slice_id_t slice_id, frame_t frameP,
 	    UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = 0;
 	}
 
+
 	rnti = UE_RNTI(Mod_id, UE_id);
 
 	for (i = 0; i < MAX_NUM_LCID; i++) {	// loop over all the logical channels
 
 	    rlc_status =
 		mac_rlc_status_ind(Mod_id, rnti, Mod_id, frameP, subframeP,
-				   ENB_FLAG_YES, MBMS_FLAG_NO, i, 0);
+				   ENB_FLAG_YES, MBMS_FLAG_NO, i, 0
+#ifdef Rel14
+                   ,0, 0
+#endif
+                   );
+
 	    UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer;	//storing the dlsch buffer for each logical channel
 	    UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
 	    UE_template->dl_buffer_head_sdu_creation_time[i] =
@@ -211,7 +217,6 @@ assign_rbs_required(module_id_t Mod_id,
 
 	//update CQI information across component carriers
 	for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) {
-
 	    CC_id = UE_list->ordered_CCids[n][UE_id];
 	    eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
 
@@ -1192,7 +1197,6 @@ dlsch_scheduler_pre_processor_reset(int module_idP,
        &ue_sched_ctl->round[CC_id],
        openair_harq_DL);
 
-
        if (ue_sched_ctl->ta_timer == 0) {
 
        // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...
diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h
index 64daede100d723348bf707ca698cf12df7915896..b5cc7917b0f22af059c0b9f5e24f977d46120abd 100644
--- a/openair2/LAYER2/MAC/proto.h
+++ b/openair2/LAYER2/MAC/proto.h
@@ -520,6 +520,15 @@ void ue_send_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frame,
 		 sub_frame_t subframe, uint8_t * sdu, uint16_t sdu_len,
 		 uint8_t CH_index);
 
+void ue_send_sl_sdu(module_id_t module_idP,
+		    uint8_t CC_id,
+		    frame_t frameP,
+		    sub_frame_t subframeP,
+		    uint8_t* sdu,
+		    uint16_t sdu_len,
+		    uint8_t eNB_index,
+	       sl_discovery_flag_t sl_discovery_flag
+		    );
 
 #if defined(Rel10) || defined(Rel14)
 /* \brief Called by PHY to transfer MCH transport block to ue MAC.
@@ -553,13 +562,36 @@ int ue_query_mch(uint8_t Mod_id, uint8_t CC_id, uint32_t frame,
 @param eNB_id Index of eNB that UE is attached to
 @param rnti C_RNTI of UE
 @param subframe subframe number
-@returns 0 for no SR, 1 for SR
 */
 void ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
 		sub_frame_t subframe, uint8_t eNB_index,
 		uint8_t * ulsch_buffer, uint16_t buflen,
 		uint8_t * access_mode);
 
+/* \brief Called by PHY to get sdu for PSBCH/SSS/PSS transmission.
+@param Mod_id Instance id of UE in machine
+@param frame_tx TX frame index
+@param subframe_tx TX subframe index
+@returns pointer to SLSS_t descriptor
+*/
+SLSS_t *ue_get_slss(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframe);
+
+/* \brief Called by PHY to get sdu for PSDCH transmission.
+@param Mod_id Instance id of UE in machine
+@param frame_tx TX frame index
+@param subframe_tx TX subframe index
+@returns pointer to SLDCH_t descriptor
+*/
+SLDCH_t *ue_get_sldch(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframe);
+
+/* \brief Called by PHY to get sdu for PSSCH transmission.
+@param Mod_id Instance id of UE in machine
+@param frame_tx TX frame index
+@param subframe_tx TX subframe index
+@returns pointer to SLSCH_t descriptor
+*/
+SLSCH_t *ue_get_slsch(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframe);
+
 /* \brief Function called by PHY to retrieve information to be transmitted using the RA procedure.  If the UE is not in PUSCH mode for a particular eNB index, this is assumed to be an Msg3 and MAC attempts to retrieves the CCCH message from RRC. If the UE is in PUSCH mode for a particular eNB index and PUCCH format 0 (Scheduling Request) is not activated, the MAC may use this resource for random-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 from 36.321)
 @param Mod_id Index of UE instance
 @param Mod_id Component Carrier Index
@@ -996,7 +1028,13 @@ int rrc_mac_config_req_ue(module_id_t module_idP,
 			  ,
 			  uint8_t num_active_cba_groups, uint16_t cba_rnti
 #endif
-    );
+#if defined(Rel14)
+           ,config_action_t config_action
+           ,const uint32_t * const sourceL2Id
+           ,const uint32_t * const destinationL2Id
+#endif
+			  );
+
 
 uint16_t getRIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs);
 
diff --git a/openair2/LAYER2/MAC/ra_procedures.c b/openair2/LAYER2/MAC/ra_procedures.c
index 8868d2d548ad30ba445b924c7e294d7df1fc8294..36518ad62210a8be718f3f7d45236fac08e11510 100644
--- a/openair2/LAYER2/MAC/ra_procedures.c
+++ b/openair2/LAYER2/MAC/ra_procedures.c
@@ -49,7 +49,11 @@
 
 #include "SIMULATION/TOOLS/defs.h"	// for taus
 
-int8_t get_DELTA_PREAMBLE(module_id_t module_idP, int CC_id)
+extern uint8_t  nfapi_mode;
+extern UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
+
+
+int8_t get_DELTA_PREAMBLE(module_id_t module_idP,int CC_id)
 {
 
     AssertFatal(CC_id == 0,
@@ -105,7 +109,6 @@ get_prach_resources(module_id_t module_idP,
 		    uint8_t first_Msg3,
 		    RACH_ConfigDedicated_t * rach_ConfigDedicated)
 {
-
     uint8_t Msg3_size = UE_mac_inst[module_idP].RA_Msg3_size;
     PRACH_RESOURCES_t *prach_resources =
 	&UE_mac_inst[module_idP].RA_prach_resources;
@@ -344,9 +347,18 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id,
 			       sub_frame_t subframeP)
 {
 
-
     uint8_t Size = 0;
-    UE_MODE_t UE_mode = get_ue_mode(module_idP, 0, eNB_indexP);
+    UE_MODE_t UE_mode;
+    // Panos: Modification for phy_stub_ue operation
+    if(nfapi_mode == 3) { // Panos: phy_stub_ue mode
+        UE_mode = UE_mac_inst[module_idP].UE_mode[0];
+        LOG_D(MAC, "ue_get_rach , UE_mode: %d", UE_mode);
+    }
+    else { // Full stack mode
+        UE_mode = get_ue_mode(module_idP,0,eNB_indexP);
+    }
+
+
     uint8_t lcid = CCCH;
     uint16_t Size16;
     struct RACH_ConfigCommon *rach_ConfigCommon =
@@ -361,6 +373,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id,
 		"Transmission on secondary CCs is not supported yet\n");
 
     if (UE_mode == PRACH) {
+        LOG_D(MAC, "ue_get_rach 3, RA_active value: %d", UE_mac_inst[module_idP].RA_active);
 	if (UE_mac_inst[module_idP].radioResourceConfigCommon) {
 	    rach_ConfigCommon =
 		&UE_mac_inst[module_idP].
@@ -392,7 +405,6 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id,
 		  module_idP, frameP, Size);
 
 	    if (Size > 0) {
-
 		UE_mac_inst[module_idP].RA_active = 1;
 		UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER =
 		    1;
@@ -447,7 +459,12 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id,
 		    mac_rlc_status_ind(module_idP,
 				       UE_mac_inst[module_idP].crnti,
 				       eNB_indexP, frameP, subframeP,
-				       ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6);
+				       ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6
+#ifdef Rel14
+               ,0, 0
+#endif
+               );
+
 
 		if (UE_mac_inst[module_idP].crnti_before_ho)
 		    LOG_D(MAC,
@@ -463,7 +480,13 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id,
 			  dcch_header_len);
 
 		sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP, ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6,	//not used
-						  (char *) &ulsch_buff[0]);
+						  (char *) &ulsch_buff[0]
+#ifdef Rel14
+						  ,0,
+						  0
+#endif
+                                     );
+
 
 		LOG_D(MAC, "[UE %d] TX Got %d bytes for DCCH\n",
 		      module_idP, sdu_lengths[0]);
diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c
index 5ca6d10bb530f4ac19246777c488a24d6c8f3b4e..c9ccddae37346a93a1b7fd0152fd84682a339d3a 100644
--- a/openair2/LAYER2/MAC/ue_procedures.c
+++ b/openair2/LAYER2/MAC/ue_procedures.c
@@ -52,6 +52,7 @@
 #include "UTIL/OPT/opt.h"
 #include "OCG.h"
 #include "OCG_extern.h"
+#include "openair2/PHY_INTERFACE/phy_stub_UE.h"
 
 #ifdef PHY_EMUL
 #include "SIMULATION/simulation_defs.h"
@@ -71,6 +72,17 @@
 
 extern uint8_t usim_test;
 
+extern UL_IND_t *UL_INFO;
+
+extern uint8_t  nfapi_mode;
+
+/*
+ *
+#ifndef USER_MODE
+#define msg debug_msg
+#endif
+ */
+
 mapping BSR_names[] = {
     {"NONE", 0},
     {"SHORT BSR", 1},
@@ -83,6 +95,7 @@ mapping BSR_names[] = {
 
 void ue_init_mac(module_id_t module_idP)
 {
+
     int i;
     // default values as deined in 36.331 sec 9.2.2
     LOG_I(MAC, "[UE%d] Applying default macMainConfig\n", module_idP);
@@ -145,6 +158,19 @@ void ue_init_mac(module_id_t module_idP)
 	UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[i] = 0;
     }
 
+  if(nfapi_mode == 3) {
+	  pthread_mutex_init(&UE_mac_inst[module_idP].UL_INFO_mutex,NULL);
+	  UE_mac_inst[module_idP].UE_mode[0] = NOT_SYNCHED; //PRACH;
+	  UE_mac_inst[module_idP].first_ULSCH_Tx =0;
+	  UE_mac_inst[module_idP].SI_Decoded = 0;
+	  next_ra_frame = 0;
+	  next_Mod_id = 0;
+	  tx_request_pdu_list = NULL;
+	  tx_req_num_elems = 0;
+
+
+  }
+
 #ifdef CBA
 
     for (i = 0; i < NUM_MAX_CBA_GROUP; i++) {
@@ -395,7 +421,8 @@ ue_send_sdu(module_id_t module_idP,
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
 	(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
 
-    LOG_T(MAC, "sdu: %x.%x.%x\n", sdu[0], sdu[1], sdu[2]);
+
+  //LOG_D(MAC,"sdu: %x.%x.%x\n",sdu[0],sdu[1],sdu[2]);
 
     if (opt_enabled) {
 	trace_pdu(1, sdu, sdu_len, module_idP, 3,
@@ -453,7 +480,16 @@ ue_send_sdu(module_id_t module_idP,
 			    LOG_E(MAC,
 				  "[UE %d][RAPROC] Contention detected, RA failed\n",
 				  module_idP);
-			    ra_failed(module_idP, CC_id, eNB_index);
+			    if(nfapi_mode == 3) { // Panos: phy_stub mode
+			    	// Panos: Modification for phy_stub mode operation here. We only need to make sure that the ue_mode is back to
+			    	// PRACH state.
+			    	LOG_I(MAC, "nfapi_mode3: Setting UE_mode BACK to PRACH 1\n");
+			    	UE_mac_inst[module_idP].UE_mode[eNB_index] = PRACH;
+			    	//ra_failed(module_idP,CC_id,eNB_index);UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
+			    	}
+			    else{
+			    	ra_failed(module_idP, CC_id, eNB_index);
+			    }
 			    UE_mac_inst
 				[module_idP].
 				RA_contention_resolution_timer_active = 0;
@@ -469,7 +505,14 @@ ue_send_sdu(module_id_t module_idP,
 		    UE_mac_inst
 			[module_idP].
 			RA_contention_resolution_timer_active = 0;
-		    ra_succeeded(module_idP, CC_id, eNB_index);
+		    if(nfapi_mode == 3) // phy_stub mode
+		    	{
+		    	//Panos: Modification for phy_stub mode operation here. We only need to change the ue_mode to PUSCH
+		    	UE_mac_inst[module_idP].UE_mode[eNB_index] = PUSCH;
+		    	}
+		    else { // Full stack mode
+		    	ra_succeeded(module_idP,CC_id,eNB_index);
+		    }
 		}
 
 		payload_ptr += 6;
@@ -480,9 +523,14 @@ ue_send_sdu(module_id_t module_idP,
 		LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i,
 		      payload_ptr[0]);
 #endif
-		process_timing_advance(module_idP, CC_id, payload_ptr[0]);
-		payload_ptr++;
-		break;
+
+	  // Panos: Eliminate call to process_timing_advance for the phy_stub UE operation mode. Is this correct?
+      if (nfapi_mode!=3)
+      {
+    	  process_timing_advance(module_idP,CC_id,payload_ptr[0]);
+      }
+      payload_ptr++;
+      break;
 
 	    case DRX_CMD:
 #ifdef DEBUG_HEADER_PARSING
@@ -498,7 +546,6 @@ ue_send_sdu(module_id_t module_idP,
 	    LOG_D(MAC, "[UE] SDU %d : LCID %d, length %d\n", i,
 		  rx_lcids[i], rx_lengths[i]);
 #endif
-
 	    if (rx_lcids[i] == CCCH) {
 
 		LOG_D(MAC,
@@ -515,6 +562,7 @@ ue_send_sdu(module_id_t module_idP,
 
 		LOG_T(MAC, "\n");
 #endif
+
 		mac_rrc_data_ind_ue(module_idP,
 				 CC_id,
 				 frameP, subframeP,
@@ -778,9 +826,93 @@ ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
 #endif
 }
 
-int8_t
-ue_get_mbsfn_sf_alloction(module_id_t module_idP,
-			  uint8_t mbsfn_sync_area, unsigned char eNB_index)
+void ue_send_sl_sdu(module_id_t module_idP,
+		    uint8_t CC_id,
+		    frame_t frameP,
+		    sub_frame_t subframeP,
+		    uint8_t* sdu,
+		    uint16_t sdu_len,
+		    uint8_t eNB_index,
+		    sl_discovery_flag_t sl_discovery_flag
+		    ) {
+
+  int rlc_sdu_len;
+  char *rlc_sdu;
+  uint32_t destinationL2Id =0x00000000;
+
+  if (sl_discovery_flag == SL_DISCOVERY_FLAG_NO) {
+
+  // Notes: 1. no control elements are supported yet
+  //        2. we exit with error if LCID != 3
+  //        3. we exit with error if E=1 (more than one SDU/CE)
+  // extract header
+  SLSCH_SUBHEADER_24_Bit_DST_LONG *longh = (SLSCH_SUBHEADER_24_Bit_DST_LONG *)sdu;
+  AssertFatal(longh->E==0,"E is non-zero\n");
+  AssertFatal(((longh->LCID==3)|(longh->LCID==10)),"LCID is %d (not 3 or 10)\n",longh->LCID);
+  //filter incoming packet based on destination address
+  destinationL2Id = (longh->DST07<<16) | (longh->DST815 <<8) | (longh->DST1623);
+  LOG_I( MAC, "[DestinationL2Id:  0x%08x]  \n", destinationL2Id );
+  //in case of 1-n communication, verify that UE belongs to that group
+  int i=0;
+  for (i=0; i< MAX_NUM_DEST; i++)
+     if (UE_mac_inst[module_idP].destinationList[i] == destinationL2Id) break;
+  //match the destinationL2Id with UE L2Id or groupL2ID
+  if (!((destinationL2Id == UE_mac_inst[module_idP].sourceL2Id) | (i < MAX_NUM_DEST))){
+     LOG_I( MAC, "[Destination Id is neither matched with Source Id nor with Group Id, drop the packet!!! \n");
+     return;
+  }
+
+
+  if (longh->F==1) {
+    rlc_sdu_len = ((longh->L_MSB<<8)&0x7F00)|(longh->L_LSB&0xFF);
+    rlc_sdu = sdu+sizeof(SLSCH_SUBHEADER_24_Bit_DST_LONG);
+  }
+  else {
+    rlc_sdu_len = ((SLSCH_SUBHEADER_24_Bit_DST_SHORT *)sdu)->L;
+    rlc_sdu = sdu+sizeof(SLSCH_SUBHEADER_24_Bit_DST_SHORT);
+  }
+  mac_rlc_data_ind(
+		   module_idP,
+		   0x1234,
+		   eNB_index,
+		   frameP,
+		   ENB_FLAG_NO,
+		   MBMS_FLAG_NO,
+		   longh->LCID, //3/10
+		   rlc_sdu,
+		   rlc_sdu_len,
+		   1,
+		   NULL);
+  } else { //SL_DISCOVERY
+     uint16_t len = sdu_len;
+     LOG_I( MAC, "SL DISCOVERY \n");
+     // Panos: Ask TTN if we should be calling mac_rrc_data_ind_ue() instead of mac_rrc_data_ind() now!
+     /*mac_rrc_data_ind(module_idP,
+                      CC_id,
+                      frameP,subframeP,
+                      UE_mac_inst[module_idP].crnti,
+                      SL_DISCOVERY,
+                      sdu, //(uint8_t*)&UE_mac_inst[Mod_id].SL_Discovery[0].Rx_buffer.Payload[0],
+                      len,
+                      ENB_FLAG_NO,
+                      eNB_index,
+                      0);*/
+     mac_rrc_data_ind_ue(module_idP,
+                           CC_id,
+                           frameP,subframeP,
+                           UE_mac_inst[module_idP].crnti,
+                           SL_DISCOVERY,
+                           sdu, //(uint8_t*)&UE_mac_inst[Mod_id].SL_Discovery[0].Rx_buffer.Payload[0],
+                           len,
+                           eNB_index,
+                           0);
+
+  }
+}
+
+
+int8_t ue_get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t mbsfn_sync_area, unsigned char eNB_index)
+
 {
     // currently there is one-to-one mapping between sf allocation pattern and sync area
     if (mbsfn_sync_area >= MAX_MBSFN_AREA) {
@@ -1496,6 +1628,7 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
 	   uint8_t * ulsch_buffer, uint16_t buflen, uint8_t * access_mode)
 {
 
+	//LOG_I(MAC, "Panos-D: UE[%d] In ue_get_sdu() 1  \n", module_idP);
     uint8_t total_rlc_pdu_header_len = 0, rlc_pdu_header_len_last = 0;
     uint16_t buflen_remain = 0;
     uint8_t bsr_len = 0, bsr_ce_len = 0, bsr_header_len = 0;
@@ -1724,9 +1857,13 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
 							 MBMS_FLAG_NO,
 							 lcid,
 							 buflen_remain,
-							 (char *)
-							 &ulsch_buff
-							 [sdu_length_total]);
+							 (char *)&ulsch_buff[sdu_length_total]
+#ifdef Rel14
+							 ,0,
+                              0
+#endif
+                         	 );
+
 
 
 		AssertFatal(buflen_remain >= sdu_lengths[num_sdus],
@@ -1864,7 +2001,15 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
     }
     // build PHR and update the timers
     if (phr_ce_len == sizeof(POWER_HEADROOM_CMD)) {
-	phr_p->PH = get_phr_mapping(module_idP, CC_id, eNB_index);
+    	if(nfapi_mode ==3){
+    		//Panos: Substitute with a static value for the MAC layer abstraction (phy_stub mode)
+    		phr_p->PH = 40;
+    	}
+    	else{
+    		phr_p->PH = get_phr_mapping(module_idP, CC_id, eNB_index);
+    	}
+
+
 	phr_p->R = 0;
 	LOG_D(MAC,
 	      "[UE %d] Frame %d report PHR with mapping (%d->%d) for LCID %d\n",
@@ -1878,7 +2023,6 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
     LOG_T(MAC, "[UE %d] Frame %d: bsr s %p bsr_l %p, phr_p %p\n",
 	  module_idP, frameP, bsr_s, bsr_l, phr_p);
 
-
     // Check BSR padding: it is done after PHR according to Logical Channel Prioritization order
     // Check for max padding size, ie MAC Hdr for last RLC PDU = 1
     /* For Padding BSR:
@@ -2073,6 +2217,7 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
 	  buflen - sdu_length_total - payload_offset);
     // cycle through SDUs and place in ulsch_buffer
     if (sdu_length_total) {
+    	//LOG_I(MAC, "Panos-D: [UE %d] ue_get_sdu() 2 before copying to ulsch_buffer, SFN/SF: %d/%d \n \n \n", module_idP, frameP, subframe);
 	memcpy(&ulsch_buffer[payload_offset], ulsch_buff,
 	       sdu_length_total);
     }
@@ -2139,6 +2284,8 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP,
     }
 }
 
+
+
 //------------------------------------------------------------------------------
 // called at each subframe
 // Performs :
@@ -2300,6 +2447,7 @@ ue_scheduler(const module_id_t module_idP,
 #if UE_TIMING_TRACE
 	    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
 #endif
+
 	    //return(RRC_OK);
 	}
 
@@ -2323,7 +2471,17 @@ ue_scheduler(const module_id_t module_idP,
 	    LOG_E(MAC,
 		  "Module id %u Contention resolution timer expired, RA failed\n",
 		  module_idP);
-	    ra_failed(module_idP, 0, eNB_indexP);
+	    if(nfapi_mode == 3) { // Panos: phy_stub mode
+	    	// Panos: Modification for phy_stub mode operation here. We only need to make sure that the ue_mode is back to
+	    	// PRACH state.
+	    	LOG_I(MAC, "nfapi_mode3: Setting UE_mode to PRACH 2 \n");
+	    	UE_mac_inst[module_idP].UE_mode[eNB_indexP] = PRACH;
+	    	//ra_failed(module_idP,CC_id,eNB_index);UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
+	    	}
+	    else{
+	    	ra_failed(module_idP, CC_id, eNB_indexP);
+	    }
+	    //ra_failed(module_idP, 0, eNB_indexP);
 	}
     }
     // Get RLC status info and update Bj for all lcids that are active
@@ -2641,92 +2799,92 @@ update_bsr(module_id_t module_idP, frame_t frameP,
 	   sub_frame_t subframeP, eNB_index_t eNB_index)
 {
 
-    mac_rlc_status_resp_t rlc_status;
-    boolean_t bsr_regular_triggered = FALSE;
-    uint8_t lcid;
-    uint8_t lcgid;
-    uint8_t num_lcid_with_data = 0;	// for LCID with data only if LCGID is defined
-    uint16_t lcgid_buffer_remain[MAX_NUM_LCGID] = { 0, 0, 0, 0 };
-    int32_t lcid_bytes_in_buffer[MAX_NUM_LCID];
-    /* Array for ordering LCID with data per decreasing priority order */
-    uint8_t lcid_reordered_array[MAX_NUM_LCID] =
-	{ MAX_NUM_LCID, MAX_NUM_LCID, MAX_NUM_LCID, MAX_NUM_LCID,
-	MAX_NUM_LCID, MAX_NUM_LCID, MAX_NUM_LCID, MAX_NUM_LCID,
-	    MAX_NUM_LCID,
-	MAX_NUM_LCID, MAX_NUM_LCID
-    };
-    uint8_t pos_next = 0;
-    uint8_t highest_priority = 16;
-    uint8_t array_index = 0;
-
-    // Reset All BSR Infos
-    lcid_bytes_in_buffer[0] = 0;
-    for (lcid = DCCH; lcid < MAX_NUM_LCID; lcid++) {
-	// Reset transmission status
-	lcid_bytes_in_buffer[lcid] = 0;
-	UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] =
-	    LCID_EMPTY;
-    }
-
-    for (lcgid = 0; lcgid < MAX_NUM_LCGID; lcgid++) {
-	// Reset Buffer Info
-	UE_mac_inst[module_idP].scheduling_info.BSR[lcgid] = 0;
-	UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] = 0;
-    }
-
-    //Get Buffer Occupancy and fill lcid_reordered_array
-    for (lcid = DCCH; lcid < MAX_NUM_LCID; lcid++) {
-	if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]) {
-	    lcgid = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid];
-
-	    // Store already available data to transmit per Group
-	    if (lcgid < MAX_NUM_LCGID) {
-		lcgid_buffer_remain[lcgid] +=
-		    UE_mac_inst[module_idP].
-		    scheduling_info.LCID_buffer_remain[lcid];
-	    }
-
-	    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti, eNB_index, frameP, subframeP, ENB_FLAG_NO, MBMS_FLAG_NO, lcid, 0xFFFF);	//TBS is not used in RLC at this step, set a special value for debug
-
-	    lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer;
-
-	    if (rlc_status.bytes_in_buffer > 0) {
-		LOG_D(MAC,
-		      "[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d subframe %d\n",
-		      module_idP, lcid, lcgid, rlc_status.bytes_in_buffer,
-		      frameP, subframeP);
-
-		UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] =
-		    LCID_NOT_EMPTY;
-		//Update BSR_bytes and position in lcid_reordered_array only if Group is defined
-		if (lcgid < MAX_NUM_LCGID) {
-		    num_lcid_with_data++;
-		    // sum lcid buffer which has same lcgid
-		    UE_mac_inst[module_idP].scheduling_info.
-			BSR_bytes[lcgid] += rlc_status.bytes_in_buffer;
-
-		    //Fill in the array
-		    array_index = 0;
-		    do {
-			if (UE_mac_inst[module_idP].logicalChannelConfig
-			    [lcid]->ul_SpecificParameters->priority <=
-			    highest_priority) {
-			    //Insert if priority is higher or equal (lower or equal in value)
-			    for (pos_next = num_lcid_with_data - 1;
-				 pos_next > array_index; pos_next--) {
-				lcid_reordered_array[pos_next] =
-				    lcid_reordered_array[pos_next - 1];
-
-			    }
-			    lcid_reordered_array[array_index] = lcid;
-			    break;
-
-			}
-			array_index++;
-		    }
-		    while ((array_index < num_lcid_with_data)
-			   && (array_index < MAX_NUM_LCID));
-		}
+  mac_rlc_status_resp_t rlc_status;
+  boolean_t bsr_regular_triggered = FALSE;
+  uint8_t lcid;
+  uint8_t lcgid;
+  uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined
+  uint16_t lcgid_buffer_remain[MAX_NUM_LCGID] = {0,0,0,0};
+  int32_t lcid_bytes_in_buffer[MAX_NUM_LCID];
+  /* Array for ordering LCID with data per decreasing priority order */
+  uint8_t lcid_reordered_array[MAX_NUM_LCID]=
+  {MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID};
+  uint8_t pos_next = 0;
+  uint8_t highest_priority = 16;
+  uint8_t array_index = 0;
+
+  // Reset All BSR Infos
+  lcid_bytes_in_buffer[0] = 0;
+  for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++)
+  {
+	  // Reset transmission status
+	  lcid_bytes_in_buffer[lcid] = 0;
+	  UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid]=LCID_EMPTY;
+  }
+
+  for (lcgid=0; lcgid < MAX_NUM_LCGID; lcgid++)
+  {
+	  // Reset Buffer Info
+	  UE_mac_inst[module_idP].scheduling_info.BSR[lcgid]=0;
+	  UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid]=0;
+  }
+
+  //Get Buffer Occupancy and fill lcid_reordered_array
+  for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++)
+  {
+	  if (UE_mac_inst[module_idP].logicalChannelConfig[lcid])
+	  {
+		  	lcgid = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid];
+
+		  	// Store already available data to transmit per Group
+		  	if (lcgid < MAX_NUM_LCGID)
+		  	{
+			  	lcgid_buffer_remain[lcgid] += UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid];
+		  	}
+
+		    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
+		                                    lcid,
+		                                    0xFFFF //TBS is not used in RLC at this step, set a special value for debug
+#ifdef Rel14
+                                          ,0, 0
+#endif
+                                          );
+
+		    lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer;
+
+		    if (rlc_status.bytes_in_buffer > 0)
+		    {
+		          LOG_D(MAC,"[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d subframe %d\n",
+		                              module_idP, lcid,lcgid,rlc_status.bytes_in_buffer,frameP,subframeP);
+
+		         UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_NOT_EMPTY;
+		         //Update BSR_bytes and position in lcid_reordered_array only if Group is defined
+		         if (lcgid < MAX_NUM_LCGID)
+		         {
+		        	 num_lcid_with_data ++;
+			         // sum lcid buffer which has same lcgid
+			         UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] += rlc_status.bytes_in_buffer;
+
+			         //Fill in the array
+			         array_index = 0;
+			         do
+					{
+			        	 if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority)
+			        	 {
+			        		 //Insert if priority is higher or equal (lower or equal in value)
+			        		 for (pos_next=num_lcid_with_data-1; pos_next > array_index; pos_next--)
+			        		 {
+			        			 lcid_reordered_array[pos_next] = lcid_reordered_array[pos_next - 1];
+
+			        		 }
+			        		 lcid_reordered_array[array_index] = lcid;
+			        		 break;
+
+			        	 }
+			        	 array_index ++;
+					}
+			         while ((array_index < num_lcid_with_data) && (array_index < MAX_NUM_LCID));
+		         }
 	    }
 	}
 
@@ -3037,3 +3195,164 @@ int get_db_dl_PathlossChange(uint8_t dl_PathlossChange)
 	break;
     }
 }
+
+
+SLSS_t *ue_get_slss(module_id_t Mod_id,int CC_id,frame_t frame_tx,sub_frame_t subframe_tx) {
+
+  return((SLSS_t*)NULL);
+}
+
+SLDCH_t *ue_get_sldch(module_id_t Mod_id,int CC_id,frame_t frame_tx,sub_frame_t subframe_tx) {
+
+    //UE_MAC_INST *ue = &UE_mac_inst[Mod_id];
+    SLDCH_t *sldch = &UE_mac_inst[Mod_id].sldch;
+    // Panos: Ask TTN if we should be calling mac_rrc_data_req_ue() instead of mac_rrc_data_req() now!
+    /*sldch->payload_length = mac_rrc_data_req(Mod_id,
+            CC_id,
+            frame_tx,
+            SL_DISCOVERY,
+            1,
+            (char*)(sldch->payload), //&UE_mac_inst[Mod_id].SL_Discovery[0].Tx_buffer.Payload[0],
+            0,
+            0, //eNB_indexP
+            0);*/
+
+    sldch->payload_length = mac_rrc_data_req_ue(Mod_id,
+                CC_id,
+                frame_tx,
+                SL_DISCOVERY,
+                1,
+                (uint8_t*)(sldch->payload), //&UE_mac_inst[Mod_id].SL_Discovery[0].Tx_buffer.Payload[0],
+                0, //eNB_indexP
+                0);
+
+
+
+   if (sldch->payload_length >0 ) {
+     LOG_I(MAC,"Got %d bytes from RRC for SLDCH @ %p\n",sldch->payload_length,sldch);
+     return (sldch);
+   }
+   else
+
+   return((SLDCH_t*)NULL);
+}
+
+
+SLSCH_t *ue_get_slsch(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframeP) {
+
+   mac_rlc_status_resp_t rlc_status; //, rlc_status_data;
+   uint32_t absSF = (frameP*10)+subframeP;
+   UE_MAC_INST *ue = &UE_mac_inst[module_idP];
+   int rvtab[4] = {0,2,3,1};
+   int sdu_length;
+   //uint8_t sl_lcids[2] = {3, 10}; //list of lcids for SL - hardcoded
+   int i = 0;
+
+   // Note: this is hard-coded for now for the default SL configuration (4 SF PSCCH, 36 SF PSSCH)
+   SLSCH_t *slsch = &UE_mac_inst[module_idP].slsch;
+
+   LOG_D(MAC,"Checking SLSCH for absSF %d\n",absSF);
+   if ((absSF%40) == 0) { // fill PSCCH data later in first subframe of SL period
+      ue->sltx_active = 0;
+
+      for (i = 0; i < MAX_NUM_LCID; i++){
+         if (ue->SL_LCID[i] > 0) {
+            for (int j = 0; j < ue->numCommFlows; j++){
+               if ((ue->sourceL2Id > 0) && (ue->destinationList[j] >0) ){
+                  rlc_status = mac_rlc_status_ind(module_idP, 0x1234,0,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
+                        ue->SL_LCID[i], 0xFFFF, ue->sourceL2Id, ue->destinationList[j]);
+                  if (rlc_status.bytes_in_buffer > 2){
+                     LOG_I(MAC,"SFN.SF %d.%d: Scheduling for %d bytes in Sidelink buffer\n",frameP,subframeP,rlc_status.bytes_in_buffer);
+                     // Fill in group id for off-network communications
+                     ue->sltx_active = 1;
+                     //store LCID, destinationL2Id
+                     ue->slsch_lcid =  ue->SL_LCID[i];
+                     ue->destinationL2Id = ue->destinationList[j];
+                     break;
+                  }
+               }
+            }
+         }
+         if ( ue->sltx_active == 1) break;
+      }
+   } // we're not in the SCCH period
+   else if (((absSF & 3) == 0 ) &&
+         (ue->sltx_active == 1)) { // every 4th subframe, check for new data from RLC
+      // 10 PRBs, mcs 19
+      int TBS = 4584/8;
+      int req;
+
+
+      if (TBS <= rlc_status.bytes_in_buffer) req = TBS;
+      else req = rlc_status.bytes_in_buffer;
+
+      if (req>0) {
+         sdu_length = mac_rlc_data_req(module_idP,
+               0x1234,
+               0,
+               frameP,
+               ENB_FLAG_NO,
+               MBMS_FLAG_NO,
+               ue->slsch_lcid,
+               req,
+               (char*)(ue->slsch_pdu.payload + sizeof(SLSCH_SUBHEADER_24_Bit_DST_LONG))
+#ifdef Rel14
+               ,ue->sourceL2Id,
+               ue->destinationL2Id
+#endif
+         );
+
+         // Notes: 1. hard-coded to 24-bit destination format for now
+         if (sdu_length > 0) {
+
+            LOG_I(MAC,"SFN.SF %d.%d : got %d bytes from Sidelink buffer (%d requested)\n",frameP,subframeP,sdu_length,req);
+            LOG_I(MAC,"sourceL2Id: 0x%08x \n",ue->sourceL2Id);
+            LOG_I(MAC,"groupL2Id/destinationL2Id: 0x%08x \n",ue->destinationL2Id);
+
+            slsch->payload = (unsigned char*)ue->slsch_pdu.payload;
+            if (sdu_length < 128) {
+               slsch->payload++;
+               SLSCH_SUBHEADER_24_Bit_DST_SHORT *shorth= (SLSCH_SUBHEADER_24_Bit_DST_SHORT *)slsch->payload;
+               shorth->F = 0;
+               shorth->L = sdu_length;
+               shorth->E = 0;
+               shorth->LCID = ue->slsch_lcid;
+               shorth->SRC07 = (ue->sourceL2Id>>16) & 0x000000ff;
+               shorth->SRC815 = (ue->sourceL2Id>>8) & 0x000000ff;
+               shorth->SRC1623 = ue->sourceL2Id & 0x000000ff;
+               shorth->DST07 = (ue->destinationL2Id >>16) & 0x000000ff;
+               shorth->DST815 = (ue->destinationL2Id >>8) & 0x000000ff;
+               shorth->DST1623 = ue->destinationL2Id & 0x000000ff;
+               shorth->V = 0x1;
+            }
+            else {
+               SLSCH_SUBHEADER_24_Bit_DST_LONG *longh= (SLSCH_SUBHEADER_24_Bit_DST_LONG *)slsch->payload;
+               longh->F = 1;
+               longh->L_LSB = sdu_length&0xff;
+               longh->L_MSB = (sdu_length>>8)&0x7f;
+               longh->E = 0;
+               longh->LCID = ue->slsch_lcid;
+               longh->SRC07 = (ue->sourceL2Id >>16) & 0x000000ff;
+               longh->SRC815 = (ue->sourceL2Id>>8) & 0x000000ff;
+               longh->SRC1623 = ue->sourceL2Id & 0x000000ff;
+               longh->DST07 = (ue->destinationL2Id >>16) & 0x000000ff;
+               longh->DST815 = (ue->destinationL2Id>>8) & 0x000000ff;
+               longh->DST1623 = ue->destinationL2Id & 0x000000ff;
+               longh->V = 0x1;
+            }
+            slsch->rvidx = 0;
+            slsch->payload_length = TBS;
+            // fill in SLSCH configuration
+            return(&ue->slsch);
+         }
+         else ue->sltx_active = 0;
+      }
+
+   } else if ((absSF%40)>3 && ue->sltx_active == 1) { // handle retransmission of SDU
+      LOG_I(MAC,"SFN.SF %d.%d : retransmission\n",frameP,subframeP);
+      slsch->rvidx = rvtab[absSF&3];
+      return(&ue->slsch);
+   }
+
+  return(NULL);
+}
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index bd95808bc32a9d3b40be9afc97a92b14fc656f25..f2976ea8641987090da00aafcb67e2bbdd11e550 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -83,6 +83,10 @@ boolean_t pdcp_data_req(
   const sdu_size_t     sdu_buffer_sizeP,
   unsigned char *const sdu_buffer_pP,
   const pdcp_transmission_mode_t modeP
+#ifdef Rel14
+    ,const uint32_t * const sourceL2Id
+    ,const uint32_t * const destinationL2Id
+#endif
 )
 //-----------------------------------------------------------------------------
 {
@@ -165,7 +169,11 @@ boolean_t pdcp_data_req(
                                 (unsigned char*)&pdcp_pdu_p->data[0],
                                 sdu_buffer_sizeP);
 #endif
-      rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_YES, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p);
+      rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_YES, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p
+#ifdef Rel14
+                                ,NULL, NULL
+#endif
+                                );
     } else {
       rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
       LOG_W(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
@@ -351,7 +359,12 @@ boolean_t pdcp_data_req(
 
     LOG_F(PDCP,"\n");
 #endif
-    rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
+    rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p
+#ifdef Rel14
+                             ,sourceL2Id
+                             ,destinationL2Id
+#endif
+                             );
 
   }
 
@@ -780,6 +793,8 @@ pdcp_data_ind(
       } else {
         ((pdcp_data_ind_header_t*) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * maxDRB);
       }
+      ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = ctxt_pP->module_id;
+
 #ifdef DEBUG_PDCP_FIFO_FLUSH_SDU
       static uint32_t pdcp_inst = 0;
       ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = pdcp_inst++;
@@ -914,6 +929,7 @@ pdcp_run (
   protocol_ctxt_t  ctxt;
 #endif
 
+
   
   if (ctxt_pP->enb_flag) {
     start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run);
@@ -965,7 +981,11 @@ pdcp_run (
                                 RRC_DCCH_DATA_REQ (msg_p).confirmp,
                                 RRC_DCCH_DATA_REQ (msg_p).sdu_size,
                                 RRC_DCCH_DATA_REQ (msg_p).sdu_p,
-                                RRC_DCCH_DATA_REQ (msg_p).mode);
+                                RRC_DCCH_DATA_REQ (msg_p).mode
+#ifdef Rel14
+                                , NULL, NULL
+#endif
+                                );
         if (result != TRUE)
           LOG_E(PDCP, "PDCP data request failed!\n");
 
@@ -1794,6 +1814,7 @@ rrc_pdcp_config_req (
 
     if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
       pdcp_p->is_ue = TRUE;
+      pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
     } else {
       pdcp_p->is_ue = FALSE;
     }
@@ -1812,9 +1833,9 @@ rrc_pdcp_config_req (
     }
 
     pdcp_p->first_missing_pdu = -1;
-      LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %d (already added) configured\n",
-            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
-            rb_idP);
+    LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %d (already added) configured\n",
+	  PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
+	  rb_idP);
     break;
 
   case CONFIG_ACTION_MODIFY:
@@ -1871,10 +1892,10 @@ rrc_pdcp_config_req (
 
         if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
           pdcp_p->is_ue = TRUE;
-
+	  pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
         } else {
           pdcp_p->is_ue = FALSE;
-}
+	}
 
         pdcp_p->next_pdcp_tx_sn = 0;
         pdcp_p->next_pdcp_rx_sn = 0;
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
index 7c8f2dd033571f3faac8d484ea99be494b020a81..54ae67fd4e13ba833c7d2a55d31b2e44151bd5f3 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
@@ -259,7 +259,12 @@ public_pdcp(boolean_t pdcp_data_req(
               const confirm_t confirmP, \
               const sdu_size_t sdu_buffer_size,
               unsigned char* const sdu_buffer,
-              const pdcp_transmission_mode_t mode));
+              const pdcp_transmission_mode_t mode
+#ifdef Rel14
+              ,const uint32_t * const sourceL2Id
+              ,const uint32_t * const destinationL2Id
+#endif
+              ));
 
 /*! \fn boolean_t pdcp_data_ind(const protocol_ctxt_t* const, srb_flag_t, MBMS_flag_t, rb_id_t, sdu_size_t, mem_block_t*, boolean_t)
 * \brief This functions handles data transfer indications coming from RLC
@@ -432,6 +437,10 @@ typedef struct pdcp_data_req_header_s {
   sdu_size_t          data_size;
   signed int          inst;
   ip_traffic_type_t   traffic_type;
+#ifdef Rel14
+  uint32_t sourceL2Id;
+  uint32_t destinationL2Id;
+#endif
 } pdcp_data_req_header_t;
 
 typedef struct pdcp_data_ind_header_s {
@@ -439,6 +448,10 @@ typedef struct pdcp_data_ind_header_s {
   sdu_size_t          data_size;
   signed int          inst;
   ip_traffic_type_t   dummy_traffic_type;
+#ifdef Rel14
+  uint32_t sourceL2Id;
+  uint32_t destinationL2Id;
+#endif
 } pdcp_data_ind_header_t;
 
 struct pdcp_netlink_element_s {
@@ -448,6 +461,43 @@ struct pdcp_netlink_element_s {
   uint8_t *data;
 };
 
+//TTN for D2D (PC5S)
+#ifdef Rel14
+#define PDCP_SOCKET_PORT_NO 9999 //temporary value
+#define PC5_SIGNALLING_PAYLOAD_SIZE   100  //should be updated with a correct value
+int pdcp_pc5_sockfd;
+struct sockaddr_in prose_ctrl_addr;
+struct sockaddr_in prose_pdcp_addr;
+struct sockaddr_in pdcp_sin;
+void pdcp_pc5_socket_init(void);
+
+typedef struct  {
+   rb_id_t             rb_id;
+   sdu_size_t          data_size;
+   signed int          inst;
+   ip_traffic_type_t   traffic_type;
+   uint32_t sourceL2Id;
+   uint32_t destinationL2Id;
+} __attribute__((__packed__)) pc5s_header_t;
+
+//new PC5S-message
+typedef struct  {
+   unsigned char bytes[PC5_SIGNALLING_PAYLOAD_SIZE];
+}  __attribute__((__packed__)) PC5SignallingMessage ;
+
+//example of PC5-S messages
+typedef struct {
+   pc5s_header_t pc5s_header;
+   union {
+      uint8_t status;
+      PC5SignallingMessage pc5_signalling_message;
+   } pc5sPrimitive;
+} __attribute__((__packed__)) sidelink_pc5s_element;
+
+
+#endif
+
+
 #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 50663cdc4fc8da1ade52b30871b7decc2581ad6f..ee044bc850d22ff3dfef617fab6f5060b23649d7 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
@@ -58,6 +58,7 @@ extern int otg_enabled;
 #include "UTIL/LOG/vcd_signal_dumper.h"
 #include "platform_constants.h"
 #include "msc.h"
+#include "pdcp.h"
 
 #include "assertions.h"
 
@@ -112,129 +113,163 @@ pdcp_data_req_header_t pdcp_read_header_g;
 //-----------------------------------------------------------------------------
 int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const  ctxt_pP)
 {
-  //-----------------------------------------------------------------------------
+   //-----------------------------------------------------------------------------
 
-//#if defined(PDCP_USE_NETLINK) && defined(LINUX)
-  int ret = 0;
-//#endif
+   //#if defined(PDCP_USE_NETLINK) && defined(LINUX)
+   int ret = 0;
+   //#endif
 
 #ifdef DEBUG_PDCP_FIFO_FLUSH_SDU
 #define THREAD_NAME_LEN 16
-  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");
-  }
+   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");
+   }
 #undef THREAD_NAME_LEN
 #endif
 
 #ifdef PDCP_SDU_FLUSH_LOCK
-  ret = pthread_mutex_trylock(&mtex);
-  if (ret == EBUSY) {
+   ret = pthread_mutex_trylock(&mtex);
+   if (ret == EBUSY) {
 #ifdef DEBUG_PDCP_FIFO_FLUSH_SDU
-    LOG_W(PDCP, "[%s] at SFN/SF=%d/%d wait for PDCP FIFO to be unlocked\n",
-        threadname, ctxt_pP->frame, ctxt_pP->subframe);
+      LOG_W(PDCP, "[%s] at SFN/SF=%d/%d wait for PDCP FIFO to be unlocked\n",
+            threadname, ctxt_pP->frame, ctxt_pP->subframe);
 #endif
-    if (pthread_mutex_lock(&mtex)) {
-      exit_fun("PDCP_SDU_FLUSH_LOCK lock error!");
-    }
+      if (pthread_mutex_lock(&mtex)) {
+         exit_fun("PDCP_SDU_FLUSH_LOCK lock error!");
+      }
 #ifdef DEBUG_PDCP_FIFO_FLUSH_SDU
-    LOG_I(PDCP, "[%s] at SFN/SF=%d/%d PDCP FIFO is unlocked\n",
-        threadname, ctxt_pP->frame, ctxt_pP->subframe);
+      LOG_I(PDCP, "[%s] at SFN/SF=%d/%d PDCP FIFO is unlocked\n",
+            threadname, ctxt_pP->frame, ctxt_pP->subframe);
 #endif
-  } else if (ret != 0) {
-    exit_fun("PDCP_SDU_FLUSH_LOCK trylock error!");
-  }
+   } else if (ret != 0) {
+      exit_fun("PDCP_SDU_FLUSH_LOCK trylock error!");
+   }
 
 #endif
 
-  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;
+   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;
 #if defined(LINK_ENB_PDCP_TO_GTPV1U)
-  //MessageDef      *message_p        = NULL;
+   //MessageDef      *message_p        = NULL;
 #endif
 
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH, 1 );
-  while (sdu_p && cont) {
+   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH, 1 );
+   while (sdu_p && cont) {
 
 #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);
+      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);
+#else
+      ((pdcp_data_ind_header_t *)(sdu_p->data))->inst = 0;
 #endif
 
 #if defined(LINK_ENB_PDCP_TO_GTPV1U)
 
-    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
-    }
+      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
+      }
 
 #endif /* defined(ENABLE_USE_MME) */
 #ifdef PDCP_DEBUG
-    LOG_D(PDCP, "PDCP->IP TTI %d INST %d: Preparing %d Bytes of data from rab %d to Nas_mesh\n",
-          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);
+      LOG_D(PDCP, "PDCP->IP TTI %d INST %d: Preparing %d Bytes of data from rab %d to Nas_mesh\n",
+            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);
 #endif //PDCP_DEBUG
-    cont = 0;
+      cont = 0;
+
+//TTN - for D2D (PC5S)
+#ifdef Rel14
+      sidelink_pc5s_element *sl_pc5s_msg_recv = NULL;
+      char send_buf[BUFSIZE];
+      int rb_id = ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id;
 
-    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);
+      if (rb_id == 10) { //hardcoded for PC5-Signaling
+      //if ((rb_id == 28) | (rb_id == 29) | (rb_id == 30))
+
+#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));
+         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);
+         free(sl_pc5s_msg_recv);
+#endif
+         memset(send_buf, 0, BUFSIZE);
+         memcpy((void *)send_buf, (void*)(sdu_p->data+sizeof(pdcp_data_ind_header_t)), sizeof(sidelink_pc5s_element));
+
+         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);
+         if (n < 0) {
+            LOG_E(PDCP, "ERROR: Failed to send to ProSe App\n");
+            exit(EXIT_FAILURE);
+         }
       }
+#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);
+         }
 
 #ifdef PDCP_USE_RT_FIFO
-      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);
+         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);
 
 #else
 #ifdef PDCP_USE_NETLINK
 #ifdef LINUX
-      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;
+         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;
 #endif //LINUX
 #endif //PDCP_USE_NETLINK
 
-      bytes_wrote = pdcp_output_header_bytes_to_write;
+         bytes_wrote = pdcp_output_header_bytes_to_write;
 #endif //PDCP_USE_RT_FIFO
 
 #ifdef PDCP_DEBUG
-      LOG_D(PDCP, "Frame %d Sent %d Bytes of header to Nas_mesh\n",
-            ctxt_pP->frame,
-            bytes_wrote);
+         LOG_D(PDCP, "Frame %d Sent %d Bytes of header to Nas_mesh\n",
+               ctxt_pP->frame,
+               bytes_wrote);
 #endif //PDCP_DEBUG
 
-      if (bytes_wrote > 0) {
-        pdcp_output_header_bytes_to_write = pdcp_output_header_bytes_to_write - bytes_wrote;
+         if (bytes_wrote > 0) {
+            pdcp_output_header_bytes_to_write = pdcp_output_header_bytes_to_write - bytes_wrote;
 
-        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!");
+            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!");
 
 #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);
+               bytes_wrote = rtf_put (PDCP2PDCP_USE_RT_FIFO, &(sdu->data[sizeof (pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
 #else
 
 #ifdef PDCP_USE_NETLINK
@@ -278,103 +313,104 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const  ctxt_pP)
 
 #endif // LINUX
 #endif //PDCP_USE_NETLINK
-          bytes_wrote= pdcp_output_sdu_bytes_to_write;
+               bytes_wrote= pdcp_output_sdu_bytes_to_write;
 #endif // PDCP_USE_RT_FIFO
 
 #ifdef PDCP_DEBUG
-          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);
+               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);
 #endif //PDCP_DEBUG
 
-          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);
+               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");
+               }
             } 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!");
+               LOG_W(PDCP, "3: RADIO->IP SEND SDU CONGESTION!\n");
             }
-          } else {
-            LOG_W(PDCP, "2: RADIO->IP SEND SDU CONGESTION!\n");
-          }
-        } else {
-          LOG_W(PDCP, "3: RADIO->IP SEND SDU CONGESTION!\n");
-        }
+         } else {
+            LOG_D(PDCP, "4 skip free_mem_block: bytes_wrote = %d\n", bytes_wrote);
+         }
       } else {
-        LOG_D(PDCP, "4 skip free_mem_block: bytes_wrote = %d\n", bytes_wrote);
-      }
-    } else {
-      // continue writing sdu
+         // continue writing sdu
 #ifdef PDCP_USE_RT_FIFO
-      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);
+         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);
 #else  // PDCP_USE_RT_FIFO
-      bytes_wrote = pdcp_output_sdu_bytes_to_write;
+         bytes_wrote = pdcp_output_sdu_bytes_to_write;
 #endif  // PDCP_USE_RT_FIFO
+         LOG_D(PDCP, "THINH 2 bytes_wrote = %d\n", bytes_wrote);
 
-      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);
+         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);
+         }
       }
-    }
-  }
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH, 0 );
+   }
+   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH, 0 );
 
 #ifdef PDCP_USE_RT_FIFO
 
-  if ((pdcp_nb_sdu_sent)) {
-    if ((pdcp_2_nas_irq > 0)) {
+   if ((pdcp_nb_sdu_sent)) {
+      if ((pdcp_2_nas_irq > 0)) {
 #ifdef PDCP_DEBUG
-      LOG_D(PDCP, "Frame %d : Trigger NAS RX interrupt\n",
-            ctxt_pP->frame);
+         LOG_D(PDCP, "Frame %d : Trigger NAS RX interrupt\n",
+               ctxt_pP->frame);
 #endif //PDCP_DEBUG
-      rt_pend_linux_srq (pdcp_2_nas_irq);
+         rt_pend_linux_srq (pdcp_2_nas_irq);
 
-    } 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);
-    }
-  }
+      } 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);
+      }
+   }
 
 #endif  //PDCP_USE_RT_FIFO
 
 #ifdef PDCP_SDU_FLUSH_LOCK
-  if (pthread_mutex_unlock(&mtex)) exit_fun("PDCP_SDU_FLUSH_LOCK unlock error!");
+   if (pthread_mutex_unlock(&mtex)) exit_fun("PDCP_SDU_FLUSH_LOCK unlock error!");
 #endif
 
-  return pdcp_nb_sdu_sent;
+   return pdcp_nb_sdu_sent;
 }
 
 //-----------------------------------------------------------------------------
@@ -437,185 +473,452 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
 #else /* UE_NAS_USE_TUN */
 
 #ifdef PDCP_USE_NETLINK
-  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;
-# 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);
+   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];
+   // Panos: Remove the following definitions due to warnings of unused variables.
+   //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;
+   pc5s_header_t *pc5s_header;
+#endif
 
-    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;
-    }
+# 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;
+      }
 
-    CHECK_CTXT_ARGS(&ctxt_cpy);
+      CHECK_CTXT_ARGS(&ctxt_cpy);
 
-    AssertFatal (rab_id    < maxDRB,                       "RB id is too high (%u/%d)!\n", rab_id, maxDRB);
+      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 "
-            "/ %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);
+      if (rab_id != 0) {
+         LOG_D(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);
 #ifdef  OAI_NW_DRIVER_TYPE_ETHERNET
 
-      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 */ ) {
+         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 */ ) {
 #if defined(Rel10) || defined(Rel14)
-          PDCP_TRANSMISSION_MODE_TRANSPARENT;
+            PDCP_TRANSMISSION_MODE_TRANSPARENT;
 #else
-          pdcp_mode= PDCP_TRANSMISSION_MODE_DATA;
+            pdcp_mode= PDCP_TRANSMISSION_MODE_DATA;
 #endif
-      } 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");
-        }
+         } 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");
+         }
 
 #else // OAI_NW_DRIVER_TYPE_ETHERNET NASMESH driver does not curreenlty support multicast traffic
-        pdcp_mode = PDCP_TRANSMISSION_MODE_DATA;
-#endif
-      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,
-                      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++) {
-        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,
-            PDCP_TRANSMISSION_MODE_DATA);
-        }
+         pdcp_mode = PDCP_TRANSMISSION_MODE_DATA;
+#endif
+         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,
+               pdcp_mode
+#ifdef Rel14
+               ,NULL, NULL
+#endif
+               );
+      } 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,
+                     PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+                     ,NULL, NULL
+#endif
+                     );
+            }
+         }
+      } 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,
+               PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+               ,NULL, NULL
+#endif
+               );
       }
-    } 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,
-        PDCP_TRANSMISSION_MODE_DATA);
-    }
 
-    free(data_p->data);
-    free(data_p);
-    data_p = NULL;
-  }
+      free(data_p->data);
+      free(data_p);
+      data_p = NULL;
+   }
 
-  return 0;
+   return 0;
 # else /* PDCP_USE_NETLINK_QUEUES*/
-  int              len = 1;
-  int  msg_len;
-  rb_id_t          rab_id  = 0;
-  int rlc_data_req_flag = 3;
- 
-  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 );
+   int              len = 1;
+   int  msg_len;
+   rb_id_t          rab_id  = 0;
+   int rlc_data_req_flag = 3;
+
+
+//TTN for D2D (PC5S)
+#ifdef Rel14
+   prose_addr_len = sizeof(prose_pdcp_addr);
+   // receive a message from ProSe App
+   memset(receive_buf, 0, BUFSIZE);
+   bytes_received = recvfrom(pdcp_pc5_sockfd, receive_buf, BUFSIZE, 0,
+         (struct sockaddr *) &prose_pdcp_addr, (socklen_t *)&prose_addr_len);
+   //  if (bytes_received < 0){
+   //    LOG_E(RRC, "ERROR: Failed to receive from ProSe App\n");
+   //    exit(EXIT_FAILURE);
+   // }
+   if (bytes_received > 0) {
+      pc5s_header = calloc(1, sizeof(pc5s_header_t));
+      memcpy((void *)pc5s_header, (void *)receive_buf, sizeof(pc5s_header_t));
+
+      if (pc5s_header->traffic_type == TRAFFIC_PC5S_SESSION_INIT){
+         //send reply to ProSe app
+         LOG_D(PDCP,"Received a request to open PDCP socket and establish a new PDCP session ... send response to ProSe App \n");
+         memset(send_buf, 0, BUFSIZE);
+         sl_pc5s_msg_send = calloc(1, sizeof(sidelink_pc5s_element));
+         sl_pc5s_msg_send->pc5s_header.traffic_type = TRAFFIC_PC5S_SESSION_INIT;
+         sl_pc5s_msg_send->pc5sPrimitive.status = 1;
+
+         memcpy((void *)send_buf, (void *)sl_pc5s_msg_send, sizeof(sidelink_pc5s_element));
+         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);
+         if (bytes_sent < 0) {
+            LOG_E(PDCP, "ERROR: Failed to send to ProSe App\n");
+            exit(EXIT_FAILURE);
+         }
+      } else if (pc5s_header->traffic_type == TRAFFIC_PC5S_SIGNALLING) { //if containing PC5-S message -> send to other UE
+         LOG_D(PDCP,"Received PC5-S message ... send to the other UE\n");
+#ifdef PDCP_DEBUG
+         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);
 
-    if (len<=0) {
-      // nothing in pdcp NAS socket
-      //LOG_D(PDCP, "[PDCP][NETLINK] Nothing in socket, length %d \n", len);
-    } 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));
-            LOG_D(PDCP, "[PDCP][NETLINK] RX pdcp_data_req_header_t inst %u, rb_id %u data_size %d\n",
-                  pdcp_read_header_g.inst, pdcp_read_header_g.rb_id, pdcp_read_header_g.data_size);
-          } 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()
+#endif
+
+#ifdef OAI_EMU
+
+         // overwrite function input parameters, because only one netlink socket for all instances
+         if (pc5s_header->inst < oai_emulation.info.nb_enb_local) {
+            ctxt.frame         = ctxt_cpy.frame;
+            ctxt.enb_flag      = ENB_FLAG_YES;
+            ctxt.module_id     = pc5s_header.inst  +  oai_emulation.info.first_enb_local;
+            ctxt.rnti          = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id ][pc5s_header->rb_id / maxDRB + oai_emulation.info.first_ue_local];
+            rab_id    = pc5s_header->rb_id % maxDRB;
+         } else {
+            ctxt.frame         = ctxt_cpy.frame;
+            ctxt.enb_flag      = ENB_FLAG_NO;
+            ctxt.module_id     = pc5s_header->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];
+            rab_id    = pc5s_header->rb_id % maxDRB;
+         }
+
+         CHECK_CTXT_ARGS(&ctxt);
+         AssertFatal (rab_id    < maxDRB,                       "RB id is too high (%u/%d)!\n", rab_id, maxDRB);
+         /*LGpdcp_read_header.inst = (pc5s_header.inst >= oai_emulation.info.nb_enb_local) ? \
+                  pc5s_header.inst - oai_emulation.info.nb_enb_local+ NB_eNB_INST + oai_emulation.info.first_ue_local :
+                  pc5s_header.inst +  oai_emulation.info.first_enb_local;*/
+#else // OAI_EMU
+         /* TODO: do we have to reset to 0 or not? not for a scenario with 1 UE at least */
+         //          pc5s_header.inst = 0;
+         //#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id"
+         ctxt.frame         = ctxt_cpy.frame;
+         ctxt.enb_flag      = ctxt_cpy.enb_flag;
+
+         LOG_I(PDCP, "[PDCP] pc5s_header->rb_id = %d\n", pc5s_header->rb_id);
+
+         if (ctxt_cpy.enb_flag) {
+            ctxt.module_id = 0;
+            rab_id      = pc5s_header->rb_id % maxDRB;
+            ctxt.rnti          = pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index];
+         } else {
+            ctxt.module_id = 0;
+            rab_id      = pc5s_header->rb_id % maxDRB;
+            ctxt.rnti          = pdcp_UE_UE_module_id_to_rnti[ctxt.module_id];
+         }
+#endif
+
+         //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",
+                        (uint8_t)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",
+                		  (uint8_t)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_D(PDCP, "[PDCP][NETLINK] Something in socket, length %zu\n",
-                nas_nlh_rx->nlmsg_len - sizeof(struct nlmsghdr));
+                  LOG_I(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d  on Rab %d \n",
+                        ctxt.frame,
+                        pc5s_header->inst,
+                        bytes_received,
+                        pc5s_header->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,
+                        pc5s_header->inst,
+                        pc5s_header->rb_id,
+                        pc5s_header->data_size,
+                        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),
+                                    pc5s_header.inst,
+                                    pc5s_header.rb_id,
+                                    rab_id,
+                                    pc5s_header.data_size);
+
+                  pdcp_data_req(
+                        &ctxt,
+                        SRB_FLAG_NO,
+                        rab_id,
+                        RLC_MUI_UNDEFINED,
+                        RLC_SDU_CONFIRM_NO,
+                        pc5s_header->data_size,
+                        (unsigned char *)receive_buf,
+                        PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+                        ,&pc5s_header->sourceL2Id
+                        ,&pc5s_header->destinationL2Id
+#endif
+                        );
+               } 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),
+                                    pc5s_header.inst,
+                                    pc5s_header.rb_id,
+                                    rab_id,
+                                    pc5s_header.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,
+                        pc5s_header->inst,
+                        pc5s_header->rb_id,
+                        pc5s_header->data_size,
+                        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,
+                     pc5s_header->inst,
+                     pc5s_header->rb_id,
+                     pc5s_header->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),
+                                 pc5s_header->inst,
+                                 pc5s_header->rb_id,
+                                 DEFAULT_RAB_ID,
+                                 pc5s_header->data_size);
+
+               pdcp_data_req (
+                     &ctxt,
+                     SRB_FLAG_NO,
+                     DEFAULT_RAB_ID,
+                     RLC_MUI_UNDEFINED,
+                     RLC_SDU_CONFIRM_NO,
+                     pc5s_header->data_size,
+                     (unsigned char *)receive_buf,
+                     PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+                     ,&pc5s_header->sourceL2Id
+                     ,&pc5s_header->destinationL2Id
 #endif
+                     );
+            }
+         }
+          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
+         //LOG_D(PDCP, "[PDCP][NETLINK] Nothing in socket, length %d \n", len);
+      } else {
 
-          /* 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;
-//#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id"
-          ctxt.frame         = ctxt_cpy.frame;
-          ctxt.enb_flag      = ctxt_cpy.enb_flag;
+         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));
+                  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 );
+               } 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] pdcp_read_header_g.rb_id = %d\n", pdcp_read_header_g.rb_id);
+               LOG_D(PDCP, "[PDCP][NETLINK] Something in socket, length %zu\n",
+                     nas_nlh_rx->nlmsg_len - sizeof(struct nlmsghdr));
 #endif
 
+#ifdef OAI_EMU
+
+
+               // 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;
+                  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];
+                  rab_id    = pdcp_read_header_g.rb_id % maxDRB;
+               } else {
+                  ctxt.frame         = ctxt_cpy.frame;
+                  ctxt.enb_flag      = ENB_FLAG_NO;
+                  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];
+                  rab_id    = pdcp_read_header_g.rb_id % maxDRB;
+               }
+
+               CHECK_CTXT_ARGS(&ctxt);
+               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;*/
+#else // OAI_EMU
+               /* 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;
+               //#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id"
+               ctxt.frame         = ctxt_cpy.frame;
+               ctxt.enb_flag      = ctxt_cpy.enb_flag;
+
+#ifdef PDCP_DEBUG
+               LOG_D(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);
+#endif
           if (ctxt_cpy.enb_flag) {
             ctxt.module_id = 0;
             rab_id      = pdcp_read_header_g.rb_id % maxDRB;
@@ -626,207 +929,233 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
             ctxt.rnti          = pdcp_UE_UE_module_id_to_rnti[ctxt.module_id];
           }
 
+#endif
+
           if (ctxt.enb_flag) {
             if (rab_id != 0) {
               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) {
+
+                     if (h_rc == HASH_TABLE_OK) {
 #ifdef PDCP_DEBUG
-                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);
-#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),
-                  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,
+                        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);
+#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),
+                                          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,
                               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 {
-                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),
-                    PDCP_TRANSMISSION_MODE_DATA);
-                }
-              }
-            }
-          } else { // enb_flag
-            if (rab_id != 0) {
-              if (rab_id == UE_IP_DEFAULT_RAB_ID) {
-                LOG_D(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);
-              } else {
-                rab_id = rab_id % maxDRB;
-                LOG_D(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);
-              }
-
-              if (h_rc == HASH_TABLE_OK) {
-                rab_id = pdcp_p->rb_id;
+                              PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+                              ,NULL, NULL
+#endif
+                              );
+                     } 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),
+                                 PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+                                ,NULL, NULL
+#endif
+                                );
+                        }
+                     }
+                  }
+               } else { // enb_flag
+                  if (rab_id != 0) {
+                     if (rab_id == UE_IP_DEFAULT_RAB_ID) {
+                        LOG_D(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_D(PDCP,"request key %x : (%d,%x,%d,%d)\n",
+                        		(uint8_t)key,ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id);
+                     } else {
+                        rab_id = rab_id % maxDRB;
+                        LOG_D(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_D(PDCP,"request key %x : (%d,%x,%d,%d)\n",
+                        		(uint8_t)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_D(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_D(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);
-#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),
-                  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),
-                  PDCP_TRANSMISSION_MODE_DATA);
-              } 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),
-                PDCP_TRANSMISSION_MODE_DATA);
-            }
-          }
+                        LOG_D(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_D(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);
+#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),
+                                          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),
+                              PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+                              ,&pdcp_read_header_g.sourceL2Id
+                              ,&pdcp_read_header_g.destinationL2Id
+#endif
+                              );
+                     } 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),
+                           PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+                           ,&pdcp_read_header_g.sourceL2Id
+                           ,&pdcp_read_header_g.destinationL2Id
+#endif
+                           );
+                  }
+               }
 
-        }
+            }
+         }
       }
-    }
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ, 0 );
-  }
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ, 0 );
+   }
 
-  return len;
+
+   return len;
 # endif
 #else // neither PDCP_USE_NETLINK nor PDCP_USE_RT_FIFO
-  return 0;
+   return 0;
 #endif // PDCP_USE_NETLINK
 #endif /* #else UE_NAS_USE_TUN */
 }
@@ -840,9 +1169,6 @@ void pdcp_fifo_read_input_sdus_from_otg (const protocol_ctxt_t* const  ctxt_pP)
   // 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
 
-
-
-
     PROTOCOL_CTXT_SET_BY_MODULE_ID(
       &ctxt,
       ctxt_pP->module_id,
@@ -854,7 +1180,44 @@ void pdcp_fifo_read_input_sdus_from_otg (const protocol_ctxt_t* const  ctxt_pP)
 
     for (dst_id = 0; dst_id<NUMBER_OF_UE_MAX; dst_id++) {
       ctxt.rnti = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id][dst_id];
-
     }
   }
 }
+
+//TTN for D2D (PC5S)
+#ifdef Rel14
+
+void
+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
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_proto_extern.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp_proto_extern.h
index afcc2fdd0255dc0f11d15df8e670ee29dec8119f..a939543432674fabc3568ce499ec32095656c675 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_proto_extern.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_proto_extern.h
@@ -52,7 +52,12 @@ extern int  reception_from_rohc_bs(void);
 #else
 extern BOOL     pdcp_data_ind (module_id_t module_idP, rb_id_t rab_idP, sdu_size_t data_sizeP, mem_block_t * sduP, uint8_t is_data_plane);
 extern BOOL     pdcp_data_req (module_id_t module_id, uint32_t frame, uint8_t eNB_flag, rb_id_t rab_id, uint32_t muiP, uint32_t confirmP, sdu_size_t sdu_buffer_size, unsigned char* sdu_buffer,
-                               uint8_t is_data_pdu);
+                               uint8_t is_data_pdu
+#ifdef Rel14
+                               ,const uint32_t * const sourceL2Id
+                               ,const uint32_t * const destinationL2Id
+#endif
+                               );
 //extern BOOL     pdcp_data_req (struct pdcp_entity *pdcpP, mem_block * sduP);
 extern void     send_pdcp_control_primitive (struct pdcp_entity *pdcpP, mem_block * cprimitiveP);
 extern void     control_pdcp (struct pdcp_entity *pdcpP);
@@ -63,4 +68,7 @@ extern void     pdcp_process_input_sdus_tr (struct pdcp_entity *pdcpP);
 extern void     init_pdcp (struct pdcp_entity *pdcpP, struct rb_dispatcher *rbP, uint8_t rb_idP);
 extern void    *pdcp_tx (void *argP);
 #endif
+
+extern void pdcp_pc5_socket_init(void);
+
 #endif
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c
index 4e2723a8f476489bb16fe1eb677f6e0ed4550ab2..895015dc883778e9255638a71981c995602c39c3 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c
@@ -93,7 +93,12 @@ void config_req_rlc_um_asn1 (
   const UL_UM_RLC_t       * const ul_rlc_pP,
   const DL_UM_RLC_t       * const dl_rlc_pP,
   const rb_id_t             rb_idP,
-  const logical_chan_id_t   chan_idP)
+  const logical_chan_id_t   chan_idP
+#ifdef Rel14
+ ,const uint32_t            sourceL2Id
+ ,const uint32_t            destinationL2Id
+#endif
+                          )
 {
   uint32_t         ul_sn_FieldLength   = 0;
   uint32_t         dl_sn_FieldLength   = 0;
@@ -117,10 +122,14 @@ void config_req_rlc_um_asn1 (
                  mbms_service_idP,
                  mbms_session_idP);
     rlc_p = &rlc_union_p->rlc.um;
+  }
+  if ((sourceL2Id >0 ) && (destinationL2Id >0)){
+     key = RLC_COLL_KEY_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, sourceL2Id, destinationL2Id, srb_flagP);
   } else
 #endif
   {
-    key  = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
+     key  = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
+  }
     h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
     AssertFatal (h_rc == HASH_TABLE_OK, "RLC NOT FOUND enb id %u ue id %i enb flag %u rb id %u, srb flag %u",
                  ctxt_pP->module_id,
@@ -129,7 +138,6 @@ void config_req_rlc_um_asn1 (
                  rb_idP,
                  srb_flagP);
     rlc_p = &rlc_union_p->rlc.um;
-  }
 
   //-----------------------------------------------------------------------------
   LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT"  CONFIG_REQ timer_reordering=%dms sn_field_length=   RB %u \n",
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.h
index 5847a8bb13bbe08b445284efaed347331faf8740..fc64e95d995983184a55e99077f0ae474f7890b6 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.h
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.h
@@ -115,7 +115,12 @@ public_rlc_um_control_primitives(   void config_req_rlc_um_asn1 (
                                       const UL_UM_RLC_t       * const ul_rlc_pP,
                                       const DL_UM_RLC_t       * const dl_rlc_pP,
                                       const rb_id_t            rb_idP,
-                                      const logical_chan_id_t  chan_idP);)
+                                      const logical_chan_id_t  chan_idP
+#ifdef Rel14
+                                      ,const uint32_t          sourceL2Id
+                                      ,const uint32_t          destinationL2Id
+#endif
+                                      );)
 
 /*! \fn void rlc_um_init (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
 * \brief    Initialize a RLC UM protocol instance, initialize all variables, lists, allocate buffers for making this instance ready to be configured with protocol configuration parameters. After this initialization the RLC UM protocol instance will be in RLC_NULL_STATE state.
diff --git a/openair2/LAYER2/RLC/rlc.c b/openair2/LAYER2/RLC/rlc.c
index 783441bd586928fb2dfe9dfc61dc1e926ca31ada..637512d54d9605dc7b6fcf5a23f05306b3c1c1af 100644
--- a/openair2/LAYER2/RLC/rlc.c
+++ b/openair2/LAYER2/RLC/rlc.c
@@ -314,7 +314,12 @@ rlc_op_status_t rlc_data_req     (const protocol_ctxt_t* const ctxt_pP,
                                   const mui_t        muiP,
                                   confirm_t    confirmP,
                                   sdu_size_t   sdu_sizeP,
-                                  mem_block_t *sdu_pP)
+                                  mem_block_t *sdu_pP
+#ifdef Rel14
+                                  ,const uint32_t * const sourceL2Id
+                                  ,const uint32_t * const destinationL2Id
+#endif
+                                  )
 {
   //-----------------------------------------------------------------------------
   mem_block_t           *new_sdu_p    = NULL;
@@ -374,6 +379,10 @@ rlc_op_status_t rlc_data_req     (const protocol_ctxt_t* const ctxt_pP,
     }
 
     key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_id_p->service_id, mbms_id_p->session_id);
+  }
+  if (sourceL2Id && destinationL2Id){
+     key = RLC_COLL_KEY_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, *sourceL2Id, *destinationL2Id, srb_flagP);
+     //key_lcid = RLC_COLL_KEY_LCID_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, *sourceL2Id, *destinationL2Id, srb_flagP);
   } else
 #endif
   {
@@ -386,7 +395,7 @@ rlc_op_status_t rlc_data_req     (const protocol_ctxt_t* const ctxt_pP,
     rlc_mode = rlc_union_p->mode;
   } else {
     rlc_mode = RLC_MODE_NONE;
-    AssertFatal (0 , "RLC not configured key %ju\n", key);
+    //AssertFatal (0 , "RLC not configured key %ju\n", key);
   }
 
   if (MBMS_flagP == 0) {
diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h
index ffd963204eeba97839d93bf27cf393dedb9846c5..a804278dc5b1c626ede9055ff67f1a76a3891a38 100644
--- a/openair2/LAYER2/RLC/rlc.h
+++ b/openair2/LAYER2/RLC/rlc.h
@@ -275,6 +275,23 @@ public_rlc(logical_chan_id_t    rlc_mbms_rbid2lcid_eNB[NUMBER_OF_eNB_MAX][NB_RB_
     (((hash_key_t)(iS_sRB)) << 33) | \
     (((hash_key_t)(0x0a))   << 34))
 
+#define RLC_COLL_KEY_SOURCE_DEST_VALUE(eNB_iD, rNTI, iS_eNB, lC_iD, sOURCE_iD, dEST_iD, iS_sRB) \
+   ((hash_key_t)eNB_iD             | \
+    (((hash_key_t)(rNTI))   << 8)  | \
+    (((hash_key_t)(iS_eNB)) << 24) | \
+    (((hash_key_t)(lC_iD))  << 25) | \
+    (((hash_key_t)(dEST_iD)) << 33) | \
+    (((hash_key_t)(0x05))   << 57))
+
+#define RLC_COLL_KEY_LCID_SOURCE_DEST_VALUE(eNB_iD, rNTI, iS_eNB, lC_iD, sOURCE_iD, dEST_iD, iS_sRB) \
+   ((hash_key_t)eNB_iD             | \
+    (((hash_key_t)(rNTI))   << 8)  | \
+    (((hash_key_t)(iS_eNB)) << 24) | \
+    (((hash_key_t)(lC_iD))  << 25) | \
+    (((hash_key_t)(dEST_iD)) << 33) | \
+    (((hash_key_t)(0x0a))   << 57))
+
+
 // service id max val is maxServiceCount = 16 (asn1_constants.h)
 
 #define RLC_COLL_KEY_MBMS_VALUE(eNB_iD, rNTI, iS_eNB, sERVICE_ID, sESSION_ID) \
@@ -324,7 +341,9 @@ public_rlc_rrc( rlc_op_status_t rrc_rlc_config_asn1_req (
                   const SRB_ToAddModList_t* const ,
                   const DRB_ToAddModList_t* const ,
                   const DRB_ToReleaseList_t* const ,
-                  const PMCH_InfoList_r9_t * const pmch_info_listP);)
+                  const PMCH_InfoList_r9_t * const pmch_info_listP ,
+                  const uint32_t ,
+                  const uint32_t );)
 #else
 /*! \fn rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t* const ctxtP, const SRB_ToAddModList_t* const srb2add_listP, const DRB_ToAddModList_t* const drb2add_listP, const DRB_ToReleaseList_t* const drb2release_listP)
 * \brief  Function for RRC to configure a Radio Bearer.
@@ -379,7 +398,12 @@ public_rlc_rrc(rlc_op_status_t rrc_rlc_remove_rlc   (const protocol_ctxt_t* cons
 * \param[in]  rlc_modeP          Mode of RLC (AM, UM, TM).
 * \return     A status about the processing, OK or error code.
 */
-private_rlc_rrc(rlc_union_t*  rrc_rlc_add_rlc      (const protocol_ctxt_t* const, const srb_flag_t,  const  MBMS_flag_t MBMS_flagP, const  rb_id_t, logical_chan_id_t, rlc_mode_t);)
+private_rlc_rrc(rlc_union_t*  rrc_rlc_add_rlc      (const protocol_ctxt_t* const, const srb_flag_t,  const  MBMS_flag_t MBMS_flagP, const  rb_id_t, logical_chan_id_t, rlc_mode_t
+#ifdef Rel14
+  ,const uint32_t  sourceL2Id,
+  const uint32_t  destinationL2Id
+#endif
+);)
 
 /*! \fn rlc_op_status_t rrc_rlc_config_req (
      const protocol_ctxt_t* const ctxtP,
@@ -440,7 +464,12 @@ public_rlc_rrc(void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_d
 * \param [in,out] bufferP          Memory area to fill with the bytes requested by MAC.
 * \return     A status about the processing, OK or error code.
 */
-public_rlc_mac(tbs_size_t            mac_rlc_data_req     (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const  eNB_flag_t, const  MBMS_flag_t, logical_chan_id_t, const tb_size_t,char*);)
+public_rlc_mac(tbs_size_t            mac_rlc_data_req     (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const  eNB_flag_t, const  MBMS_flag_t, logical_chan_id_t, const tb_size_t,char*
+#ifdef Rel14
+                                                           ,const uint32_t sourceL2Id
+                                                           ,const uint32_t destinationL2Id
+#endif
+);)
 
 /*! \fn void mac_rlc_data_ind     (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const  eNB_flag_t eNB_flagP, const  MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP, uint32_t frameP, char* bufferP, tb_size_t tb_sizeP, num_tb_t num_tbP, crc_t *crcs)
 * \brief    Interface with MAC layer, deserialize the transport blocks sent by MAC, then map data indication to the RLC instance corresponding to the radio bearer identifier.
@@ -470,7 +499,12 @@ public_rlc_mac(void                  mac_rlc_data_ind     (const module_id_t, co
 * \param[in]  tb_sizeP         Size of a transport block set in bytes.
 * \return     The maximum number of bytes that the RLC instance can send in the next transmission sequence.
 */
-public_rlc_mac(mac_rlc_status_resp_t mac_rlc_status_ind   (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const  eNB_flag_t, const  MBMS_flag_t, logical_chan_id_t, tb_size_t );)
+public_rlc_mac(mac_rlc_status_resp_t mac_rlc_status_ind   (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const  eNB_flag_t, const  MBMS_flag_t, logical_chan_id_t, tb_size_t
+#ifdef Rel14
+                                                           ,const uint32_t sourceL2Id
+                                                           ,const uint32_t destinationL2Id
+#endif
+  );)
 
 /*! \fn rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind(const module_id_t module_idP, const rnti_t rntiP, const eNB_index_t eNB_index, const frame_t frameP, const sub_frame_t subframeP,const eNB_flag_t enb_flagP, const logical_chan_id_t channel_idP)
 * \brief    Interface with MAC layer, UE only: request and get the number of bytes scheduled for transmission by the RLC instance corresponding to the radio bearer identifier.
@@ -520,7 +554,12 @@ public_rlc(rlc_op_status_t rlc_data_req     (
              const  mui_t ,
              const confirm_t ,
              const sdu_size_t ,
-             mem_block_t * const);)
+             mem_block_t * const
+#ifdef Rel14
+             ,const uint32_t * const
+             ,const uint32_t * const
+#endif
+             );)
 
 /*! \fn void rlc_data_ind     (const protocol_ctxt_t* const ctxtP, const  srb_flag_t srb_flagP, const  MBMS_flag_t MBMS_flagP, const  rb_id_t rb_idP, const sdu_size_t sdu_sizeP, mem_block_t* sduP) {
 * \brief    Interface with higher layers, route SDUs coming from RLC protocol instances to upper layer instance.
diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c
index 497937d073841cdb37ce5ddf17b0f8aadee419cf..29fa5e8cb1868fb48bec921268db3a48c3fa7dbd 100644
--- a/openair2/LAYER2/RLC/rlc_mac.c
+++ b/openair2/LAYER2/RLC/rlc_mac.c
@@ -126,7 +126,12 @@ tbs_size_t mac_rlc_data_req(
   const MBMS_flag_t       MBMS_flagP,
   const logical_chan_id_t channel_idP,
   const tb_size_t         tb_sizeP,
-  char             *buffer_pP)
+  char             *buffer_pP
+#ifdef Rel14
+  ,const uint32_t sourceL2Id
+  ,const uint32_t destinationL2Id
+#endif
+   )
 {
   //-----------------------------------------------------------------------------
   struct mac_data_req    data_request;
@@ -143,7 +148,7 @@ tbs_size_t mac_rlc_data_req(
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_REQ,VCD_FUNCTION_IN);
 #ifdef DEBUG_MAC_INTERFACE
-  LOG_D(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_REQ channel %d (%d) MAX RB %d, Num_tb %d\n",
+  LOG_D(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_REQ channel %d (%d) MAX RB %d\n",
         PROTOCOL_CTXT_ARGS((&ctxt)),
         channel_idP,
         RLC_MAX_LC,
@@ -166,6 +171,10 @@ tbs_size_t mac_rlc_data_req(
     }
   } else {
     key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag);
+#ifdef Rel14
+    if ((sourceL2Id > 0) && (destinationL2Id > 0))
+       key = RLC_COLL_KEY_LCID_SOURCE_DEST_VALUE(module_idP, rntiP, enb_flagP, channel_idP, sourceL2Id, destinationL2Id, srb_flag);
+#endif
   }
 
   h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
@@ -189,7 +198,7 @@ tbs_size_t mac_rlc_data_req(
     break;
 
   case RLC_MODE_UM:
-	if (!enb_flagP) rlc_um_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.um,tb_sizeP);
+    if (!enb_flagP) rlc_um_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.um,tb_sizeP);
 	data_request = rlc_um_mac_data_request(&ctxt, &rlc_union_p->rlc.um,enb_flagP);
     ret_tb_size = mac_rlc_serialize_tb(buffer_pP, data_request.data);
     break;
@@ -308,7 +317,12 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
   const eNB_flag_t        enb_flagP,
   const MBMS_flag_t       MBMS_flagP,
   const logical_chan_id_t channel_idP,
-  const tb_size_t         tb_sizeP)
+  const tb_size_t         tb_sizeP
+#ifdef Rel14
+  ,const uint32_t sourceL2Id
+  ,const uint32_t destinationL2Id
+#endif
+  )
 {
   //-----------------------------------------------------------------------------
   mac_rlc_status_resp_t  mac_rlc_status_resp;
@@ -337,16 +351,26 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
 
     key = RLC_COLL_KEY_MBMS_VALUE(module_idP, rntiP, enb_flagP, mbms_id_p->service_id, mbms_id_p->session_id);
   } else {
+#ifdef Rel14
+    if ((sourceL2Id > 0) && (destinationL2Id > 0)) {
+       key = RLC_COLL_KEY_SOURCE_DEST_VALUE(module_idP, rntiP, enb_flagP, channel_idP, sourceL2Id, destinationL2Id, srb_flag);
+    } else
+#endif
+    {
+    	//LOG_I(RLC, "Panos-D mac_rlc_status_ind 1 enb_flagP: %d, channel_idP: %d, srb_flag: %d \n", enb_flagP, channel_idP, srb_flag);
     key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag);
-  }
+    }
+}
 
+  //LOG_I(RLC, "Panos-D mac_rlc_status_ind 2 enb_flagP: %d, channel_idP: %d, srb_flag: %d \n", enb_flagP, channel_idP, srb_flag);
   h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
 
   if (h_rc == HASH_TABLE_OK) {
     rlc_mode = rlc_union_p->mode;
   } else {
     rlc_mode = RLC_MODE_NONE;
-    //LOG_W(RLC , "[%s] RLC not configured rb id %u lcid %u module %u!\n", __FUNCTION__, rb_id, channel_idP, ue_module_idP);
+    //LOG_D(RLC , "Panos-D: mac_rlc_status_ind() In RLC_MODE_NONE \n");
+    //LOG_W(RLC , "[%s] RLC not configured lcid %u module %u!\n", __FUNCTION__, channel_idP, module_idP);
     //LOG_D(RLC , "[%s] RLC not configured rb id %u lcid %u module %u!\n", __FUNCTION__, rb_id, channel_idP, ue_module_idP);
   }
 
diff --git a/openair2/LAYER2/RLC/rlc_mpls.c b/openair2/LAYER2/RLC/rlc_mpls.c
index 34e4f028aec13ccc4f6a234413cffca1791c0643..900741fe2672300f22522a07133b9ef280bed8de 100644
--- a/openair2/LAYER2/RLC/rlc_mpls.c
+++ b/openair2/LAYER2/RLC/rlc_mpls.c
@@ -40,6 +40,10 @@ rlc_op_status_t mpls_rlc_data_req     (
 {
   //-----------------------------------------------------------------------------
   // third arg should be set to 1 or 0
-  return rlc_data_req(ctxtP, SRB_FLAG_NO, MBMS_FLAG_NO, rb_idP, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO, sdu_sizeP, sduP);
+  return rlc_data_req(ctxtP, SRB_FLAG_NO, MBMS_FLAG_NO, rb_idP, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO, sdu_sizeP, sduP
+#ifdef Rel14
+                      ,NULL, NULL
+#endif
+                      );
 }
 
diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c
index dee6ba700017d6dc48151b32ccac8f7a82eead0c..bb2abb560f2929c12f664c2beb4992cdaef6c613 100644
--- a/openair2/LAYER2/RLC/rlc_rrc.c
+++ b/openair2/LAYER2/RLC/rlc_rrc.c
@@ -52,6 +52,8 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
     const DRB_ToReleaseList_t  * const drb2release_listP
 #if defined(Rel10) || defined(Rel14)
     ,const PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP
+    ,const uint32_t sourceL2Id
+    ,const uint32_t destinationL2Id
 #endif
                                         )
 {
@@ -104,7 +106,12 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
             break;
 
           case RLC_Config_PR_am:
-            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_AM) != NULL) {
+            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_AM
+#ifdef Rel14
+                                ,0,
+                                0
+#endif
+                  ) != NULL) {
               config_req_rlc_am_asn1 (
                 ctxt_pP,
                 SRB_FLAG_YES,
@@ -119,7 +126,12 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
             break;
 
           case RLC_Config_PR_um_Bi_Directional:
-            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
+            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM
+#ifdef Rel14
+                                ,0,
+                                0
+#endif
+            ) != NULL) {
               config_req_rlc_um_asn1(
                 ctxt_pP,
                 SRB_FLAG_YES,
@@ -128,7 +140,11 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
                 UNUSED_PARAM_MBMS_SERVICE_ID,
                 &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Bi_Directional.ul_UM_RLC,
                 &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Bi_Directional.dl_UM_RLC,
-                rb_id, lc_id);
+                rb_id, lc_id
+#ifdef Rel14
+               ,0, 0
+#endif
+               );
             } else {
               LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                     PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -138,7 +154,12 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
             break;
 
           case RLC_Config_PR_um_Uni_Directional_UL:
-            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
+            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM
+#ifdef Rel14
+                                 ,0,
+                                 0
+#endif
+                  ) != NULL) {
               config_req_rlc_um_asn1(
                 ctxt_pP,
                 SRB_FLAG_YES,
@@ -147,7 +168,11 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
                 UNUSED_PARAM_MBMS_SERVICE_ID,
                 &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Uni_Directional_UL.ul_UM_RLC,
                 NULL,
-                rb_id, lc_id);
+                rb_id, lc_id
+#ifdef Rel14
+               ,0, 0
+#endif
+               );
             } else {
               LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                     PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -157,7 +182,12 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
             break;
 
           case RLC_Config_PR_um_Uni_Directional_DL:
-            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
+            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM
+#ifdef Rel14
+                                 ,0,
+                                 0
+#endif
+                                 ) != NULL) {
               config_req_rlc_um_asn1(
                 ctxt_pP,
                 SRB_FLAG_YES,
@@ -166,7 +196,11 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
                 UNUSED_PARAM_MBMS_SERVICE_ID,
                 NULL,
                 &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Uni_Directional_DL.dl_UM_RLC,
-                rb_id, lc_id);
+                rb_id, lc_id
+#ifdef Rel14
+               ,0, 0
+#endif
+               );
             } else {
               LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                     PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -195,7 +229,12 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
           config_am_pP->ul_AM_RLC.pollByte         = PollByte_kBinfinity;
           config_am_pP->ul_AM_RLC.maxRetxThreshold = UL_AM_RLC__maxRetxThreshold_t4;
 
-          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_AM) != NULL) {
+          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_AM
+#ifdef Rel14
+                               ,0,
+                               0
+#endif
+                               ) != NULL) {
             config_req_rlc_am_asn1 (
               ctxt_pP,
               SRB_FLAG_YES,
@@ -252,7 +291,6 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
 
       LOG_D(RLC, "Adding DRB %ld, lc_id %d\n",drb_id,lc_id);
 
-
       if (drb_toaddmod_p->rlc_Config) {
 
         switch (drb_toaddmod_p->rlc_Config->present) {
@@ -260,7 +298,12 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
           break;
 
         case RLC_Config_PR_am:
-          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_AM) != NULL) {
+          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_AM
+#ifdef Rel14
+                               ,0,
+                               0
+#endif
+            ) != NULL) {
             config_req_rlc_am_asn1 (
               ctxt_pP,
               SRB_FLAG_NO,
@@ -271,7 +314,12 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
           break;
 
         case RLC_Config_PR_um_Bi_Directional:
-          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM) != NULL) {
+          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM
+#ifdef Rel14
+                               ,sourceL2Id,
+                               destinationL2Id
+#endif
+              ) != NULL) {
             config_req_rlc_um_asn1(
               ctxt_pP,
               SRB_FLAG_NO,
@@ -280,13 +328,23 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
               UNUSED_PARAM_MBMS_SERVICE_ID,
               &drb_toaddmod_p->rlc_Config->choice.um_Bi_Directional.ul_UM_RLC,
               &drb_toaddmod_p->rlc_Config->choice.um_Bi_Directional.dl_UM_RLC,
-              drb_id, lc_id);
+              drb_id, lc_id
+#ifdef Rel14
+              ,sourceL2Id,
+              destinationL2Id
+#endif
+              );
           }
 
           break;
 
         case RLC_Config_PR_um_Uni_Directional_UL:
-          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM) != NULL) {
+          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM
+#ifdef Rel14
+                              ,0,
+                               0
+#endif
+             ) != NULL) {
             config_req_rlc_um_asn1(
               ctxt_pP,
               SRB_FLAG_NO,
@@ -295,13 +353,22 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
               UNUSED_PARAM_MBMS_SERVICE_ID,
               &drb_toaddmod_p->rlc_Config->choice.um_Uni_Directional_UL.ul_UM_RLC,
               NULL,
-              drb_id, lc_id);
+              drb_id, lc_id
+#ifdef Rel14
+               ,0, 0
+#endif
+               );
           }
 
           break;
 
         case RLC_Config_PR_um_Uni_Directional_DL:
-          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM) != NULL) {
+          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM
+#ifdef Rel14
+                              ,0,
+                               0
+#endif
+                               ) != NULL) {
             config_req_rlc_um_asn1(
               ctxt_pP,
               SRB_FLAG_NO,
@@ -310,7 +377,11 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
               UNUSED_PARAM_MBMS_SERVICE_ID,
               NULL,
               &drb_toaddmod_p->rlc_Config->choice.um_Uni_Directional_DL.dl_UM_RLC,
-              drb_id, lc_id);
+              drb_id, lc_id
+#ifdef Rel14
+               ,0, 0
+#endif
+               );
           }
 
           break;
@@ -372,7 +443,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
                           MBMS_FLAG_YES,
                           rb_id,
                           lc_id,
-                          RLC_MODE_UM);
+                          RLC_MODE_UM, 0, 0);
           AssertFatal(rlc_union_p != NULL, "ADD MBMS RLC UM FAILED");
         }
 
@@ -394,7 +465,11 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
           mbms_service_id,
           NULL,
           &dl_um_rlc,
-          rb_id, lc_id);
+          rb_id, lc_id
+#ifdef Rel14
+          ,0, 0
+#endif
+               );
       }
     }
   }
@@ -571,8 +646,14 @@ rlc_union_t* rrc_rlc_add_rlc   (
   const MBMS_flag_t       MBMS_flagP,
   const rb_id_t           rb_idP,
   const logical_chan_id_t chan_idP,
-  const rlc_mode_t        rlc_modeP)
+  const rlc_mode_t        rlc_modeP
+#ifdef Rel14
+  ,const uint32_t sourceL2Id,
+  const uint32_t  destinationL2Id
+#endif
+)
 {
+
   //-----------------------------------------------------------------------------
   hash_key_t             key         = HASHTABLE_NOT_A_KEY_VALUE;
   hashtable_rc_t         h_rc;
@@ -584,6 +665,7 @@ rlc_union_t* rrc_rlc_add_rlc   (
   logical_chan_id_t      lcid            = 0;
 #endif
 
+
   if (MBMS_flagP == FALSE) {
     AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
     AssertFatal (chan_idP < RLC_MAX_LC, "LC id is too high (%u/%d)!\n", chan_idP, RLC_MAX_LC);
@@ -608,6 +690,10 @@ rlc_union_t* rrc_rlc_add_rlc   (
     }
 
     key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_id_p->service_id, mbms_id_p->session_id);
+  }
+  if ((sourceL2Id > 0) && (destinationL2Id > 0) ){
+     key = RLC_COLL_KEY_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, sourceL2Id, destinationL2Id, srb_flagP);
+     key_lcid = RLC_COLL_KEY_LCID_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, sourceL2Id, destinationL2Id, srb_flagP);
   } else
 #endif
   {
@@ -668,7 +754,6 @@ rlc_union_t* rrc_rlc_add_rlc   (
           rb_idP,
           (srb_flagP) ? "SRB" : "DRB");
   }
-
   return NULL;
 }
 //-----------------------------------------------------------------------------
@@ -692,7 +777,12 @@ rlc_op_status_t rrc_rlc_config_req   (
   switch (actionP) {
 
   case CONFIG_ACTION_ADD:
-    if (rrc_rlc_add_rlc(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, rb_idP, rlc_infoP.rlc_mode) != NULL) {
+    if (rrc_rlc_add_rlc(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, rb_idP, rlc_infoP.rlc_mode
+#ifdef Rel14
+                        ,0,
+                        0
+#endif
+    ) != NULL) {
       return RLC_OP_STATUS_INTERNAL_ERROR;
     }
 
@@ -766,7 +856,11 @@ rlc_op_status_t rrc_rlc_data_req     (
 
   if (sdu != NULL) {
     memcpy (sdu->data, sduP, sdu_sizeP);
-    return rlc_data_req(ctxt_pP, SRB_FLAG_YES, MBMS_flagP, rb_idP, muiP, confirmP, sdu_sizeP, sdu);
+    return rlc_data_req(ctxt_pP, SRB_FLAG_YES, MBMS_flagP, rb_idP, muiP, confirmP, sdu_sizeP, sdu
+#ifdef Rel14
+                        ,NULL, NULL
+#endif
+                        );
   } else {
     return RLC_OP_STATUS_INTERNAL_ERROR;
   }
diff --git a/openair2/NETWORK_DRIVER/UE_IP/common.c b/openair2/NETWORK_DRIVER/UE_IP/common.c
index 99712cc5d2fc7e749109280c01a59e808b1e28e1..e8ff5fc7ac66d9917f1624e0615a5ee94899e70a 100644
--- a/openair2/NETWORK_DRIVER/UE_IP/common.c
+++ b/openair2/NETWORK_DRIVER/UE_IP/common.c
@@ -248,6 +248,13 @@ ue_ip_common_ip2wireless(
   //---------------------------------------------------------------------------
   struct pdcp_data_req_header_s     pdcph;
   ue_ip_priv_t                     *priv_p=netdev_priv(ue_ip_dev[instP]);
+#ifdef Rel14
+  ipversion_t         *ipv_p             = NULL;
+  unsigned int         hard_header_len   = 0;
+  unsigned char       *src_addr          = 0;
+  unsigned char       *dst_addr          = 0;
+#endif
+
 #ifdef LOOPBACK_TEST
   int i;
 #endif
@@ -278,6 +285,37 @@ ue_ip_common_ip2wireless(
 
   pdcph.inst       = instP;
 
+  //pass source/destination IP addresses to PDCP header
+  hard_header_len = ue_ip_dev[instP]->hard_header_len;
+  ipv_p = (ipversion_t *)((void *)&(skb_pP->data[hard_header_len]));
+
+  switch (ipv_p->version) {
+  case 6:
+    printk("[UE_IP_DRV][%s] receive IPv6 message\n",__FUNCTION__);
+    //TODO
+    break;
+
+  case 4:
+     src_addr = (unsigned char *)&((struct iphdr *)&skb_pP->data[hard_header_len])->saddr;
+    if (src_addr) {
+      printk("[UE_IP_DRV][%s] Source %d.%d.%d.%d\n",__FUNCTION__, src_addr[0],src_addr[1],src_addr[2],src_addr[3]);
+    }
+    dst_addr = (unsigned char *)&((struct iphdr *)&skb_pP->data[hard_header_len])->daddr;
+    if (dst_addr) {
+      printk("[UE_IP_DRV][%s] Dest %d.%d.%d.%d\n",__FUNCTION__, dst_addr[0],dst_addr[1],dst_addr[2],dst_addr[3]);
+    }
+
+    //get Ipv4 address and pass to PCDP header
+    printk("[UE_IP_DRV] source Id: 0x%08x\n",pdcph.sourceL2Id );
+    printk("[UE_IP_DRV] destinationL2Id Id: 0x%08x\n",pdcph.destinationL2Id );
+    pdcph.sourceL2Id = ntohl( ((struct iphdr *)&skb_pP->data[hard_header_len])->saddr) & 0x00FFFFFF;
+    pdcph.destinationL2Id = ntohl( ((struct iphdr *)&skb_pP->data[hard_header_len])->daddr) & 0x00FFFFFF;
+    break;
+
+  default:
+     break;
+  }
+
 
   bytes_wrote = ue_ip_netlink_send((char *)&pdcph,UE_IP_PDCPH_SIZE);
 #ifdef OAI_DRV_DEBUG_SEND
diff --git a/openair2/NETWORK_DRIVER/UE_IP/local.h b/openair2/NETWORK_DRIVER/UE_IP/local.h
index ac3b0409954daab75466448b14a1727c94d76ada..976222967d326d885dc02288b12562e7bc953665 100644
--- a/openair2/NETWORK_DRIVER/UE_IP/local.h
+++ b/openair2/NETWORK_DRIVER/UE_IP/local.h
@@ -89,6 +89,10 @@ typedef struct pdcp_data_req_header_s {
   sdu_size_t          data_size;
   signed int          inst;
   ip_traffic_type_t   traffic_type;
+#ifdef Rel14
+  uint32_t sourceL2Id;
+  uint32_t destinationL2Id;
+#endif
 } pdcp_data_req_header_t;
 
 typedef struct pdcp_data_ind_header_s {
@@ -96,6 +100,10 @@ typedef struct pdcp_data_ind_header_s {
   sdu_size_t          data_size;
   signed int          inst;
   ip_traffic_type_t   dummy_traffic_type;
+#ifdef Rel14
+  uint32_t sourceL2Id;
+  uint32_t destinationL2Id;
+#endif
 } pdcp_data_ind_header_t;
 
 
diff --git a/openair2/PHY_INTERFACE/UE_MAC_interface.h b/openair2/PHY_INTERFACE/UE_MAC_interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..0e4777d0b028cf0e5af141fc23a538e77448503f
--- /dev/null
+++ b/openair2/PHY_INTERFACE/UE_MAC_interface.h
@@ -0,0 +1,498 @@
+/*
+ * 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
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * 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
+ */
+
+/* This is the interface module between PHY
+ * Provided the FAPI style interface structures for P7.
+ */
+
+/*! \file openair2/PHY_INTERFACE/IF_Module.h
+* \brief data structures for PHY/MAC interface modules
+* \author EURECOM/NTUST
+* \date 2017
+* \version 0.1
+* \company Eurecom
+* \email: raymond.knopp@eurecom.fr
+* \note
+* \warning
+*/
+#ifndef __UE_MAC_INTERFACE__H__
+#define __UE_MAC_INTERFACE__H__
+
+#include "nfapi_interface.h"
+#include "openair1/PHY/impl_defs_lte.h"
+#include "targets/COMMON/openairinterface5g_limits.h"
+
+
+
+#define MAX_NUM_DL_PDU 100
+#define MAX_NUM_UL_PDU 100
+#define MAX_NUM_HI_DCI0_PDU 100
+#define MAX_NUM_TX_REQUEST_PDU 100
+
+#define MAX_NUM_HARQ_IND 100
+#define MAX_NUM_CRC_IND 100
+#define MAX_NUM_SR_IND 100
+#define MAX_NUM_CQI_IND 100
+#define MAX_NUM_RACH_IND 100
+#define MAX_NUM_SRS_IND 100
+
+
+// UE_MAC enums
+typedef enum {
+	UE_MAC_DL_IND_PDSCH_PDU_TYPE =0,
+	UE_MAC_DL_IND_SI_PDSCH_PDU_TYPE,
+	UE_MAC_DL_IND_P_PDSCH_PDU_TYPE,
+	UE_MAC_DL_IND_DLSCH_RAR_PDU_TYPE
+} UE_MAC_dl_ind_pdu_type_e;
+
+// UE_MAC enums
+typedef enum {
+	UE_MAC_Tx_IND_Msg1_TYPE =0,
+	UE_MAC_Tx_IND_Msg3_TYPE
+} UE_MAC_Tx_ind_type_e;
+
+
+
+// *** UE_UL_Config.request related structures
+
+
+typedef struct{
+	//module_id_t module_idP;
+	//int CC_id;
+	//frame_t frameP;
+	uint8_t eNB_id;
+	//uint16_t rnti;
+	//sub_frame_t subframe_tx;
+	uint32_t SR_payload; //0 or 1
+}UE_MAC_ul_config_SR;
+
+
+
+typedef struct{
+	//module_id_t module_idP;
+	//int CC_id;
+	//frame_t frameP;
+	uint8_t eNB_indexP;
+	//sub_frame_t subframeP;
+
+	uint8_t ra_RACH_MaskIndex;
+	int8_t ra_PREAMBLE_RECEIVED_TARGET_POWER;
+	uint8_t ra_TDD_map_index;
+	uint16_t ra_RNTI;
+	uint8_t *Msg3;
+}UE_MAC_ul_config_rach;
+
+typedef struct {
+	union {
+		UE_MAC_ul_config_rach			ue_rach_config;
+		//UE_MAC_ul_config_ULSCH     		ue_ULSCH_pdu;
+		UE_MAC_ul_config_SR     		ue_SR_config;
+	};
+} UE_MAC_ul_config_request_list;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length_list;
+	UE_MAC_ul_config_request_list* ue_ul_config_list;
+} UE_MAC_ul_config_request_body_t;
+
+typedef struct {
+	//nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	UE_MAC_ul_config_request_body_t ue_ul_config_request_body; //nfapi_dl_config_request_body_t
+} UE_MAC_ul_config_request_t;
+
+
+
+
+
+
+
+
+
+// *** UE_Tx.request related structures
+
+typedef struct {
+	uint16_t pdu_length;
+	uint16_t pdu_index;
+	uint8_t num_segments;
+	struct {
+		uint32_t segment_length;
+		uint8_t* segment_data;
+	} segments[NFAPI_TX_MAX_SEGMENTS];
+} UE_MAC_tx_request_pdu_t;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	UE_MAC_tx_request_pdu_t* ue_tx_pdu_list;
+} UE_MAC_tx_request_body_t;
+
+
+typedef struct {
+	//nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	UE_MAC_tx_request_body_t ue_tx_request_body;
+} UE_MAC_tx_request_t;
+
+
+typedef struct{
+
+
+}UE_MAC_sl_config_request_Tx_t;
+
+typedef struct{
+
+
+}UE_MAC_sl_config_request_Rx_t;
+
+
+typedef struct{
+
+
+}UE_MAC_sl_tx_request_t;
+
+
+
+
+
+
+// *** UE_DL.indication related structures
+
+typedef struct{
+	unsigned char eNB_index;
+	uint8_t       first_sync; //boolean 0 or 1
+	uint8_t       sync; // boolean 0 or 1 to indicate whether rrc_out_of_sync_ind() or dl_phy_sync_success()
+						// should be called from the handler function of the interface respectively.
+}UE_MAC_bch_indication_pdu_t;
+
+
+typedef struct{
+	nfapi_tl_t tl;
+	UE_MAC_bch_indication_pdu_t* bch_ind_list;
+}UE_MAC_BCH_indication_body_t;
+
+
+// Panos: Corresponding to inputs of MAC functions: ue_send_sdu(), ue_decode_si(), ue_decode_p().
+typedef struct{
+	uint8_t* 	data;
+	uint16_t 	data_len;
+}UE_MAC_dlsch_pdu;
+
+
+// Panos: Corresponding to inputs of MAC function: process_rar().
+typedef struct{
+	rnti_t 		ra_rnti;
+	uint8_t* 	rar_input_buffer; // Originating from PHY
+	rnti_t* 	t_crnti;
+	uint8_t 	preamble_index;
+	uint8_t* 	rar_output_buffer; //should be returned to PHY: dlsch0->harq_processes[0]->b
+}UE_MAC_dlsch_rar_pdu;
+
+
+typedef struct{
+	uint8_t pdu_type;
+	uint8_t eNB_index;
+	union{
+		UE_MAC_dlsch_pdu 	 dlsch_pdu_ind;
+		UE_MAC_dlsch_rar_pdu dlsch_rar_pdu_ind;
+	};
+}UE_MAC_dlsch_indication_pdu_t;
+
+
+typedef struct{
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	UE_MAC_dlsch_indication_pdu_t* dlsch_ind_list;
+}UE_MAC_DLSCH_indication_body_t;
+
+
+
+
+
+
+// *** UE_SL.indication related structures
+
+typedef struct{
+
+}ue_sci_indication_body_t;
+
+
+typedef struct{
+
+}ue_SLSCH_indication_body_t;
+
+
+typedef struct{
+
+}ue_SLDCH_indication_body_t;
+
+typedef struct{
+
+}ue_SLBCH_indication_body_t;
+
+
+// *** UE_Config_common.request related structures
+
+typedef struct {
+	uint8_t subframeAssignment;
+	uint8_t specialSubframePatterns;
+}UE_PHY_tdd_frame_structure_t;
+
+
+typedef struct {
+	uint16_t rootSequenceIndex;
+	uint8_t prach_Config_enabled;
+	uint8_t prach_ConfigIndex;
+	uint8_t highSpeedFlag;
+	uint8_t zeroCorrelationZoneConfig;
+	uint8_t prach_FreqOffset;
+}UE_PHY_prach_config_t;
+
+typedef struct {
+	uint8_t deltaPUCCH_Shift;
+	uint8_t nRB_CQI;
+	uint8_t nCS_AN;
+	uint16_t n1PUCCH_AN;
+}UE_PHY_pucch_config_t;
+
+
+typedef struct {
+	int8_t referenceSignalPower;
+	uint8_t p_b;
+}UE_PHY_pdsch_config_t;
+
+
+typedef struct {
+	uint8_t n_SB;
+	PUSCH_HOPPING_t hoppingMode;
+	uint8_t pusch_HoppingOffset;
+	uint8_t enable64QAM;
+	uint8_t groupHoppingEnabled;
+	uint8_t groupAssignmentPUSCH;
+	uint8_t sequenceHoppingEnabled;
+	uint8_t cyclicShift;
+}UE_PHY_pusch_config_t;
+
+
+typedef struct{
+	uint8_t enabled_flag;
+	uint8_t srs_BandwidthConfig;
+	uint8_t srs_SubframeConfig;
+	uint8_t ackNackSRS_SimultaneousTransmission;
+	uint8_t srs_MaxUpPts;
+}UE_PHY_SRS_config_t;
+
+typedef struct{
+	int8_t p0_NominalPUSCH;
+	PUSCH_alpha_t alpha;
+	int8_t p0_NominalPUCCH;
+	int8_t deltaPreambleMsg3;
+	long deltaF_PUCCH_Format1;
+	long deltaF_PUCCH_Format1b;
+	long deltaF_PUCCH_Format2;
+	long deltaF_PUCCH_Format2a;
+	long deltaF_PUCCH_Format2b;
+}UE_PHY_UL_power_control_config_t;
+
+
+typedef struct{
+	uint8_t maxHARQ_Msg3Tx;
+}UE_PHY_HARQ_Msg3_config_t;
+
+typedef struct{
+	uint8_t nb_antennas_tx;
+}UE_PHY_antenna_config_t;
+
+typedef struct{
+	PHICH_RESOURCE_t phich_resource;
+	PHICH_DURATION_t phich_duration;
+}UE_PHY_phich_config_t;
+
+
+typedef struct {
+	UE_PHY_tdd_frame_structure_t ue_tdd_frame_structure_config;
+	UE_PHY_prach_config_t ue_prach_config;
+	UE_PHY_pucch_config_t ue_pucch_config;
+	UE_PHY_pdsch_config_t ue_pdsch_config;
+	UE_PHY_pusch_config_t ue_pusch_config;
+	UE_PHY_SRS_config_t   ue_srs_config;
+	UE_PHY_UL_power_control_config_t ue_ul_pow_cntl_config;
+	UE_PHY_HARQ_Msg3_config_t ue_harq_msg3_config;
+	/* Where can we find the types and values of the configuration for the PCH?
+	UE_MAC_pusch_config_t ue_pch_config
+	radioResourceConfigCommon->pcch_Config.defaultPagingCycle, radioResourceConfigCommon->pcch_Config.nB*/
+	UE_PHY_antenna_config_t ue_ant_config;
+	UE_PHY_phich_config_t ue_phich_config;
+	/* MBSFN?*/
+}UE_PHY_config_common_request_t;
+
+
+
+
+
+
+
+// *** UE_Config_dedicated. request related structures
+
+typedef struct{
+	PA_t p_a;
+}UE_PHY_pdsch_config_dedicated_t;
+
+
+typedef struct{
+	uint8_t ackNackRepetition;
+	ANFBmode_t tdd_AckNackFeedbackMode;
+	//ACKNAKREP_t repetitionFactor;
+	//uint16_t n1PUCCH_AN_Rep;
+}UE_PHY_pucch_config_dedicated_t;
+
+
+typedef struct{
+	uint16_t betaOffset_ACK_Index;
+	uint16_t betaOffset_RI_Index;
+	uint16_t betaOffset_CQI_Index;
+}UE_PHY_pusch_config_dedicated_t;
+
+
+typedef struct{
+	int8_t p0_UE_PUSCH;
+	uint8_t deltaMCS_Enabled;
+	uint8_t accumulationEnabled;
+	int8_t p0_UE_PUCCH;
+	int8_t pSRS_Offset;
+	uint8_t filterCoefficient;
+}UE_PHY_ul_power_control_config_dedicated_t;
+
+
+typedef struct{
+	uint16_t sr_PUCCH_ResourceIndex;
+	uint8_t sr_ConfigIndex;
+	DSR_TRANSMAX_t dsr_TransMax;
+}UE_PHY_SR_config_dedicated_t;
+
+
+typedef struct{
+	uint8_t srsConfigDedicatedSetup;
+	uint8_t duration;
+	uint8_t cyclicShift;
+	uint8_t freqDomainPosition;
+	uint8_t srs_Bandwidth;
+	uint16_t srs_ConfigIndex;
+	uint8_t srs_HoppingBandwidth;
+	uint8_t transmissionComb;
+	//uint8_t srsCellSubframe;
+	//uint8_t srsUeSubframe;
+}UE_PHY_srs_ul_config_dedicated_t;
+
+
+typedef struct{
+	CQI_REPORTMODEAPERIODIC cqi_ReportModeAperiodic;
+	CQI_REPORTPERIODIC CQI_ReportPeriodic;
+	//int8_t nomPDSCH_RS_EPRE_Offset;
+}UE_PHY_cqi_report_config_dedicated_t;
+
+
+
+typedef struct{
+	uint8_t transmission_mode [NUMBER_OF_CONNECTED_eNB_MAX];
+	UE_PHY_pdsch_config_dedicated_t ue_pdsch_config;
+	UE_PHY_pucch_config_dedicated_t ue_pucch_config;
+	UE_PHY_pusch_config_dedicated_t ue_pusch_config;
+	UE_PHY_ul_power_control_config_dedicated_t ue_ul_pow_cntrl_config;
+	UE_PHY_SR_config_dedicated_t	ue_SR_config;
+	UE_PHY_srs_ul_config_dedicated_t ue_srs_ul_config;
+	UE_PHY_cqi_report_config_dedicated_t ue_cqi_report_config;
+}UE_PHY_config_dedicated_request_t;
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t num_tlv;
+	nfapi_subframe_config_t subframe_config;
+	nfapi_rf_config_t rf_config;
+	nfapi_phich_config_t phich_config;
+	nfapi_sch_config_t sch_config;
+	nfapi_prach_config_t prach_config;
+	nfapi_pusch_config_t pusch_config;
+	nfapi_pucch_config_t pucch_config;
+	nfapi_srs_config_t srs_config;
+	nfapi_uplink_reference_signal_config_t uplink_reference_signal_config;
+	nfapi_laa_config_t laa_config;
+	nfapi_emtc_config_t emtc_config;
+	nfapi_tdd_frame_structure_t tdd_frame_structure_config;
+	nfapi_l23_config_t l23_config;
+	nfapi_nb_iot_config_t nb_iot_config;
+
+	// addition nfapi tlvs as per table 2-16 in idle or configure
+	nfapi_nfapi_t nfapi_config;
+
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_config_request_t;
+
+
+
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dci_format;
+	uint8_t cce_index;
+	uint8_t aggregation_level;
+	uint16_t rnti;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_block;
+	uint8_t mcs_1;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t frequency_hopping_bits;
+	uint8_t new_data_indication_1;
+	uint8_t ue_tx_antenna_seleciton;
+	uint8_t tpc;
+	uint8_t cqi_csi_request;
+	uint8_t ul_index;
+	uint8_t dl_assignment_index;
+	uint32_t tpc_bitmap;
+	uint16_t transmission_power;
+} nfapi_hi_dci0_dci_pdu_rel8_t;
+
+*/
diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c
new file mode 100644
index 0000000000000000000000000000000000000000..f24c113c175b1a07f8c19540ce7ed282685c21cc
--- /dev/null
+++ b/openair2/PHY_INTERFACE/phy_stub_UE.c
@@ -0,0 +1,1022 @@
+
+//#include "openair1/PHY/defs.h"
+//#include "openair2/PHY_INTERFACE/IF_Module.h"
+//#include "openair1/PHY/extern.h"
+#include "openair2/LAYER2/MAC/extern.h"
+#include "openair2/LAYER2/MAC/defs.h"
+#include "openair2/LAYER2/MAC/proto.h"
+//#include "openair2/LAYER2/MAC/vars.h"
+#include "openair1/SCHED/defs.h"
+#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
+//#include "common/ran_context.h"
+#include "openair2/PHY_INTERFACE/phy_stub_UE.h"
+#include "openair2/ENB_APP/L1_paramdef.h"
+#include "openair2/ENB_APP/enb_paramdef.h"
+#include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
+#include "common/config/config_load_configmodule.h"
+#include "common/config/config_userapi.h"
+
+//#define DEADLINE_SCHEDULER 1
+
+
+extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind);
+extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind);
+extern int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind);
+void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port);
+
+
+
+
+//extern uint8_t nfapi_pnf;
+//UL_IND_t *UL_INFO;
+extern nfapi_tx_request_pdu_t* tx_request_pdu[1023][10][10];
+//extern int timer_subframe;
+//extern int timer_frame;
+
+extern uint16_t sf_ahead;
+
+void Msg1_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id);
+void Msg3_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id);
+
+
+
+void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe, UL_IND_t* UL_INFO, uint8_t *ulsch_buffer, uint16_t buflen, uint16_t rnti, int index)
+{
+	  nfapi_rx_indication_pdu_t *pdu;
+
+	  int timing_advance_update;
+
+
+	  pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+
+
+	  UL_INFO->rx_ind.sfn_sf                    = frame<<4| subframe;
+	  UL_INFO->rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;
+	  UL_INFO->rx_ind.vendor_extension		     = ul_config_req->vendor_extension;
+
+
+	  pdu                                    = &UL_INFO->rx_ind.rx_indication_body.rx_pdu_list[UL_INFO->rx_ind.rx_indication_body.number_of_pdus];
+	  //pdu                                    = &UL_INFO->rx_ind.rx_indication_body.rx_pdu_list[index];
+
+	  //  pdu->rx_ue_information.handle          = eNB->ulsch[UE_id]->handle;
+	  pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
+	  pdu->rx_ue_information.rnti            = rnti;
+	  pdu->rx_indication_rel8.tl.tag         = NFAPI_RX_INDICATION_REL8_TAG;
+	  //pdu->rx_indication_rel8.length         = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3;
+	  pdu->rx_indication_rel8.length         = buflen;
+	  pdu->rx_indication_rel8.offset         = 1;   // DJP - I dont understand - but broken unless 1 ????  0;  // filled in at the end of the UL_INFO formation
+	  pdu->data                              = ulsch_buffer;
+	  // estimate timing advance for MAC
+	  //sync_pos                               = lte_est_timing_advance_pusch(eNB,UE_id);
+	  timing_advance_update                  = 0;  //Panos: Don't know what to put here
+	  pdu->rx_indication_rel8.timing_advance = timing_advance_update;
+
+		  int SNRtimes10 = 640;
+
+	  if      (SNRtimes10 < -640) pdu->rx_indication_rel8.ul_cqi=0;
+	  else if (SNRtimes10 >  635) pdu->rx_indication_rel8.ul_cqi=255;
+	  else                        pdu->rx_indication_rel8.ul_cqi=(640+SNRtimes10)/5;
+
+
+	  UL_INFO->rx_ind.rx_indication_body.number_of_pdus++;
+	  UL_INFO->rx_ind.sfn_sf = frame<<4 | subframe;
+	  pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+
+
+}
+
+void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint16_t rnti) {
+
+
+  pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+
+  nfapi_sr_indication_t       *sr_ind = &UL_INFO->sr_ind;
+  nfapi_sr_indication_body_t  *sr_ind_body =    &sr_ind->sr_indication_body;
+  nfapi_sr_indication_pdu_t *pdu =   &sr_ind_body->sr_pdu_list[sr_ind_body->number_of_srs];
+  UL_INFO->sr_ind.vendor_extension		     = ul_config_req->vendor_extension;
+
+  //nfapi_sr_indication_pdu_t *pdu =   &UL_INFO->sr_ind.sr_indication_body.sr_pdu_list[UL_INFO->rx_ind.rx_indication_body.number_of_pdus];
+
+  sr_ind->sfn_sf = frame<<4|subframe;
+  sr_ind->header.message_id = NFAPI_RX_SR_INDICATION;
+
+  sr_ind_body->tl.tag = NFAPI_SR_INDICATION_BODY_TAG;
+
+  pdu->instance_length                                = 0; // don't know what to do with this
+  //  pdu->rx_ue_information.handle                       = handle;
+  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
+  pdu->rx_ue_information.rnti                         = rnti; //UE_mac_inst[Mod_id].crnti;; //Panos: Is this the right RNTI?
+
+
+  // Panos dependency from PHY not sure how to substitute this. Should we hardcode it?
+  //int SNRtimes10 = dB_fixed_times10(stat) - 200;//(10*eNB->measurements.n0_power_dB[0]);
+  int SNRtimes10 = 640;
+
+  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+
+
+  if      (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0;
+  else if (SNRtimes10 >  635) pdu->ul_cqi_information.ul_cqi=255;
+  else                        pdu->ul_cqi_information.ul_cqi=(640+SNRtimes10)/5;
+  pdu->ul_cqi_information.channel = 0;
+
+  //UL_INFO->rx_ind.rx_indication_body.number_of_pdus++;
+  sr_ind_body->number_of_srs++;
+  pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+}
+
+
+void fill_crc_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t crc_flag, int index, uint16_t rnti) {
+
+  pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+
+  //Panos: REMEMBER HAVE EXCHANGED THE FOLLOWING TWO LINES HERE!
+  nfapi_crc_indication_pdu_t *pdu =   &UL_INFO->crc_ind.crc_indication_body.crc_pdu_list[UL_INFO->crc_ind.crc_indication_body.number_of_crcs];
+
+  UL_INFO->crc_ind.sfn_sf                    = frame<<4| subframe;
+  UL_INFO->crc_ind.vendor_extension		     = ul_config_req->vendor_extension;
+  UL_INFO->crc_ind.header.message_id              = NFAPI_CRC_INDICATION;
+  UL_INFO->crc_ind.crc_indication_body.tl.tag = NFAPI_CRC_INDICATION_BODY_TAG;
+
+  pdu->instance_length                                = 0; // don't know what to do with this
+  //  pdu->rx_ue_information.handle                       = handle;
+  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
+
+  //pdu->rx_ue_information.rnti                         = UE_mac_inst[Mod_id].crnti;
+  pdu->rx_ue_information.rnti                         = rnti;
+  pdu->crc_indication_rel8.tl.tag                     = NFAPI_CRC_INDICATION_REL8_TAG;
+  pdu->crc_indication_rel8.crc_flag                   = crc_flag;
+
+  UL_INFO->crc_ind.crc_indication_body.number_of_crcs++;
+
+  LOG_D(PHY, "%s() rnti:%04x pdus:%d\n", __FUNCTION__, pdu->rx_ue_information.rnti, UL_INFO->crc_ind.crc_indication_body.number_of_crcs);
+
+  pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+}
+
+void fill_rach_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t ra_PreambleIndex, uint16_t ra_RNTI) {
+
+	LOG_D(MAC, "fill_rach_indication_UE_MAC 1 \n");
+	pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+	UL_INFO = (UL_IND_t*)malloc(sizeof(UL_IND_t));
+
+	    UL_INFO->rach_ind.rach_indication_body.number_of_preambles                 = 1;
+
+	    //eNB->UL_INFO.rach_ind.preamble_list                       = &eNB->preamble_list[0];
+	    UL_INFO->rach_ind.header.message_id                         = NFAPI_RACH_INDICATION;
+	    UL_INFO->rach_ind.sfn_sf                                    = frame<<4 | subframe;
+	    UL_INFO->rach_ind.vendor_extension							= NULL;
+
+	    UL_INFO->rach_ind.rach_indication_body.tl.tag                              = NFAPI_RACH_INDICATION_BODY_TAG;
+
+
+	    UL_INFO->rach_ind.rach_indication_body.preamble_list = (nfapi_preamble_pdu_t*)malloc(UL_INFO->rach_ind.rach_indication_body.number_of_preambles*sizeof(nfapi_preamble_pdu_t));
+	    UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.tl.tag   		= NFAPI_PREAMBLE_REL8_TAG;
+	    UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.timing_advance = 0; //Panos: Not sure about that
+
+	    //Panos: The two following should get extracted from the call to get_prach_resources().
+	    UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.preamble = ra_PreambleIndex;
+	    UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.rnti 	  = ra_RNTI;
+	    //UL_INFO->rach_ind.rach_indication_body.number_of_preambles++;
+
+
+	    UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel13.rach_resource_type = 0;
+	    UL_INFO->rach_ind.rach_indication_body.preamble_list[0].instance_length					 = 0;
+
+
+	          LOG_E(PHY,"\n\n\n\nDJP - this needs to be sent to VNF **********************************************\n\n\n\n");
+	          LOG_E(PHY,"UE Filling NFAPI indication for RACH : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n",
+	        	  UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.timing_advance,
+	        	  UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.preamble,
+	        	  UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.rnti,
+	        	  UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel13.rach_resource_type);
+
+	          //Panos: This function is currently defined only in the nfapi-RU-RAU-split so we should call it when we merge
+	          // with that branch.
+	          oai_nfapi_rach_ind(&UL_INFO->rach_ind);
+	          free(UL_INFO->rach_ind.rach_indication_body.preamble_list);
+	          free(UL_INFO);
+
+	        //}
+	      pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+
+}
+
+void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint16_t frame,uint8_t subframe, UL_IND_t *UL_INFO, uint16_t rnti) {
+
+	pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+	nfapi_cqi_indication_pdu_t *pdu         = &UL_INFO->cqi_ind.cqi_pdu_list[UL_INFO->cqi_ind.number_of_cqis];
+	nfapi_cqi_indication_raw_pdu_t *raw_pdu = &UL_INFO->cqi_ind.cqi_raw_pdu_list[UL_INFO->cqi_ind.number_of_cqis];
+
+	pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
+	pdu->rx_ue_information.rnti = rnti;
+	//Panos: Since we assume that CRC flag is always 0 (ACK) I guess that data_offset should always be 0.
+	pdu->cqi_indication_rel9.data_offset = 0;
+
+	// by default set O to rank 1 value
+	//pdu->cqi_indication_rel9.length = (ulsch_harq->Or1>>3) + ((ulsch_harq->Or1&7) > 0 ? 1 : 0);
+	// Panos: Not useful field for our case
+	pdu->cqi_indication_rel9.tl.tag = NFAPI_CQI_INDICATION_REL9_TAG;
+	pdu->cqi_indication_rel9.length = 0;
+	pdu->cqi_indication_rel9.ri[0]  = 0;
+
+
+	pdu->cqi_indication_rel9.timing_advance = 0;
+  pdu->cqi_indication_rel9.number_of_cc_reported = 1;
+  pdu->ul_cqi_information.channel = 1; // PUSCH
+
+  //Panos: Not sure how to substitute this. This should be the actual CQI value? So can
+  // we hardcode it to a specific value?
+  //memcpy((void*)raw_pdu->pdu,ulsch_harq->o,pdu->cqi_indication_rel9.length);
+  raw_pdu->pdu[0] = 7;
+
+
+
+  UL_INFO->cqi_ind.number_of_cqis++;
+  pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+
+}
+
+void fill_ulsch_harq_indication_UE_MAC(int Mod_id, int frame,int subframe, UL_IND_t *UL_INFO, nfapi_ul_config_ulsch_harq_information *harq_information, uint16_t rnti)
+{
+
+  pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+  nfapi_harq_indication_pdu_t *pdu =   &UL_INFO->harq_ind.harq_indication_body.harq_pdu_list[UL_INFO->harq_ind.harq_indication_body.number_of_harqs];
+  int i;
+
+  UL_INFO->harq_ind.header.message_id = NFAPI_HARQ_INDICATION;
+  UL_INFO->harq_ind.sfn_sf = frame<<4|subframe;
+  UL_INFO->harq_ind.vendor_extension		     = ul_config_req->vendor_extension;
+
+  UL_INFO->harq_ind.harq_indication_body.tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
+
+  pdu->instance_length                                = 0; // don't know what to do with this
+  //  pdu->rx_ue_information.handle                       = handle;
+  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
+  pdu->rx_ue_information.rnti                         = rnti;
+
+  //Panos: For now we consider only FDD
+  //if (eNB->frame_parms.frame_type == FDD) {
+    pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
+    pdu->harq_indication_fdd_rel13.mode = 0;
+    pdu->harq_indication_fdd_rel13.number_of_ack_nack = harq_information->harq_information_rel10.harq_size;
+
+    //Panos: Could this be wrong? Is the number_of_ack_nack field equivalent to O_ACK?
+    //pdu->harq_indication_fdd_rel13.number_of_ack_nack = ulsch_harq->O_ACK;
+
+    for (i=0;i<harq_information->harq_information_rel10.harq_size;i++) {
+
+      pdu->harq_indication_fdd_rel13.harq_tb_n[i] = 1; //Panos: Assuming always an ACK (No NACK or DTX)
+
+    }
+
+  UL_INFO->harq_ind.harq_indication_body.number_of_harqs++;
+  pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+}
+
+
+void fill_uci_harq_indication_UE_MAC(int Mod_id,
+			      int frame,
+			      int subframe,
+			      UL_IND_t *UL_INFO,
+			      nfapi_ul_config_harq_information *harq_information,
+			      uint16_t rnti
+			      /*uint8_t tdd_mapping_mode,
+			      uint16_t tdd_multiplexing_mask*/) {
+
+
+  pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+  nfapi_harq_indication_t *ind       = &UL_INFO->harq_ind;
+  nfapi_harq_indication_body_t *body = &ind->harq_indication_body;
+  nfapi_harq_indication_pdu_t *pdu =   &body->harq_pdu_list[UL_INFO->harq_ind.harq_indication_body.number_of_harqs];
+
+  UL_INFO->harq_ind.vendor_extension		     = ul_config_req->vendor_extension;
+
+  ind->sfn_sf = frame<<4|subframe;
+  ind->header.message_id = NFAPI_HARQ_INDICATION;
+
+  body->tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
+  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
+
+  pdu->instance_length                                = 0; // don't know what to do with this
+  //  pdu->rx_ue_information.handle                       = handle;
+  pdu->rx_ue_information.rnti                         = rnti;
+
+  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
+
+  int SNRtimes10 = 640;
+
+
+  if      (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0;
+  else if (SNRtimes10 >  635) pdu->ul_cqi_information.ul_cqi=255;
+  else                        pdu->ul_cqi_information.ul_cqi=(640+SNRtimes10)/5;
+  pdu->ul_cqi_information.channel = 0;
+      if ((harq_information->harq_information_rel9_fdd.ack_nack_mode == 0) &&
+          (harq_information->harq_information_rel9_fdd.harq_size == 1)) {
+
+      pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
+      pdu->harq_indication_fdd_rel13.mode = 0;
+      pdu->harq_indication_fdd_rel13.number_of_ack_nack = 1;
+
+      //AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n",harq_ack[0]);
+      pdu->harq_indication_fdd_rel13.harq_tb_n[0] = 1; //Panos: Assuming always an ACK (No NACK or DTX)
+
+
+    }
+    else if ((harq_information->harq_information_rel9_fdd.ack_nack_mode == 0) &&
+                 (harq_information->harq_information_rel9_fdd.harq_size == 2)) {
+      pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
+      pdu->harq_indication_fdd_rel13.mode = 0;
+      pdu->harq_indication_fdd_rel13.number_of_ack_nack = 2;
+      pdu->harq_indication_fdd_rel13.harq_tb_n[0] = 1; //Panos: Assuming always an ACK (No NACK or DTX)
+      pdu->harq_indication_fdd_rel13.harq_tb_n[1] = 1; //Panos: Assuming always an ACK (No NACK or DTX)
+
+    }
+    else AssertFatal(1==0,"only format 1a/b for now, received \n");
+
+
+  UL_INFO->harq_ind.harq_indication_body.number_of_harqs++;
+  LOG_D(PHY,"Incremented eNB->UL_INFO.harq_ind.number_of_harqs:%d\n", UL_INFO->harq_ind.harq_indication_body.number_of_harqs);
+  pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
+
+}
+
+
+void handle_nfapi_ul_pdu_UE_MAC(module_id_t Mod_id,
+                         nfapi_ul_config_request_pdu_t *ul_config_pdu,
+                         uint16_t frame,uint8_t subframe,uint8_t srs_present, int index)
+{
+  nfapi_ul_config_ulsch_pdu_rel8_t *rel8 = &ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8;
+
+  if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE) {
+    LOG_D(PHY,"Applying UL config for UE, rnti %x for frame %d, subframe %d\n",
+         rel8->rnti,frame,subframe);
+    uint8_t ulsch_buffer[5477] __attribute__ ((aligned(32)));
+    uint16_t buflen = ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size;
+
+    uint16_t rnti = ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti;
+    uint8_t access_mode=SCHEDULED_ACCESS;
+    if(buflen>0){
+    	if(UE_mac_inst[Mod_id].first_ULSCH_Tx == 1){ // Msg3 case
+    		LOG_D(MAC, "handle_nfapi_ul_pdu_UE_MAC 2.2, Mod_id:%d, SFN/SF: %d/%d \n", Mod_id, frame, subframe);
+    		fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti);
+    		fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, UE_mac_inst[Mod_id].RA_prach_resources.Msg3,buflen, rnti, index);
+    		Msg3_transmitted(Mod_id, 0, frame, 0);
+    		// Panos: Modification
+    		UE_mac_inst[Mod_id].UE_mode[0] = PUSCH;
+    		UE_mac_inst[Mod_id].first_ULSCH_Tx = 0;
+
+    		// Panos: This should be done after the reception of the respective hi_dci0
+    		//UE_mac_inst[Mod_id].first_ULSCH_Tx = 0;
+    	}
+    	else {
+    		//LOG_I(MAC, "Panos-D: handle_nfapi_ul_pdu_UE_MAC 2.3 \n");
+    		ue_get_sdu( Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode);
+    		fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti);
+    		fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer,buflen, rnti, index);
+    	}
+    }
+  }
+
+  else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE) {
+
+	  //AssertFatal((UE_id = find_ulsch(ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE))>=0,
+    //            "No available UE ULSCH for rnti %x\n",ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti);
+	  uint8_t ulsch_buffer[5477] __attribute__ ((aligned(32)));
+	  uint16_t buflen = ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.size;
+	  nfapi_ul_config_ulsch_harq_information *ulsch_harq_information = &ul_config_pdu->ulsch_harq_pdu.harq_information;
+	  uint16_t rnti = ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti;
+	  uint8_t access_mode=SCHEDULED_ACCESS;
+	  if(buflen>0){
+		  if(UE_mac_inst[Mod_id].first_ULSCH_Tx == 1){ // Msg3 case
+			  fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti);
+			  fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, UE_mac_inst[Mod_id].RA_prach_resources.Msg3,buflen, rnti, index);
+			  Msg3_transmitted(Mod_id, 0, frame, 0);
+			  //UE_mac_inst[Mod_id].first_ULSCH_Tx = 0;
+			  // Panos: Modification
+			  UE_mac_inst[Mod_id].UE_mode[0] = PUSCH;
+			  UE_mac_inst[Mod_id].first_ULSCH_Tx = 0;
+		  }
+		  else {
+			  //LOG_I(MAC, "Panos-D: handle_nfapi_ul_pdu_UE_MAC 3.1 \n");
+			  ue_get_sdu( Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode);
+			  fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti);
+			  fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer,buflen, rnti, index);
+		  }
+
+	  }
+	  if(ulsch_harq_information!=NULL)
+		  fill_ulsch_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_harq_information, rnti);
+
+  }
+  else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) {
+	 uint8_t ulsch_buffer[5477] __attribute__ ((aligned(32)));
+	  uint16_t buflen = ul_config_pdu->ulsch_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.size;
+
+	  uint16_t rnti = ul_config_pdu->ulsch_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti;
+	  uint8_t access_mode=SCHEDULED_ACCESS;
+	  if(buflen>0){
+		  if(UE_mac_inst[Mod_id].first_ULSCH_Tx == 1){ // Msg3 case
+			  fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti);
+			  fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, UE_mac_inst[Mod_id].RA_prach_resources.Msg3,buflen, rnti, index);
+			  Msg3_transmitted(Mod_id, 0, frame, 0);
+			  //UE_mac_inst[Mod_id].first_ULSCH_Tx = 0;
+			  // Panos: Modification
+			  UE_mac_inst[Mod_id].UE_mode[0] = PUSCH;
+			  UE_mac_inst[Mod_id].first_ULSCH_Tx = 0;
+		  }
+		  else {
+			  ue_get_sdu( Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode);
+			  fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti);
+			  fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer,buflen, rnti, index);
+		  }
+	  }
+	  fill_ulsch_cqi_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, rnti);
+
+  }
+  else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE) {
+
+	  uint8_t ulsch_buffer[5477] __attribute__ ((aligned(32)));
+	  uint16_t buflen = ul_config_pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.size;
+	  nfapi_ul_config_ulsch_harq_information *ulsch_harq_information = &ul_config_pdu->ulsch_cqi_harq_ri_pdu.harq_information;
+
+	  uint16_t rnti = ul_config_pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti;
+	  uint8_t access_mode=SCHEDULED_ACCESS;
+	  if(buflen>0){
+		  if(UE_mac_inst[Mod_id].first_ULSCH_Tx == 1){ // Msg3 case
+			  fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti);
+			  fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, UE_mac_inst[Mod_id].RA_prach_resources.Msg3,buflen, rnti, index);
+			  Msg3_transmitted(Mod_id, 0, frame, 0);
+			  //UE_mac_inst[Mod_id].first_ULSCH_Tx = 0;
+			  // Panos: Modification
+			  UE_mac_inst[Mod_id].UE_mode[0] = PUSCH;
+			  UE_mac_inst[Mod_id].first_ULSCH_Tx = 0;
+		  }
+		  else {
+			  ue_get_sdu( Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode);
+			  fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti);
+			  fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer,buflen, rnti, index);
+		  }
+	  }
+
+	  if(ulsch_harq_information!=NULL)
+		  fill_ulsch_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_harq_information, rnti);
+	  fill_ulsch_cqi_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, rnti);
+
+  }
+  else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) {
+
+	  uint16_t rnti = ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti;
+
+	  nfapi_ul_config_harq_information *ulsch_harq_information = &ul_config_pdu->uci_harq_pdu.harq_information;
+	  if(ulsch_harq_information != NULL)
+		  fill_uci_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO,ulsch_harq_information, rnti);
+  }
+  else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE) {
+    AssertFatal(1==0,"NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE not handled yet\n");
+  }
+  else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE) {
+    AssertFatal(1==0,"NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE not handled yet\n");
+  }
+  else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE) {
+    AssertFatal(1==0,"NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE not handled yet\n");
+  }
+  else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE) {
+
+	  uint16_t rnti = ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti;
+
+	  if (ue_get_SR(Mod_id ,0,frame, 0, rnti, subframe))
+		  fill_sr_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, rnti);
+
+  }
+  else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE) {
+    //AssertFatal((UE_id = find_uci(rel8->rnti,proc->frame_tx,proc->subframe_tx,eNB,SEARCH_EXIST_OR_FREE))>=0,
+    //            "No available UE UCI for rnti %x\n",ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti);
+
+	  uint16_t rnti = ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti;
+
+	  // We fill the sr_indication only if ue_get_sr() would normally instruct PHY to send a SR.
+	  if (ue_get_SR(Mod_id ,0,frame, 0, rnti, subframe))
+		  fill_sr_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO,rnti);
+
+	  nfapi_ul_config_harq_information *ulsch_harq_information = &ul_config_pdu->uci_sr_harq_pdu.harq_information;
+	  if (ulsch_harq_information != NULL)
+		  fill_uci_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO,ulsch_harq_information, rnti);
+
+  }
+
+}
+
+
+
+
+
+
+int ul_config_req_UE_MAC(nfapi_ul_config_request_t* req, int timer_frame, int timer_subframe, module_id_t Mod_id)
+{
+	//if (req!=NULL){ // && req->ul_config_request_body.ul_config_pdu_list !=NULL){
+  LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n",
+      __FUNCTION__,
+      NFAPI_SFNSF2DEC(req->sfn_sf),
+      req->ul_config_request_body.number_of_pdus,
+      req->ul_config_request_body.rach_prach_frequency_resources,
+      req->ul_config_request_body.srs_present
+      );
+
+  int sfn = NFAPI_SFNSF2SFN(req->sfn_sf);
+  int sf = NFAPI_SFNSF2SF(req->sfn_sf);
+
+
+  LOG_D(MAC, "ul_config_req_UE_MAC() TOTAL NUMBER OF UL_CONFIG PDUs: %d, SFN/SF: %d/%d \n", req->ul_config_request_body.number_of_pdus, timer_frame, timer_subframe);
+
+
+
+  for (int i=0;i<req->ul_config_request_body.number_of_pdus;i++)
+  {
+
+    if (
+    		(req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE && req->ul_config_request_body.ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_mac_inst[Mod_id].crnti) ||
+    		(req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE && req->ul_config_request_body.ul_config_pdu_list[i].ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == UE_mac_inst[Mod_id].crnti) ||
+    		(req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE && req->ul_config_request_body.ul_config_pdu_list[i].ulsch_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == UE_mac_inst[Mod_id].crnti) ||
+    		(req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE && req->ul_config_request_body.ul_config_pdu_list[i].ulsch_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == UE_mac_inst[Mod_id].crnti) ||
+    		(req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && req->ul_config_request_body.ul_config_pdu_list[i].uci_cqi_harq_pdu.ue_information.ue_information_rel8.rnti == UE_mac_inst[Mod_id].crnti) ||
+    		(req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE && req->ul_config_request_body.ul_config_pdu_list[i].uci_sr_pdu.ue_information.ue_information_rel8.rnti == UE_mac_inst[Mod_id].crnti) ||
+    		(req->ul_config_request_body.ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE && req->ul_config_request_body.ul_config_pdu_list[i].uci_cqi_sr_harq_pdu.ue_information.ue_information_rel8.rnti == UE_mac_inst[Mod_id].crnti)
+       )
+    {
+
+      handle_nfapi_ul_pdu_UE_MAC(Mod_id,&req->ul_config_request_body.ul_config_pdu_list[i],sfn,sf,req->ul_config_request_body.srs_present, i);
+
+    }
+    else
+    {
+      //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() PDU:%i UNKNOWN type :%d\n", __FUNCTION__, i, ul_config_pdu_list[i].pdu_type);
+    }
+  }
+
+//	}
+
+  return 0;
+}
+
+
+
+int tx_req_UE_MAC(nfapi_tx_request_t* req)
+{
+  uint16_t sfn = NFAPI_SFNSF2SFN(req->sfn_sf);
+  uint16_t sf = NFAPI_SFNSF2SF(req->sfn_sf);
+
+  LOG_D(PHY,"%s() SFN/SF:%d/%d PDUs:%d\n", __FUNCTION__, sfn, sf, req->tx_request_body.number_of_pdus);
+
+
+    for (int i=0; i<req->tx_request_body.number_of_pdus; i++)
+    {
+      LOG_D(PHY,"%s() SFN/SF:%d/%d number_of_pdus:%d [PDU:%d] pdu_length:%d pdu_index:%d num_segments:%d\n",
+          __FUNCTION__,
+          sfn, sf,
+          req->tx_request_body.number_of_pdus,
+          i,
+          req->tx_request_body.tx_pdu_list[i].pdu_length,
+          req->tx_request_body.tx_pdu_list[i].pdu_index,
+          req->tx_request_body.tx_pdu_list[i].num_segments
+          );
+
+    }
+
+  return 0;
+}
+
+
+int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, module_id_t Mod_id) //, nfapi_tx_request_pdu_t* tx_request_pdu_list)
+{
+	//if (req!=NULL && tx_request_pdu_list!=NULL){
+  int sfn = NFAPI_SFNSF2SFN(req->sfn_sf);
+  int sf = NFAPI_SFNSF2SF(req->sfn_sf);
+  //Mod_id = 0; // Currently static (only for one UE) but this should change.
+
+  /*struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
+  eNB_rxtx_proc_t *proc = &eNB->proc.proc_rxtx[0];*/
+  nfapi_dl_config_request_pdu_t* dl_config_pdu_list = req->dl_config_request_body.dl_config_pdu_list;
+  nfapi_dl_config_request_pdu_t *dl_config_pdu_tmp;
+
+  //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d sfn_sf:%d DCI:%d PDU:%d\n", __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->frame_rx, proc->subframe_rx, NFAPI_SFNSF2DEC(req->sfn_sf), req->dl_config_request_body.number_dci, req->dl_config_request_body.number_pdu);
+
+
+
+  //LOG_D(PHY,"NFAPI: Sched_INFO:SFN/SF:%d%d dl_pdu:%d tx_req:%d hi_dci0:%d ul_cfg:%d num_pdcch_symbols:%d\n",
+  //	frame,subframe,number_dl_pdu,TX_req->tx_request_body.number_of_pdus,number_hi_dci0_pdu,number_ul_pdu, eNB->pdcch_vars[subframe&1].num_pdcch_symbols);
+
+  for (int i=0;i<req->dl_config_request_body.number_pdu;i++)
+  {
+    //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sfn/sf:%d PDU[%d] size:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size);
+	  //LOG_E(MAC, "dl_config_req_UE_MAC 2 Received real ones: sfn/sf:%d.%d PDU[%d] size:%d\n", sfn, sf, i, dl_config_pdu_list[i].pdu_size);
+
+    if (dl_config_pdu_list[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
+    {
+		if (dl_config_pdu_list[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type == 1) {
+			// C-RNTI (Normal DLSCH case)
+			dl_config_pdu_tmp = &dl_config_pdu_list[i+1];
+			if (dl_config_pdu_tmp->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE && UE_mac_inst[Mod_id].crnti == dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.rnti){
+
+				/*nfapi_tx_request_pdu_t *ptr = tx_request_pdu_list;
+				ptr += dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index*(sizeof(nfapi_tx_request_pdu_t));
+				nfapi_tx_request_pdu_t temp;
+				memset(&temp, 0, sizeof(nfapi_tx_request_pdu_t));
+				//if (!memcmp(&temp, ptr, sizeof(temp)) ...
+				if( *(char*)ptr != 0){
+				//if(tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data!= NULL && tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_length >0){
+				*/
+
+				if(dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index <= tx_req_num_elems -1){
+				//if(tx_request_pdu_list + dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index!= NULL){
+
+					LOG_E(MAC, "dl_config_req_UE_MAC 2 Received data: sfn/sf:%d PDU[%d] size:%d, TX_PDU index: %d, tx_req_num_elems: %d \n", NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size, dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index, tx_req_num_elems);
+
+					ue_send_sdu(Mod_id, 0, sfn, sf,
+							tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data,
+							tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_length,
+							0);
+					i++;
+				}
+				else{
+					LOG_E(MAC,"dl_config_req_UE_MAC 2: Problem with receiving data: sfn/sf:%d PDU[%d] size:%d, TX_PDU index: %d\n", NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size, dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index);
+					i++;
+				}
+			}
+			else {
+				LOG_E(MAC,"[UE %d] Frame %d, subframe %d : DLSCH PDU from NFAPI not for this UE \n",Mod_id, sfn,sf);
+				i++;
+			}
+		}
+		else if (dl_config_pdu_list[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type == 2) {
+			dl_config_pdu_tmp = &dl_config_pdu_list[i+1];
+			if(dl_config_pdu_tmp->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE && dl_config_pdu_list[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti == 0xFFFF && UE_mac_inst[Mod_id].UE_mode[0] != NOT_SYNCHED){ //&& UE_mac_inst[Mod_id].UE_mode[0] != NOT_SYNCHED
+
+				if(dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index <= tx_req_num_elems -1){
+				//if(tx_request_pdu_list + dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index!= NULL){
+					ue_decode_si(Mod_id, 0, sfn, 0,
+							tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data,
+							tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_length);
+					i++;
+				}
+				else{
+					LOG_E(MAC,"dl_config_req_UE_MAC 3: Problem with receiving SI: sfn/sf:%d PDU[%d] size:%d, TX_PDU index: %d\n", NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size, dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index);
+					i++;
+				}
+			}
+			else if(dl_config_pdu_tmp->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE && dl_config_pdu_list[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti == 0xFFFE){
+				// P_RNTI case
+				//pdu = Tx_req->tx_request_body.tx_pdu_list[dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data;
+
+				if (dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index <= tx_req_num_elems -1){
+				//if(tx_request_pdu_list + dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index!= NULL){
+					ue_decode_p(Mod_id, 0, sfn, 0,
+							tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data,
+							tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_length);
+					i++;
+				}
+				else{
+					LOG_E(MAC,"dl_config_req_UE_MAC: Problem with receiving Paging: sfn/sf:%d PDU[%d] size:%d, TX_PDU index: %d\n", NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size, dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index);
+					i++;
+				}
+			}
+			else if(dl_config_pdu_tmp->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE) {
+				// RA-RNTI case
+				LOG_E(MAC,"dl_config_req_UE_MAC 4 Received RAR? \n");
+				// RNTI parameter not actually used. Provided only to comply with existing function definition.
+				// Not sure about parameters to fill the preamble index.
+				//rnti_t c_rnti = UE_mac_inst[Mod_id].crnti;
+				rnti_t ra_rnti = UE_mac_inst[Mod_id].RA_prach_resources.ra_RNTI;
+				if ((UE_mac_inst[Mod_id].UE_mode[0] != PUSCH) &&
+				  (UE_mac_inst[Mod_id].RA_prach_resources.Msg3!=NULL) && (ra_rnti== dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.rnti) &&
+				  //(tx_request_pdu_list + dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index!= NULL)) {
+				  (dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index <= tx_req_num_elems -1)) {
+					LOG_E(MAC,"dl_config_req_UE_MAC 5 Received RAR, PreambleIndex: %d \n", UE_mac_inst[Mod_id].RA_prach_resources.ra_PreambleIndex);
+					ue_process_rar(Mod_id, 0, sfn,
+							ra_rnti, //RA-RNTI
+							tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data,
+							&dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.rnti, //t-crnti
+							UE_mac_inst[Mod_id].RA_prach_resources.ra_PreambleIndex,
+							tx_request_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data);
+					UE_mac_inst[Mod_id].UE_mode[0] = RA_RESPONSE;
+					UE_mac_inst[Mod_id].first_ULSCH_Tx = 1; //Expecting an UL_CONFIG_ULSCH_PDU to enable Msg3 Txon (first ULSCH Txon for the UE)
+				}
+				i++;
+			}
+			else {
+				LOG_E(MAC,"[UE %d] Frame %d, subframe %d : Cannot extract DLSCH PDU from NFAPI 2\n",Mod_id, sfn, sf);
+				i++;
+			}
+
+		}
+    }
+    else if (dl_config_pdu_list[i].pdu_type == NFAPI_DL_CONFIG_BCH_PDU_TYPE)
+    {
+    	// BCH case
+    	// Last parameter is 1 if first time synchronization and zero otherwise. Not sure which value to put
+    	// for our case.
+    	//LOG_E(MAC,"dl_config_req_UE_MAC 4 Received MIB: sfn/sf: %d.%d \n", sfn, sf);
+    	if(UE_mac_inst[Mod_id].UE_mode[0] == NOT_SYNCHED){
+    		dl_phy_sync_success(Mod_id,sfn,0, 1);
+    		LOG_E(MAC,"dl_config_req_UE_MAC 5 Received MIB: UE_mode: %d, sfn/sf: %d.%d\n", UE_mac_inst[Mod_id].UE_mode[0], sfn, sf);
+    		UE_mac_inst[Mod_id].UE_mode[0]=PRACH;
+    	}
+    	else
+    		dl_phy_sync_success(Mod_id,sfn,0, 0);
+
+    }
+
+    else
+    {
+      //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() UNKNOWN:%d\n", __FUNCTION__, dl_config_pdu_list[i].pdu_type);
+    }
+  }
+
+  return 0;
+
+}
+
+
+int hi_dci0_req_UE_MAC(nfapi_hi_dci0_request_t* req, module_id_t Mod_id)
+{
+	if (req!=NULL && req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
+  LOG_D(PHY,"[UE-PHY_STUB] hi dci0 request sfn_sf:%d number_of_dci:%d number_of_hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi);
+
+
+
+  for (int i=0; i<req->hi_dci0_request_body.number_of_dci + req->hi_dci0_request_body.number_of_hi; i++)
+  {
+    LOG_D(PHY,"[UE-PHY_STUB] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i);
+
+    if (req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE)
+    {
+      LOG_D(PHY,"[UE-PHY_STUB] HI_DCI0_REQ sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_DCI_PDU_TYPE not used \n", NFAPI_SFNSF2DEC(req->sfn_sf), i);
+
+    }
+    else if (req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type == NFAPI_HI_DCI0_HI_PDU_TYPE)
+    {
+      //LOG_I(MAC,"[UE-PHY_STUB] HI_DCI0_REQ sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_HI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i);
+
+      nfapi_hi_dci0_request_pdu_t *hi_dci0_req_pdu = &req->hi_dci0_request_body.hi_dci0_pdu_list[i];
+
+      // This is meaningful only after ACKnowledging the first ULSCH Txon (i.e. Msg3)
+      if(hi_dci0_req_pdu->hi_pdu.hi_pdu_rel8.hi_value == 1 && UE_mac_inst[Mod_id].first_ULSCH_Tx == 1){
+    	  //LOG_I(MAC,"[UE-PHY_STUB] HI_DCI0_REQ 2 sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_HI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i);
+    	  //UE_mac_inst[Mod_id].UE_mode[0] = PUSCH;
+    	  //UE_mac_inst[Mod_id].first_ULSCH_Tx = 0;
+      }
+
+    }
+    else
+    {
+      LOG_E(PHY,"[UE-PHY_STUB] HI_DCI0_REQ sfn_sf:%d PDU[%d] - unknown pdu type:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), i, req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type);
+    }
+  }
+
+  }
+
+
+  return 0;
+}
+
+
+
+
+
+// The following set of memcpy functions should be getting called as callback functions from
+// pnf_p7_subframe_ind.
+int memcpy_dl_config_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_dl_config_request_t* req)
+{
+
+	//module_id_t Mod_id = 0; //Panos: Currently static (only for one UE) but this should change.
+
+	//for (Mod_id=0; Mod_id<NB_UE_INST; Mod_id++){
+
+	dl_config_req = (nfapi_dl_config_request_t*)malloc(sizeof(nfapi_dl_config_request_t));
+	//LOG_I(MAC, "Panos-D: memcpy_dl_config_req 1, Mod_id:%d \n", Mod_id);
+
+
+	//UE_mac_inst[Mod_id].dl_config_req->header = req->header;
+	dl_config_req->sfn_sf = req->sfn_sf;
+
+	dl_config_req->vendor_extension = req->vendor_extension;
+
+	dl_config_req->dl_config_request_body.number_dci = req->dl_config_request_body.number_dci;
+	dl_config_req->dl_config_request_body.number_pdcch_ofdm_symbols = req->dl_config_request_body.number_pdcch_ofdm_symbols;
+	dl_config_req->dl_config_request_body.number_pdsch_rnti = req->dl_config_request_body.number_pdsch_rnti;
+	dl_config_req->dl_config_request_body.number_pdu = req->dl_config_request_body.number_pdu;
+
+	dl_config_req->dl_config_request_body.tl.tag = req->dl_config_request_body.tl.tag;
+	dl_config_req->dl_config_request_body.tl.length = req->dl_config_request_body.tl.length;
+
+	dl_config_req->dl_config_request_body.dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*) calloc(req->dl_config_request_body.number_pdu, sizeof(nfapi_dl_config_request_pdu_t));
+	for(int i=0; i<dl_config_req->dl_config_request_body.number_pdu; i++) {
+		dl_config_req->dl_config_request_body.dl_config_pdu_list[i] = req->dl_config_request_body.dl_config_pdu_list[i];
+	}
+
+	//}
+
+	return 0;
+
+}
+
+int memcpy_ul_config_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req)
+{
+	//LOG_D(MAC, "Panos-D: memcpy_ul_config_req 1 \n");
+
+	//module_id_t Mod_id = 0; //Panos: Currently static (only for one UE) but this should change.
+
+
+	//for (Mod_id=0; Mod_id<NB_UE_INST; Mod_id++){
+
+		ul_config_req = (nfapi_ul_config_request_t*)malloc(sizeof(nfapi_ul_config_request_t));
+
+	ul_config_req->sfn_sf = req->sfn_sf;
+	ul_config_req->vendor_extension = req->vendor_extension;
+
+
+	ul_config_req->ul_config_request_body.number_of_pdus = req->ul_config_request_body.number_of_pdus;
+	ul_config_req->ul_config_request_body.rach_prach_frequency_resources = req->ul_config_request_body.rach_prach_frequency_resources;
+	ul_config_req->ul_config_request_body.srs_present = req->ul_config_request_body.srs_present;
+
+	ul_config_req->ul_config_request_body.tl.tag = req->ul_config_request_body.tl.tag;
+	ul_config_req->ul_config_request_body.tl.length = req->ul_config_request_body.tl.length;
+
+	//LOG_D(MAC, "memcpy_ul_config_req 1 #ofULPDUs: %d \n", UE_mac_inst[Mod_id].ul_config_req->ul_config_request_body.number_of_pdus); //req->ul_config_request_body.number_of_pdus);
+	ul_config_req->ul_config_request_body.ul_config_pdu_list = (nfapi_ul_config_request_pdu_t*) malloc(req->ul_config_request_body.number_of_pdus*sizeof(nfapi_ul_config_request_pdu_t));
+	for(int i=0; i<ul_config_req->ul_config_request_body.number_of_pdus; i++) {
+			ul_config_req->ul_config_request_body.ul_config_pdu_list[i] = req->ul_config_request_body.ul_config_pdu_list[i];
+		}
+	//}
+
+	return 0;
+}
+
+
+
+
+int memcpy_tx_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_tx_request_t* req)
+{
+	//module_id_t Mod_id = 0; //Panos: Currently static (only for one UE) but this should change.
+
+
+	tx_req_num_elems = req->tx_request_body.number_of_pdus;
+	tx_request_pdu_list = (nfapi_tx_request_pdu_t*) calloc(tx_req_num_elems, sizeof(nfapi_tx_request_pdu_t));
+	for (int i=0; i<tx_req_num_elems; i++) {
+		tx_request_pdu_list[i].num_segments = req->tx_request_body.tx_pdu_list[i].num_segments;
+		tx_request_pdu_list[i].pdu_index = req->tx_request_body.tx_pdu_list[i].pdu_index;
+		tx_request_pdu_list[i].pdu_length = req->tx_request_body.tx_pdu_list[i].pdu_length;
+		for (int j=0; j<req->tx_request_body.tx_pdu_list[i].num_segments; j++){
+			//*tx_request_pdu_list[i].segments[j].segment_data = *req->tx_request_body.tx_pdu_list[i].segments[j].segment_data;
+			tx_request_pdu_list[i].segments[j].segment_length = req->tx_request_body.tx_pdu_list[i].segments[j].segment_length;
+			if(tx_request_pdu_list[i].segments[j].segment_length > 0){
+				tx_request_pdu_list[i].segments[j].segment_data = (uint8_t*)malloc(tx_request_pdu_list[i].segments[j].segment_length*sizeof (uint8_t));
+			memcpy(tx_request_pdu_list[i].segments[j].segment_data, req->tx_request_body.tx_pdu_list[i].segments[j].segment_data, tx_request_pdu_list[i].segments[j].segment_length);
+			}
+		}
+
+	}
+
+	return 0;
+}
+
+int memcpy_hi_dci0_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_hi_dci0_request_t* req)
+{
+
+	//if(req!=0){
+	//module_id_t Mod_id = 0; //Panos: Currently static (only for one UE) but this should change.
+
+	//for (Mod_id=0; Mod_id<NB_UE_INST; Mod_id++){
+	hi_dci0_req = (nfapi_hi_dci0_request_t*)malloc(sizeof(nfapi_hi_dci0_request_t));
+
+	hi_dci0_req->sfn_sf = req->sfn_sf;
+	hi_dci0_req->vendor_extension = req->vendor_extension;
+
+	hi_dci0_req->hi_dci0_request_body.number_of_dci = req->hi_dci0_request_body.number_of_dci;
+	hi_dci0_req->hi_dci0_request_body.number_of_hi = req->hi_dci0_request_body.number_of_hi;
+	hi_dci0_req->hi_dci0_request_body.sfnsf = req->hi_dci0_request_body.sfnsf;
+
+	//UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.tl = req->hi_dci0_request_body.tl;
+	hi_dci0_req->hi_dci0_request_body.tl.tag = req->hi_dci0_request_body.tl.tag;
+	hi_dci0_req->hi_dci0_request_body.tl.length = req->hi_dci0_request_body.tl.length;
+
+	int total_pdus = hi_dci0_req->hi_dci0_request_body.number_of_dci + hi_dci0_req->hi_dci0_request_body.number_of_hi;
+
+	hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*) malloc(total_pdus*sizeof(nfapi_hi_dci0_request_pdu_t));
+
+	for(int i=0; i<total_pdus; i++){
+		hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list[i] = req->hi_dci0_request_body.hi_dci0_pdu_list[i];
+		//LOG_I(MAC, "Original hi_dci0 req. type:%d, Copy type: %d \n",req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type, UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type);
+	}
+
+	//}
+		return 0;
+}
+
+
+
+void UE_config_stub_pnf(void) {
+  int               j;
+  paramdef_t L1_Params[] = L1PARAMS_DESC;
+  paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST,NULL,0};
+
+  config_getlist( &L1_ParamList,L1_Params,sizeof(L1_Params)/sizeof(paramdef_t), NULL);
+  if (L1_ParamList.numelt > 0) {
+	  for (j=0; j<L1_ParamList.numelt; j++){
+		  //nb_L1_CC = *(L1_ParamList.paramarray[j][L1_CC_IDX].uptr); // Number of component carriers is of no use for the
+	                                                            // phy_stub mode UE pnf. Maybe we can completely skip it.
+
+		  if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
+			  sf_ahead = 4; // Need 4 subframe gap between RX and TX
+			  }
+		  // Panos: Right now that we have only one UE (thread) it is ok to put the eth_params in the UE_mac_inst.
+		  // Later I think we have to change that to attribute eth_params to a global element for all the UEs.
+		  else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
+			  stub_eth_params.local_if_name            = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_IF_NAME_IDX].strptr));
+			  stub_eth_params.my_addr                  = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr));
+			  stub_eth_params.remote_addr              = strdup(*(L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr));
+			  stub_eth_params.my_portc                 = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr);
+			  stub_eth_params.remote_portc             = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr);
+			  stub_eth_params.my_portd                 = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr);
+			  stub_eth_params.remote_portd             = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr);
+			  stub_eth_params.transp_preference        = ETH_UDP_MODE;
+
+			  sf_ahead = 2; // Cannot cope with 4 subframes betweem RX and TX - set it to 2
+			  //configure_nfapi_pnf(UE_mac_inst[0].eth_params_n.remote_addr, UE_mac_inst[0].eth_params_n.remote_portc, UE_mac_inst[0].eth_params_n.my_addr, UE_mac_inst[0].eth_params_n.my_portd, UE_mac_inst[0].eth_params_n.remote_portd);
+			  configure_nfapi_pnf(stub_eth_params.remote_addr, stub_eth_params.remote_portc, stub_eth_params.my_addr, stub_eth_params.my_portd, stub_eth_params.remote_portd);
+		  }
+		  else { // other midhaul
+		  }
+	  }
+  }
+  else {
+
+  }
+}
+
+
+/* Dummy functions*/
+
+void handle_nfapi_hi_dci0_dci_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,eNB_rxtx_proc_t *proc,
+                                  nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu)
+{
+
+}
+
+
+void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,eNB_rxtx_proc_t *proc,
+                                 nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu)
+{
+
+}
+
+
+void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB *eNB,
+                             int frame, int subframe,
+                             eNB_rxtx_proc_t *proc,
+                             nfapi_dl_config_request_pdu_t *dl_config_pdu)
+{
+
+}
+
+
+void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
+                          nfapi_dl_config_request_pdu_t *dl_config_pdu,
+                          uint8_t *sdu)
+{
+
+}
+
+
+void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,eNB_rxtx_proc_t *proc,
+                            nfapi_dl_config_request_pdu_t *dl_config_pdu,
+                            uint8_t codeword_index,
+                            uint8_t *sdu)
+{
+
+}
+
+
+void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
+                         nfapi_ul_config_request_pdu_t *ul_config_pdu,
+                         uint16_t frame,uint8_t subframe,uint8_t srs_present)
+{
+
+}
+
+void phy_config_request(PHY_Config_t *phy_config) {
+
+}
+
+uint32_t from_earfcn(int eutra_bandP, uint32_t dl_earfcn) { return(0);}
+
+int32_t get_uldl_offset(int eutra_bandP) { return(0);}
+
+int l1_north_init_eNB() {
+return 0;
+}
+
+void init_eNB_afterRU(void) {
+
+}
+
diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.h b/openair2/PHY_INTERFACE/phy_stub_UE.h
new file mode 100644
index 0000000000000000000000000000000000000000..9865be3eebb2eab81fd10acde8b97bafe6fe2846
--- /dev/null
+++ b/openair2/PHY_INTERFACE/phy_stub_UE.h
@@ -0,0 +1,118 @@
+/*
+ * phy_stub_UE.h
+ *
+ *  Created on: Sep 14, 2017
+ *      Author: montre
+ */
+
+
+#ifndef __PHY_STUB_UE__H__
+#define __PHY_STUB_UE__H__
+
+#include <stdint.h>
+#include "openair2/PHY_INTERFACE/IF_Module.h"
+#include "nfapi_interface.h"
+#include "nfapi_pnf_interface.h"
+//#include "openair1/PHY/LTE_TRANSPORT/defs.h"
+//#include "openair1/PHY/defs.h"
+//#include "openair1/PHY/LTE_TRANSPORT/defs.h"
+
+UL_IND_t *UL_INFO;
+
+nfapi_tx_request_pdu_t* tx_request_pdu_list;
+// New
+/// Panos: Pointers to config_request types. Used from nfapi callback functions.
+nfapi_dl_config_request_t* dl_config_req;
+nfapi_ul_config_request_t* ul_config_req;
+nfapi_hi_dci0_request_t* hi_dci0_req;
+
+int	tx_req_num_elems;
+
+int next_ra_frame;
+module_id_t next_Mod_id;
+eth_params_t         stub_eth_params;
+
+
+
+
+// Panos: This function should return all the sched_response config messages which concern a specific UE. Inside this
+// function we should somehow make the translation of config message's rnti to Mod_ID.
+Sched_Rsp_t get_nfapi_sched_response(uint8_t Mod_id);
+
+// This function will be processing DL_config and Tx.requests and trigger all the MAC Rx related calls at the UE side,
+// namely:ue_send_sdu(), or ue_decode_si(), or ue_decode_p(), or ue_process_rar() based on the rnti type.
+//void handle_nfapi_UE_Rx(uint8_t Mod_id, Sched_Rsp_t *Sched_INFO, int eNB_id);
+
+int pnf_ul_config_req_UE_MAC(nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req);
+
+// This function will be processing UL and HI_DCI0 config requests to trigger all the MAC Tx related calls
+// at the UE side, namely: ue_get_SR(), ue_get_rach(), ue_get_sdu() based on the pdu configuration type.
+// The output of these calls will be put to an UL_IND_t structure which will then be the input to
+// send_nfapi_UL_indications().
+UL_IND_t generate_nfapi_UL_indications(Sched_Rsp_t sched_response);
+
+// This function should pass the UL indication messages to the eNB side through the socket interface.
+void send_nfapi_UL_indications(UL_IND_t UL_INFO);
+
+// This function should be filling the nfapi ULSCH indications at the MAC level of the UE in a similar manner
+// as fill_rx_indication() does. It should get called from ue_get_SDU()
+
+//void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe);
+
+void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t *ulsch_buffer, uint16_t buflen, uint16_t rnti, int index);
+
+
+// This function should be indicating directly to the eNB when there is a planned scheduling request at the MAC layer
+// of the UE. It should get called from ue_get_SR()
+void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint16_t rnti);
+
+// In our case the this function will be always indicating ACK to the MAC of the eNB (i.e. always assuming)
+// successful decoding.
+void fill_crc_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t crc_flag, int index, uint16_t rnti);
+
+
+void fill_rach_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t ra_PreambleIndex, uint16_t ra_RNTI);
+
+
+void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint16_t frame,uint8_t subframe, UL_IND_t *UL_INFO, uint16_t rnti);
+
+
+void fill_ulsch_harq_indication_UE_MAC(int Mod_id, int frame,int subframe, UL_IND_t *UL_INFO, nfapi_ul_config_ulsch_harq_information *harq_information, uint16_t rnti);
+
+void fill_uci_harq_indication_UE_MAC(int Mod_id, int frame, int subframe, UL_IND_t *UL_INFO,nfapi_ul_config_harq_information *harq_information, uint16_t rnti
+			      /*uint8_t tdd_mapping_mode,
+			      uint16_t tdd_multiplexing_mask*/);
+
+int ul_config_req_UE_MAC(nfapi_ul_config_request_t* req, int frame, int subframe, module_id_t Mod_id);
+
+void handle_nfapi_ul_pdu_UE_MAC(module_id_t Mod_id,
+                         nfapi_ul_config_request_pdu_t *ul_config_pdu,
+                         uint16_t frame,uint8_t subframe,uint8_t srs_present, int index);
+
+//int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, nfapi_tx_request_pdu_t* tx_request_pdu_list);
+int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, module_id_t Mod_id);
+
+int tx_req_UE_MAC(nfapi_tx_request_t* req);
+
+
+int hi_dci0_req_UE_MAC(nfapi_hi_dci0_request_t* req, module_id_t Mod_id);
+
+// The following set of memcpy functions should be getting called as callback functions from
+// pnf_p7_subframe_ind.
+
+int memcpy_dl_config_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_dl_config_request_t* req);
+
+
+int memcpy_ul_config_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req);
+
+
+int memcpy_tx_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_tx_request_t* req);
+
+
+int memcpy_hi_dci0_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_hi_dci0_request_t* req);
+
+void UE_config_stub_pnf(void);
+
+
+
+#endif /* PHY_STUB_UE_H_ */
diff --git a/openair2/RRC/LITE/L2_interface_ue.c b/openair2/RRC/LITE/L2_interface_ue.c
index 244f0d2253bbd6cd78f5724650be5b3dcf7a29d3..4c85c2d2478219001b9980da86a1ce0b19984c1e 100644
--- a/openair2/RRC/LITE/L2_interface_ue.c
+++ b/openair2/RRC/LITE/L2_interface_ue.c
@@ -71,6 +71,21 @@ mac_rrc_data_req_ue(
   LOG_I(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%d\n",Mod_idP,Srb_id);
 #endif
 
+
+#ifdef Rel14
+     LOG_D(RRC,"[UE %d] Frame %d Filling SL DISCOVERY SRB_ID %d\n",Mod_idP,frameP,Srb_id);
+     LOG_D(RRC,"[UE %d] Frame %d buffer_pP status %d,\n",Mod_idP,frameP, UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.payload_size);
+
+   //TTN (for D2D)
+     if (Srb_id  == SL_DISCOVERY && UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.payload_size > 0){
+        memcpy(&buffer_pP[0],&UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.Payload[0],UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.payload_size);
+        uint8_t Ret_size=UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.payload_size;
+        LOG_I(RRC,"[UE %d] Sending SL_Discovery, size %d bytes\n",Mod_idP,Ret_size);
+        UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.payload_size = 0;
+        return(Ret_size);
+     }
+#endif
+
   LOG_D(RRC,"[UE %d] Frame %d Filling CCCH SRB_ID %d\n",Mod_idP,frameP,Srb_id);
   LOG_D(RRC,"[UE %d] Frame %d buffer_pP status %d,\n",Mod_idP,frameP, UE_rrc_inst[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size);
 
@@ -241,6 +256,11 @@ mac_rrc_data_ind_ue(
       decode_MCCH_Message(&ctxt, eNB_indexP, sduP, sdu_lenP, mbsfn_sync_areaP);
 #endif
     }
+    //TTN (for D2D)
+    if(srb_idP == SL_DISCOVERY) {
+    	LOG_I(RRC,"[UE %d] Received SDU (%d bytes) for SL_DISCOVERY on SRB %d from eNB %d\n",module_idP, sdu_lenP, srb_idP,eNB_indexP);
+    	decode_SL_Discovery_Message(&ctxt, eNB_indexP, sduP, sdu_lenP);
+    }
 
 #endif // Rel10 || Rel14
 
@@ -315,7 +335,11 @@ rrc_data_req_ue(
            confirmP,
            sdu_sizeP,
            buffer_pP,
-           modeP);
+           modeP
+#ifdef Rel14
+           ,NULL, NULL
+#endif
+           );
 #endif
 }
 
@@ -384,6 +408,7 @@ void rrc_in_sync_ind(module_id_t Mod_idP, frame_t frameP, uint16_t eNB_index)
   UE_rrc_inst[Mod_idP].Info[eNB_index].N310_cnt=0;
 
   if (UE_rrc_inst[Mod_idP].Info[eNB_index].T310_active==1) {
+    LOG_D(RRC, "Panos-D: rrc_in_sync_ind 1 \n");
     UE_rrc_inst[Mod_idP].Info[eNB_index].N311_cnt++;
   }
 
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.c b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
index 77ba0c4cade0378c36db0cb8807d4f1a23b30ace..6b076d27bc1024c72a091526a00e256a29e5fe04 100644
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
@@ -70,6 +70,8 @@
 #include "SIB-Type.h"
 
 #include "BCCH-DL-SCH-Message.h"
+#include "SBCCH-SL-BCH-MessageType.h"
+#include "SBCCH-SL-BCH-Message.h"
 
 #include "PHY/defs.h"
 
@@ -272,6 +274,67 @@ uint8_t do_MIB(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t phich
   return((enc_rval.encoded+7)/8);
 }
 
+//TTN for D2D
+// 3GPP 36.331 (Section 5.10.7.4)
+uint8_t do_MIB_SL(const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, uint32_t frame, uint8_t subframe, uint8_t in_coverage, uint8_t mode)
+{
+
+   asn_enc_rval_t enc_rval;
+   SBCCH_SL_BCH_MessageType_t *mib_sl = &UE_rrc_inst[ctxt_pP->module_id].mib_sl[eNB_index];
+   uint8_t sfn = (uint8_t)((frame>>2)&0xff);
+   UE_rrc_inst[ctxt_pP->module_id].MIB = (uint8_t*) malloc16(4);
+
+   if (in_coverage > 0 ){
+      //in coverage
+      mib_sl->inCoverage_r12 = TRUE;
+      mib_sl->sl_Bandwidth_r12 = *UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->freqInfo.ul_Bandwidth;
+      if (UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]->tdd_Config) {
+         mib_sl->tdd_ConfigSL_r12.subframeAssignmentSL_r12 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]->tdd_Config->subframeAssignment;
+      } else {
+         mib_sl->tdd_ConfigSL_r12.subframeAssignmentSL_r12 = TDD_ConfigSL_r12__subframeAssignmentSL_r12_none;
+      }
+      //if triggered by sl communication
+      if (UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index]->commConfig_r12->commSyncConfig_r12->list.array[0]->txParameters_r12->syncInfoReserved_r12){
+         mib_sl->reserved_r12 = *UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index]->commConfig_r12->commSyncConfig_r12->list.array[0]->txParameters_r12->syncInfoReserved_r12;
+      }
+      //if triggered by sl discovery
+      if (UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index]->discConfig_r12->discSyncConfig_r12->list.array[0]->txParameters_r12->syncInfoReserved_r12){
+              mib_sl->reserved_r12 = *UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index]->discConfig_r12->discSyncConfig_r12->list.array[0]->txParameters_r12->syncInfoReserved_r12;
+       }
+      //Todo - if triggered by v2x
+   } else {
+   //Todo - out of coverage for V2X
+   // Todo - UE has a selected SyncRef UE
+   mib_sl->inCoverage_r12 = FALSE;
+   //set sl-Bandwidth, subframeAssignmentSL and reserved from the pre-configured parameters
+   }
+
+   //set FrameNumber, subFrameNumber
+   mib_sl->directFrameNumber_r12.buf =  &sfn;
+   mib_sl->directFrameNumber_r12.size = 1;
+   mib_sl->directFrameNumber_r12.bits_unused=0;
+   mib_sl->directSubframeNumber_r12 = subframe;
+
+
+  LOG_I(RRC,"[MIB-SL] sfn %x, subframe %x\n", (uint32_t)sfn, (uint8_t)subframe);
+
+
+  enc_rval = uper_encode_to_buffer(&asn_DEF_SBCCH_SL_BCH_Message,
+                                   (void*)mib_sl,
+                                   UE_rrc_inst[ctxt_pP->module_id].MIB,
+                                   24);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+
+  if (enc_rval.encoded==-1) {
+    return(-1);
+  }
+
+  return((enc_rval.encoded+7)/8);
+}
+
+
 uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
 		int Mod_id,int CC_id
 #if defined(ENABLE_ITTI)
@@ -414,6 +477,16 @@ uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
   ASN_SEQUENCE_ADD(&schedulingInfo.sib_MappingInfo.list,&sib_type);
   ASN_SEQUENCE_ADD(&(*sib1)->schedulingInfoList.list,&schedulingInfo);
 
+  //TTN - This is for SIB18
+  sib_type=SIB_Type_sibType18_v1250;
+  ASN_SEQUENCE_ADD(&schedulingInfo.sib_MappingInfo.list,&sib_type);
+  ASN_SEQUENCE_ADD(&(*sib1)->schedulingInfoList.list,&schedulingInfo);
+
+  //TTN - This is for SIB19
+  sib_type=SIB_Type_sibType19_v1250;
+  ASN_SEQUENCE_ADD(&schedulingInfo.sib_MappingInfo.list,&sib_type);
+  ASN_SEQUENCE_ADD(&(*sib1)->schedulingInfoList.list,&schedulingInfo);
+
   //  ASN_SEQUENCE_ADD(&schedulingInfo.sib_MappingInfo.list,NULL);
 
 #if defined(ENABLE_ITTI)
@@ -487,7 +560,21 @@ uint8_t do_SIB23(uint8_t Mod_id,
 #endif
                 )
 {
+
   struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member *sib2_part,*sib3_part;
+
+#if defined(Rel14)
+  //TTN - for D2D
+  struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member *sib18_part, *sib19_part, *sib21_part;
+  SL_CommRxPoolList_r12_t *SL_CommRxPoolList; //for SIB18
+  struct SL_CommResourcePool_r12 *SL_CommResourcePool; //for SIB18
+  SL_DiscRxPoolList_r12_t *SL_DiscRxPoolList; //for SIB19 (discRxPool)
+  struct SL_DiscResourcePool_r12 *SL_DiscResourcePool; //for SIB19 (discRxPool)
+  //SL_DiscRxPoolList_r12_t *SL_DiscRxPoolPSList; //for SIB19 (discRxPoolPS)
+  //struct SL_DiscResourcePool_r12 *SL_DiscResourcePoolPS; //for SIB19 (discRxPoolPS)
+  //struct SL_V2X_ConfigCommon_r14 *SL_V2X_ConfigCommon;
+#endif
+
 #if defined(Rel10) || defined(Rel14)
   struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member *sib13_part;
   MBSFN_SubframeConfigList_t *MBSFNSubframeConfigList;
@@ -505,6 +592,13 @@ uint8_t do_SIB23(uint8_t Mod_id,
   uint8_t                           MBMS_flag     = RC.rrc[Mod_id]->carrier[CC_id].MBMS_flag;
 #endif
 
+#if defined(Rel10) || defined(Rel14)
+  //TTN - for D2D
+  SystemInformationBlockType18_r12_t     **sib18        = &RC.rrc[Mod_id]->carrier[CC_id].sib18;
+  SystemInformationBlockType19_r12_t     **sib19        = &RC.rrc[Mod_id]->carrier[CC_id].sib19;
+  SystemInformationBlockType21_r14_t     **sib21        = &RC.rrc[Mod_id]->carrier[CC_id].sib21;
+#endif
+
   if (bcch_message) {
     memset(bcch_message,0,sizeof(BCCH_DL_SCH_Message_t));
   } else {
@@ -549,6 +643,26 @@ uint8_t do_SIB23(uint8_t Mod_id,
 
 #endif
 
+#if defined(Rel10) || defined(Rel14)
+  //TTN - for D2D
+  sib18_part = CALLOC(1,sizeof(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+  sib19_part = CALLOC(1,sizeof(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+  sib21_part = CALLOC(1,sizeof(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+  memset(sib18_part,0,sizeof(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+  memset(sib19_part,0,sizeof(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+  memset(sib21_part,0,sizeof(struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member));
+
+  sib18_part->present = SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib18_v1250;
+  sib19_part->present = SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib19_v1250;
+  sib21_part->present = SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib21_v1430;
+
+  *sib18 = &sib18_part->choice.sib18_v1250;
+  *sib19 = &sib19_part->choice.sib19_v1250;
+  *sib21 = &sib21_part->choice.sib21_v1430;
+
+#endif
+
+
   // sib2
 
   (*sib2)->ac_BarringInfo = NULL;
@@ -942,6 +1056,298 @@ uint8_t do_SIB23(uint8_t Mod_id,
 
 #endif
 
+
+#if defined(Rel10) || defined(Rel14)
+  //TTN - for D2D
+  // SIB18
+  //commRxPool_r12
+  (*sib18)->commConfig_r12 = CALLOC (1, sizeof(*(*sib18)->commConfig_r12));
+  SL_CommRxPoolList= &(*sib18)->commConfig_r12->commRxPool_r12;
+  memset(SL_CommRxPoolList,0,sizeof(*SL_CommRxPoolList));
+
+  SL_CommResourcePool = CALLOC(1, sizeof(*SL_CommResourcePool));
+  memset(SL_CommResourcePool,0,sizeof(*SL_CommResourcePool));
+
+  SL_CommResourcePool->sc_CP_Len_r12 = configuration->rxPool_sc_CP_Len[CC_id];
+  SL_CommResourcePool->sc_Period_r12 = configuration->rxPool_sc_Period[CC_id];
+  SL_CommResourcePool->data_CP_Len_r12  = configuration->rxPool_data_CP_Len[CC_id];
+  //sc_TF_ResourceConfig_r12
+  SL_CommResourcePool->sc_TF_ResourceConfig_r12.prb_Num_r12 = configuration->rxPool_ResourceConfig_prb_Num[CC_id];
+  SL_CommResourcePool->sc_TF_ResourceConfig_r12.prb_Start_r12 = configuration->rxPool_ResourceConfig_prb_Start[CC_id];
+  SL_CommResourcePool->sc_TF_ResourceConfig_r12.prb_End_r12 = configuration->rxPool_ResourceConfig_prb_End[CC_id];
+  SL_CommResourcePool->sc_TF_ResourceConfig_r12.offsetIndicator_r12.present = configuration->rxPool_ResourceConfig_offsetIndicator_present[CC_id];
+
+  if (SL_CommResourcePool->sc_TF_ResourceConfig_r12.offsetIndicator_r12.present == SL_OffsetIndicator_r12_PR_small_r12 ) {
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12 = configuration->rxPool_ResourceConfig_offsetIndicator_choice[CC_id] ;
+  } else if (SL_CommResourcePool->sc_TF_ResourceConfig_r12.offsetIndicator_r12.present == SL_OffsetIndicator_r12_PR_large_r12 ){
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.offsetIndicator_r12.choice.large_r12 = configuration->rxPool_ResourceConfig_offsetIndicator_choice[CC_id] ;
+  }
+
+  SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present = configuration->rxPool_ResourceConfig_subframeBitmap_present[CC_id];
+  if (SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs4_r12){
+     //for BS4
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.size = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf  = (uint8_t *)configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.bits_unused = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  } else if (SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs8_r12){
+     //for BS8
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs8_r12.size = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs8_r12.buf  = (uint8_t *)configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs8_r12.bits_unused = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  } else if (SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs12_r12){
+     //for BS12
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs12_r12.size = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs12_r12.buf  = (uint8_t *)configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs12_r12.bits_unused = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs16_r12){
+     //for BS16
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.size = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.buf  = (uint8_t *)configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.bits_unused = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs30_r12){
+     //for BS30
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs30_r12.size = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs30_r12.buf  = (uint8_t *)configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs30_r12.bits_unused = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs40_r12){
+     //for BS40
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.size = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf  = (uint8_t *)configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.bits_unused = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs42_r12){
+     //for BS42
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs42_r12.size = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs42_r12.buf  = (uint8_t *)configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_CommResourcePool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs42_r12.bits_unused = configuration->rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }
+
+  //dataHoppingConfig_r12
+  SL_CommResourcePool->dataHoppingConfig_r12.hoppingParameter_r12 = 0;
+  SL_CommResourcePool->dataHoppingConfig_r12.numSubbands_r12  =  SL_HoppingConfigComm_r12__numSubbands_r12_ns1;
+  SL_CommResourcePool->dataHoppingConfig_r12.rb_Offset_r12 = 0;
+
+  //ue_SelectedResourceConfig_r12
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12 = CALLOC (1, sizeof (*SL_CommResourcePool->ue_SelectedResourceConfig_r12));
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.prb_Num_r12 = 20;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.prb_Start_r12 = 5;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.prb_End_r12 = 44;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.offsetIndicator_r12.present = SL_OffsetIndicator_r12_PR_small_r12;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12 = 0 ;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.present = SubframeBitmapSL_r12_PR_bs40_r12;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.size = 5;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf  = CALLOC(1,5);
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.bits_unused = 0;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[0] = 0xF0;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[1] = 0xFF;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[2] = 0xFF;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[3] = 0xFF;
+  SL_CommResourcePool->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[4] = 0xFF;
+  //SL_CommResourcePool->ue_SelectedResourceConfig_r12->trpt_Subset_r12 = CALLOC (1, sizeof(*SL_CommResourcePool->ue_SelectedResourceConfig_r12->trpt_Subset_r12));
+  //rxParametersNCell_r12
+  SL_CommResourcePool->rxParametersNCell_r12 = CALLOC (1, sizeof (*SL_CommResourcePool->rxParametersNCell_r12));
+  SL_CommResourcePool->rxParametersNCell_r12->tdd_Config_r12 = CALLOC (1, sizeof (*SL_CommResourcePool->rxParametersNCell_r12->tdd_Config_r12));
+  SL_CommResourcePool->rxParametersNCell_r12->tdd_Config_r12->subframeAssignment = 0 ;
+  SL_CommResourcePool->rxParametersNCell_r12->tdd_Config_r12->specialSubframePatterns = 0;
+  SL_CommResourcePool->rxParametersNCell_r12->syncConfigIndex_r12 = 0;
+  //txParameters_r12
+  SL_CommResourcePool->txParameters_r12 = CALLOC (1, sizeof (*SL_CommResourcePool->txParameters_r12));
+  SL_CommResourcePool->txParameters_r12->sc_TxParameters_r12.alpha_r12 = Alpha_r12_al0;
+  SL_CommResourcePool->txParameters_r12->sc_TxParameters_r12.p0_r12 = 0;
+
+  SL_CommResourcePool->ext1 = NULL ;
+  //end SL_CommResourcePool
+  //add SL_CommResourcePool to SL_CommRxPoolList
+  ASN_SEQUENCE_ADD(&SL_CommRxPoolList->list,SL_CommResourcePool);
+  //end commRxPool_r12
+
+  //TODO:  commTxPoolNormalCommon_r12, similar to commRxPool_r12
+  //TODO: commTxPoolExceptional_r12
+  //TODO: commSyncConfig_r12
+  // may add commTxResourceUC-ReqAllowed with Ext1
+  (*sib18)->ext1 = NULL;
+  (*sib18)->lateNonCriticalExtension = NULL;
+  // end SIB18
+
+  // SIB19
+  // fill in all elements of SIB19 if present
+
+  //discConfig_r12
+  (*sib19)->discConfig_r12 = CALLOC (1, sizeof(*(*sib19)->discConfig_r12));
+  SL_DiscRxPoolList = &(*sib19)->discConfig_r12->discRxPool_r12;
+  memset(SL_DiscRxPoolList,0,sizeof(*SL_DiscRxPoolList));
+  //fill SL_DiscResourcePool
+  SL_DiscResourcePool = CALLOC(1, sizeof(*SL_DiscResourcePool));
+
+  SL_DiscResourcePool->cp_Len_r12 = configuration->discRxPool_cp_Len[CC_id];
+  SL_DiscResourcePool->discPeriod_r12 = configuration->discRxPool_discPeriod[CC_id];
+  //sc_TF_ResourceConfig_r12
+  SL_DiscResourcePool->numRetx_r12 = configuration->discRxPool_numRetx[CC_id];
+  SL_DiscResourcePool->numRepetition_r12 = configuration->discRxPool_numRepetition[CC_id];
+  SL_DiscResourcePool->tf_ResourceConfig_r12.prb_Num_r12 = configuration->discRxPool_ResourceConfig_prb_Num[CC_id];
+  SL_DiscResourcePool->tf_ResourceConfig_r12.prb_Start_r12 = configuration->discRxPool_ResourceConfig_prb_Start[CC_id];
+  SL_DiscResourcePool->tf_ResourceConfig_r12.prb_End_r12 = configuration->discRxPool_ResourceConfig_prb_End[CC_id];
+  SL_DiscResourcePool->tf_ResourceConfig_r12.offsetIndicator_r12.present = configuration->discRxPool_ResourceConfig_offsetIndicator_present[CC_id];
+  if (SL_DiscResourcePool->tf_ResourceConfig_r12.offsetIndicator_r12.present == SL_OffsetIndicator_r12_PR_small_r12 ) {
+     SL_DiscResourcePool->tf_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12 = configuration->discRxPool_ResourceConfig_offsetIndicator_choice[CC_id] ;
+  } else if (SL_DiscResourcePool->tf_ResourceConfig_r12.offsetIndicator_r12.present == SL_OffsetIndicator_r12_PR_large_r12 ){
+     SL_DiscResourcePool->tf_ResourceConfig_r12.offsetIndicator_r12.choice.large_r12 = configuration->discRxPool_ResourceConfig_offsetIndicator_choice[CC_id] ;
+  }
+  SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.present = configuration->discRxPool_ResourceConfig_subframeBitmap_present[CC_id];
+  if (SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs4_r12){
+     //for BS4
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.size = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf  =  (uint8_t *)configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.bits_unused = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  } else if (SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs8_r12){
+     //for BS8
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs8_r12.size = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs8_r12.buf  = (uint8_t *)configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs8_r12.bits_unused = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  } else if (SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs12_r12){
+     //for BS12
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs12_r12.size = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs12_r12.buf  = (uint8_t *)configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs12_r12.bits_unused = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs16_r12){
+     //for BS16
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.size = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.buf  = (uint8_t *)configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.bits_unused = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs30_r12){
+     //for BS30
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs30_r12.size = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs30_r12.buf  = (uint8_t *)configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs30_r12.bits_unused = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs40_r12){
+     //for BS40
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.size = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf  = (uint8_t *)configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.bits_unused = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs42_r12){
+     //for BS42
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs42_r12.size = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs42_r12.buf  = (uint8_t *)configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePool->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs42_r12.bits_unused = configuration->discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }
+
+  //add SL_DiscResourcePool to SL_DiscRxPoolList
+  ASN_SEQUENCE_ADD(&SL_DiscRxPoolList->list,SL_DiscResourcePool);
+
+/*
+  //for DiscRxPoolPS
+  (*sib19)->ext1 = CALLOC (1, sizeof(*(*sib19)->ext1));
+  (*sib19)->ext1->discConfigPS_13 = CALLOC (1, sizeof(*((*sib19)->ext1->discConfigPS_13)));
+
+  SL_DiscRxPoolPSList = &(*sib19)->ext1->discConfigPS_13->discRxPoolPS_r13;
+  memset(SL_DiscRxPoolPSList,0,sizeof(*SL_DiscRxPoolPSList));
+  //fill SL_DiscResourcePool
+  SL_DiscResourcePoolPS = CALLOC(1, sizeof(*SL_DiscResourcePoolPS));
+
+  SL_DiscResourcePoolPS->cp_Len_r12 = configuration->discRxPoolPS_cp_Len[CC_id];
+  SL_DiscResourcePoolPS->discPeriod_r12 = configuration->discRxPoolPS_discPeriod[CC_id];
+  //sc_TF_ResourceConfig_r12
+  SL_DiscResourcePoolPS->numRetx_r12 = configuration->discRxPoolPS_numRetx[CC_id];
+  SL_DiscResourcePoolPS->numRepetition_r12 =  configuration->discRxPoolPS_numRepetition[CC_id];
+
+  SL_DiscResourcePoolPS->tf_ResourceConfig_r12.prb_Num_r12 = configuration->discRxPoolPS_ResourceConfig_prb_Num[CC_id];
+  SL_DiscResourcePoolPS->tf_ResourceConfig_r12.prb_Start_r12 = configuration->discRxPoolPS_ResourceConfig_prb_Start[CC_id];
+  SL_DiscResourcePoolPS->tf_ResourceConfig_r12.prb_End_r12 = configuration->discRxPoolPS_ResourceConfig_prb_End[CC_id];
+
+  SL_DiscResourcePoolPS->tf_ResourceConfig_r12.offsetIndicator_r12.present = configuration->discRxPoolPS_ResourceConfig_offsetIndicator_present[CC_id];
+  if (SL_DiscResourcePoolPS->tf_ResourceConfig_r12.offsetIndicator_r12.present == SL_OffsetIndicator_r12_PR_small_r12 ) {
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12 = configuration->discRxPoolPS_ResourceConfig_offsetIndicator_choice[CC_id] ;
+  } else if (SL_DiscResourcePoolPS->tf_ResourceConfig_r12.offsetIndicator_r12.present == SL_OffsetIndicator_r12_PR_large_r12 ){
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.offsetIndicator_r12.choice.large_r12 = configuration->discRxPoolPS_ResourceConfig_offsetIndicator_choice[CC_id] ;
+  }
+
+  SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.present = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_present[CC_id];
+  if (SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs4_r12){
+     //for BS4
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.size = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf  = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.bits_unused = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  } else if (SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs8_r12){
+     //for BS8
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs8_r12.size = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs8_r12.buf  = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs8_r12.bits_unused = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  } else if (SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs12_r12){
+     //for BS12
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs12_r12.size = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs12_r12.buf  = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs12_r12.bits_unused = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs16_r12){
+     //for BS16
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.size = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.buf  = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.bits_unused = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs30_r12){
+     //for BS30
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs30_r12.size = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs30_r12.buf  = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs30_r12.bits_unused = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs40_r12){
+     //for BS40
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.size = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf  = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.bits_unused = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }else if (SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.present == SubframeBitmapSL_r12_PR_bs42_r12){
+     //for BS42
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs42_r12.size = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size[CC_id];
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs42_r12.buf  = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf[CC_id];;
+     SL_DiscResourcePoolPS->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs42_r12.bits_unused = configuration->discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused[CC_id];
+  }
+
+  //add SL_DiscResourcePool to SL_DiscRxPoolList
+  ASN_SEQUENCE_ADD(&SL_DiscRxPoolPSList->list,SL_DiscResourcePoolPS);
+*/
+
+  (*sib19)->lateNonCriticalExtension = NULL;
+  //end SIB19
+
+  //SIB21
+  (*sib21)->sl_V2X_ConfigCommon_r14 = CALLOC (1, sizeof(*(*sib21)->sl_V2X_ConfigCommon_r14));
+  //SL_V2X_ConfigCommon= (*sib21)->sl_V2X_ConfigCommon_r14;
+  memset((*sib21)->sl_V2X_ConfigCommon_r14,0,sizeof(*(*sib21)->sl_V2X_ConfigCommon_r14));
+
+  struct SL_CommRxPoolListV2X_r14 *SL_CommRxPoolListV2X;
+  struct SL_CommResourcePoolV2X_r14 *SL_CommResourcePoolV2X;
+  (*sib21)->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14 = CALLOC(1, sizeof(*(*sib21)->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14));
+  SL_CommRxPoolListV2X = (*sib21)->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14;
+
+  SL_CommResourcePoolV2X = CALLOC(1, sizeof(*SL_CommResourcePoolV2X));
+  memset(SL_CommResourcePoolV2X,0,sizeof(*SL_CommResourcePoolV2X));
+
+  SL_CommResourcePoolV2X->sl_OffsetIndicator_r14 = CALLOC(1, sizeof(*SL_CommResourcePoolV2X->sl_OffsetIndicator_r14));
+  SL_CommResourcePoolV2X->sl_OffsetIndicator_r14->present  = SL_OffsetIndicator_r12_PR_small_r12;
+  SL_CommResourcePoolV2X->sl_OffsetIndicator_r14->choice.small_r12 = 0;
+  SL_CommResourcePoolV2X->sl_Subframe_r14.present = SubframeBitmapSL_r14_PR_bs40_r14;
+  SL_CommResourcePoolV2X->sl_Subframe_r14.choice.bs40_r14.size =  5;
+  SL_CommResourcePoolV2X->sl_Subframe_r14.choice.bs40_r14.buf =  CALLOC(1,5);
+  SL_CommResourcePoolV2X->sl_Subframe_r14.choice.bs40_r14.bits_unused = 0;
+  SL_CommResourcePoolV2X->sl_Subframe_r14.choice.bs40_r14.buf[0] = 0xF0;
+  SL_CommResourcePoolV2X->sl_Subframe_r14.choice.bs40_r14.buf[1] = 0xFF;
+  SL_CommResourcePoolV2X->sl_Subframe_r14.choice.bs40_r14.buf[2] = 0xFF;
+  SL_CommResourcePoolV2X->sl_Subframe_r14.choice.bs40_r14.buf[3] = 0xFF;
+  SL_CommResourcePoolV2X->sl_Subframe_r14.choice.bs40_r14.buf[4] = 0xFF;
+
+  SL_CommResourcePoolV2X->adjacencyPSCCH_PSSCH_r14 = 1;
+  SL_CommResourcePoolV2X->sizeSubchannel_r14 = 10;
+  SL_CommResourcePoolV2X->numSubchannel_r14 =  5;
+  SL_CommResourcePoolV2X->startRB_Subchannel_r14 = 10;
+
+  //rxParametersNCell_r12
+  SL_CommResourcePoolV2X->rxParametersNCell_r14 = CALLOC (1, sizeof (*SL_CommResourcePoolV2X->rxParametersNCell_r14));
+  SL_CommResourcePoolV2X->rxParametersNCell_r14->tdd_Config_r14 = CALLOC (1, sizeof (*SL_CommResourcePoolV2X->rxParametersNCell_r14->tdd_Config_r14));
+  SL_CommResourcePoolV2X->rxParametersNCell_r14->tdd_Config_r14->subframeAssignment = 0 ;
+  SL_CommResourcePoolV2X->rxParametersNCell_r14->tdd_Config_r14->specialSubframePatterns = 0;
+  SL_CommResourcePoolV2X->rxParametersNCell_r14->syncConfigIndex_r14 = 0;
+
+  ASN_SEQUENCE_ADD(&SL_CommRxPoolListV2X->list,SL_CommResourcePoolV2X);
+  //end SIB21
+#endif
+ 
+
   bcch_message->message.present = BCCH_DL_SCH_MessageType_PR_c1;
   bcch_message->message.choice.c1.present = BCCH_DL_SCH_MessageType__c1_PR_systemInformation;
 
@@ -950,7 +1356,6 @@ uint8_t do_SIB23(uint8_t Mod_id,
    sizeof(SystemInformation_t));*/
 
   bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.present = SystemInformation__criticalExtensions_PR_systemInformation_r8;
-
   bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count=0;
 
   //  asn_set_empty(&systemInformation->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list);//.size=0;
@@ -965,8 +1370,20 @@ uint8_t do_SIB23(uint8_t Mod_id,
     ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list,sib13_part);
   }
 
+#if 0
+  /* TODO: this is disabled for the moment.
+   * Maybe we shouldn't put this together with SIBs 2/3.
+   * The problem is that the MAC message is now 92 bytes, which
+   * is too much in the SIB scheduler (the scheduler allocates
+   * 4 RBs with max MCS 8).
+   */
+  //for D2D
+  ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list, sib18_part);
+  ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list, sib19_part);
+  ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list, sib21_part);
 #endif
 
+#endif
 
 #ifdef XER_PRINT
   xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message, (void*)bcch_message);
@@ -1091,6 +1508,176 @@ uint8_t do_RRCConnectionRequest(uint8_t Mod_id, uint8_t *buffer,uint8_t *rv)
 
 }
 
+
+//TTN for D2D - 3GPP TS 36.331 (Section 5.10.2.3)
+uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer,  SL_DestinationInfoList_r12_t  *destinationInfoList, long *discTxResourceReq, SL_TRIGGER_t mode)
+{
+
+   asn_enc_rval_t enc_rval;
+   UL_DCCH_Message_t ul_dcch_msg;
+   SidelinkUEInformation_r12_t *sidelinkUEInformation;
+   ARFCN_ValueEUTRA_r9_t carrierFreq = 25655;//sidelink communication frequency (hardcoded - should come from SIB2)
+
+   memset((void *)&ul_dcch_msg,0,sizeof(UL_DCCH_Message_t));
+   ul_dcch_msg.message.present = UL_DCCH_MessageType_PR_messageClassExtension;
+   ul_dcch_msg.message.choice.messageClassExtension.present  = UL_DCCH_MessageType__messageClassExtension_PR_c2;
+   ul_dcch_msg.message.choice.messageClassExtension.choice.c2.present =  UL_DCCH_MessageType__messageClassExtension__c2_PR_sidelinkUEInformation_r12;
+   sidelinkUEInformation            = &ul_dcch_msg.message.choice.messageClassExtension.choice.c2.choice.sidelinkUEInformation_r12;
+
+   //3GPP TS 36.331 (Section 5.10.2.3)
+   sidelinkUEInformation->criticalExtensions.present = SidelinkUEInformation_r12__criticalExtensions_PR_c1;
+   sidelinkUEInformation->criticalExtensions.choice.c1.present = SidelinkUEInformation_r12__criticalExtensions__c1_PR_sidelinkUEInformation_r12;
+   switch(mode) {
+   //if SIB18 is available
+   case SL_RECEIVE_COMMUNICATION: // to receive sidelink communication
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commRxInterestedFreq_r12 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commRxInterestedFreq_r12));
+      memcpy((void*)sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commRxInterestedFreq_r12, (void*)&carrierFreq,
+            sizeof(ARFCN_ValueEUTRA_r9_t));
+      break;
+
+   case SL_TRANSMIT_NON_RELAY_ONE_TO_MANY: //to transmit non-relay related one-to-many sidelink communication
+      //commTxResourceReq
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12));
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12->carrierFreq_r12 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12->carrierFreq_r12));
+      memcpy((void*)sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12->carrierFreq_r12, (void*)&carrierFreq,
+            sizeof(ARFCN_ValueEUTRA_r9_t));
+      memcpy(&sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12->destinationInfoList_r12,
+            destinationInfoList,
+            sizeof(SL_DestinationInfoList_r12_t));
+      break;
+
+   case SL_TRANSMIT_NON_RELAY_ONE_TO_ONE://transmit non-relay related one-to-one sidelink communication
+      //if commTxResourceUC-ReqAllowed is included in SIB18
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension));
+
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13));
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13->carrierFreq_r12 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13->carrierFreq_r12));
+      memcpy((void*)sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13->carrierFreq_r12, (void*)&carrierFreq,
+            sizeof (ARFCN_ValueEUTRA_r9_t));
+      memcpy(&sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13->destinationInfoList_r12,
+            destinationInfoList,
+            sizeof(SL_DestinationInfoList_r12_t));
+      break;
+
+   case SL_TRANSMIT_RELAY_ONE_TO_ONE: //transmit relay related one-to-one sidelink communication
+      //if SIB19 includes discConfigRelay and UE acts a relay or UE has a selected relay
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension));
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13= CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13));
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelayUC_r13 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelayUC_r13));
+      memcpy(&sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelayUC_r13->destinationInfoList_r12,
+            destinationInfoList,
+            sizeof(*destinationInfoList));
+      //set ue-type to relayUE or remoteUE
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->ue_Type_r13 =SidelinkUEInformation_v1310_IEs__commTxResourceInfoReqRelay_r13__ue_Type_r13_relayUE;
+      //sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12->nonCriticalExtension->commTxResourceInfoReqRelay_r13->ue_Type_r13 =SidelinkUEInformation_v1310_IEs__commTxResourceInfoReqRelay_r13__ue_Type_r13_remoteUE;
+      break;
+
+   case SL_TRANSMIT_RELAY_ONE_TO_MANY: //transmit relay related one-to-many sidelink communication
+      //if SIB19 includes discConfigRelay and UE acts a relay
+      //set ue-type to relayUE
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension));
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13= CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13));
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelay_r13 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelay_r13));
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->ue_Type_r13 =SidelinkUEInformation_v1310_IEs__commTxResourceInfoReqRelay_r13__ue_Type_r13_relayUE;
+      memcpy(&sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelay_r13->destinationInfoList_r12,
+            destinationInfoList,
+            sizeof(*destinationInfoList));
+      break;
+
+      //if SIB19 is available
+      //we consider only one frequency  - a serving frequency
+   case SL_RECEIVE_DISCOVERY: //receive sidelink discovery announcements
+
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.discRxInterest_r12 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.discRxInterest_r12));
+      *sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.discRxInterest_r12 = SidelinkUEInformation_r12_IEs__discRxInterest_r12_true;
+      break;
+   case SL_TRANSMIT_NON_PS_DISCOVERY://to transmit non-PS related sidelink discovery announcements
+      //for the first frequency
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.discTxResourceReq_r12 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.discTxResourceReq_r12));
+
+      memcpy((void*)sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.discTxResourceReq_r12,
+            (void*)discTxResourceReq,
+            sizeof(long));
+      //for additional frequency
+      break;
+
+   case SL_TRANSMIT_PS_DISCOVERY://to transmit PS related sidelink discovery announcements
+      //if to transmit non-relay PS related discovery announcements and SIB19 includes discConfigPS
+      //if UE is acting as relay UE and SIB includes discConfigRelay (relay threshold condition)
+      //if relay UE/has a selected relay UE and if SIB19 includes discConfigRelay
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension));
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->discTxResourceReqPS_r13 = CALLOC(1,
+            sizeof(*sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->discTxResourceReqPS_r13));
+      sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->discTxResourceReqPS_r13->discTxResourceReq_r13 = *discTxResourceReq;
+      break;
+      //SIB21
+   case SL_RECEIVE_V2X:
+      //TODO
+      break;
+   case SL_TRANSMIT_V2X:
+      //TODO
+      break;
+      //TODO: request sidelink discovery transmission/reception gaps
+      //TODO: report the system information parameters related to sidelink discovery of carriers other than the primary
+   default:
+      break;
+   }
+
+#ifdef XER_PRINT
+  xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void*)&ul_dcch_msg);
+#endif
+
+
+   enc_rval = uper_encode_to_buffer(&asn_DEF_UL_DCCH_Message,
+         (void*)&ul_dcch_msg,
+         buffer,
+         100);
+   AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+         enc_rval.failed_type->name, enc_rval.encoded);
+
+#if defined(ENABLE_ITTI)
+# if !defined(DISABLE_XER_SPRINT)
+   {
+      char        message_string[20000];
+      size_t      message_string_size;
+
+      if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_UL_DCCH_Message, (void *) &ul_dcch_msg)) > 0) {
+         MessageDef *msg_p;
+
+         msg_p = itti_alloc_new_message_sized (TASK_RRC_UE, RRC_UL_DCCH, message_string_size + sizeof (IttiMsgText));
+         msg_p->ittiMsg.rrc_ul_dcch.size = message_string_size;
+         memcpy(&msg_p->ittiMsg.rrc_ul_dcch.text, message_string, message_string_size);
+
+         itti_send_msg_to_task(TASK_UNKNOWN, NB_eNB_INST + Mod_id, msg_p);
+      }
+   }
+# endif
+#endif
+
+#ifdef USER_MODE
+   LOG_D(RRC,"SidelinkUEInformation Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+#endif
+
+   return((enc_rval.encoded+7)/8);
+
+}
+
+
 uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS)
 {
 
@@ -1798,11 +2385,13 @@ do_RRCConnectionReconfiguration(
   RSRP_Range_t                       *rsrp,
   C_RNTI_t                           *cba_rnti,
   struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList
-  *dedicatedInfoNASList
-
+  *dedicatedInfoNASList,
+  SL_CommConfig_r12_t                *sl_CommConfig,
+  SL_DiscConfig_r12_t                *sl_DiscConfig
 #if defined(Rel10) || defined(Rel14)
   , SCellToAddMod_r10_t  *SCell_config
 #endif
+
 )
 //------------------------------------------------------------------------------
 {
@@ -1894,6 +2483,45 @@ do_RRCConnectionReconfiguration(
   rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.dedicatedInfoNASList = dedicatedInfoNASList;
   rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO     = NULL;
 
+  //TTN for D2D
+  //allocate dedicated resource pools for SL communication (sl_CommConfig_r12)
+  if (sl_CommConfig != NULL) {
+     LOG_I(RRC,"[RRCConnectionReconfiguration] allocating a dedicated resource pool for SL communication \n");
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension = CALLOC(1,
+           sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension = CALLOC(1,
+           sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension = CALLOC(1,
+           sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension = CALLOC(1,
+           sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension = CALLOC(1,
+           sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_CommConfig_r12 = CALLOC(1,
+           sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_CommConfig_r12));
+     memcpy((void*)rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_CommConfig_r12, (void*)sl_CommConfig,
+               sizeof(SL_CommConfig_r12_t));
+  }
+
+  //allocate dedicated resource pools for SL discovery (sl_DiscConfig)
+  if (sl_DiscConfig != NULL){
+     LOG_I(RRC,"[RRCConnectionReconfiguration] allocating a dedicated resource pool for SL discovery \n");
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension = CALLOC(1,
+            sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension = CALLOC(1,
+            sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension = CALLOC(1,
+            sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension = CALLOC(1,
+            sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension = CALLOC(1,
+            sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension));
+     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_DiscConfig_r12 = CALLOC(1,
+            sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_DiscConfig_r12));
+     memcpy((void*)rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_DiscConfig_r12, (void*)sl_DiscConfig,
+            sizeof(SL_DiscConfig_r12_t));
+  }
+
   enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message,
                                    (void*)&dl_dcch_msg,
                                    buffer,
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.h b/openair2/RRC/LITE/MESSAGES/asn1_msg.h
index 05396bf727961b03a8278f00ddbbf606da6bd629..efb1c85b48270e8ad612fb75e2c714035db6454c 100644
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg.h
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.h
@@ -40,6 +40,7 @@
 #include <asn_internal.h> /* for _ASN_DEFAULT_STACK_MAX */
 
 #include "RRC/LITE/defs.h"
+#include "SL-DestinationInfoList-r12.h"
 
 /*
  * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC)
@@ -103,6 +104,14 @@ routine only generates an mo-data establishment cause.
 
 uint8_t do_RRCConnectionRequest(uint8_t Mod_id, uint8_t *buffer,uint8_t *rv);
 
+/**
+\brief Generate an SidelinkUEInformation UL-DCCH-Message (UE).
+@param destinationInfoList Pointer to a list of destination for which UE requests E-UTRAN to assign dedicated resources
+@param discTxResourceReq Pointer to  number of discovery messages for discovery announcements for which  UE requests E-UTRAN to assign dedicated resources
+@param mode Indicates different requests from upper layers
+@returns Size of encoded bit stream in bytes*/
+uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, SL_DestinationInfoList_r12_t  *destinationInfoList, long *discTxResourceReq, SL_TRIGGER_t mode);
+
 /** \brief Generate an RRCConnectionSetupComplete UL-DCCH-Message (UE)
 @param buffer Pointer to PER-encoded ASN.1 description of UL-DCCH-Message PDU
 @returns Size of encoded bit stream in bytes*/
@@ -186,7 +195,9 @@ do_RRCConnectionReconfiguration(
     struct MeasConfig__speedStatePars  *speedStatePars,
     RSRP_Range_t                       *rsrp,
     C_RNTI_t                           *cba_rnti,
-  struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList* dedicatedInfoNASList
+  struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList* dedicatedInfoNASList,
+  SL_CommConfig_r12_t                *sl_CommConfig,
+  SL_DiscConfig_r12_t                *sl_DiscConfig
 #if defined(Rel10) || defined(Rel14)
     , SCellToAddMod_r10_t  *SCell_config
 #endif
diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h
index 08ac30f8363f9453921c73598a3b8447fc7abc93..4c69c4c4eea734fbef6b13b56dc87f141afcdcb2 100644
--- a/openair2/RRC/LITE/defs.h
+++ b/openair2/RRC/LITE/defs.h
@@ -45,6 +45,131 @@
 
 #include "LAYER2/MAC/defs.h"
 
+//for D2D
+#define DEBUG_CTRL_SOCKET
+#define BUFSIZE                1024
+#define CONTROL_SOCKET_PORT_NO 8888
+#define MAX_NUM_DEST           10
+//netlink
+//#define DEBUG_PDCP
+#define UE_IP_PDCP_NETLINK_ID  31
+#define PDCP_PID               1
+#define NETLINK_HEADER_SIZE    16
+#define SL_DEFAULT_RAB_ID      3
+#define SLRB_ID                3
+
+#define MAX_PAYLOAD 1024 /* maximum payload size*/
+
+#define UE_STATE_NOTIFICATION_INTERVAL      50
+
+#define IPV4_ADDR    "%u.%u.%u.%u"
+#define IPV4_ADDR_FORMAT(aDDRESS)                 \
+      (uint8_t)((aDDRESS)  & 0x000000ff),         \
+      (uint8_t)(((aDDRESS) & 0x0000ff00) >> 8 ),  \
+      (uint8_t)(((aDDRESS) & 0x00ff0000) >> 16),  \
+      (uint8_t)(((aDDRESS) & 0xff000000) >> 24)
+
+
+//-----------------------------------------------------
+// header for Control socket
+
+//Primitives
+#define SESSION_INIT_REQ                    1
+#define UE_STATUS_INFO                      2
+#define GROUP_COMMUNICATION_ESTABLISH_REQ   3
+#define GROUP_COMMUNICATION_ESTABLISH_RSP   4
+#define DIRECT_COMMUNICATION_ESTABLISH_REQ  5
+#define DIRECT_COMMUNICATION_ESTABLISH_RSP  6
+#define GROUP_COMMUNICATION_RELEASE_REQ     7
+#define GROUP_COMMUNICATION_RELEASE_RSP     8
+#define PC5S_ESTABLISH_REQ                  9
+#define PC5S_ESTABLISH_RSP                  10
+#define PC5_DISCOVERY_MESSAGE          	  11
+
+
+#define PC5_DISCOVERY_PAYLOAD_SIZE	    29
+
+
+typedef enum {
+   UE_STATE_OFF_NETWORK,
+   UE_STATE_ON_NETWORK
+} SL_UE_STATE_t;
+
+typedef enum {
+   GROUP_COMMUNICATION_RELEASE_OK = 0,
+   GROUP_COMMUNICATION_RELEASE_FAILURE
+} Group_Communication_Status_t;
+
+struct GroupCommunicationEstablishReq {
+   uint32_t sourceL2Id;
+   uint32_t groupL2Id;
+   uint32_t groupIpAddress;
+   uint8_t pppp;
+};
+
+struct GroupCommunicationReleaseReq {
+   uint32_t sourceL2Id;
+   uint32_t groupL2Id;
+   int slrb_id;
+};
+
+struct DirectCommunicationEstablishReq {
+   uint32_t sourceL2Id;
+   uint32_t destinationL2Id;
+   uint32_t pppp;
+};
+
+struct PC5SEstablishReq{
+   uint8_t type;
+   uint32_t sourceL2Id;
+   uint32_t destinationL2Id;
+};
+
+struct PC5SEstablishRsp{
+   uint32_t slrbid_lcid28;
+   uint32_t slrbid_lcid29;
+   uint32_t slrbid_lcid30;
+};
+
+
+//PC5_DISCOVERY MESSAGE
+typedef struct  {
+   unsigned char payload[PC5_DISCOVERY_PAYLOAD_SIZE];
+   uint32_t measuredPower;
+}  __attribute__((__packed__)) PC5DiscoveryMessage ;
+
+
+struct sidelink_ctrl_element {
+   unsigned short type;
+   union {
+      struct GroupCommunicationEstablishReq group_comm_establish_req;
+      struct DirectCommunicationEstablishReq direct_comm_establish_req;
+      Group_Communication_Status_t group_comm_release_rsp;
+      //struct DirectCommunicationReleaseReq  direct_comm_release_req;
+      SL_UE_STATE_t ue_state;
+      int slrb_id;
+      struct PC5SEstablishReq pc5s_establish_req;
+      struct PC5SEstablishRsp pc5s_establish_rsp;
+      PC5DiscoveryMessage pc5_discovery_message;
+   } sidelinkPrimitive;
+};
+
+
+//global variables
+extern struct sockaddr_in clientaddr;
+extern int slrb_id;
+extern pthread_mutex_t slrb_mutex;
+
+//the thread function
+void *send_UE_status_notification(void *);
+
+
+
+//#include "COMMON/openair_defs.h"
+#ifndef USER_MODE
+//#include <rtai.h>
+#endif
+
 #include "SystemInformationBlockType1.h"
 #include "SystemInformation.h"
 #include "RRCConnectionReconfiguration.h"
@@ -54,6 +179,7 @@
 #include "RRCConnectionRequest.h"
 #include "RRCConnectionReestablishmentRequest.h"
 #include "BCCH-DL-SCH-Message.h"
+#include "SBCCH-SL-BCH-MessageType.h"
 #include "BCCH-BCH-Message.h"
 #if defined(Rel10) || defined(Rel14)
 #include "MCCH-Message.h"
@@ -64,6 +190,7 @@
 #include "AS-Context.h"
 #include "UE-EUTRA-Capability.h"
 #include "MeasResults.h"
+#include "SidelinkUEInformation-r12.h"
 
 /* for ImsiMobileIdentity_t */
 #include "MobileIdentity.h"
@@ -185,7 +312,7 @@ typedef struct uid_linear_allocator_s {
 
 #define PROTOCOL_RRC_CTXT_FMT           PROTOCOL_CTXT_FMT
 #define PROTOCOL_RRC_CTXT_ARGS(CTXT_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp)
-/** @defgroup _rrc RRC 
+/** @defgroup _rrc RRC
  * @ingroup _oai2
  * @{
  */
@@ -219,6 +346,21 @@ typedef enum HO_STATE_e {
   HO_COMPLETE // initiated by the target eNB
 } HO_STATE_t;
 
+typedef enum SL_TRIGGER_e {
+  SL_RECEIVE_COMMUNICATION=0,
+  SL_TRANSMIT_RELAY_ONE_TO_ONE,
+  SL_TRANSMIT_RELAY_ONE_TO_MANY,
+  SL_TRANSMIT_NON_RELAY_ONE_TO_ONE,
+  SL_TRANSMIT_NON_RELAY_ONE_TO_MANY,
+  SL_RECEIVE_DISCOVERY,
+  SL_TRANSMIT_NON_PS_DISCOVERY,
+  SL_TRANSMIT_PS_DISCOVERY,
+  SL_RECEIVE_V2X,
+  SL_TRANSMIT_V2X,
+  SL_REQUEST_DISCOVERY_TRANSMISSION_GAPS,
+  SL_REQUEST_DISCOVERY_RECEPTION_GAPS
+} SL_TRIGGER_t;
+
 //#define NUMBER_OF_UE_MAX MAX_MOBILES_PER_RG
 #define RRM_FREE(p)       if ( (p) != NULL) { free(p) ; p=NULL ; }
 #define RRM_MALLOC(t,n)   (t *) malloc16( sizeof(t) * n )
@@ -355,7 +497,7 @@ typedef struct SRB_INFO_TABLE_ENTRY_s {
   SRB_INFO Srb_info;
   uint8_t Active;
   uint8_t Status;
-  uint32_t Next_check_frame; 
+  uint32_t Next_check_frame;
 } SRB_INFO_TABLE_ENTRY;
 
 typedef struct MEAS_REPORT_LIST_s {
@@ -519,6 +661,11 @@ typedef struct {
   MBSFNAreaConfiguration_r9_t       *mcch_message;
   SRB_INFO                          MCCH_MESS[8];// MAX_MBSFN_AREA
 #endif
+  //TTN - SIB 18,19,21 for D2D
+  SystemInformationBlockType18_r12_t *sib18;
+  SystemInformationBlockType19_r12_t *sib19;
+  SystemInformationBlockType21_r14_t *sib21;
+  // End - TTN
   SRB_INFO                          SI;
   SRB_INFO                          Srb0;
   uint8_t                           *paging[NUMBER_OF_UE_MAX];
@@ -610,6 +757,27 @@ typedef struct UE_RRC_INST_s {
   SystemInformationBlockType9_t *sib9[NB_CNX_UE];
   SystemInformationBlockType10_t *sib10[NB_CNX_UE];
   SystemInformationBlockType11_t *sib11[NB_CNX_UE];
+  uint8_t                           *MIB;
+#ifdef Rel14
+  //SIB18
+  SystemInformationBlockType18_r12_t *sib18[NB_CNX_UE];
+  SystemInformationBlockType19_r12_t *sib19[NB_CNX_UE];
+  SystemInformationBlockType21_r14_t *sib21[NB_CNX_UE];
+
+  SBCCH_SL_BCH_MessageType_t   mib_sl[NB_CNX_UE];
+  /// Preconfiguration for Sidelink
+  struct SL_Preconfiguration_r12 *SL_Preconfiguration[NB_CNX_UE];
+  //source L2 Id
+  uint32_t sourceL2Id;
+  //group L2 Id
+  uint32_t groupL2Id;
+  //current destination
+  uint32_t destinationL2Id;
+  //List of destinations
+   uint32_t destinationList[MAX_NUM_DEST];
+  //sl_discovery..
+  SRB_INFO SL_Discovery[NB_CNX_UE];
+#endif
 
 #if defined(Rel10) || defined(Rel14)
   uint8_t                           MBMS_flag;
@@ -657,6 +825,11 @@ typedef struct UE_RRC_INST_s {
   /* Used integrity/ciphering algorithms */
   CipheringAlgorithm_r12_t                          ciphering_algorithm;
   e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm;
+
+#ifdef Rel14
+  /// Used for Sidelink Preconfiguration
+  DRB_ToAddModList_t *DRB_configList;
+#endif
 } UE_RRC_INST;
 
 typedef struct UE_PF_PO_s {
diff --git a/openair2/RRC/LITE/proto.h b/openair2/RRC/LITE/proto.h
index b92058741940a5aa8ee91b18b664f2cbd5bb0d46..e692668370e9e25aabadb125a0545e01cc39617f 100644
--- a/openair2/RRC/LITE/proto.h
+++ b/openair2/RRC/LITE/proto.h
@@ -25,7 +25,7 @@
  * \date 2010 - 2014
  * \email navid.nikaein@eurecom.fr
  * \version 1.0
- 
+
  */
 /** \addtogroup _rrc
  *  @{
@@ -106,6 +106,14 @@ rrc_ue_decode_dcch(
   const uint8_t                eNB_indexP
 );
 
+#ifdef Rel14
+int decode_SL_Discovery_Message(
+  const protocol_ctxt_t* const ctxt_pP,
+  const uint8_t                eNB_index,
+  uint8_t*               const Sdu,
+  const uint8_t                Sdu_len);
+#endif
+
 /** \brief Generate/Encodes RRCConnnectionRequest message at UE
     \param ctxt_pP Running context
     \param eNB_index Index of corresponding eNB/CH*/
@@ -181,6 +189,28 @@ void rrc_ue_process_radioResourceConfigDedicated(
   uint8_t eNB_index,
   RadioResourceConfigDedicated_t *radioResourceConfigDedicated);
 
+
+/** \brief Process a RadioResourceConfig and configure PHY/MAC for SL communication/discovery
+    \param Mod_idP
+    \param eNB_index Index of corresponding CH/eNB
+    \param sib18 Pointer to SIB18 from SI message
+    \param sib19 Pointer to SIB19 from SI message
+    \param sl_CommConfig Pointer to SL_CommConfig RRCConnectionConfiguration
+    \param sl_DiscConfig Pointer to SL_DiscConfig RRCConnectionConfiguration */
+void rrc_ue_process_sidelink_radioResourceConfig(
+  module_id_t Mod_idP,
+  uint8_t eNB_index,
+  SystemInformationBlockType18_r12_t     *sib18,
+  SystemInformationBlockType19_r12_t     *sib19,
+  SL_CommConfig_r12_t* sl_CommConfig,
+  SL_DiscConfig_r12_t* sl_DiscConfig);
+
+/** \brief Init control socket to listen to incoming packets from ProSe App
+ *
+ */
+void rrc_control_socket_init(void);
+
+
 // eNB/CH RRC Procedures
 
 /**\brief Function to get the next transaction identifier.
@@ -327,6 +357,54 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
   const uint32_t                nas_length
 );
 
+/**\brief Generate/decode the RRCConnectionReconfiguration for Sidelink at eNB
+   \param ctxt_pP       Running context
+   \param ue_context_pP RRC UE context
+   \param destinationInfoList List of the destinations
+   \param n_discoveryMessages Number of discovery messages*/
+int
+rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(
+      const protocol_ctxt_t* const ctxt_pP,
+      rrc_eNB_ue_context_t*           const ue_context_pP,
+      SL_DestinationInfoList_r12_t  *destinationInfoList,
+      int n_discoveryMessages
+);
+
+/** \brief process the received SidelinkUEInformation message at eNB
+    \param ctxt_pP Running context
+    \param sidelinkUEInformation sidelinkUEInformation message from UE*/
+uint8_t
+rrc_eNB_process_SidelinkUEInformation(
+      const protocol_ctxt_t* const ctxt_pP,
+      rrc_eNB_ue_context_t*         ue_context_pP,
+      SidelinkUEInformation_r12_t*  sidelinkUEInformation
+);
+
+/** \brief Get a Resource Pool to transmit SL communication
+    \param ctxt_pP Running context
+    \param ue_context_pP UE context
+    \param destinationInfoList Pointer to the list of SL destinations*/
+SL_CommConfig_r12_t rrc_eNB_get_sidelink_commTXPool(
+      const protocol_ctxt_t* const ctxt_pP,
+      rrc_eNB_ue_context_t* const ue_context_pP,
+      SL_DestinationInfoList_r12_t  *destinationInfoList
+);
+
+/** \brief Get a Resource Pool for Discovery
+    \param ctxt_pP Running context
+    \param ue_context_pP UE context
+    \param n_discoveryMessages Number of discovery messages*/
+SL_DiscConfig_r12_t rrc_eNB_get_sidelink_discTXPool(
+      const protocol_ctxt_t* const ctxt_pP,
+      rrc_eNB_ue_context_t* const ue_context_pP,
+      int n_discoveryMessages
+);
+
+/** \brief Process request from control socket
+ *  \param arg
+ */
+void *rrc_control_socket_thread_fct(void *arg);
+
 //L2_interface.c
 int8_t
 mac_rrc_data_req(
@@ -380,8 +458,8 @@ mac_rrc_data_ind_ue(
 
 void mac_sync_ind( module_id_t Mod_instP, uint8_t status);
 
-void mac_eNB_rrc_ul_failure(const module_id_t Mod_instP, 
-			    const int CC_id, 
+void mac_eNB_rrc_ul_failure(const module_id_t Mod_instP,
+			    const int CC_id,
 			    const frame_t frameP,
 			    const sub_frame_t subframeP,
 			    const rnti_t rnti);
diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c
index 3edf230ac2817ca736956c7affd80342980629f4..e907f1a8f9e0756be97f131e87262606e768975b 100644
--- a/openair2/RRC/LITE/rrc_UE.c
+++ b/openair2/RRC/LITE/rrc_UE.c
@@ -30,6 +30,7 @@
 
 #define RRC_UE
 #define RRC_UE_C
+#define _GNU_SOURCE
 
 #include "assertions.h"
 #include "hashtable.h"
@@ -82,6 +83,16 @@
 
 #include "SIMULATION/TOOLS/defs.h" // for taus
 
+#ifdef Rel14
+#include "SL-Preconfiguration-r12.h"
+
+//for D2D
+int ctrl_sock_fd;
+#define BUFSIZE 1024
+struct sockaddr_in prose_app_addr;
+int slrb_id;
+int send_ue_information = 0;
+#endif
 
 #ifdef PHY_EMUL
 extern EMULATION_VARS *Emul_vars;
@@ -141,6 +152,7 @@ static uint8_t check_trigger_meas_event(
 
 #if defined(Rel10) || defined(Rel14)
 static void decode_MBSFNAreaConfiguration(module_id_t module_idP, uint8_t eNB_index, frame_t frameP,uint8_t mbsfn_sync_area);
+uint8_t rrc_ue_generate_SidelinkUEInformation( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index,SL_DestinationInfoList_r12_t  *destinationInfoList, long *discTxResourceReq, SL_TRIGGER_t mode);
 #endif
 
 
@@ -277,6 +289,10 @@ static void init_SI_UE( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_
 #if defined(Rel10) || defined(Rel14)
   UE_rrc_inst[ctxt_pP->module_id].sib12[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType12_r9_t) );
   UE_rrc_inst[ctxt_pP->module_id].sib13[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType13_r9_t) );
+  UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType18_r12_t) );
+  UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType19_r12_t) );
+  UE_rrc_inst[ctxt_pP->module_id].sib21[eNB_index] = malloc16_clear( sizeof(SystemInformationBlockType21_r14_t) );
+
 #endif
   UE_rrc_inst[ctxt_pP->module_id].SI[eNB_index] = (uint8_t*)malloc16_clear( 64 );
 
@@ -286,10 +302,184 @@ static void init_SI_UE( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_
   UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt    = 0;
 }
 
+#ifdef Rel14
+void init_SL_preconfig(UE_RRC_INST *UE, const uint8_t eNB_index )
+{
+  LOG_I(RRC,"Initializing Sidelink Pre-configuration for UE\n");
+
+  UE->SL_Preconfiguration[eNB_index] = malloc16_clear( sizeof(struct SL_Preconfiguration_r12) );
+  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.rohc_Profiles_r12.profile0x0001_r12       = true;
+  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.carrierFreq_r12                           = 3350;
+  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.maxTxPower_r12                            = 0;
+  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.additionalSpectrumEmission_r12            = 0;
+  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.sl_bandwidth_r12                          = SL_PreconfigGeneral_r12__sl_bandwidth_r12_n50;
+  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.tdd_ConfigSL_r12.subframeAssignmentSL_r12 = TDD_ConfigSL_r12__subframeAssignmentSL_r12_none;
+
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncCP_Len_r12            = SL_CP_Len_r12_normal;
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncOffsetIndicator1_r12  = 0;
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncOffsetIndicator2_r12  = 0;
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncTxParameters_r12      = 0;
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncTxThreshOoC_r12       = 0;
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.filterCoefficient_r12     = FilterCoefficient_fc0;
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncRefMinHyst_r12        = SL_PreconfigSync_r12__syncRefMinHyst_r12_dB0;
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncRefDiffHyst_r12       = SL_PreconfigSync_r12__syncRefDiffHyst_r12_dB0;
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.ext1                      = malloc16_clear(sizeof(struct SL_PreconfigSync_r12__ext1));
+  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.ext1->syncTxPeriodic_r13  = NULL;
+
+  struct SL_PreconfigCommPool_r12 *preconfigpool = malloc16_clear(sizeof(struct SL_PreconfigCommPool_r12));
+  preconfigpool->sc_CP_Len_r12                                                    = SL_CP_Len_r12_normal;
+  preconfigpool->sc_Period_r12                                                    = SL_PeriodComm_r12_sf40;
+  // 20 PRBs for SL communications
+  preconfigpool->sc_TF_ResourceConfig_r12.prb_Num_r12                             = 20;
+  preconfigpool->sc_TF_ResourceConfig_r12.prb_Start_r12                           = 5;
+  preconfigpool->sc_TF_ResourceConfig_r12.prb_End_r12                             = 44;
+  // Offset set to 0 subframes
+  preconfigpool->sc_TF_ResourceConfig_r12.offsetIndicator_r12.present             = SL_OffsetIndicator_r12_PR_small_r12;
+  preconfigpool->sc_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12    = 0;
+  // 40 ms SL Period
+  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present              = SubframeBitmapSL_r12_PR_bs40_r12;
+  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf         = CALLOC(1,5);
+  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.size        = 5;
+  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.bits_unused = 0;
+  // 1st 4 subframes for PSCCH
+  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[0]      = 0xF;
+  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[1]      = 0;
+  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[2]      = 0;
+  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[3]      = 0;
+  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[4]      = 0;
+  preconfigpool->sc_TxParameters_r12                                              = 0;
+
+  preconfigpool->data_CP_Len_r12                                                  = SL_CP_Len_r12_normal;
+  // 20 PRBs for SL communications
+  preconfigpool->data_TF_ResourceConfig_r12.prb_Num_r12                             = 20;
+  preconfigpool->data_TF_ResourceConfig_r12.prb_Start_r12                           = 5;
+  preconfigpool->data_TF_ResourceConfig_r12.prb_End_r12                             = 44;
+  // Offset set to 0 subframes
+  preconfigpool->data_TF_ResourceConfig_r12.offsetIndicator_r12.present             = SL_OffsetIndicator_r12_PR_small_r12;
+  preconfigpool->data_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12    = 0;
+  // 40 ms SL Period
+  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.present              = SubframeBitmapSL_r12_PR_bs40_r12;
+  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf         = CALLOC(1,5);
+  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.size        = 5;
+  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.bits_unused = 0;
+  // last 36 subframes for PSCCH
+  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[0]      = 0xF0;
+  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[1]      = 0xFF;
+  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[2]      = 0xFF;
+  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[3]      = 0xFF;
+  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[5]      = 0xFF;
+
+  preconfigpool->dataHoppingConfig_r12.hoppingParameter_r12                         = 0;
+  preconfigpool->dataHoppingConfig_r12.numSubbands_r12                              = SL_HoppingConfigComm_r12__numSubbands_r12_ns1;
+  preconfigpool->dataHoppingConfig_r12.rb_Offset_r12                                = 0;
+
+  preconfigpool->dataTxParameters_r12                                               = 0;
+
+  ASN_SEQUENCE_ADD(&UE->SL_Preconfiguration[eNB_index]->preconfigComm_r12.list,preconfigpool);
+
+  // Rel13 extensions
+  UE->SL_Preconfiguration[eNB_index]->ext1 = NULL;
+/*
+  // Establish a SLRB (using DRB 3 for now)
+  protocol_ctxt_t ctxt;
+  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0);
+
+  UE->DRB_config[0][0] = CALLOC(1,sizeof(struct DRB_ToAddMod));
+  UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+  UE->DRB_config[0][0]->drb_Identity =  3;
+  UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+  // allowed value 5..15, value : x+4
+  *(UE->DRB_config[0][0]->eps_BearerIdentity) = 3;
+  UE->DRB_config[0][0]->logicalChannelIdentity = CALLOC(1, sizeof(long));
+  *(UE->DRB_config[0][0]->logicalChannelIdentity) = UE->DRB_config[0][0]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2
+
+  // TTN - Establish a new SLRB for PC5-S (using DRB 10 for now)
+  UE->DRB_config[0][1] = CALLOC(1,sizeof(struct DRB_ToAddMod));
+  UE->DRB_config[0][1]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+  UE->DRB_config[0][1]->drb_Identity =  10;
+  UE->DRB_config[0][1]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+  // allowed value 5..15, value : x+4
+  *(UE->DRB_config[0][1]->eps_BearerIdentity) = 10;
+  UE->DRB_config[0][1]->logicalChannelIdentity = CALLOC(1, sizeof(long));
+  *(UE->DRB_config[0][1]->logicalChannelIdentity) = UE->DRB_config[0][1]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2
+
+  struct RLC_Config                  *DRB_rlc_config                   = CALLOC(1,sizeof(struct RLC_Config));
+  struct PDCP_Config                 *DRB_pdcp_config                  = CALLOC(1,sizeof(struct PDCP_Config));
+  struct PDCP_Config__rlc_UM         *PDCP_rlc_UM                      = CALLOC(1,sizeof(struct PDCP_Config__rlc_UM));
+  struct LogicalChannelConfig        *DRB_lchan_config                 = CALLOC(1,sizeof(struct LogicalChannelConfig));
+  struct LogicalChannelConfig__ul_SpecificParameters
+    *DRB_ul_SpecificParameters                                         = CALLOC(1, sizeof(struct LogicalChannelConfig__ul_SpecificParameters));
+  long                               *logicalchannelgroup_drb          = CALLOC(1, sizeof(long));
+
+  DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional;
+  DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+  DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+  DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = T_Reordering_ms35;
+  UE->DRB_config[0][0]->rlc_Config = DRB_rlc_config;
+  UE->DRB_config[0][1]->rlc_Config = DRB_rlc_config;
+
+  DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config));
+  UE->DRB_config[0][0]->pdcp_Config = DRB_pdcp_config;
+  UE->DRB_config[0][1]->pdcp_Config = DRB_pdcp_config;
+  DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long));
+  *DRB_pdcp_config->discardTimer = PDCP_Config__discardTimer_infinity;
+  DRB_pdcp_config->rlc_AM = NULL;
+  DRB_pdcp_config->rlc_UM = NULL;
+
+  // avoid gcc warnings
+  (void)PDCP_rlc_UM;
+
+  DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
+  PDCP_rlc_UM->pdcp_SN_Size = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
+  DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed;
+
+  UE->DRB_config[0][0]->logicalChannelConfig = DRB_lchan_config;
+  UE->DRB_config[0][1]->logicalChannelConfig = DRB_lchan_config;
+  DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
+  DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;
+
+  DRB_ul_SpecificParameters->priority = 12;    // lower priority than srb1, srb2 and other dedicated bearer
+  DRB_ul_SpecificParameters->prioritisedBitRate =LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
+    //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
+  DRB_ul_SpecificParameters->bucketSizeDuration =
+    LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;
+
+  // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM)
+
+  *logicalchannelgroup_drb = 1;
+  DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb;
+
+  UE->DRB_configList = CALLOC(1,sizeof(DRB_ToAddModList_t));
+  ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][0]);
+  ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][1]);
+
+  rrc_pdcp_config_asn1_req(&ctxt,
+			   (SRB_ToAddModList_t *) NULL,
+			   UE->DRB_configList,
+			   (DRB_ToReleaseList_t*) NULL,
+			   0xff, NULL, NULL, NULL
+#if defined(Rel10) || defined(Rel14)
+                           , (PMCH_InfoList_r9_t *) NULL
+#endif
+                           ,NULL);
+
+  rrc_rlc_config_asn1_req(&ctxt,
+			  (SRB_ToAddModList_t*)NULL,
+			  UE->DRB_configList,
+			  (DRB_ToReleaseList_t*)NULL
+#if defined(Rel10) || defined(Rel14)
+			  ,(PMCH_InfoList_r9_t *)NULL
+#endif
+			  );
+*/
+}
+
+#endif
+
 #if defined(Rel10) || defined(Rel14)
 //-----------------------------------------------------------------------------
 #if 0
-static void init_MCCH_UE(module_id_t ue_mod_idP, uint8_t eNB_index)
+void init_MCCH_UE(module_id_t ue_mod_idP, uint8_t eNB_index)
 {
   int i;
   UE_rrc_inst[ue_mod_idP].sizeof_MCCH_MESSAGE[eNB_index] = 0;
@@ -305,7 +495,7 @@ static void init_MCCH_UE(module_id_t ue_mod_idP, uint8_t eNB_index)
 #endif
 
 //-----------------------------------------------------------------------------
-static void openair_rrc_ue_init_security( const protocol_ctxt_t* const ctxt_pP )
+void openair_rrc_ue_init_security( const protocol_ctxt_t* const ctxt_pP )
 {
 #if defined(ENABLE_SECURITY)
   //    uint8_t *kRRCenc;
@@ -358,6 +548,12 @@ char openair_rrc_ue_init( const module_id_t ue_mod_idP, const unsigned char eNB_
   LOG_D(RRC,PROTOCOL_RRC_CTXT_FMT"  INIT: phy_sync_2_ch_ind\n",
         PROTOCOL_RRC_CTXT_ARGS(&ctxt));
 
+
+
+#ifndef NO_RRM
+  send_msg(&S_rrc,msg_rrc_phy_synch_to_CH_ind(ctxt.module_id,eNB_index,UE_rrc_inst[ctxt.module_id].Mac_id));
+#endif
+
 #ifndef NO_RRM
   send_msg(&S_rrc,msg_rrc_phy_synch_to_CH_ind(ctxt.module_id,eNB_index,UE_rrc_inst[ctxt.module_id].Mac_id));
 #endif
@@ -530,7 +726,7 @@ static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t* c
 }
 
 //-----------------------------------------------------------------------------
-static void rrc_ue_generate_RRCConnectionReconfigurationComplete( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id )
+void rrc_ue_generate_RRCConnectionReconfigurationComplete( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id )
 {
 
   uint8_t buffer[32], size;
@@ -594,6 +790,7 @@ int rrc_ue_decode_ccch( const protocol_ctxt_t* const ctxt_pP, const SRB_INFO* co
     char        message_string[10000];
     size_t      message_string_size;
 
+    //LOG_I(RRC, "Panos-D: rrc_ue_decode_ccch, Before xer_sprint() \n");
     if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_CCCH_Message, (void *)dl_ccch_msg)) > 0) {
       MessageDef *msg_p;
 
@@ -900,6 +1097,12 @@ rrc_ue_process_measConfig(
 			  ,
 			  0,
 			  0
+#endif
+#if defined(Rel14)
+           ,
+           0,
+           NULL,
+           NULL
 #endif
 			  );
   }
@@ -1347,6 +1550,7 @@ rrc_ue_process_radioResourceConfigDedicated(
                             (DRB_ToReleaseList_t*)NULL
 #if defined(Rel10) || defined(Rel14)
                             ,(PMCH_InfoList_r9_t *)NULL
+                            , 0, 0
 #endif
                            );
 
@@ -1412,6 +1616,12 @@ rrc_ue_process_radioResourceConfigDedicated(
 				,
 				0,
 				0
+#endif
+#if defined(Rel14)
+           ,
+           0,
+           NULL,
+           NULL
 #endif
 				);
         }
@@ -1471,6 +1681,12 @@ rrc_ue_process_radioResourceConfigDedicated(
 				,
 				0,
 				0
+#endif
+#if defined(Rel14)
+           ,
+           0,
+           NULL,
+           NULL
 #endif
 				);
         }
@@ -1529,6 +1745,7 @@ rrc_ue_process_radioResourceConfigDedicated(
                             (DRB_ToReleaseList_t*)NULL
 #if defined(Rel10) || defined(Rel14)
                             ,(PMCH_InfoList_r9_t *)NULL
+                            , 0, 0
 #endif
                            );
 
@@ -1578,13 +1795,19 @@ rrc_ue_process_radioResourceConfigDedicated(
 			      ,
 			      UE_rrc_inst[ue_mod_idP].num_active_cba_groups, //
 			      UE_rrc_inst[ue_mod_idP].cba_rnti[0]
+#endif
+#if defined(Rel14)
+           ,
+           0,
+           NULL,
+           NULL
 #endif
 			      );
-	
+
       }
     }
   }
-  
+
   UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State = RRC_CONNECTED;
   LOG_I(RRC,"[UE %d] State = RRC_CONNECTED (eNB %d)\n",ctxt_pP->module_id,eNB_index);
 }
@@ -1607,8 +1830,8 @@ rrc_ue_process_securityModeCommand(
   uint8_t buffer[200];
   int i, securityMode;
 
-  LOG_I(RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing securityModeCommand (eNB %d)\n",
-        ctxt_pP->module_id,ctxt_pP->frame,eNB_index);
+  LOG_I(RRC,"[UE %d] SFN/SF %d/%d: Receiving from SRB1 (DL-DCCH), Processing securityModeCommand (eNB %d)\n",
+        ctxt_pP->module_id,ctxt_pP->frame, ctxt_pP->subframe, eNB_index);
 
   switch (securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm) {
   case CipheringAlgorithm_r12_eea0:
@@ -1665,8 +1888,10 @@ rrc_ue_process_securityModeCommand(
   ul_dcch_msg.message.present           = UL_DCCH_MessageType_PR_c1;
 
   if (securityMode >= NO_SECURITY_MODE) {
+	  LOG_I(RRC, "rrc_ue_process_securityModeCommand, security mode complete case \n");
     ul_dcch_msg.message.choice.c1.present = UL_DCCH_MessageType__c1_PR_securityModeComplete;
   } else {
+	  LOG_I(RRC, "rrc_ue_process_securityModeCommand, security mode failure case \n");
     ul_dcch_msg.message.choice.c1.present = UL_DCCH_MessageType__c1_PR_securityModeFailure;
   }
 
@@ -1717,11 +1942,11 @@ rrc_ue_process_securityModeCommand(
               | (UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm << 4),
           kRRCenc, kRRCint, kUPenc);
     } else {
-      LOG_W(RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x",
+      LOG_I(RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x",
           securityMode);
     }
   } else {
-    LOG_W(RRC, "Could not get PDCP instance where key=0x%ld\n", key);
+    LOG_I(RRC, "Could not get PDCP instance where key=0x%ld\n", key);
   }
 
 #endif //#if defined(ENABLE_SECURITY)
@@ -1736,8 +1961,8 @@ rrc_ue_process_securityModeCommand(
     ul_dcch_msg.message.choice.c1.choice.securityModeComplete.criticalExtensions.present = SecurityModeCommand__criticalExtensions_PR_c1;
     ul_dcch_msg.message.choice.c1.choice.securityModeComplete.criticalExtensions.choice.securityModeComplete_r8.nonCriticalExtension =NULL;
     
-    LOG_I(RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), encoding securityModeComplete (eNB %d)\n",
-	  ctxt_pP->module_id,ctxt_pP->frame,eNB_index);
+    LOG_I(RRC,"[UE %d] SFN/SF %d/%d: Receiving from SRB1 (DL-DCCH), encoding securityModeComplete (eNB %d), rrc_TransactionIdentifier: %ld\n",
+	  ctxt_pP->module_id,ctxt_pP->frame, ctxt_pP->subframe, eNB_index, securityModeCommand->rrc_TransactionIdentifier);
     
     enc_rval = uper_encode_to_buffer(&asn_DEF_UL_DCCH_Message,
 				     (void*)&ul_dcch_msg,
@@ -1756,6 +1981,7 @@ rrc_ue_process_securityModeCommand(
       char        message_string[20000];
       size_t      message_string_size;
       
+      //LOG_I(RRC, "Panos-D: rrc_ue_process_securityModeCommand, Before xer_sprint() \n");
       if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_UL_DCCH_Message, (void *) &ul_dcch_msg)) > 0) {
 	MessageDef *msg_p;
 	
@@ -1836,7 +2062,7 @@ rrc_ue_process_ueCapabilityEnquiry(
 	      UECapabilityEnquiry->criticalExtensions.present,UECapabilityEnquiry__criticalExtensions_PR_c1);
 
   if (UECapabilityEnquiry->criticalExtensions.choice.c1.present != UECapabilityEnquiry__criticalExtensions__c1_PR_ueCapabilityEnquiry_r8)
-    LOG_W(RRC,"UECapabilityEnquiry->criticalExtensions.choice.c1.present (%d) != UECapabilityEnquiry__criticalExtensions__c1_PR_ueCapabilityEnquiry_r8)\n",
+    LOG_I(RRC,"UECapabilityEnquiry->criticalExtensions.choice.c1.present (%d) != UECapabilityEnquiry__criticalExtensions__c1_PR_ueCapabilityEnquiry_r8)\n",
 	  UECapabilityEnquiry->criticalExtensions.choice.c1.present);
   
   ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.present           = UECapabilityInformation__criticalExtensions_PR_c1;
@@ -1867,6 +2093,7 @@ rrc_ue_process_ueCapabilityEnquiry(
 	char        message_string[20000];
 	size_t      message_string_size;
 	
+	//LOG_I(RRC, "Panos-D: rrc_ue_process_ueCapabilityEnquiry, Before xer_sprint() \n");
 	if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_UL_DCCH_Message, (void *) &ul_dcch_msg)) > 0) {
 	  MessageDef *msg_p;
 	  
@@ -1881,7 +2108,7 @@ rrc_ue_process_ueCapabilityEnquiry(
 #endif
 	
 
-          LOG_D(RRC,"UECapabilityInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+          LOG_I(RRC,"UECapabilityInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
 
           for (i = 0; i < (enc_rval.encoded + 7) / 8; i++) {
             LOG_T(RRC, "%02x.", buffer[i]);
@@ -1940,6 +2167,45 @@ rrc_ue_process_rrcConnectionReconfiguration(
         rrc_ue_process_radioResourceConfigDedicated(ctxt_pP,eNB_index, rrcConnectionReconfiguration_r8->radioResourceConfigDedicated);
       }
 
+      //TTN for D2D
+      //if RRCConnectionReconfiguration message includes the sl-CommConfig
+      if ((rrcConnectionReconfiguration_r8->nonCriticalExtension != NULL)
+            && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension
+                  != NULL)
+                  && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension
+                        != NULL)
+                        && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension
+                              != NULL)
+                              && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension
+                                    != NULL)
+                                    && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_CommConfig_r12
+                                          != NULL)) {
+         if (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_CommConfig_r12->commTxResources_r12->present != SL_CommConfig_r12__commTxResources_r12_PR_NOTHING){
+            LOG_I(RRC,"sl-CommConfig is present\n");
+            //process sl-CommConfig
+            rrc_ue_process_sidelink_radioResourceConfig(ctxt_pP->module_id,eNB_index,
+                  (SystemInformationBlockType18_r12_t *)NULL,
+                  (SystemInformationBlockType19_r12_t *)NULL,
+                  rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_CommConfig_r12,
+                  (SL_DiscConfig_r12_t *)NULL
+            );
+         }
+      }
+
+/*
+      //if RRCConnectionReconfiguration message includes the sl-DiscConfig
+      if (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_DiscConfig_r12->discTxResources_r12->present != SL_DiscConfig_r12__discTxResources_r12_PR_NOTHING ){
+         LOG_I(RRC,"sl-DiscConfig is present\n");
+         //process sl-DiscConfig
+         rrc_ue_process_sidelink_radioResourceConfig(ctxt_pP->module_id,eNB_index,
+               (SystemInformationBlockType18_r12_t *)NULL,
+               (SystemInformationBlockType19_r12_t *)NULL,
+               (SL_CommConfig_r12_t* )NULL,
+               rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_DiscConfig_r12
+               );
+      }
+*/
+
 #if defined(ENABLE_ITTI)
 
       /* Check if there is dedicated NAS information to forward to NAS */
@@ -2131,9 +2397,15 @@ rrc_ue_process_mobilityControlInfo(
 #ifdef CBA
 			,0,
 			0
+#endif
+#if defined(Rel14)
+           ,
+           0,
+           NULL,
+           NULL
 #endif
 			);
-  
+
   // Re-establish PDCP for all RBs that are established
   // rrc_pdcp_config_req (ue_mod_idP+NB_eNB_INST, frameP, 0, CONFIG_ACTION_ADD, ue_mod_idP+DCCH);
   // rrc_pdcp_config_req (ue_mod_idP+NB_eNB_INST, frameP, 0, CONFIG_ACTION_ADD, ue_mod_idP+DCCH1);
@@ -2216,6 +2488,7 @@ rrc_ue_decode_dcch(
     char        message_string[30000];
     size_t      message_string_size;
 
+    //LOG_I(RRC, "Panos-D: rrc_ue_decode_dcch, Before xer_sprint() \n");
     if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_DCCH_Message, (void *)dl_dcch_msg)) > 0) {
       msg_p = itti_alloc_new_message_sized (TASK_RRC_UE, RRC_DL_DCCH, message_string_size + sizeof (IttiMsgText));
       msg_p->ittiMsg.rrc_dl_dcch.size = message_string_size;
@@ -2431,6 +2704,22 @@ rrc_ue_decode_dcch(
 
         }
 
+        //TTN test D2D (should not be here - in reality, this message will be triggered from ProSeApp)
+        if (send_ue_information == 0) {
+           LOG_I(RRC, "TEST SidelinkUEInformation [UE %d] Received  (eNB %d)\n",
+                 ctxt_pP->module_id, eNB_indexP);
+           SL_DestinationInfoList_r12_t *destinationInfoList = CALLOC(1, sizeof(SL_DestinationInfoList_r12_t));
+           SL_DestinationIdentity_r12_t *sl_destination_identity = CALLOC(1, sizeof(SL_DestinationIdentity_r12_t));
+           sl_destination_identity->size = 3;
+           sl_destination_identity->buf = CALLOC(1,3);
+           sl_destination_identity->buf[0] = 0x00;
+           sl_destination_identity->buf[1] = 0x00;
+           sl_destination_identity->buf[2] = 0x01;
+           sl_destination_identity->bits_unused = 0;
+           ASN_SEQUENCE_ADD(&destinationInfoList->list,sl_destination_identity);
+           rrc_ue_generate_SidelinkUEInformation(ctxt_pP, eNB_indexP, destinationInfoList, NULL, SL_TRANSMIT_NON_RELAY_ONE_TO_ONE);
+           send_ue_information ++;
+        }
         break;
 
       case DL_DCCH_MessageType__c1_PR_rrcConnectionRelease:
@@ -2514,7 +2803,7 @@ const char SIBType[12][6] = {"SIB3","SIB4","SIB5","SIB6","SIB7","SIB8","SIB9","S
 const char SIBPeriod[8][6]= {"rf8","rf16","rf32","rf64","rf128","rf256","rf512","ERR"};
 int siPeriod_int[7] = {80,160,320,640,1280,2560,5120};
 
-static const char* SIBreserved( long value )
+const char* SIBreserved( long value )
 {
   if (value < 0 || value > 1)
     return "ERR";
@@ -2524,7 +2813,7 @@ static const char* SIBreserved( long value )
 
   return "reserved";
 }
-static const char* SIBbarred( long value )
+const char* SIBbarred( long value )
 {
   if (value < 0 || value > 1)
     return "ERR";
@@ -2534,7 +2823,7 @@ static const char* SIBbarred( long value )
 
   return "barred";
 }
-static const char* SIBallowed( long value )
+const char* SIBallowed( long value )
 {
   if (value < 0 || value > 1)
     return "ERR";
@@ -2544,7 +2833,7 @@ static const char* SIBallowed( long value )
 
   return "allowed";
 }
-static const char* SIB2SoundingPresent( int value )
+const char* SIB2SoundingPresent( int value )
 {
   switch (value) {
   case SoundingRS_UL_ConfigCommon_PR_NOTHING:
@@ -2559,7 +2848,7 @@ static const char* SIB2SoundingPresent( int value )
 
   return "ERR";
 }
-static const char* SIB2numberOfRA_Preambles( long value )
+const char* SIB2numberOfRA_Preambles( long value )
 {
   static char temp[4] = {0};
 
@@ -2570,7 +2859,7 @@ static const char* SIB2numberOfRA_Preambles( long value )
   temp[3] = 0; // terminate string
   return temp;
 }
-static const char* SIB2powerRampingStep( long value )
+const char* SIB2powerRampingStep( long value )
 {
   if (value < 0 || value > 3)
     return "ERR";
@@ -2578,7 +2867,7 @@ static const char* SIB2powerRampingStep( long value )
   static const char str[4][4] = {"dB0","dB2","dB4","dB6"};
   return str[value];
 }
-static const char* SIB2preambleInitialReceivedTargetPower( long value )
+const char* SIB2preambleInitialReceivedTargetPower( long value )
 {
   static char temp[8] = {0};
 
@@ -2589,7 +2878,7 @@ static const char* SIB2preambleInitialReceivedTargetPower( long value )
   temp[7] = 0; // terminate string
   return temp;
 }
-static const char* SIB2preambleTransMax( long value )
+const char* SIB2preambleTransMax( long value )
 {
   static char temp[5] = {0};
 
@@ -2621,7 +2910,7 @@ static const char* SIB2preambleTransMax( long value )
   /* unreachable but gcc warns... */
   return "ERR";
 }
-static const char* SIB2ra_ResponseWindowSize( long value )
+const char* SIB2ra_ResponseWindowSize( long value )
 {
   static char temp[4] = {0};
 
@@ -2634,7 +2923,7 @@ static const char* SIB2ra_ResponseWindowSize( long value )
   snprintf( temp, sizeof(temp), "sf%ld", value+2 );
   return temp;
 }
-static const char* SIB2mac_ContentionResolutionTimer( long value )
+const char* SIB2mac_ContentionResolutionTimer( long value )
 {
   static char temp[5] = {0};
 
@@ -2644,7 +2933,7 @@ static const char* SIB2mac_ContentionResolutionTimer( long value )
   snprintf( temp, sizeof(temp), "sf%ld", 8 + value*8 );
   return temp;
 }
-static const char* SIB2modificationPeriodCoeff( long value )
+const char* SIB2modificationPeriodCoeff( long value )
 {
   static char temp[32] = {0};
 
@@ -2654,7 +2943,7 @@ static const char* SIB2modificationPeriodCoeff( long value )
   snprintf( temp, sizeof(temp), "n%d", (int)pow(2,value+1) );
   return temp;
 }
-static const char* SIB2defaultPagingCycle( long value )
+const char* SIB2defaultPagingCycle( long value )
 {
   static char temp[32] = {0};
 
@@ -2664,7 +2953,7 @@ static const char* SIB2defaultPagingCycle( long value )
   snprintf( temp, sizeof(temp), "rf%d", (int)pow(2,value+4) );
   return temp;
 }
-static const char* SIB2nB( long value )
+const char* SIB2nB( long value )
 {
   if (value < 0 || value > 7)
     return "ERR";
@@ -2735,6 +3024,7 @@ int decode_BCCH_DLSCH_Message(
     char        message_string[15000];
     size_t      message_string_size;
 
+    //LOG_I(RRC, "Panos-D: decode_BCCH_DLSCH_Message, Before xer_sprint() \n");
     if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_BCCH_DL_SCH_Message, (void *)bcch_message)) > 0) {
       MessageDef *msg_p;
 
@@ -2759,6 +3049,9 @@ int decode_BCCH_DLSCH_Message(
                   (void*)&bcch_message->message.choice.c1.choice.systemInformationBlockType1,
                   sizeof(SystemInformationBlockType1_t) );
           LOG_D( RRC, "[UE %"PRIu8"] Decoding First SIB1\n", ctxt_pP->module_id );
+
+          //LOG_I( RRC, "Panos-D: decode_BCCH_DLSCH_Message1 BEFORE decode_SIB1");
+          //printf("Panos-D: decode_BCCH_DLSCH_Message1 BEFORE decode_SIB1");
           decode_SIB1( ctxt_pP, eNB_index, rsrq, rsrp );
         }
       }
@@ -2777,8 +3070,11 @@ int decode_BCCH_DLSCH_Message(
         LOG_D( RRC, "[UE %"PRIu8"] Decoding SI for frameP %"PRIu32"\n",
                ctxt_pP->module_id,
                ctxt_pP->frame );
-
+        //LOG_I( RRC, "Panos-D: decode_BCCH_DLSCH_Message1 BEFORE OTHER decode_SI");
+        //printf("Panos-D: decode_BCCH_DLSCH_Message1 BEFORE OTHER decode_SI");
         decode_SI( ctxt_pP, eNB_index );
+        //if (nfapi_mode == 3)
+        	UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1;
       }
 
       break;
@@ -2838,7 +3134,7 @@ int decode_PCCH_DLSCH_Message(
 }
 
 //-----------------------------------------------------------------------------
-static int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t rsrq, const uint8_t rsrp )
+int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t rsrq, const uint8_t rsrp )
 {
   SystemInformationBlockType1_t* sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index];
 
@@ -2989,9 +3285,15 @@ static int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_
 			,
 			0,
 			0
+#endif
+#if defined(Rel14)
+           ,
+           0,
+           NULL,
+           NULL
 #endif
 			);
-  
+
   UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus = 1;
   UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIB1systemInfoValueTag = sib1->systemInfoValueTag;
 
@@ -3069,7 +3371,7 @@ static int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_
 
 
 //-----------------------------------------------------------------------------
-static void dump_sib2( SystemInformationBlockType2_t *sib2 )
+ void dump_sib2( SystemInformationBlockType2_t *sib2 )
 {
   // ac_BarringInfo
   if (sib2->ac_BarringInfo) {
@@ -3310,7 +3612,7 @@ static void dump_sib2( SystemInformationBlockType2_t *sib2 )
 }
 
 //-----------------------------------------------------------------------------
-static void dump_sib3( SystemInformationBlockType3_t *sib3 )
+ void dump_sib3( SystemInformationBlockType3_t *sib3 )
 {
   LOG_I( RRC, "Dumping SIB3 (see TS36.331 V8.21.0)\n" );
 
@@ -3385,7 +3687,7 @@ int Qoffsettab[31] = {-24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-5,-4,-3,-2,-1,0,1,2
 int PhysCellIdRange[16] = {4,8,12,16,24,32,48,64,84,96,128,168,252,504,0,0};
 
 uint64_t arfcn_to_freq(long arfcn) {
-  
+
   if (arfcn < 600)  // Band 1
     return((uint64_t)2110000000 + (arfcn*100000));
   else if (arfcn <1200) // Band 2
@@ -3459,14 +3761,14 @@ uint64_t arfcn_to_freq(long arfcn) {
     exit(1);
   }
 }
-static void dump_sib5( SystemInformationBlockType5_t *sib5 )
+ void dump_sib5( SystemInformationBlockType5_t *sib5 )
 {
   InterFreqCarrierFreqList_t interFreqCarrierFreqList = sib5->interFreqCarrierFreqList;
   int i,j;
   InterFreqCarrierFreqInfo_t *ifcfInfo;
 
   LOG_I( RRC, "Dumping SIB5 (see TS36.331 V8.21.0)\n" );
-  
+
   for (i=0;i<interFreqCarrierFreqList.list.count;i++) {
     LOG_I(RRC, "SIB5 InterFreqCarrierFreq element %d/%d\n",i,interFreqCarrierFreqList.list.count);
     ifcfInfo = interFreqCarrierFreqList.list.array[i];
@@ -3520,16 +3822,16 @@ static void dump_sib5( SystemInformationBlockType5_t *sib5 )
     if (ifcfInfo->q_OffsetFreq)
       LOG_I(RRC,"   Q_OffsetFreq : %d\n",Qoffsettab[*ifcfInfo->q_OffsetFreq]);
     if (ifcfInfo->interFreqNeighCellList) {
-      
+
       for (j=0;j<ifcfInfo->interFreqNeighCellList->list.count;j++) {
 	LOG_I(RRC,"   Cell %d\n", j);
 	LOG_I(RRC,"      PhysCellId : %ld\n",ifcfInfo->interFreqNeighCellList->list.array[j]->physCellId);
 	LOG_I(RRC,"      Q_OffsetRange : %ld\n",ifcfInfo->interFreqNeighCellList->list.array[j]->q_OffsetCell);
-	
+
       }
     }
     if (ifcfInfo->interFreqBlackCellList) {
-      
+
       for (j=0;j<ifcfInfo->interFreqBlackCellList->list.count;j++) {
 	LOG_I(RRC,"   Cell %d\n", j);
 	LOG_I(RRC,"      PhysCellId start: %ld\n",ifcfInfo->interFreqBlackCellList->list.array[j]->start);
@@ -3541,18 +3843,18 @@ static void dump_sib5( SystemInformationBlockType5_t *sib5 )
 #if defined(Rel10) || defined(Rel14)
     if (ifcfInfo->ext1 && ifcfInfo->ext1->q_QualMin_r9)
       LOG_I(RRC,"   Q_QualMin_r9 : %ld\n",*ifcfInfo->ext1->q_QualMin_r9);
-    
+
     if (ifcfInfo->ext1 && ifcfInfo->ext1->threshX_Q_r9) {
       LOG_I(RRC,"   threshX_HighQ_r9 : %ld\n",ifcfInfo->ext1->threshX_Q_r9->threshX_HighQ_r9);
       LOG_I(RRC,"   threshX_LowQ_r9: %ld\n",ifcfInfo->ext1->threshX_Q_r9->threshX_LowQ_r9);
     }
 #endif
   }
-  
+
 }
-  
+
 #if defined(Rel10) || defined(Rel14)
-static void dump_sib13( SystemInformationBlockType13_r9_t *sib13 )
+ void dump_sib13( SystemInformationBlockType13_r9_t *sib13 )
 {
   LOG_I( RRC, "[UE] Dumping SIB13\n" );
   LOG_I( RRC, "[UE] dumping sib13 second time\n" );
@@ -3560,34 +3862,88 @@ static void dump_sib13( SystemInformationBlockType13_r9_t *sib13 )
   LOG_I( RRC, "[UE] NotificationOffset-r9 : %d\n", (int)sib13->notificationConfig_r9.notificationOffset_r9 );
   LOG_I( RRC, "[UE] NotificationSF-Index-r9 : %d\n", (int)sib13->notificationConfig_r9.notificationSF_Index_r9 );
 }
-#endif
 
+
+//TTN - SIB18
 //-----------------------------------------------------------------------------
-static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index )
-{
+ void dump_sib18(SystemInformationBlockType18_r12_t *sib18){
+   LOG_I( RRC, "[UE] Dumping SIB18\n" );
+   for (int i = 0; i < sib18->commConfig_r12->commRxPool_r12.list.count; i++) {
+       LOG_I(RRC, " Contents of SIB18 %d/%d \n", i+1, sib18->commConfig_r12->commRxPool_r12.list.count);
+       LOG_I(RRC, " SIB18 rxPool_sc_CP_Len: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_CP_Len_r12);
+       LOG_I(RRC, " SIB18 sc_Period_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_Period_r12);
+       LOG_I(RRC, " SIB18 data_CP_Len_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->data_CP_Len_r12);
+       LOG_I(RRC, " SIB18 prb_Num_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_TF_ResourceConfig_r12.prb_Num_r12);
+       LOG_I(RRC, " SIB18 prb_Start_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_TF_ResourceConfig_r12.prb_Start_r12);
+       LOG_I(RRC, " SIB18 prb_End_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_TF_ResourceConfig_r12.prb_End_r12);
+       //to add more log
+     }
+}
 
+//TTN -  SIB19
+//-----------------------------------------------------------------------------
+ void dump_sib19(SystemInformationBlockType19_r12_t *sib19){
+   LOG_I( RRC, "[UE] Dumping SIB19\n" );
+   for (int i = 0; i < sib19->discConfig_r12->discRxPool_r12.list.count; i++) {
+       LOG_I(RRC, " Contents of SIB19 %d/%d \n", i+1, sib19->discConfig_r12->discRxPool_r12.list.count);
+       LOG_I(RRC, " SIB19 cp_Len_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->cp_Len_r12);
+       LOG_I(RRC, " SIB19 discPeriod_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->discPeriod_r12);
+       LOG_I(RRC, " SIB19 numRetx_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->numRetx_r12);
+       LOG_I(RRC, " SIB19 numRepetition_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->numRepetition_r12);
+       LOG_I(RRC, " SIB19 prb_Num_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->tf_ResourceConfig_r12.prb_Num_r12);
+       LOG_I(RRC, " SIB19 prb_Start_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->tf_ResourceConfig_r12.prb_Start_r12);
+       LOG_I(RRC, " SIB19 prb_End_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->tf_ResourceConfig_r12.prb_End_r12);
+       //to add more log
+     }
+}
+
+ void dump_sib21(SystemInformationBlockType21_r14_t *sib21){
+    if ((sib21->sl_V2X_ConfigCommon_r14 != NULL) && (sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14 !=NULL) ){
+       for (int i = 0; i < sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.count; i++) {
+          LOG_I(RRC, " Contents of SIB21 %d/%d \n", i+1, sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.count);
+          LOG_I(RRC, " SIB21 sl_Subframe_r14: %d \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->sl_Subframe_r14.present);
+          LOG_I(RRC, " SIB21 adjacencyPSCCH_PSSCH_r14: %d \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->adjacencyPSCCH_PSSCH_r14);
+          LOG_I(RRC, " SIB21 sizeSubchannel_r14: %ld \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->sizeSubchannel_r14);
+          LOG_I(RRC, " SIB21 numSubchannel_r14: %ld \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->numSubchannel_r14);
+          LOG_I(RRC, " SIB21 startRB_Subchannel_r14: %ld \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->startRB_Subchannel_r14);
+          //to add more log
+       }
+    }
+ }
+
+
+#endif
+//-----------------------------------------------------------------------------
+ int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index )
+{
+  //LOG_D( RRC, "Panos-D: decode_SI 1 \n");
   SystemInformation_t** si = &UE_rrc_inst[ctxt_pP->module_id].si[eNB_index];
   int new_sib = 0;
   SystemInformationBlockType1_t* sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index];
 
+  //LOG_D( RRC, "Panos-D: decode_SI 2 \n");
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN );
 
   // Dump contents
-  if ((*si)->criticalExtensions.present == SystemInformation__criticalExtensions_PR_systemInformation_r8) {
+  if ((*si)->criticalExtensions.present == SystemInformation__criticalExtensions_PR_systemInformation_r8 ||
+		  (*si)->criticalExtensions.present == SystemInformation__criticalExtensions_PR_criticalExtensionsFuture) {
     LOG_D( RRC, "[UE] (*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count %d\n",
            (*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count );
   } else {
+	  //LOG_D( RRC, "Panos-D: decode_SI 2.3 \n");
     LOG_D( RRC, "[UE] Unknown criticalExtension version (not Rel8)\n" );
     return -1;
   }
 
+  LOG_D( RRC, "Panos-D: decode_SI 3 \n");
   for (int i=0; i<(*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count; i++) {
-    LOG_D( RRC, "SI count %d\n", i );
+    //LOG_I( RRC, "Panos-D: SI count %d\n", i );
     struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member *typeandinfo;
     typeandinfo = (*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.array[i];
 
     switch(typeandinfo->present) {
     case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2:
+    	//LOG_D( RRC, "Panos-D: decode_SI 4 \n");
       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&2) == 0) {
 	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=2;
 	new_sib=1;
@@ -3625,6 +3981,12 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
 #ifdef CBA
 			      ,0,
 			      0
+#endif
+#if defined(Rel14)
+           ,
+           0,
+           NULL,
+           NULL
 #endif
 			      );
 	// After SI is received, prepare RRCConnectionRequest
@@ -3634,9 +3996,9 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
 #endif
 #if !(defined(ENABLE_ITTI) && defined(ENABLE_USE_MME))
 	  rrc_ue_generate_RRCConnectionRequest( ctxt_pP, eNB_index );
-	
+
 #endif
-	
+
 	if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State == RRC_IDLE) {
 	  LOG_I( RRC, "[UE %d] Received SIB1/SIB2/SIB3 Switching to RRC_SI_RECEIVED\n", ctxt_pP->module_id );
 	  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State = RRC_SI_RECEIVED;
@@ -3644,7 +4006,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
 	  {
 	    MessageDef                            *message_ral_p = NULL;
 	    rrc_ral_system_information_ind_t       ral_si_ind;
-	    
+
 	    message_ral_p = itti_alloc_new_message (TASK_RRC_UE, RRC_RAL_SYSTEM_INFORMATION_IND);
 	    memset(&ral_si_ind, 0, sizeof(rrc_ral_system_information_ind_t));
 	    ral_si_ind.plmn_id.MCCdigit2 = '0';
@@ -3671,6 +4033,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
       break; // case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2
 
     case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3:
+    	//LOG_D( RRC, "Panos-D: decode_SI 5 \n");
       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&4) == 0) {
 	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=4;
 	new_sib=1;
@@ -3695,7 +4058,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&16) == 0) {
 	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=16;
 	new_sib=1;
-     
+
 	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib5[eNB_index], &typeandinfo->choice.sib5, sizeof(SystemInformationBlockType5_t) );
 	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB5 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
 	dump_sib5(UE_rrc_inst[ctxt_pP->module_id].sib5[eNB_index]);
@@ -3706,7 +4069,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&32) == 0) {
 	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=32;
 	new_sib=1;
-     
+
 	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib6[eNB_index], &typeandinfo->choice.sib6, sizeof(SystemInformationBlockType6_t) );
 	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB6 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
       }
@@ -3734,7 +4097,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&256) == 0) {
 	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=256;
 	new_sib=1;
-      
+
 	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib9[eNB_index], &typeandinfo->choice.sib9, sizeof(SystemInformationBlockType9_t) );
 	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB9 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
       }
@@ -3769,12 +4132,12 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
 	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB12 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
       }
       break;
-	
+
     case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920:
       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&4096) == 0) {
 	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=4096;
 	new_sib=1;
-	
+
 	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib13[eNB_index], &typeandinfo->choice.sib13_v920, sizeof(SystemInformationBlockType13_r9_t) );
 	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB13 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
 	dump_sib13( UE_rrc_inst[ctxt_pP->module_id].sib13[eNB_index] );
@@ -3804,10 +4167,84 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
 #ifdef CBA
 			      ,0,
 			      0
+#endif
+#if defined(Rel14)
+           ,
+           0,
+           NULL,
+           NULL
 #endif
 			      );
 	break;
       }
+#endif
+
+#if defined(Rel10) || defined(Rel14)
+      //SIB18
+    case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib18_v1250:
+       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&8192) == 0) {
+          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=8192;
+          new_sib=1;
+
+          memcpy( UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index], &typeandinfo->choice.sib18_v1250, sizeof(SystemInformationBlockType18_r12_t) );
+          LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB18 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
+          dump_sib18( UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index] );
+          // adding here function to store necessary parameters to transfer to PHY layer
+          LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB18 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
+                ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
+
+          //process SIB18 to transfer SL-related parameters to PHY
+          rrc_ue_process_sidelink_radioResourceConfig(ctxt_pP->module_id,eNB_index,
+                UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index],
+                (SystemInformationBlockType19_r12_t *)NULL,
+                (SL_CommConfig_r12_t *)NULL,
+                (SL_DiscConfig_r12_t *)NULL
+          );
+
+       }
+       break;
+
+       //SIB19
+    case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib19_v1250:
+       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&16384) == 0) {
+          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=16384;
+          new_sib=1;
+
+          memcpy( UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index], &typeandinfo->choice.sib19_v1250, sizeof(SystemInformationBlockType19_r12_t) );
+          LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB19 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
+          dump_sib19( UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index] );
+          // adding here function to store necessary parameters to transfer to PHY layer
+          LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB19 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
+                ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
+          //process SIB19 to transfer SL-related parameters to PHY
+          rrc_ue_process_sidelink_radioResourceConfig(ctxt_pP->module_id,eNB_index,
+                (SystemInformationBlockType18_r12_t *)NULL,
+                UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index],
+                (SL_CommConfig_r12_t *)NULL,
+                (SL_DiscConfig_r12_t *)NULL
+          );
+
+       }
+       break;
+
+       //SIB21
+    case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib21_v1430:
+       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&32768) == 0) {
+          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=32768;
+          new_sib=1;
+
+          memcpy( UE_rrc_inst[ctxt_pP->module_id].sib21[eNB_index], &typeandinfo->choice.sib21_v1430, sizeof(SystemInformationBlockType21_r14_t) );
+          LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB21 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
+          dump_sib21( UE_rrc_inst[ctxt_pP->module_id].sib21[eNB_index] );
+          // adding here function to store necessary parameters to transfer to PHY layer
+          LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB21 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
+                ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
+          //process SIB21
+          //TODO
+       }
+       break;
+
+
 #endif
     default:
       break;
@@ -3820,7 +4257,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
     if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt == sib1->schedulingInfoList.list.count)
       rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE );
 
-    LOG_I(RRC,"SIStatus %x, SIcnt %d/%d\n", 
+    LOG_I(RRC,"SIStatus %x, SIcnt %d/%d\n",
 	  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus,
 	  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt,
 	  sib1->schedulingInfoList.list.count);
@@ -3893,7 +4330,7 @@ void ue_meas_filtering( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_
 
 //Below routine implements Measurement Reporting procedure from 36.331 Section 5.5.5
 //-----------------------------------------------------------------------------
-static void rrc_ue_generate_MeasurementReport(protocol_ctxt_t* const ctxt_pP, uint8_t eNB_index )
+ void rrc_ue_generate_MeasurementReport(protocol_ctxt_t* const ctxt_pP, uint8_t eNB_index )
 {
 
   uint8_t             buffer[32], size;
@@ -3961,7 +4398,11 @@ static void rrc_ue_generate_MeasurementReport(protocol_ctxt_t* const ctxt_pP, ui
         size = do_MeasurementReport(ctxt_pP->module_id, buffer,measId,targetCellId,rsrp_s,rsrq_s,rsrp_t,rsrq_t);
         LOG_I(RRC, "[UE %d] Frame %d : Generating Measurement Report for eNB %d\n",
               ctxt_pP->module_id, ctxt_pP->frame, eNB_index);
-        result = pdcp_data_req(ctxt_pP,  SRB_FLAG_YES, DCCH, rrc_mui++, 0, size, buffer, PDCP_TRANSMISSION_MODE_DATA);
+        result = pdcp_data_req(ctxt_pP,  SRB_FLAG_YES, DCCH, rrc_mui++, 0, size, buffer, PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+                               ,NULL, NULL
+#endif
+                               );
         AssertFatal (result == TRUE, "PDCP data request failed!\n");
         //LOG_D(RRC, "[UE %d] Frame %d Sending MeasReport (%d bytes) through DCCH%d to PDCP \n",ue_mod_idP,frameP, size, DCCH);
       }
@@ -4087,7 +4528,7 @@ void ue_measurement_report_triggering(protocol_ctxt_t* const ctxt_pP, const uint
 //check_trigger_meas_event(ue_mod_idP, frameP, eNB_index, i,j,ofn,ocn,hys,ofs,ocs,a3_offset,ttt_ms)
 //-----------------------------------------------------------------------------
 
-static uint8_t check_trigger_meas_event(
+ uint8_t check_trigger_meas_event(
   module_id_t     ue_mod_idP,
   frame_t         frameP,
   uint8_t         eNB_index,
@@ -4214,7 +4655,7 @@ int decode_MCCH_Message( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB
 }
 
 //-----------------------------------------------------------------------------
-static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_index, frame_t frameP, uint8_t mbsfn_sync_area )
+ void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_index, frame_t frameP, uint8_t mbsfn_sync_area )
 {
   protocol_ctxt_t               ctxt;
 
@@ -4253,9 +4694,15 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i
 			,
 			0,
 			0
+#endif
+#if defined(Rel14)
+           ,
+           0,
+           NULL,
+           NULL
 #endif
 			);
-  
+
   UE_rrc_inst[ue_mod_idP].Info[eNB_index].MCCHStatus[mbsfn_sync_area] = 1;
 
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_idP, ENB_FLAG_NO, UE_rrc_inst[ue_mod_idP].Info[eNB_index].rnti, frameP, 0,eNB_index);
@@ -4280,6 +4727,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i
                           NULL,// DRB_ToReleaseList
 #if defined(Rel10) || defined(Rel14)
                           &(UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9)
+                          , 0, 0
 #endif
                          );
   // */
@@ -4397,6 +4845,15 @@ void *rrc_ue_task( void *args_p )
         RRC_MAC_MCCH_DATA_IND (msg_p).sdu_size,
         RRC_MAC_MCCH_DATA_IND (msg_p).mbsfn_sync_area);
       break;
+
+  /*  //TTN (for D2D)
+    case RRC_MAC_SL_DISCOVERY_DATA_IND:
+       LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, msg_name,
+             RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).frame, RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).enb_index);
+       PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, M_RNTI, RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).frame, 0,RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).enb_index);
+       //send to ProSeApp
+       break;
+*/
 # endif
 
       /* PDCP messages */
@@ -4576,7 +5033,7 @@ void *rrc_ue_task( void *args_p )
       /* Transfer data to PDCP */
       PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, UE_rrc_inst[ue_mod_id].Info[0].rnti, 0, 0,0);
 
-      // check if SRB2 is created, if yes request data_req on DCCH1 (SRB2) 
+      // check if SRB2 is created, if yes request data_req on DCCH1 (SRB2)
       if(UE_rrc_inst[ue_mod_id].SRB2_config[0] == NULL)
       {
           rrc_data_req_ue (&ctxt,
@@ -4597,7 +5054,7 @@ void *rrc_ue_task( void *args_p )
       }
       break;
     }
-      
+
 # endif
 
 # if ENABLE_RAL
@@ -4813,6 +5270,11 @@ openair_rrc_top_init_ue(
     }
 
 #endif
+
+#ifdef Rel14
+  init_SL_preconfig(&UE_rrc_inst[module_id],0);
+#endif
+
   } else {
     UE_rrc_inst = NULL;
   }
@@ -4828,11 +5290,1091 @@ rrc_top_cleanup_ue(
 {
 
   if (NB_UE_INST > 0) free (UE_rrc_inst);
-  
 
+
+}
+
+
+//-----------------------------------------------------------------------------
+uint8_t rrc_ue_generate_SidelinkUEInformation( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index,SL_DestinationInfoList_r12_t  *destinationInfoList, long *discTxResourceReq, SL_TRIGGER_t mode)
+{
+   uint8_t    size=0;
+   uint8_t buffer[100];
+
+   //Generate SidelinkUEInformation
+   if (((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&8192) > 0) && (destinationInfoList != NULL)) {//if SIB18 is available
+      size = do_SidelinkUEInformation(ctxt_pP->module_id, buffer, destinationInfoList, NULL, mode);
+      LOG_I(RRC,"[UE %d][RRC_UE] Frame %d : Logical Channel UL-DCCH, Generating SidelinkUEInformation (bytes%d, eNB %d)\n",
+            ctxt_pP->module_id,ctxt_pP->frame, size, eNB_index);
+      //return size;
+   }
+   if (((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&16384) > 0) && (discTxResourceReq != NULL)) {//if SIB19 is available
+      size = do_SidelinkUEInformation(ctxt_pP->module_id, buffer, NULL, discTxResourceReq, mode);
+      LOG_I(RRC,"[UE %d][RRC_UE] Frame %d : Logical Channel UL-DCCH, Generating SidelinkUEInformation (bytes%d, eNB %d)\n",
+            ctxt_pP->module_id,ctxt_pP->frame, size, eNB_index);
+     //return size;
+   }
+
+   rrc_data_req_ue (
+       ctxt_pP,
+       DCCH,
+       rrc_mui++,
+       SDU_CONFIRM_NO,
+       size,
+       buffer,
+       PDCP_TRANSMISSION_MODE_CONTROL);
+   return size;
+}
+
+
+// 3GPP 36.331 (Section 5.10.7.3)
+uint8_t fill_SLSS(const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, SLSSID_r12_t *slss_id, uint8_t *subframe, uint8_t mode)
+{
+   long syncOffsetIndicator = 0;
+   switch(mode) {
+   case 1: //if triggered by SL discovery announcement and in-coverage
+      //discSyncConfig_r12 contains only one element
+      *slss_id = UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index]->discConfig_r12->discSyncConfig_r12->list.array[0]->slssid_r12;
+      syncOffsetIndicator = UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index]->discConfig_r12->discSyncConfig_r12->list.array[0]->syncOffsetIndicator_r12;
+      //select subframe for SLSS
+      break;
+   case 2: //if triggered by SL communication and in-coverage
+
+      if (UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index]->commConfig_r12->commSyncConfig_r12->list.array[0]->txParameters_r12) {
+         *slss_id = UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index]->commConfig_r12->commSyncConfig_r12->list.array[0]->slssid_r12;
+         syncOffsetIndicator = UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index]->commConfig_r12->commSyncConfig_r12->list.array[0]->syncOffsetIndicator_r12;
+
+         //if RRC_CONNECTED (Todo: and if networkControlledSyncTx (RRCConnectionReconfiguration) is configured and set to On)
+         if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State == RRC_CONNECTED){
+            //select subframe(s) indicated by syncOffsetIndicator
+            *subframe = syncOffsetIndicator;
+         } else {
+            //select subframe(s) indicated by syncOffsetIndicator within SC period
+         }
+         break;
+   case 3: //if triggered by V2X communication and in coverage
+
+      break;
+   case 4: //if triggered by V2X communication and out-of-coverage
+
+      break;
+   case 5: //if triggered by V2X communication and UE has GNSS as the synchronization reference
+
+   default:
+      //if UE has a selected SyncRefUE
+      //TODO
+      //else (no SyncRefUE Selected)
+      //Todo  if trigger by V2X
+      //else randomly select an SLSSID from the set defined for out-of-coverage
+      *slss_id = 170;//hardcoded
+      //select the subframe according to syncOffsetIndicator1/2 from the preconfigured parameters
+      break;
+      }
+   }
+   return 0;
 }
 
 
+//-----------------------------------------------------------------------------
+void
+rrc_ue_process_sidelink_radioResourceConfig(
+      module_id_t                      Mod_idP,
+      uint8_t                          eNB_index,
+      SystemInformationBlockType18_r12_t     *sib18,
+      SystemInformationBlockType19_r12_t     *sib19,
+      SL_CommConfig_r12_t* sl_CommConfig,
+      SL_DiscConfig_r12_t* sl_DiscConfig
+)
+//-----------------------------------------------------------------------------
+{
+   //process SIB18, configure MAC/PHY for receiving SL communication (RRC_IDLE and RRC_CONNECTED), for transmitting SL communication (RRC_IDLE)
+   if (sib18 != NULL) {
+      if (sib18->commConfig_r12 != NULL) {
+         //do not consider commTXPoolExceptional for the moment
+         //configure PHY/MAC to receive SL communication by using the RPs indicated by commRxPool
+         //sib18->commConfig_r12->commRxPool_r12
+         //TODO
+
+         if (sib18->commConfig_r12->commTxPoolNormalCommon_r12 !=NULL) { //commTxPoolNormalCommon - to transmit SL communication in RRC_IDLE
+            //maybe we don't consider this case for the moment since UE will immediately establish a RRC connection after receiving SIB messages
+            //configure PHY/MAC to transmit SL communication using the RPs indicated by the first entry in commTxPoolNormalCommon
+            //SL_CommResourcePool_r12_t sl_CommResourcePool = sib18->commConfig_r12->commTxPoolNormalCommon_r12->list.array[0];
+         }
+      }
+   }
+
+   //process SIB19, configure MAC/PHY for receiving SL discovery (RRC_IDLE and RRC_CONNECTED), for transmitting SL discovery (RRC_IDLE)
+   if (sib19 != NULL) {
+      //to receive non-PS related discovery announcements (discRxPool)
+      //sib19->discConfig_r12->discRxPool_r12;
+
+      //to receive PS related discovery announcements (discRxPoolPS)
+      //sib19->ext1->discConfigPS_13->discRxPoolPS_r13;
+
+      //to transmit non-PS related discovery in RRC_IDLE
+      //sib19->discConfig_r12->discTxPoolCommon_r12;
+
+      //to transmit PS related discovery in RRC_IDLE
+      //sib19->ext1->discConfigPS_13->discTxPoolPS_Common_r13;
+   }
+
+   //process sl_CommConfig, configure MAC/PHY for transmitting SL communication (RRC_CONNECTED)
+   if (sl_CommConfig != NULL) {
+
+      if (sl_CommConfig->commTxResources_r12 != NULL) {
+         switch (sl_CommConfig->commTxResources_r12->present){
+         case SL_CommConfig_r12__commTxResources_r12_PR_setup:
+            if (sl_CommConfig->commTxResources_r12->choice.setup.present == SL_CommConfig_r12__commTxResources_r12__setup_PR_scheduled_r12 ){
+
+               LOG_I(RRC,"[UE %d][RRC_UE] scheduled resource for SL, sl_RNTI size %d  \n",
+                     Mod_idP, sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sl_RNTI_r12.size );
+               LOG_I(RRC,"[UE %d][RRC_UE] scheduled resource for SL, sl_RNTI buf 0x%08x \n",
+                     Mod_idP, sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sl_RNTI_r12.buf );
+               LOG_I(RRC,"[UE %d][RRC_UE] scheduled resource for SL, Mac_MainConfig_r12.retx_BSR_TimerSL %ld \n",
+                     Mod_idP, sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.mac_MainConfig_r12.retx_BSR_TimerSL );
+               LOG_I(RRC,"[UE %d][RRC_UE] scheduled resource for SL, sc_CommTxConfig %ld \n",
+                     Mod_idP, sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.mac_MainConfig_r12.retx_BSR_TimerSL );
+               //configure scheduled resource for SL
+               //TODO
+            } else if (sl_CommConfig->commTxResources_r12->choice.setup.present == SL_CommConfig_r12__commTxResources_r12__setup_PR_ue_Selected_r12){
+               //configure dedicated resources (commTxPoolNormalDedicated) for SL from which UE can autonomously select
+               //sl_CommConfig->commTxResources_r12->choice.setup.choice.ue_Selected_r12.commTxPoolNormalDedicated_r12;
+
+               //for the moment, only pass the first entry (e.g., do not consider priorityList in commTxPoolNormalDedicated (3GPP 36.331 Section 5.10.4 1>2>3>4))
+               //sl_CommConfig->commTxResources_r12->choice.setup.choice.ue_Selected_r12.commTxPoolNormalDedicated_r12.poolToAddModList_r12->list.array[0];
+            } else {
+               //SL_CommConfig_r12__commTxResources_r12__setup_PR_NOTHING /* No components present */
+            }
+            break;
+
+         case SL_CommConfig_r12__commTxResources_r12_PR_release:
+            //release dedicated resources for SL communication
+            break;
+
+         case SL_CommConfig_r12__commTxResources_r12_PR_NOTHING: /* No components present */
+            break;
+
+         default:
+            break;
+         }
+      }
+
+   }
+
+   //process sl_DiscConfig, configure MAC/PHY for transmitting SL discovery announcements (RRC_CONNECTED)
+   if (sl_DiscConfig != NULL) {
+      //dedicated resources for transmitting non-PS related discovery
+      if (sl_DiscConfig->discTxResources_r12 != NULL) {
+
+         switch (sl_DiscConfig->discTxResources_r12->present) {
+         case SL_DiscConfig_r12__discTxResources_r12_PR_setup:
+            if (sl_DiscConfig->discTxResources_r12->choice.setup.present == SL_DiscConfig_r12__discTxResources_r12__setup_PR_scheduled_r12) {
+               //sl_DiscConfig->discTxResources_r12->choice.setup.choice.scheduled_r12.discHoppingConfig_r12;
+               //sl_DiscConfig->discTxResources_r12->choice.setup.choice.scheduled_r12.discTF_IndexList_r12;
+               //sl_DiscConfig->discTxResources_r12->choice.setup.choice.scheduled_r12.discTxConfig_r12;
+            } else if (sl_DiscConfig->discTxResources_r12->choice.setup.present == SL_DiscConfig_r12__discTxResources_r12__setup_PR_ue_Selected_r12) {
+               //sl_DiscConfig->discTxResources_r12->choice.setup.choice.ue_Selected_r12.discTxPoolDedicated_r12;
+            } else {
+               //SL_DiscConfig_r12__discTxResources_r12__setup_PR_NOTHING,   /* No components present */
+            }
+            break;
+         case SL_DiscConfig_r12__discTxResources_r12_PR_release:
+            //release dedicated resources for SL discovery
+            break;
+         case SL_DiscConfig_r12__discTxResources_r12_PR_NOTHING: /* No components present */
+            break;
+         default:
+            break;
+         }
+
+      }
+      //dedicated resources for transmitting PS related discovery
+      if (sl_DiscConfig->ext2->discTxResourcesPS_r13 != NULL){
+         switch (sl_DiscConfig->ext2->discTxResourcesPS_r13->present) {
+         case SL_DiscConfig_r12__ext2__discTxResourcesPS_r13_PR_setup:
+            if (sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.present == SL_DiscConfig_r12__ext2__discTxResourcesPS_r13__setup_PR_scheduled_r13) {
+               //sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.choice.scheduled_r13.discHoppingConfig_r13;
+               //sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.choice.scheduled_r13.discTxConfig_r13
+            } else if (sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.present == SL_DiscConfig_r12__ext2__discTxResourcesPS_r13__setup_PR_ue_Selected_r13) {
+               //sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.choice.ue_Selected_r13.discTxPoolPS_Dedicated_r13;
+            } else {
+               //SL_DiscConfig_r12__ext2__discTxResourcesPS_r13__setup_PR_NOTHING, /* No components present */
+            }
+
+            break;
+         case SL_DiscConfig_r12__ext2__discTxResourcesPS_r13_PR_release:
+            break;
+         case SL_DiscConfig_r12__ext2__discTxResourcesPS_r13_PR_NOTHING:
+            /* No components present */
+            break;
+         default:
+            break;
+         }
+      }
+   }
+}
+
+#ifdef Rel14
+//-----------------------------------------------------------
+void
+rrc_control_socket_init(){
+
+   struct sockaddr_in rrc_ctrl_socket_addr;
+   pthread_attr_t     attr;
+   struct sched_param sched_param;
+   int optval; // flag value for setsockopt
+   //int n; // message byte size
+
+
+   // create the control socket
+   ctrl_sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+   if (ctrl_sock_fd == -1) {
+      LOG_E(RRC,"[rrc_control_socket_init] :Error opening socket %d (%d:%s)\n",ctrl_sock_fd,errno, strerror(errno));
+      exit(EXIT_FAILURE);
+   }
+   //   if (ctrl_sock_fd < 0)
+   //      error("ERROR: Failed on opening socket");
+   optval = 1;
+   setsockopt(ctrl_sock_fd, SOL_SOCKET, SO_REUSEADDR,
+         (const void *)&optval , sizeof(int));
+
+   //build the server's  address
+   bzero((char *) &rrc_ctrl_socket_addr, sizeof(rrc_ctrl_socket_addr));
+   rrc_ctrl_socket_addr.sin_family = AF_INET;
+   rrc_ctrl_socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+   rrc_ctrl_socket_addr.sin_port = htons(CONTROL_SOCKET_PORT_NO);
+   // associate the parent socket with a port
+   if (bind(ctrl_sock_fd, (struct sockaddr *) &rrc_ctrl_socket_addr,
+         sizeof(rrc_ctrl_socket_addr)) < 0) {
+      LOG_E(RRC,"[rrc_control_socket_init] ERROR: Failed on binding the socket\n");
+      exit(1);
+   }
+   //create thread to listen to incoming packets
+   if (pthread_attr_init(&attr) != 0) {
+      LOG_E(RRC, "[rrc_control_socket_init]Failed to initialize pthread attribute for ProSe -> RRC 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);
+
+   pthread_t rrc_control_socket_thread;
+
+   if (pthread_create(&rrc_control_socket_thread, &attr, rrc_control_socket_thread_fct, NULL) != 0) {
+      LOG_E(RRC, "[rrc_control_socket_init]Failed to create new thread for RRC/ProSeApp communication (%d:%s)\n",
+            errno, strerror(errno));
+      exit(EXIT_FAILURE);
+   }
+
+   pthread_setname_np( rrc_control_socket_thread, "RRC Control Socket" );
+
+}
+
+//--------------------------------------------------------
+void *rrc_control_socket_thread_fct(void *arg)
+{
+
+   int prose_addr_len;
+   char send_buf[BUFSIZE];
+   char receive_buf[BUFSIZE];
+   //int optval;
+   int n;
+   struct sidelink_ctrl_element *sl_ctrl_msg_recv = NULL;
+   struct sidelink_ctrl_element *sl_ctrl_msg_send = NULL;
+   uint32_t sourceL2Id, groupL2Id, destinationL2Id;
+   module_id_t         module_id = 0; //hardcoded for testing only
+   uint8_t type;
+   UE_RRC_INST *UE  = NULL;
+   protocol_ctxt_t ctxt;
+   struct RLC_Config                  *DRB_rlc_config                   = NULL;
+   struct PDCP_Config                 *DRB_pdcp_config                  = NULL;
+   struct PDCP_Config__rlc_UM         *PDCP_rlc_UM                      = NULL;
+   struct LogicalChannelConfig        *DRB_lchan_config                 = NULL;
+   struct LogicalChannelConfig__ul_SpecificParameters  *DRB_ul_SpecificParameters = NULL;
+   long                               *logicalchannelgroup_drb          = NULL;
+   int j = 0;
+   int i = 0;
+
+   //from the main program, listen for the incoming messages from control socket (ProSe App)
+   prose_addr_len = sizeof(prose_app_addr);
+   //int enable_notification = 1;
+   while (1) {
+      LOG_I(RRC,"Listening to incoming connection from ProSe App \n");
+      // receive a message from ProSe App
+      memset(receive_buf, 0, BUFSIZE);
+      n = recvfrom(ctrl_sock_fd, receive_buf, BUFSIZE, 0,
+            (struct sockaddr *) &prose_app_addr, (socklen_t *)&prose_addr_len);
+      if (n < 0){
+         LOG_E(RRC, "ERROR: Failed to receive from ProSe App\n");
+         exit(EXIT_FAILURE);
+      }
+      //TODO: should store the address of ProSeApp [UE_rrc_inst] to be able to send UE state notification to the App
+
+      //sl_ctrl_msg_recv = (struct sidelink_ctrl_element *) receive_buf;
+      sl_ctrl_msg_recv = calloc(1, sizeof(struct sidelink_ctrl_element));
+      memcpy((void *)sl_ctrl_msg_recv, (void *)receive_buf, sizeof(struct sidelink_ctrl_element));
+
+      //process the message
+      switch (sl_ctrl_msg_recv->type) {
+      case SESSION_INIT_REQ:
+#ifdef DEBUG_CTRL_SOCKET
+         LOG_I(RRC,"Received SessionInitializationRequest on socket from ProSe App (msg type: %d)\n", sl_ctrl_msg_recv->type);
+#endif
+         //TODO: get SL_UE_STATE from lower layer
+
+         LOG_I(RRC,"Send UEStateInformation to ProSe App \n");
+         memset(send_buf, 0, BUFSIZE);
+
+         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
+         sl_ctrl_msg_send->type = UE_STATUS_INFO;
+         sl_ctrl_msg_send->sidelinkPrimitive.ue_state = UE_STATE_OFF_NETWORK; //off-network
+         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
+         free(sl_ctrl_msg_send);
+
+         prose_addr_len = sizeof(prose_app_addr);
+         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
+         if (n < 0) {
+            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
+            exit(EXIT_FAILURE);
+         }
+
+
+#ifdef DEBUG_CTRL_SOCKET
+         struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
+         ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
+         LOG_I(RRC,"[UEStateInformation] msg type: %d\n",ptr_ctrl_msg->type);
+         LOG_I(RRC,"[UEStateInformation] UE state: %d\n",ptr_ctrl_msg->sidelinkPrimitive.ue_state);
+#endif
+
+         /*  if (enable_notification > 0) {
+              //create thread to send status notification (for testing purpose, status notification will be sent e.g., every 20 seconds)
+              pthread_t notification_thread;
+              if( pthread_create( &notification_thread , NULL ,  send_UE_status_notification , (void*) &sockfd) < 0)
+                 error("ERROR: could not create thread");
+           }
+           enable_notification = 0;
+          */
+         break;
+
+      case GROUP_COMMUNICATION_ESTABLISH_REQ:
+         sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id;
+         groupL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id;
+
+#ifdef DEBUG_CTRL_SOCKET
+         LOG_I(RRC,"[GroupCommunicationEstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
+         LOG_I(RRC,"[GroupCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
+         LOG_I(RRC,"[GroupCommunicationEstablishReq] group Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id);
+         LOG_I(RRC,"[GroupCommunicationEstablishReq] group IP Address: " IPV4_ADDR "\n",IPV4_ADDR_FORMAT(sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupIpAddress));
+#endif
+
+         //store sourceL2Id/groupL2Id
+         UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
+         UE_rrc_inst[module_id].groupL2Id = groupL2Id;
+         j = 0;
+         i = 0;
+         for (i=0; i< MAX_NUM_DEST; i++) {
+            if ((UE_rrc_inst[module_id].destinationList[i] == 0) && (j == 0)) j = i+1;
+            if (UE_rrc_inst[module_id].destinationList[i] == groupL2Id) break; //group already exists!
+         }
+         if ((i == MAX_NUM_DEST) && (j > 0))  UE_mac_inst[module_id].destinationList[j-1] = groupL2Id;
+
+         // configure lower layers PDCP/MAC/PHY for this communication
+         //Establish a new RBID/LCID for this communication
+         // Establish a SLRB (using DRB 3 for now)
+         UE  = &UE_rrc_inst[module_id];
+         PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0);
+
+         UE->DRB_config[0][0] = CALLOC(1,sizeof(struct DRB_ToAddMod));
+         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+         UE->DRB_config[0][0]->drb_Identity =  3;
+         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+         // allowed value 5..15, value : x+4
+         *(UE->DRB_config[0][0]->eps_BearerIdentity) = 3;
+         UE->DRB_config[0][0]->logicalChannelIdentity = CALLOC(1, sizeof(long));
+         *(UE->DRB_config[0][0]->logicalChannelIdentity) = UE->DRB_config[0][0]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2
+
+         DRB_rlc_config                   = CALLOC(1,sizeof(struct RLC_Config));
+         DRB_pdcp_config                  = CALLOC(1,sizeof(struct PDCP_Config));
+         PDCP_rlc_UM                      = CALLOC(1,sizeof(struct PDCP_Config__rlc_UM));
+         DRB_lchan_config                 = CALLOC(1,sizeof(struct LogicalChannelConfig));
+         DRB_ul_SpecificParameters                                         = CALLOC(1, sizeof(struct LogicalChannelConfig__ul_SpecificParameters));
+         logicalchannelgroup_drb          = CALLOC(1, sizeof(long));
+
+         DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional;
+         DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = T_Reordering_ms35;
+         UE->DRB_config[0][0]->rlc_Config = DRB_rlc_config;
+
+         DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config));
+         UE->DRB_config[0][0]->pdcp_Config = DRB_pdcp_config;
+         DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long));
+         *DRB_pdcp_config->discardTimer = PDCP_Config__discardTimer_infinity;
+         DRB_pdcp_config->rlc_AM = NULL;
+         DRB_pdcp_config->rlc_UM = NULL;
+
+         /* avoid gcc warnings */
+         (void)PDCP_rlc_UM;
+
+         DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
+         PDCP_rlc_UM->pdcp_SN_Size = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
+         DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed;
+
+         UE->DRB_config[0][0]->logicalChannelConfig = DRB_lchan_config;
+         DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
+         DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;
+
+         DRB_ul_SpecificParameters->priority = 12;    // lower priority than srb1, srb2 and other dedicated bearer
+         DRB_ul_SpecificParameters->prioritisedBitRate =LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
+         //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
+         DRB_ul_SpecificParameters->bucketSizeDuration =
+               LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;
+
+         // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM)
+
+         *logicalchannelgroup_drb = 1;
+         DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb;
+
+         UE->DRB_configList = CALLOC(1,sizeof(DRB_ToAddModList_t));
+         ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][0]);
+
+         rrc_pdcp_config_asn1_req(&ctxt,
+               (SRB_ToAddModList_t *) NULL,
+               UE->DRB_configList,
+               (DRB_ToReleaseList_t*) NULL,
+               0xff, NULL, NULL, NULL
+#if defined(Rel10) || defined(Rel14)
+               , (PMCH_InfoList_r9_t *) NULL
+#endif
+               ,NULL);
+
+
+         rrc_rlc_config_asn1_req(&ctxt,
+               (SRB_ToAddModList_t*)NULL,
+               UE->DRB_configList,
+               (DRB_ToReleaseList_t*)NULL
+#if defined(Rel10) || defined(Rel14)
+               ,(PMCH_InfoList_r9_t *)NULL
+               , 0, 0
+#endif
+         );
+
+         rrc_rlc_config_asn1_req(&ctxt,
+               (SRB_ToAddModList_t*)NULL,
+               UE->DRB_configList,
+               (DRB_ToReleaseList_t*)NULL
+#ifdef Rel14
+               ,(PMCH_InfoList_r9_t *)NULL
+               , sourceL2Id, groupL2Id
+#endif
+         );
+
+
+         //configure MAC with sourceL2Id/groupL2ID
+         rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
+               (RadioResourceConfigCommonSIB_t *)NULL,
+               (struct PhysicalConfigDedicated *)NULL,
+#if defined(Rel10) || defined(Rel14)
+               (SCellToAddMod_r10_t *)NULL,
+               //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
+#endif
+               (MeasObjectToAddMod_t **)NULL,
+               (MAC_MainConfig_t *)NULL,
+               3, //LCID
+               (struct LogicalChannelConfig *)NULL,
+               (MeasGapConfig_t *)NULL,
+               (TDD_Config_t *)NULL,
+               (MobilityControlInfo_t *)NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL
+#if defined(Rel10) || defined(Rel14)
+               ,0,
+               (MBSFN_AreaInfoList_r9_t *)NULL,
+               (PMCH_InfoList_r9_t *)NULL
+
+#endif
+#ifdef CBA
+               ,
+               0,
+               0
+#endif
+#if defined(Rel10) || defined(Rel14)
+               ,CONFIG_ACTION_ADD,
+               &sourceL2Id,
+               &groupL2Id
+#endif
+         );
+
+         LOG_I(RRC,"Send GroupCommunicationEstablishResp to ProSe App\n");
+         memset(send_buf, 0, BUFSIZE);
+         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
+         sl_ctrl_msg_send->type = GROUP_COMMUNICATION_ESTABLISH_RSP;
+         sl_ctrl_msg_send->sidelinkPrimitive.slrb_id = 3; //slrb_id
+
+         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
+         free(sl_ctrl_msg_send);
+
+         prose_addr_len = sizeof(prose_app_addr);
+         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
+         if (n < 0){
+            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
+            exit(EXIT_FAILURE);
+         }
+
+
+#ifdef DEBUG_CTRL_SOCKET
+         ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
+         LOG_I(RRC,"[GroupCommunicationEstablishResponse]  msg type: %d\n",ptr_ctrl_msg->type);
+         LOG_I(RRC,"[GroupCommunicationEstablishResponse]  slrb_id: %d\n",ptr_ctrl_msg->sidelinkPrimitive.slrb_id);
+#endif
+         break;
+
+      case GROUP_COMMUNICATION_RELEASE_REQ:
+         printf("-----------------------------------\n");
+#ifdef DEBUG_CTRL_SOCKET
+         LOG_I(RRC,"[GroupCommunicationReleaseRequest] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
+         LOG_I(RRC,"[GroupCommunicationReleaseRequest] Slrb Id: %i\n",sl_ctrl_msg_recv->sidelinkPrimitive.slrb_id);
+#endif
+         //reset groupL2ID from MAC LAYER
+         UE_rrc_inst[module_id].groupL2Id = 0x00000000;
+         sourceL2Id = UE_rrc_inst[module_id].sourceL2Id;
+
+         rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
+                    (RadioResourceConfigCommonSIB_t *)NULL,
+                    (struct PhysicalConfigDedicated *)NULL,
+         #if defined(Rel10) || defined(Rel14)
+                    (SCellToAddMod_r10_t *)NULL,
+                    //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
+         #endif
+                    (MeasObjectToAddMod_t **)NULL,
+                    (MAC_MainConfig_t *)NULL,
+                    0,
+                    (struct LogicalChannelConfig *)NULL,
+                    (MeasGapConfig_t *)NULL,
+                    (TDD_Config_t *)NULL,
+                    (MobilityControlInfo_t *)NULL,
+                    NULL,
+                    NULL,
+                    NULL,
+                    NULL,
+                    NULL,
+                    NULL
+         #if defined(Rel10) || defined(Rel14)
+                    ,0,
+                    (MBSFN_AreaInfoList_r9_t *)NULL,
+                    (PMCH_InfoList_r9_t *)NULL
+
+         #endif
+         #ifdef CBA
+                    ,
+                    0,
+                    0
+         #endif
+         #if defined(Rel10) || defined(Rel14)
+                    ,CONFIG_ACTION_REMOVE,
+                    &sourceL2Id,
+                    &destinationL2Id
+         #endif
+                    );
+
+
+         LOG_I(RRC,"Send GroupCommunicationReleaseResponse to ProSe App \n");
+         memset(send_buf, 0, BUFSIZE);
+
+         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
+         sl_ctrl_msg_send->type = GROUP_COMMUNICATION_RELEASE_RSP;
+         //if the requested id exists -> release this ID
+         if (sl_ctrl_msg_recv->sidelinkPrimitive.slrb_id == slrb_id) {
+            sl_ctrl_msg_send->sidelinkPrimitive.group_comm_release_rsp = GROUP_COMMUNICATION_RELEASE_OK;
+            slrb_id = 0; //Reset slrb_id
+         } else {
+            sl_ctrl_msg_send->sidelinkPrimitive.group_comm_release_rsp = GROUP_COMMUNICATION_RELEASE_FAILURE;
+         }
+         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
+         free(sl_ctrl_msg_send);
+
+         prose_addr_len = sizeof(prose_app_addr);
+         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
+         if (n < 0){
+            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
+            exit(EXIT_FAILURE);
+         }
+         break;
+
+
+      case DIRECT_COMMUNICATION_ESTABLISH_REQ:
+         sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.direct_comm_establish_req.sourceL2Id;
+         destinationL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.direct_comm_establish_req.destinationL2Id;
+
+#ifdef DEBUG_CTRL_SOCKET
+         LOG_I(RRC,"[DirectCommunicationEstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
+         LOG_I(RRC,"[DirectCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
+         LOG_I(RRC,"[DirectCommunicationEstablishReq] destination Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id);
+#endif
+
+         //store sourceL2Id/destinationL2Id
+         UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
+         i = 0;
+         j = 0;
+         for (i=0; i< MAX_NUM_DEST; i++) {
+            if ((UE_rrc_inst[module_id].destinationList[i] == 0) && (j == 0)) j = i+1;
+            if (UE_rrc_inst[module_id].destinationList[i] == destinationL2Id) break; //destination already exists!
+         }
+         if ((i == MAX_NUM_DEST) && (j > 0))  UE_mac_inst[module_id].destinationList[j-1] = destinationL2Id;
+
+         // configure lower layers PDCP/MAC/PHY for this communication
+         //Establish a new RBID/LCID for this communication
+         // Establish a SLRB (using DRB 3 for now)
+         UE  = &UE_rrc_inst[module_id];
+         PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0);
+
+         UE->DRB_config[0][0] = CALLOC(1,sizeof(struct DRB_ToAddMod));
+         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+         UE->DRB_config[0][0]->drb_Identity =  3;
+         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+         // allowed value 5..15, value : x+4
+         *(UE->DRB_config[0][0]->eps_BearerIdentity) = 3;
+         UE->DRB_config[0][0]->logicalChannelIdentity = CALLOC(1, sizeof(long));
+         *(UE->DRB_config[0][0]->logicalChannelIdentity) = UE->DRB_config[0][0]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2
+
+         DRB_rlc_config                   = CALLOC(1,sizeof(struct RLC_Config));
+         DRB_pdcp_config                  = CALLOC(1,sizeof(struct PDCP_Config));
+         PDCP_rlc_UM                      = CALLOC(1,sizeof(struct PDCP_Config__rlc_UM));
+         DRB_lchan_config                 = CALLOC(1,sizeof(struct LogicalChannelConfig));
+         DRB_ul_SpecificParameters                                         = CALLOC(1, sizeof(struct LogicalChannelConfig__ul_SpecificParameters));
+         logicalchannelgroup_drb          = CALLOC(1, sizeof(long));
+
+         DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional;
+         DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = T_Reordering_ms35;
+         UE->DRB_config[0][0]->rlc_Config = DRB_rlc_config;
+
+         DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config));
+         UE->DRB_config[0][0]->pdcp_Config = DRB_pdcp_config;
+         DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long));
+         *DRB_pdcp_config->discardTimer = PDCP_Config__discardTimer_infinity;
+         DRB_pdcp_config->rlc_AM = NULL;
+         DRB_pdcp_config->rlc_UM = NULL;
+
+         /* avoid gcc warnings */
+         (void)PDCP_rlc_UM;
+
+         DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
+         PDCP_rlc_UM->pdcp_SN_Size = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
+         DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed;
+
+         UE->DRB_config[0][0]->logicalChannelConfig = DRB_lchan_config;
+         DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
+         DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;
+
+         DRB_ul_SpecificParameters->priority = 12;    // lower priority than srb1, srb2 and other dedicated bearer
+         DRB_ul_SpecificParameters->prioritisedBitRate =LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
+         //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
+         DRB_ul_SpecificParameters->bucketSizeDuration =
+               LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;
+
+         // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM)
+
+         *logicalchannelgroup_drb = 1;
+         DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb;
+
+         UE->DRB_configList = CALLOC(1,sizeof(DRB_ToAddModList_t));
+         ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][0]);
+
+         rrc_pdcp_config_asn1_req(&ctxt,
+               (SRB_ToAddModList_t *) NULL,
+               UE->DRB_configList,
+               (DRB_ToReleaseList_t*) NULL,
+               0xff, NULL, NULL, NULL
+#if defined(Rel10) || defined(Rel14)
+               , (PMCH_InfoList_r9_t *) NULL
+#endif
+               ,NULL);
+
+
+         rrc_rlc_config_asn1_req(&ctxt,
+               (SRB_ToAddModList_t*)NULL,
+               UE->DRB_configList,
+               (DRB_ToReleaseList_t*)NULL
+#if defined(Rel10) || defined(Rel14)
+               ,(PMCH_InfoList_r9_t *)NULL
+               , 0, 0
+#endif
+         );
+
+         rrc_rlc_config_asn1_req(&ctxt,
+               (SRB_ToAddModList_t*)NULL,
+               UE->DRB_configList,
+               (DRB_ToReleaseList_t*)NULL
+#ifdef Rel14
+               ,(PMCH_InfoList_r9_t *)NULL
+               , sourceL2Id, destinationL2Id
+#endif
+         );
+
+
+         //configure MAC with sourceL2Id/destinationL2Id
+         rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
+               (RadioResourceConfigCommonSIB_t *)NULL,
+               (struct PhysicalConfigDedicated *)NULL,
+#if defined(Rel10) || defined(Rel14)
+               (SCellToAddMod_r10_t *)NULL,
+               //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
+#endif
+               (MeasObjectToAddMod_t **)NULL,
+               (MAC_MainConfig_t *)NULL,
+               3, //LCID
+               (struct LogicalChannelConfig *)NULL,
+               (MeasGapConfig_t *)NULL,
+               (TDD_Config_t *)NULL,
+               (MobilityControlInfo_t *)NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL,
+               NULL
+#if defined(Rel10) || defined(Rel14)
+               ,0,
+               (MBSFN_AreaInfoList_r9_t *)NULL,
+               (PMCH_InfoList_r9_t *)NULL
+
+#endif
+#ifdef CBA
+               ,
+               0,
+               0
+#endif
+#if defined(Rel10) || defined(Rel14)
+               ,CONFIG_ACTION_ADD,
+               &sourceL2Id,
+               &destinationL2Id
+#endif
+         );
+
+         LOG_I(RRC,"Send DirectCommunicationEstablishResp to ProSe App\n");
+         memset(send_buf, 0, BUFSIZE);
+         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
+         sl_ctrl_msg_send->type = DIRECT_COMMUNICATION_ESTABLISH_RSP;
+         sl_ctrl_msg_send->sidelinkPrimitive.slrb_id = 3; //slrb_id
+
+         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
+         free(sl_ctrl_msg_send);
+
+         prose_addr_len = sizeof(prose_app_addr);
+         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
+         if (n < 0){
+            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
+            exit(EXIT_FAILURE);
+         }
+
+
+#ifdef DEBUG_CTRL_SOCKET
+         ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
+         LOG_I(RRC,"[DirectCommunicationEstablishResponse]  msg type: %d\n",ptr_ctrl_msg->type);
+         LOG_I(RRC,"[DirectCommunicationEstablishResponse]  slrb_id: %d\n",ptr_ctrl_msg->sidelinkPrimitive.slrb_id);
+#endif
+         break;
+
+      case PC5S_ESTABLISH_REQ:
+         type =  sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.type;
+         sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.sourceL2Id;
+#ifdef DEBUG_CTRL_SOCKET
+         LOG_I(RRC,"[PC5EstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
+         LOG_I(RRC,"[PC5EstablishReq] type: %d\n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.type); //RX/TX
+         LOG_I(RRC,"[PC5EstablishReq] source Id: 0x%08x \n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.sourceL2Id);
+#endif
+         if (type > 0) {
+            destinationL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.destinationL2Id;
+#ifdef DEBUG_CTRL_SOCKET
+            LOG_I(RRC,"[PC5EstablishReq] destination Id: 0x%08x \n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.destinationL2Id);
+#endif
+         }
+
+         //store sourceL2Id/destinationL2Id
+         if (type > 0) { //TX
+            UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
+            j = 0;
+            i = 0;
+            for (i=0; i< MAX_NUM_DEST; i++) {
+               if ((UE_rrc_inst[module_id].destinationList[i] == 0) && (j == 0)) j = i+1;
+               if (UE_rrc_inst[module_id].destinationList[i] == destinationL2Id) break; //group already exists!
+            }
+            if ((i == MAX_NUM_DEST) && (j > 0))  UE_mac_inst[module_id].destinationList[j-1] = destinationL2Id;
+         } else {//RX
+            UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
+         }
+
+         // configure lower layers PDCP/MAC/PHY for this communication
+         //Establish a new RBID/LCID for this communication
+         // Establish a SLRB (using DRB 10 for now)
+         UE  = &UE_rrc_inst[module_id];
+         PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0);
+
+         UE->DRB_config[0][0] = CALLOC(1,sizeof(struct DRB_ToAddMod));
+         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+         UE->DRB_config[0][0]->drb_Identity =  10;
+         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
+         // allowed value 5..15, value : x+4
+         *(UE->DRB_config[0][0]->eps_BearerIdentity) = 10;
+         UE->DRB_config[0][0]->logicalChannelIdentity = CALLOC(1, sizeof(long));
+         *(UE->DRB_config[0][0]->logicalChannelIdentity) = UE->DRB_config[0][0]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2
+
+         DRB_rlc_config                   = CALLOC(1,sizeof(struct RLC_Config));
+         DRB_pdcp_config                  = CALLOC(1,sizeof(struct PDCP_Config));
+         PDCP_rlc_UM                      = CALLOC(1,sizeof(struct PDCP_Config__rlc_UM));
+         DRB_lchan_config                 = CALLOC(1,sizeof(struct LogicalChannelConfig));
+         DRB_ul_SpecificParameters                                         = CALLOC(1, sizeof(struct LogicalChannelConfig__ul_SpecificParameters));
+         logicalchannelgroup_drb          = CALLOC(1, sizeof(long));
+
+         DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional;
+         DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = T_Reordering_ms35;
+         UE->DRB_config[0][0]->rlc_Config = DRB_rlc_config;
+
+         DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config));
+         UE->DRB_config[0][0]->pdcp_Config = DRB_pdcp_config;
+         DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long));
+         *DRB_pdcp_config->discardTimer = PDCP_Config__discardTimer_infinity;
+         DRB_pdcp_config->rlc_AM = NULL;
+         DRB_pdcp_config->rlc_UM = NULL;
+
+         /* avoid gcc warnings */
+         (void)PDCP_rlc_UM;
+
+         DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
+         PDCP_rlc_UM->pdcp_SN_Size = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
+         DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed;
+
+         UE->DRB_config[0][0]->logicalChannelConfig = DRB_lchan_config;
+         DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
+         DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;
+
+         DRB_ul_SpecificParameters->priority = 12;    // lower priority than srb1, srb2 and other dedicated bearer
+         DRB_ul_SpecificParameters->prioritisedBitRate =LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
+         //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
+         DRB_ul_SpecificParameters->bucketSizeDuration =
+               LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;
+
+         // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM)
+
+         *logicalchannelgroup_drb = 1;
+         DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb;
+
+         UE->DRB_configList = CALLOC(1,sizeof(DRB_ToAddModList_t));
+         ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][0]);
+
+         rrc_pdcp_config_asn1_req(&ctxt,
+               (SRB_ToAddModList_t *) NULL,
+               UE->DRB_configList,
+               (DRB_ToReleaseList_t*) NULL,
+               0xff, NULL, NULL, NULL
+#if defined(Rel10) || defined(Rel14)
+               , (PMCH_InfoList_r9_t *) NULL
+#endif
+               ,NULL);
+
+
+         rrc_rlc_config_asn1_req(&ctxt,
+               (SRB_ToAddModList_t*)NULL,
+               UE->DRB_configList,
+               (DRB_ToReleaseList_t*)NULL
+#if defined(Rel10) || defined(Rel14)
+               ,(PMCH_InfoList_r9_t *)NULL
+               , 0, 0
+#endif
+         );
+
+         //TX
+         if (type > 0) {
+            rrc_rlc_config_asn1_req(&ctxt,
+                  (SRB_ToAddModList_t*)NULL,
+                  UE->DRB_configList,
+                  (DRB_ToReleaseList_t*)NULL
+#ifdef Rel14
+                  ,(PMCH_InfoList_r9_t *)NULL
+                  , sourceL2Id, destinationL2Id
+#endif
+            );
+
+            //configure MAC with sourceL2Id/groupL2ID
+            rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
+                  (RadioResourceConfigCommonSIB_t *)NULL,
+                  (struct PhysicalConfigDedicated *)NULL,
+#if defined(Rel10) || defined(Rel14)
+                  (SCellToAddMod_r10_t *)NULL,
+                  //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
+#endif
+                  (MeasObjectToAddMod_t **)NULL,
+                  (MAC_MainConfig_t *)NULL,
+                  10, //LCID
+                  (struct LogicalChannelConfig *)NULL,
+                  (MeasGapConfig_t *)NULL,
+                  (TDD_Config_t *)NULL,
+                  (MobilityControlInfo_t *)NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL
+#if defined(Rel10) || defined(Rel14)
+                  ,0,
+                  (MBSFN_AreaInfoList_r9_t *)NULL,
+                  (PMCH_InfoList_r9_t *)NULL
+
+#endif
+#ifdef CBA
+                  ,
+                  0,
+                  0
+#endif
+#if defined(Rel10) || defined(Rel14)
+                  ,CONFIG_ACTION_ADD,
+                  &sourceL2Id,
+                  &destinationL2Id
+#endif
+            );
+         } else {//RX
+            //configure MAC with sourceL2Id/groupL2ID
+            rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
+                  (RadioResourceConfigCommonSIB_t *)NULL,
+                  (struct PhysicalConfigDedicated *)NULL,
+#if defined(Rel10) || defined(Rel14)
+                  (SCellToAddMod_r10_t *)NULL,
+                  //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
+#endif
+                  (MeasObjectToAddMod_t **)NULL,
+                  (MAC_MainConfig_t *)NULL,
+                  10, //LCID
+                  (struct LogicalChannelConfig *)NULL,
+                  (MeasGapConfig_t *)NULL,
+                  (TDD_Config_t *)NULL,
+                  (MobilityControlInfo_t *)NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL
+#if defined(Rel10) || defined(Rel14)
+                  ,0,
+                  (MBSFN_AreaInfoList_r9_t *)NULL,
+                  (PMCH_InfoList_r9_t *)NULL
+
+#endif
+#ifdef CBA
+                  ,
+                  0,
+                  0
+#endif
+#if defined(Rel10) || defined(Rel14)
+                  ,CONFIG_ACTION_ADD,
+                  &sourceL2Id,
+                  NULL
+#endif
+            );
+
+         }
+
+         LOG_I(RRC,"Send PC5EstablishRsp to ProSe App\n");
+         memset(send_buf, 0, BUFSIZE);
+         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
+         sl_ctrl_msg_send->type = PC5S_ESTABLISH_RSP;
+         sl_ctrl_msg_send->sidelinkPrimitive.pc5s_establish_rsp.slrbid_lcid28 = 10;
+         sl_ctrl_msg_send->sidelinkPrimitive.pc5s_establish_rsp.slrbid_lcid29 = 10;
+         sl_ctrl_msg_send->sidelinkPrimitive.pc5s_establish_rsp.slrbid_lcid30 = 10;
+         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
+
+         prose_addr_len = sizeof(prose_app_addr);
+         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
+//         free(sl_ctrl_msg_send);
+         if (n < 0){
+            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
+            exit(EXIT_FAILURE);
+         }
+         break;
+
+
+      case PC5_DISCOVERY_MESSAGE:
+
+ #ifdef DEBUG_CTRL_SOCKET
+           LOG_I(RRC,"[PC5DiscoveryMessage] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
+ #endif
+        //prepare SL_Discovery buffer
+         if (UE_rrc_inst) {
+           memcpy((void*)&UE_rrc_inst[module_id].SL_Discovery[0].Tx_buffer.Payload[0], (void*)&sl_ctrl_msg_recv->sidelinkPrimitive.pc5_discovery_message.payload[0], PC5_DISCOVERY_PAYLOAD_SIZE);
+           UE_rrc_inst[module_id].SL_Discovery[0].Tx_buffer.payload_size = PC5_DISCOVERY_PAYLOAD_SIZE;
+           LOG_I(RRC,"[PC5DiscoveryMessage] Copied %d bytes\n",PC5_DISCOVERY_PAYLOAD_SIZE);
+         }
+         break;
+      default:
+         break;
+      }
+   }
+   free (sl_ctrl_msg_recv);
+   return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+int decode_SL_Discovery_Message(
+  const protocol_ctxt_t* const ctxt_pP,
+  const uint8_t                eNB_index,
+  uint8_t*               const Sdu,
+  const uint8_t                Sdu_len)
+{
+
+   int prose_addr_len;
+   char send_buf[BUFSIZE];
+   int n;
+   struct sidelink_ctrl_element *sl_ctrl_msg_send = NULL;
+
+   //from the main program, listen for the incoming messages from control socket (ProSe App)
+   prose_addr_len = sizeof(prose_app_addr);
+
+   //Store in Rx_buffer
+   memcpy((void*)&UE_rrc_inst[ctxt_pP->module_id].SL_Discovery[0].Rx_buffer.Payload[0], (void*)Sdu, Sdu_len);
+   UE_rrc_inst[ctxt_pP->module_id].SL_Discovery[0].Rx_buffer.payload_size = Sdu_len;
+
+   memset(send_buf, 0, BUFSIZE);
+   //send to ProSeApp
+   memcpy((void *)send_buf, (void*)Sdu, Sdu_len);
+   prose_addr_len = sizeof(prose_app_addr);
+
+   sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
+   sl_ctrl_msg_send->type = PC5_DISCOVERY_MESSAGE;
+   // TODO:  Add a check for the SDU size.
+   memcpy((void*)&sl_ctrl_msg_send->sidelinkPrimitive.pc5_discovery_message.payload[0], (void*) Sdu,  PC5_DISCOVERY_PAYLOAD_SIZE);
+
+   memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
+   free(sl_ctrl_msg_send);
+
+   prose_addr_len = sizeof(prose_app_addr);
+
+   n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
+   if (n < 0){
+      // TODO:  We should not just exit if the Prose App has not yet attached.  It creates a race condition.
+      LOG_I(RRC, "ERROR: Failed to send to ProSe App\n");
+      //exit(EXIT_FAILURE);
+   }
+
+
+
+  return(0);
+}
+
+#endif
+
 //-----------------------------------------------------------------------------
 RRC_status_t
 rrc_rx_tx_ue(
@@ -4945,3 +6487,4 @@ rrc_rx_tx_ue(
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
   return (RRC_OK);
 }
+
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index 9faa686ef6532afafa413a9c5f4ae633940dcff7..f54b20dc4d9ca377c7b026523e2f52ec187bab2c 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -56,6 +56,9 @@
 #include "rrc_eNB_UE_context.h"
 #include "platform_types.h"
 #include "msc.h"
+#include "SL-CommConfig-r12.h"
+#include "PeriodicBSR-Timer-r12.h"
+#include "RetxBSR-Timer-r12.h"
 #include "UTIL/LOG/vcd_signal_dumper.h"
 
 #include "T.h"
@@ -239,7 +242,7 @@ init_SI(
 	PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
 	RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib2->radioResourceConfigCommon.pusch_ConfigCommon.
 	ul_ReferenceSignalsPUSCH.cyclicShift);
-  
+
 #if defined(Rel10) || defined(Rel14)
 
   if (RC.rrc[ctxt_pP->module_id]->carrier[CC_id].MBMS_flag > 0) {
@@ -260,7 +263,7 @@ init_SI(
 	    PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
 	    RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib2->mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset);
     }
-    
+
     //   SIB13
     for (i = 0; i < RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib13->mbsfn_AreaInfoList_r9.list.count; i++) {
       LOG_D(RRC, PROTOCOL_RRC_CTXT_FMT" SIB13 contents for MBSFN sync area %d/%d (partial)\n",
@@ -276,6 +279,76 @@ init_SI(
     }
   }
   else memset((void*)&RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib13,0,sizeof(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib13));
+
+  //TTN - SIB 18
+  for (int j = 0; j < RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.count; j++) {
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" Contents of SIB18 %d/%d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           j+1,
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.count);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB18 rxPool_sc_CP_Len: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.array[j]->sc_CP_Len_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB18 sc_Period_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.array[j]->sc_Period_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB18 data_CP_Len_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.array[j]->data_CP_Len_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB18 prb_Num_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.array[j]->sc_TF_ResourceConfig_r12.prb_Num_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB18 prb_Start_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.array[j]->sc_TF_ResourceConfig_r12.prb_Start_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB18 prb_End_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.array[j]->sc_TF_ResourceConfig_r12.prb_End_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB18 offsetIndicator: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.array[j]->sc_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB18 subframeBitmap_choice_bs_buf: %s \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib18->commConfig_r12->commRxPool_r12.list.array[j]->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.buf);
+
+  }
+
+  //TTN - SIB 19
+  for (int j = 0; j < RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.count; j++) {
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" Contents of SIB19 %d/%d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           j+1,
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.count);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB19 cp_Len_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.array[j]->cp_Len_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB19 discPeriod_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.array[j]->discPeriod_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB19 numRetx_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.array[j]->numRetx_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB19 numRepetition_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.array[j]->numRepetition_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB19 tf_ResourceConfig_r12 prb_Num_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.array[j]->tf_ResourceConfig_r12.prb_Num_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB19 tf_ResourceConfig_r12 prb_Start_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.array[j]->tf_ResourceConfig_r12.prb_Start_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB19 tf_ResourceConfig_r12 prb_End_r12: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.array[j]->tf_ResourceConfig_r12.prb_End_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB19 tf_ResourceConfig_r12 offsetIndicator: %d \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.array[j]->tf_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12);
+     LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" SIB19 tf_ResourceConfig_r12 subframeBitmap_choice_bs_buf: %s \n",
+           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
+           RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib19->discConfig_r12->discRxPool_r12.list.array[j]->tf_ResourceConfig_r12.subframeBitmap_r12.choice.bs16_r12.buf);
+
+  }
+
 #endif
 
   LOG_D(RRC,
@@ -479,7 +552,12 @@ static void init_MBMS(
                             NULL, // SRB_ToAddModList
                             NULL,   // DRB_ToAddModList
                             NULL,   // DRB_ToReleaseList
-                            &(RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message->pmch_InfoList_r9));
+                            &(RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message->pmch_InfoList_r9)
+
+#ifdef Rel14
+                            ,0, 0
+#endif
+                            );
 
     //rrc_mac_config_req();
   }
@@ -640,6 +718,7 @@ void rrc_eNB_emulation_notify_ue_module_id(
   const uint8_t     cell_identity_byte2P,
   const uint8_t     cell_identity_byte3P)
 {
+	LOG_I(RRC, "Panos-D: rrc_eNB_emulation_notify_ue_module_id 1 \n");
   module_id_t                         enb_module_id;
   struct rrc_eNB_ue_context_s*        ue_context_p = NULL;
   int                                 CC_id;
@@ -1747,7 +1826,9 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete(
                                          (struct MeasConfig__speedStatePars*)Sparams, // Sparams,
                                          (RSRP_Range_t*)rsrp, // rsrp,
                                          (C_RNTI_t*)cba_RNTI,  // cba_RNTI
-                                         (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList //dedicatedInfoNASList
+                                         (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList, //dedicatedInfoNASList
+                                         (SL_CommConfig_r12_t*)NULL,
+                                         (SL_DiscConfig_r12_t*)NULL
 #if defined(Rel10) || defined(Rel14)
                                          , (SCellToAddMod_r10_t*)NULL
 #endif
@@ -2182,7 +2263,9 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
                                          (struct SPS_Config*)NULL,    // *sps_Config,
 					  NULL, NULL, NULL, NULL,NULL,
 					  NULL, NULL,  NULL, NULL, NULL, NULL, 
-					  (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList
+					  (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList,
+					  (SL_CommConfig_r12_t*)NULL,
+					  (SL_DiscConfig_r12_t*)NULL
 #if defined(Rel10) || defined(Rel14)
                                          , (SCellToAddMod_r10_t*)NULL
 #endif
@@ -2441,20 +2524,22 @@ rrc_eNB_modify_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* cons
 
   memset(buffer, 0, RRC_BUF_SIZE);
 
-  size = do_RRCConnectionReconfiguration(ctxt_pP,
-                                          buffer,
-                                          xid,
-                                          (SRB_ToAddModList_t*)NULL,
-                                          (DRB_ToAddModList_t*)DRB_configList2,
-                                          (DRB_ToReleaseList_t*)NULL,  // DRB2_list,
-                                          (struct SPS_Config*)NULL,    // *sps_Config,
-                                          NULL, NULL, NULL, NULL,NULL,
-                                          NULL, NULL,  NULL, NULL, NULL, NULL,
-                                          (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList
+   size = do_RRCConnectionReconfiguration(ctxt_pP,
+					  buffer,
+					  xid,
+					  (SRB_ToAddModList_t*)NULL, 
+					  (DRB_ToAddModList_t*)DRB_configList2,
+					  (DRB_ToReleaseList_t*)NULL,  // DRB2_list,
+                                         (struct SPS_Config*)NULL,    // *sps_Config,
+					  NULL, NULL, NULL, NULL,NULL,
+					  NULL, NULL,  NULL, NULL, NULL, NULL, 
+					  (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList,
+					  (SL_CommConfig_r12_t*)NULL,
+					  (SL_DiscConfig_r12_t*)NULL
 #if defined(Rel10) || defined(Rel14)
-                                          , (SCellToAddMod_r10_t*)NULL
+					  , (SCellToAddMod_r10_t*)NULL
 #endif
-                                          );
+   	   	   	   	   	  );
 
 
 #ifdef RRC_MSG_PRINT
@@ -2573,7 +2658,9 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_release(  const protocol_
                                     NULL,
                                     NULL,
                                     NULL,
-                                    (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList
+                                    (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList,
+                                    (SL_CommConfig_r12_t*)NULL,
+                                    (SL_DiscConfig_r12_t*)NULL
 #if defined(Rel10) || defined(Rel14)
                                     , (SCellToAddMod_r10_t*)NULL
 #endif
@@ -3301,7 +3388,9 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
                                          (struct MeasConfig__speedStatePars*)Sparams,
                                          (RSRP_Range_t*)rsrp,
                                          (C_RNTI_t*)cba_RNTI,
-                                         (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList
+                                         (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList,
+                                         (SL_CommConfig_r12_t*)NULL,
+                                         (SL_DiscConfig_r12_t*)NULL
 #if defined(Rel10) || defined(Rel14)
                                          , (SCellToAddMod_r10_t*)NULL
 #endif
@@ -3891,7 +3980,9 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt
                                          (struct MeasConfig__speedStatePars*)Sparams,
                                          (RSRP_Range_t*)rsrp,
                                          (C_RNTI_t*)cba_RNTI,
-                                         (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList
+                                         (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList,
+                                         (SL_CommConfig_r12_t*)NULL,
+                                         (SL_DiscConfig_r12_t*)NULL
 #if defined(Rel10) || defined(Rel14)
                                          , (SCellToAddMod_r10_t*)NULL
 #endif
@@ -3994,7 +4085,9 @@ rrc_eNB_generate_RRCConnectionReconfiguration_SCell(
                                          (struct MeasConfig__speedStatePars*)NULL,
                                          (RSRP_Range_t*)NULL,
                                          (C_RNTI_t*)NULL,
-                                         (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)NULL
+                                         (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)NULL,
+                                         (SL_CommConfig_r12_t*)NULL,
+                                         (SL_DiscConfig_r12_t*)NULL
 
 #if defined(Rel10) || defined(Rel14)
                                          , ue_context_pP->ue_context.sCell_config
@@ -4285,7 +4378,11 @@ check_handovers(
                                SDU_CONFIRM_NO,
                                ue_context_p->ue_context.handover_info->size,
                                ue_context_p->ue_context.handover_info->buf,
-                               PDCP_TRANSMISSION_MODE_CONTROL);
+                               PDCP_TRANSMISSION_MODE_CONTROL
+#ifdef Rel14
+                               ,NULL, NULL
+#endif
+                               );
         AssertFatal(result == TRUE, "PDCP data request failed!\n");
         ue_context_p->ue_context.handover_info->ho_complete = 0xF2;
       }
@@ -5110,6 +5207,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
                           (DRB_ToAddModList_t *) NULL, (DRB_ToReleaseList_t *) NULL
 #if defined(Rel10) || defined(Rel14)
                           , (PMCH_InfoList_r9_t *) NULL
+                          , 0, 0
 #endif
                          );
 
@@ -5138,7 +5236,9 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
            Sparams,
            NULL,
            NULL,
-           dedicatedInfoNASList
+           dedicatedInfoNASList,
+           (SL_CommConfig_r12_t*)NULL,
+           (SL_DiscConfig_r12_t*)NULL
 #if defined(Rel10) || defined(Rel14)
            , NULL   // SCellToAddMod_r10_t
 #endif
@@ -5336,6 +5436,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
     DRB_Release_configList2
 #if defined(Rel10) || defined(Rel14)
     , (PMCH_InfoList_r9_t *) NULL
+    , 0, 0
 #endif
   );
   
@@ -6122,7 +6223,8 @@ rrc_eNB_decode_ccch(
                               (DRB_ToAddModList_t*) NULL,
                               (DRB_ToReleaseList_t*) NULL
 #   if defined(Rel10) || defined(Rel14)
-                              , (PMCH_InfoList_r9_t *) NULL
+                              , (PMCH_InfoList_r9_t *) NULL,
+                              0,0
 #   endif
                              );
 #endif //NO_RRM
@@ -6362,6 +6464,7 @@ rrc_eNB_decode_ccch(
                               (DRB_ToReleaseList_t*) NULL
 #   if defined(Rel10) || defined(Rel14)
                               , (PMCH_InfoList_r9_t *) NULL
+                              , 0, 0
 #   endif
                              );
 #endif //NO_RRM
@@ -7027,6 +7130,53 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
     }
 
     return 0;
+    //TTN for D2D
+  } else if (ul_dcch_msg->message.present == UL_DCCH_MessageType_PR_messageClassExtension){
+     LOG_I(RRC, "THINH [UL_DCCH_MessageType_PR_messageClassExtension]\n");
+
+     switch (ul_dcch_msg->message.choice.messageClassExtension.present) {
+     case UL_DCCH_MessageType__messageClassExtension_PR_NOTHING: /* No components present */
+        break;
+     case UL_DCCH_MessageType__messageClassExtension_PR_c2: //SidelinkUEInformation
+     //case UL_DCCH_MessageType__messageClassExtension__c2_PR_sidelinkUEInformation_r12: //SidelinkUEInformation
+        LOG_I(RRC,"THINH [UL_DCCH_MessageType__messageClassExtension_PR_c2]\n");
+
+#ifdef RRC_MSG_PRINT
+        LOG_F(RRC,"[MSG] SidelinkUEInformation\n");
+
+        for (i = 0; i < sdu_sizeP; i++) {
+           LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]);
+        }
+
+        LOG_F(RRC,"\n");
+#endif
+
+        MSC_LOG_RX_MESSAGE(
+              MSC_RRC_ENB,
+              MSC_RRC_UE,
+              Rx_sdu,
+              sdu_sizeP,
+              MSC_AS_TIME_FMT" SidelinkUEInformation UE %x size %u",
+              MSC_AS_TIME_ARGS(ctxt_pP),
+              ue_context_p->ue_context.rnti,
+              sdu_sizeP);
+
+        LOG_I(RRC,
+              PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
+              "(SidelinkUEInformation) ---> RRC_eNB\n",
+              PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
+              DCCH,
+              sdu_sizeP);
+
+        rrc_eNB_process_SidelinkUEInformation(
+              ctxt_pP,
+              ue_context_p,
+              &ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.sidelinkUEInformation_r12);
+        break;
+     default:
+        break;
+     }
+     //end TTN
   } else {
     LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Unknown error %s:%u\n",
           PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
@@ -7287,6 +7437,283 @@ rrc_top_cleanup_eNB(
 
 
 //-----------------------------------------------------------------------------
+//TTN - for D2D
+uint8_t
+rrc_eNB_process_SidelinkUEInformation(
+      const protocol_ctxt_t* const ctxt_pP,
+      rrc_eNB_ue_context_t*         ue_context_pP,
+      SidelinkUEInformation_r12_t * sidelinkUEInformation
+)
+//-----------------------------------------------------------------------------
+{
+   SL_DestinationInfoList_r12_t  *destinationInfoList;
+   int n_destinations = 0;
+   int ue_type = 0;
+   int n_discoveryMessages = 0;
+
+   LOG_I(RRC,
+         PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, " "processing SidelinkUEInformation from UE (SRB1 Active)\n",
+         PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
+
+   //For SL Communication
+   if (sidelinkUEInformation->criticalExtensions.present ==  SidelinkUEInformation_r12__criticalExtensions_PR_c1){
+      if (sidelinkUEInformation->criticalExtensions.choice.c1.present == SidelinkUEInformation_r12__criticalExtensions__c1_PR_sidelinkUEInformation_r12){
+         // express its interest to receive SL communication
+         if (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commRxInterestedFreq_r12 !=  NULL){
+
+         }
+
+         // express its interest to transmit  non-relay one-to-many SL communication
+         if ((sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12 != NULL) && (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12->carrierFreq_r12 != NULL)){
+            n_destinations = sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12->destinationInfoList_r12.list.count;
+            destinationInfoList = CALLOC(1, sizeof(SL_DestinationInfoList_r12_t));
+            for (int i=0; i< n_destinations; i++ ){
+               //sl_DestinationIdentityList[i] = *(sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12->destinationInfoList_r12.list.array[i]);
+               ASN_SEQUENCE_ADD(&destinationInfoList->list, sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.commTxResourceReq_r12->destinationInfoList_r12.list.array[i]);
+            }
+            //generate RRC Reconfiguration
+            rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(ctxt_pP, ue_context_pP, destinationInfoList, 0);
+            return 0;
+
+         }
+
+         // express its interest to transmit  non-relay one-to-one SL communication
+         if ((sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension != NULL) && (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13 != NULL)) {
+            if (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13->carrierFreq_r12 != NULL){
+               n_destinations = sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13->destinationInfoList_r12.list.count;
+               destinationInfoList = CALLOC(1, sizeof(SL_DestinationInfoList_r12_t));
+               for (int i=0; i< n_destinations; i++ ){
+                  //sl_DestinationIdentityList[i] = *(sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13->destinationInfoList_r12.list.array[i]);
+                  ASN_SEQUENCE_ADD(&destinationInfoList->list,sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceReqUC_r13->destinationInfoList_r12.list.array[i]);
+               }
+               //generate RRC Reconfiguration
+               rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(ctxt_pP, ue_context_pP, destinationInfoList, 0);
+               return 0;
+            }
+         }
+
+         // express its interest to transmit relay related one-to-one SL communication
+         if ((sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension != NULL) &&(sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelayUC_r13 != NULL)) {
+            if (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelayUC_r13->destinationInfoList_r12.list.count > 0) {
+               n_destinations = sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelayUC_r13->destinationInfoList_r12.list.count;
+               ue_type = sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->ue_Type_r13;
+               destinationInfoList = CALLOC(1, sizeof(SL_DestinationInfoList_r12_t));
+               for (int i=0; i< n_destinations; i++ ){
+                  //sl_DestinationIdentityList[i] = *(sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelayUC_r13->destinationInfoList_r12.list.array[i]);
+                  ASN_SEQUENCE_ADD(&destinationInfoList->list, sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelayUC_r13->destinationInfoList_r12.list.array[i]);
+               }
+               //generate RRC Reconfiguration
+               rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(ctxt_pP, ue_context_pP, destinationInfoList, 0);
+               return 0;
+            }
+         }
+
+         //express its interest to transmit relay related one-to-many SL communication
+         if ((sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension != NULL) && (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13 != NULL)) {
+            if (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelay_r13->destinationInfoList_r12.list.count > 0){
+               n_destinations = sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelay_r13->destinationInfoList_r12.list.count;
+               ue_type = sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->ue_Type_r13;
+               destinationInfoList = CALLOC(1, sizeof(SL_DestinationInfoList_r12_t));
+               for (int i=0; i< n_destinations; i++ ){
+                  //sl_DestinationIdentityList[i] = *(sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelay_r13->destinationInfoList_r12.list.array[i]);
+                  ASN_SEQUENCE_ADD(&destinationInfoList->list,sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->commTxResourceInfoReqRelay_r13->commTxResourceReqRelay_r13->destinationInfoList_r12.list.array[i]);
+               }
+               //generate RRC Reconfiguration
+               rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(ctxt_pP, ue_context_pP, destinationInfoList, 0);
+               return 0;
+            }
+         }
+
+         //For SL Discovery
+         //express its interest to receive SL discovery announcements
+         //express its interest to transmit non-PS related discovery announcements
+         if (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.discTxResourceReq_r12 != NULL){
+            n_discoveryMessages = *(sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.discTxResourceReq_r12);
+            //generate RRC Reconfiguration
+            rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(ctxt_pP, ue_context_pP, NULL, n_discoveryMessages);
+            return 0;
+         }
+         //express its interest to transmit PS related discovery announcements
+         if ((sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension != NULL) && (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->discTxResourceReqPS_r13 !=NULL)) {
+            if (sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->discTxResourceReqPS_r13->discTxResourceReq_r13 > 0){
+               n_discoveryMessages = sidelinkUEInformation->criticalExtensions.choice.c1.choice.sidelinkUEInformation_r12.nonCriticalExtension->discTxResourceReqPS_r13->discTxResourceReq_r13;
+               //generate RRC Reconfiguration
+               rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(ctxt_pP, ue_context_pP, NULL, n_discoveryMessages);
+               return 0;
+            }
+         }
+      }
+   }
+   return 0;
+}
+
+//-----------------------------------------------------------------------------
+int
+rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(
+  const protocol_ctxt_t* const ctxt_pP,
+  rrc_eNB_ue_context_t* const ue_context_pP,
+  SL_DestinationInfoList_r12_t  *destinationInfoList,
+  int n_discoveryMessages
+)
+//-----------------------------------------------------------------------------
+{
+
+  uint8_t                             buffer[RRC_BUF_SIZE];
+  uint16_t                            size;
+  memset(buffer, 0, RRC_BUF_SIZE);
+
+  // allocate dedicated pools for UE -sl-CommConfig/sl-DiscConfig (sl-V2X-ConfigDedicated)
+  //populate dedicated resources for SL communication (sl-CommConfig)
+  if ((destinationInfoList != NULL) && (destinationInfoList->list.count > 0)) {
+
+     LOG_I(RRC,"[eNB %d] Frame %d, Generate RRCConnectionReconfiguration_Sidelink (bytes %d, UE id %x), number of destinations %d\n",
+            ctxt_pP->module_id,ctxt_pP->frame, size, ue_context_pP->ue_context.rnti,destinationInfoList->list.count );
+     //get dedicated resources from available pool and assign to the UE
+     SL_CommConfig_r12_t  sl_CommConfig[destinationInfoList->list.count];
+     //get a RP from the available RPs
+     sl_CommConfig[0] = rrc_eNB_get_sidelink_commTXPool(ctxt_pP, ue_context_pP, destinationInfoList);
+
+     size = do_RRCConnectionReconfiguration(ctxt_pP,
+                   buffer,
+                   rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id),   //Transaction_id
+                   (SRB_ToAddModList_t*)NULL,
+                   (DRB_ToAddModList_t*)NULL,
+                   (DRB_ToReleaseList_t*)NULL,  // DRB2_list,
+                   (struct SPS_Config*)NULL,    // *sps_Config,
+                   NULL, NULL, NULL, NULL,NULL,
+                   NULL, NULL,  NULL, NULL, NULL, NULL,
+                   (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)NULL,
+                   (SL_CommConfig_r12_t*)&sl_CommConfig,
+                   (SL_DiscConfig_r12_t*)NULL
+  #if defined(Rel10) || defined(Rel14)
+                                           , (SCellToAddMod_r10_t*)NULL
+  #endif
+                                           );
+     //
+  }
+  //populate dedicated resources for SL discovery (sl-DiscConfig)
+  if (n_discoveryMessages > 0) {
+     SL_DiscConfig_r12_t sl_DiscConfig[n_discoveryMessages];
+     //get a RP from the available RPs
+     sl_DiscConfig[0] = rrc_eNB_get_sidelink_discTXPool(ctxt_pP, ue_context_pP, n_discoveryMessages );
+     size = do_RRCConnectionReconfiguration(ctxt_pP,
+                   buffer,
+                   rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id),   //Transaction_id
+                   (SRB_ToAddModList_t*)NULL,
+                   (DRB_ToAddModList_t*)NULL,
+                   (DRB_ToReleaseList_t*)NULL,  // DRB2_list,
+                   (struct SPS_Config*)NULL,    // *sps_Config,
+                   NULL, NULL, NULL, NULL,NULL,
+                   NULL, NULL,  NULL, NULL, NULL, NULL,
+                   (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)NULL,
+                   (SL_CommConfig_r12_t*)NULL,
+                   (SL_DiscConfig_r12_t*)&sl_DiscConfig
+  #if defined(Rel10) || defined(Rel14)
+                                           , (SCellToAddMod_r10_t*)NULL
+  #endif
+                                           );
+  }
+
+  LOG_I(RRC,"[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCConnectionReconfiguration_Sidelink (bytes %d, UE id %x)\n",
+        ctxt_pP->module_id,ctxt_pP->frame, size, ue_context_pP->ue_context.rnti);
+
+  rrc_data_req(
+    ctxt_pP,
+    DCCH,
+    rrc_eNB_mui++,
+    SDU_CONFIRM_NO,
+    size,
+    buffer,
+    PDCP_TRANSMISSION_MODE_CONTROL);
+
+  // rrc_data_req();
+
+  return size;
+}
+
+SL_CommConfig_r12_t rrc_eNB_get_sidelink_commTXPool( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP,  SL_DestinationInfoList_r12_t  *destinationInfoList ){
+   // for the moment, use scheduled resource allocation
+   SL_CommConfig_r12_t  *sl_CommConfig;
+   SL_CommResourcePool_r12_t    *sc_CommTxConfig;
+
+   sl_CommConfig = CALLOC(1, sizeof(struct SL_CommConfig_r12));
+   sl_CommConfig->commTxResources_r12 = CALLOC(1, sizeof(*sl_CommConfig->commTxResources_r12));
+   sl_CommConfig->commTxResources_r12->present = SL_CommConfig_r12__commTxResources_r12_PR_setup;
+
+   sl_CommConfig->commTxResources_r12->choice.setup.present = SL_CommConfig_r12__commTxResources_r12__setup_PR_scheduled_r12;
+   sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sl_RNTI_r12.size = 2;
+   sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sl_RNTI_r12.buf = CALLOC(1,2);
+   sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sl_RNTI_r12.buf[0] = 0x00;
+   sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sl_RNTI_r12.buf[1] = 0x01;//ctxt_pP->rnti;//rnti
+   sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sl_RNTI_r12.bits_unused = 0;
+   sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.mcs_r12 = CALLOC(1,sizeof(*sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.mcs_r12));
+   //*sl_CommConfig_test->commTxResources_r12->choice.setup.choice.scheduled_r12.mcs_r12 = 12; //Msc
+   sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.mac_MainConfig_r12.retx_BSR_TimerSL = RetxBSR_Timer_r12_sf320; //MacConfig, for testing only
+   //sl_CommConfig_test->commTxResources_r12->choice.setup.choice.scheduled_r12.sc_CommTxConfig_r12;
+
+   sc_CommTxConfig = & sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sc_CommTxConfig_r12;
+
+   sc_CommTxConfig->sc_CP_Len_r12 = SL_CP_Len_r12_normal;
+   sc_CommTxConfig->sc_Period_r12 = SL_PeriodComm_r12_sf40;
+   sc_CommTxConfig->data_CP_Len_r12  = SL_CP_Len_r12_normal;
+   //sc_TF_ResourceConfig_r12
+   sc_CommTxConfig->sc_TF_ResourceConfig_r12.prb_Num_r12 = 20;
+   sc_CommTxConfig->sc_TF_ResourceConfig_r12.prb_Start_r12 = 5;
+   sc_CommTxConfig->sc_TF_ResourceConfig_r12.prb_End_r12 = 44;
+   sc_CommTxConfig->sc_TF_ResourceConfig_r12.offsetIndicator_r12.present = SL_OffsetIndicator_r12_PR_small_r12;
+   sc_CommTxConfig->sc_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12 = 0;
+
+   sc_CommTxConfig->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present = SubframeBitmapSL_r12_PR_bs40_r12;
+   sc_CommTxConfig->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.size = 5;
+   sc_CommTxConfig->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf  = CALLOC(1,5);
+   sc_CommTxConfig->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.bits_unused = 0;
+   //dataHoppingConfig_r12
+   sc_CommTxConfig->dataHoppingConfig_r12.hoppingParameter_r12 = 0;
+   sc_CommTxConfig->dataHoppingConfig_r12.numSubbands_r12  =  SL_HoppingConfigComm_r12__numSubbands_r12_ns1;
+   sc_CommTxConfig->dataHoppingConfig_r12.rb_Offset_r12 = 0;
+   //ue_SelectedResourceConfig_r12
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12 = CALLOC (1, sizeof (*sc_CommTxConfig->ue_SelectedResourceConfig_r12));
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.prb_Num_r12 = 20;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.prb_Start_r12 = 5;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.prb_End_r12 = 44;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.offsetIndicator_r12.present = SL_OffsetIndicator_r12_PR_small_r12;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12 = 0 ;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.present = SubframeBitmapSL_r12_PR_bs40_r12;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.size = 5;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf  = CALLOC(1,5);
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.bits_unused = 0;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[0] = 0xF0;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[1] = 0xFF;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[2] = 0xFF;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[3] = 0xFF;
+   sc_CommTxConfig->ue_SelectedResourceConfig_r12->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs4_r12.buf[4] = 0xFF;
+   //rxParametersNCell_r12
+   sc_CommTxConfig->rxParametersNCell_r12 = CALLOC (1, sizeof (*sc_CommTxConfig->rxParametersNCell_r12));
+   sc_CommTxConfig->rxParametersNCell_r12->tdd_Config_r12 = CALLOC (1, sizeof (*sc_CommTxConfig->rxParametersNCell_r12->tdd_Config_r12 ));
+   sc_CommTxConfig->rxParametersNCell_r12->tdd_Config_r12->subframeAssignment = 0 ;
+   sc_CommTxConfig->rxParametersNCell_r12->tdd_Config_r12->specialSubframePatterns = 0;
+   sc_CommTxConfig->rxParametersNCell_r12->syncConfigIndex_r12 = 0;
+   //txParameters_r12
+   sc_CommTxConfig->txParameters_r12 = CALLOC (1, sizeof (*sc_CommTxConfig->txParameters_r12));
+   sc_CommTxConfig->txParameters_r12->sc_TxParameters_r12.alpha_r12 = Alpha_r12_al0;
+   sc_CommTxConfig->txParameters_r12->sc_TxParameters_r12.p0_r12 = 0;
+   sc_CommTxConfig->ext1 = NULL ;
+
+   return *sl_CommConfig;
+}
+
+
+SL_DiscConfig_r12_t rrc_eNB_get_sidelink_discTXPool( const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP,  int n_discoveryMessages ){
+   //TODO
+   SL_DiscConfig_r12_t  sl_DiscConfig;
+   sl_DiscConfig.discTxResources_r12 = CALLOC(1,sizeof(*sl_DiscConfig.discTxResources_r12));
+   sl_DiscConfig.discTxResources_r12->present = SL_DiscConfig_r12__discTxResources_r12_PR_setup;
+   sl_DiscConfig.discTxResources_r12->choice.setup.present = SL_DiscConfig_r12__discTxResources_r12__setup_PR_scheduled_r12;
+   //sl_DiscConfig.discTxResources_r12->choice.setup.choice.scheduled_r12.discHoppingConfig_r12;
+   //sl_DiscConfig.discTxResources_r12->choice.setup.choice.scheduled_r12.discTF_IndexList_r12;
+   //sl_DiscConfig.discTxResources_r12->choice.setup.choice.scheduled_r12.discTxConfig_r12;
+   return sl_DiscConfig;
+}
 RRC_status_t
 rrc_rx_tx(
   protocol_ctxt_t* const ctxt_pP,
@@ -7368,7 +7795,7 @@ rrc_rx_tx(
 	ue_context_p->ue_context.ue_release_timer++;
 	if (ue_context_p->ue_context.ue_release_timer >= 
 	    ue_context_p->ue_context.ue_release_timer_thres) {
-	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
+	  LOG_I(RRC,"Removing UE %x instance, Release timer: %d, Release timer thres.: %d \n",ue_context_p->ue_context.rnti, ue_context_p->ue_context.ue_release_timer, ue_context_p->ue_context.ue_release_timer_thres);
 	  ue_to_be_removed = ue_context_p;
 	  break;
 	}
diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c
index 7ba3d88a878e1e294a8d29ca58e7b6d0127b2c38..784245c0d36cb1ef4e1902af160fb3bf4a9fab2e 100644
--- a/openair3/GTPV1-U/gtpv1u_eNB.c
+++ b/openair3/GTPV1-U/gtpv1u_eNB.c
@@ -62,6 +62,13 @@ extern boolean_t pdcp_data_req(
   const confirm_t      confirmP,
   const sdu_size_t     sdu_buffer_sizeP,
   unsigned char *const sdu_buffer_pP,
+  const pdcp_transmission_mode_t modeP
+#ifdef Rel14
+    ,const uint32_t * const sourceL2Id
+    ,const uint32_t * const destinationL2Id
+#endif
+    );
+
   const pdcp_transmission_mode_t modeP);
 */
 extern unsigned char NB_eNB_INST;
@@ -355,7 +362,11 @@ NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
 			     SDU_CONFIRM_NO, // confirm
 			     buffer_len,
 			     buffer,
-			     PDCP_TRANSMISSION_MODE_DATA);
+			     PDCP_TRANSMISSION_MODE_DATA
+#ifdef Rel14
+              ,NULL, NULL
+#endif
+              );
       
       
       if ( result == FALSE ) {
diff --git a/targets/DOCS/nfapi-L2-emulator-setup.txt b/targets/DOCS/nfapi-L2-emulator-setup.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3e502e2137edcf25450b06bef409b71bbac9882b
--- /dev/null
+++ b/targets/DOCS/nfapi-L2-emulator-setup.txt
@@ -0,0 +1,31 @@
+
+#Build instructions
+source oaienv
+cd cmake_targets
+
+#Create lte-uesoftmodem-nos1 (UE) and lte-softmodem-nos1 (eNB) executables
+./build_oai --UE --noS1 -x -t ETHERNET 
+
+./build_oai --eNB --noS1 -x -t ETHERNET
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------
+
+#Execution instuctions (Currently running eNB (VNF) and UE side (PNF) on the same machine using the loopback interface)
+cd cmake_targets/tools
+
+# Loading nasmesh
+source init_nas_nos1
+
+# Add a new loopback interface address
+sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up
+
+cd ..
+cd lte_noS1_build_oai/build/
+
+# Run the eNB process on one terminal (VNF)
+sudo ./lte-softmodem-nos1 -O PATH_OF:rcc.band7.tm1.50PRB.nfapi.conf
+
+# Run the UE process on the other terminal (PNF) (--L2-emul specifying the operation in nfapi-L2-emulation mode
+# and it has to be equal to 3, --num_ues specifying the number of UEs)
+sudo ./lte-uesoftmodem-nos1 -U -O PATH_OF:oaiL1.nfapi.usrpb210.conf --L2-emul 3 --num-ues 5 > debug_log.txt
+
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf
new file mode 100644
index 0000000000000000000000000000000000000000..087f379c4d7afa36127e4a9bbf506f386eb1689c
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210-d2d.conf
@@ -0,0 +1,245 @@
+Active_eNBs = ( "eNB_Eurecom_LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    ////////// Identification parameters:
+    eNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_ENB";
+
+    eNB_name  =  "eNB_Eurecom_LTEBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  "1";
+
+    mobile_country_code =  "208";
+
+    mobile_network_code =  "93";
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "3GPP_eNODEB";
+      node_timing               = "synch_to_ext_device";
+      node_synch_ref            = 0;
+      frame_type					      = "FDD";
+      tdd_config 					      = 3;
+      tdd_config_s            			      = 0;
+      prefix_type             			      = "NORMAL";
+      eutra_band              			      = 7;
+      downlink_frequency      			      = 2685000000L;
+      uplink_frequency_offset 			      = -120000000;
+      Nid_cell					      = 0;
+      N_RB_DL                 			      = 50;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 1;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 125;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 1;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 32;
+      pdsch_referenceSignalPower 			      = -27;
+      pdsch_p_b                  			      = 0;
+      pusch_n_SB                 			      = 1;
+      pusch_enable64QAM          			      = "DISABLE";
+      pusch_hoppingMode                                  = "interSubFrame";
+      pusch_hoppingOffset                                = 0;
+      pusch_groupHoppingEnabled  			      = "ENABLE";
+      pusch_groupAssignment      			      = 0;
+      pusch_sequenceHoppingEnabled		   	      = "DISABLE";
+      pusch_nDMRS1                                       = 1;
+      phich_duration                                     = "NORMAL";
+      phich_resource                                     = "ONESIXTH";
+      srs_enable                                         = "DISABLE";
+      /*  srs_BandwidthConfig                                =;
+      srs_SubframeConfig                                 =;
+      srs_ackNackST                                      =;
+      srs_MaxUpPts                                       =;*/
+
+      pusch_p0_Nominal                                   = -96;
+      pusch_alpha                                        = "AL1";
+      pucch_p0_Nominal                                   = -104;
+      msg3_delta_Preamble                                = 6;
+      pucch_deltaF_Format1                               = "deltaF2";
+      pucch_deltaF_Format1b                              = "deltaF3";
+      pucch_deltaF_Format2                               = "deltaF0";
+      pucch_deltaF_Format2a                              = "deltaF0";
+      pucch_deltaF_Format2b		    	      = "deltaF0";
+
+      rach_numberOfRA_Preambles                          = 64;
+      rach_preamblesGroupAConfig                         = "DISABLE";
+      /*
+      rach_sizeOfRA_PreamblesGroupA                      = ;
+      rach_messageSizeGroupA                             = ;
+      rach_messagePowerOffsetGroupB                      = ;
+      */
+      rach_powerRampingStep                              = 4;
+      rach_preambleInitialReceivedTargetPower            = -108;
+      rach_preambleTransMax                              = 10;
+      rach_raResponseWindowSize                          = 10;
+      rach_macContentionResolutionTimer                  = 48;
+      rach_maxHARQ_Msg3Tx                                = 4;
+
+      pcch_default_PagingCycle                           = 128;
+      pcch_nB                                            = "oneT";
+      bcch_modificationPeriodCoeff			      = 2;
+      ue_TimersAndConstants_t300			      = 1000;
+      ue_TimersAndConstants_t301			      = 1000;
+      ue_TimersAndConstants_t310			      = 1000;
+      ue_TimersAndConstants_t311			      = 10000;
+      ue_TimersAndConstants_n310			      = 20;
+      ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                                    = 1;
+      
+      //Parameters for SIB18
+      rxPool_sc_CP_Len                                       = "normal"; 
+      rxPool_sc_Period                                       = "sf80";  
+      rxPool_data_CP_Len                                     = "normal";  
+      rxPool_ResourceConfig_prb_Num                          = 3;
+      rxPool_ResourceConfig_prb_Start                        = 4;
+      rxPool_ResourceConfig_prb_End                          = 9;
+      rxPool_ResourceConfig_offsetIndicator_present          = "prSmall";
+      rxPool_ResourceConfig_offsetIndicator_choice           = 3;      
+      rxPool_ResourceConfig_subframeBitmap_present           = "prBs16";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_buf              = "1100110011001100";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_size             = 16;
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused      = 0;
+/*    rxPool_dataHoppingConfig_hoppingParameter                       = 0;
+      rxPool_dataHoppingConfig_numSubbands                            = "ns1";
+      rxPool_dataHoppingConfig_rbOffset                               = 0;
+      rxPool_commTxResourceUC-ReqAllowed                              = "TRUE";
+*/    
+      // Parameters for SIB19
+      discRxPool_cp_Len                                               = "normal"
+      discRxPool_discPeriod                                           = "rf64"
+      discRxPool_numRetx                                              = 1;   
+      discRxPool_numRepetition                                        = 2;
+      discRxPool_ResourceConfig_prb_Num                               = 3;  
+      discRxPool_ResourceConfig_prb_Start                             = 4;
+      discRxPool_ResourceConfig_prb_End                               = 5;
+      discRxPool_ResourceConfig_offsetIndicator_present               = "prSmall";
+      discRxPool_ResourceConfig_offsetIndicator_choice                = 4;      
+      discRxPool_ResourceConfig_subframeBitmap_present                = "prBs16";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf          = "1001100110011001";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_size         = 16;
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused  = 0;
+      
+      }
+    );
+
+
+    srb1_parameters :
+    {
+        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
+        timer_poll_retransmit    = 80;
+
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = 35;
+
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = 0;
+
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  4;
+
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  99999;
+
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+    }
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "127.0.0.3";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "lo";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "127.0.0.2/24";
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "127.0.0.4/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+        
+        
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        }  
+);
+
+RUs = (
+    {		  
+       local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 125;
+         eNB_instances  = [0];
+
+    }
+);  
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
index cfbfa51cab275669015604756f7e00f9436121e1..614a85d54ce536b6cbe05c2e2f302385a945751d 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
@@ -105,6 +105,40 @@ eNBs =
       ue_TimersAndConstants_n310			      = 20;
       ue_TimersAndConstants_n311			      = 1;
       ue_TransmissionMode                                    = 1;
+
+      //Parameters for SIB18
+      rxPool_sc_CP_Len                                       = "normal";
+      rxPool_sc_Period                                       = "sf40";
+      rxPool_data_CP_Len                                     = "normal";
+      rxPool_ResourceConfig_prb_Num                          = 20;
+      rxPool_ResourceConfig_prb_Start                        = 5;
+      rxPool_ResourceConfig_prb_End                          = 44;
+      rxPool_ResourceConfig_offsetIndicator_present          = "prSmall";
+      rxPool_ResourceConfig_offsetIndicator_choice           = 0;
+      rxPool_ResourceConfig_subframeBitmap_present           = "prBs40";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_buf              = "00000000000000000000";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_size             = 5;
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused      = 0;
+/*    rxPool_dataHoppingConfig_hoppingParameter                       = 0;
+      rxPool_dataHoppingConfig_numSubbands                            = "ns1";
+      rxPool_dataHoppingConfig_rbOffset                               = 0;
+      rxPool_commTxResourceUC-ReqAllowed                              = "TRUE";
+*/
+      // Parameters for SIB19
+      discRxPool_cp_Len                                               = "normal"
+      discRxPool_discPeriod                                           = "rf32"
+      discRxPool_numRetx                                              = 1;
+      discRxPool_numRepetition                                        = 2;
+      discRxPool_ResourceConfig_prb_Num                               = 5;
+      discRxPool_ResourceConfig_prb_Start                             = 3;
+      discRxPool_ResourceConfig_prb_End                               = 21;
+      discRxPool_ResourceConfig_offsetIndicator_present               = "prSmall";
+      discRxPool_ResourceConfig_offsetIndicator_choice                = 0;
+      discRxPool_ResourceConfig_subframeBitmap_present                = "prBs40";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf          = "f0ffffffff";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_size         = 5;
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused  = 0;
+
       }
     );
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpb210.conf
index 9393872b308ad72f67f4128a47a64e5460193b02..b13962aee90335a968e72b594dc5b02b20edbaf6 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpb210.conf
@@ -4,28 +4,47 @@ log_config = {
   hw_log_level                          ="info";
   hw_log_verbosity                      ="medium";
   phy_log_level                         ="info";
-  phy_log_verbosity                     ="low";
-  mac_log_level                         ="info";
+  phy_log_verbosity                     ="medium";
+  mac_log_level                         ="debug";
   mac_log_verbosity                     ="medium";
   rlc_log_level                         ="info";
   rlc_log_verbosity                     ="medium";
   pdcp_log_level                        ="info";
   pdcp_log_verbosity                    ="medium";
-  rrc_log_level                         ="info";
-  rrc_log_verbosity                     ="medium";
+  rrc_log_level                         ="debug";
+  rrc_log_verbosity                     ="full";
 };
 
+
+#L1s = (
+#    	{
+#	num_cc = 1;
+#	tr_n_preference = "nfapi";
+#      	local_n_if_name  = "eno1";
+#      	remote_n_address = "192.168.1.28";
+#    	local_n_address  = "192.168.1.74";
+#    	local_n_portc    = 50000;
+#    	remote_n_portc   = 50001;
+#    	local_n_portd    = 50010;
+#    	remote_n_portd   = 50011;
+#        }  
+#);
+
+
 L1s = (
     	{
 	num_cc = 1;
 	tr_n_preference = "nfapi";
-      	local_n_if_name  = "lo";			  
+      	#local_n_if_name  = "enp0s31f6";
+      	#remote_n_address = "10.0.0.2";
+    	#local_n_address  = "10.0.0.1";
+    	local_n_if_name  = "lo";
       	remote_n_address = "127.0.0.2";
-    	local_n_address  = "127.0.0.1"; 
-    	local_n_portc    = 50000;	
-        remote_n_portc   = 50001;
-        local_n_portd    = 50010;
-        remote_n_portd   = 50011;
+    	local_n_address  = "127.0.0.1";
+    	local_n_portc    = 50000;
+    	remote_n_portc   = 50001;
+    	local_n_portd    = 50010;
+    	remote_n_portd   = 50011;
         }  
 );
 
@@ -34,11 +53,10 @@ RUs = (
        local_rf       = "yes"
        nb_tx          = 1
        nb_rx          = 1
-       att_tx         = 0
+       att_tx         = 90
        att_rx         = 0;
        bands          = [7,38,42,43];
        max_pdschReferenceSignalPower = -27;
        max_rxgain                    = 125;
-       eNB_instances  = [0];
     }		      
-);  
+);
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf
new file mode 100644
index 0000000000000000000000000000000000000000..4de676ec9a42b41a83d2eaa1eda524cd60a1cb0d
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi-STUB.conf
@@ -0,0 +1,201 @@
+Active_eNBs = ( "eNB_Eurecom_LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    ////////// Identification parameters:
+    eNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_ENB";
+
+    eNB_name  =  "eNB_Eurecom_LTEBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  "1";
+
+    mobile_country_code =  "208";
+
+    #mobile_network_code =  "93";
+    mobile_network_code =  "92";
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "3GPP_eNODEB";
+      node_timing               = "synch_to_ext_device";
+      node_synch_ref            = 0;
+      frame_type					      = "FDD";
+      tdd_config 					      = 3;
+      tdd_config_s            			      = 0;
+      prefix_type             			      = "NORMAL";
+      eutra_band              			      = 7;
+      downlink_frequency      			      = 2685000000L;
+      uplink_frequency_offset 			      = -120000000;
+      Nid_cell					      = 0;
+      #N_RB_DL                 			      = 50;
+      N_RB_DL                 			      = 25;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 1;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 115;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 0;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 32;
+      #pdsch_referenceSignalPower 			      = -27;
+      pdsch_referenceSignalPower 			      = -30;
+      pdsch_p_b                  			      = 0;
+      pusch_n_SB                 			      = 1;
+      pusch_enable64QAM          			      = "DISABLE";
+      pusch_hoppingMode                                  = "interSubFrame";
+      pusch_hoppingOffset                                = 0;
+      pusch_groupHoppingEnabled  			      = "ENABLE";
+      pusch_groupAssignment      			      = 0;
+      pusch_sequenceHoppingEnabled		   	      = "DISABLE";
+      pusch_nDMRS1                                       = 1;
+      phich_duration                                     = "NORMAL";
+      phich_resource                                     = "ONESIXTH";
+      srs_enable                                         = "DISABLE";
+      /*  srs_BandwidthConfig                                =;
+      srs_SubframeConfig                                 =;
+      srs_ackNackST                                      =;
+      srs_MaxUpPts                                       =;*/
+
+      pusch_p0_Nominal                                   = -96;
+      pusch_alpha                                        = "AL1";
+      pucch_p0_Nominal                                   = -104;
+      msg3_delta_Preamble                                = 6;
+      pucch_deltaF_Format1                               = "deltaF2";
+      pucch_deltaF_Format1b                              = "deltaF3";
+      pucch_deltaF_Format2                               = "deltaF0";
+      pucch_deltaF_Format2a                              = "deltaF0";
+      pucch_deltaF_Format2b		    	      = "deltaF0";
+
+      rach_numberOfRA_Preambles                          = 64;
+      rach_preamblesGroupAConfig                         = "DISABLE";
+      /*
+      rach_sizeOfRA_PreamblesGroupA                      = ;
+      rach_messageSizeGroupA                             = ;
+      rach_messagePowerOffsetGroupB                      = ;
+      */
+      rach_powerRampingStep                              = 4;
+      #rach_preambleInitialReceivedTargetPower            = -108;
+      rach_preambleInitialReceivedTargetPower            = -104;
+      rach_preambleTransMax                              = 10;
+      rach_raResponseWindowSize                          = 10;
+      rach_macContentionResolutionTimer                  = 48;
+      rach_maxHARQ_Msg3Tx                                = 4;
+
+      pcch_default_PagingCycle                           = 128;
+      pcch_nB                                            = "oneT";
+      bcch_modificationPeriodCoeff			      = 2;
+      ue_TimersAndConstants_t300			      = 1000;
+      ue_TimersAndConstants_t301			      = 1000;
+      ue_TimersAndConstants_t310			      = 1000;
+      ue_TimersAndConstants_t311			      = 10000;
+      ue_TimersAndConstants_n310			      = 20;
+      ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                                    = 1;
+      }
+    );
+
+
+    srb1_parameters :
+    {
+        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
+        timer_poll_retransmit    = 80;
+
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = 35;
+
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = 0;
+
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  4;
+
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  99999;
+
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+    }
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.56.102";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "vboxnet0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.56.1/24";
+        ENB_INTERFACE_NAME_FOR_S1U               = "vboxnet0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.56.1/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+      	local_s_if_name  = "eno1";			  
+      	remote_s_address = "10.0.0.2";
+    	#local_s_address  = "192.168.1.78"; 
+    	local_s_address  = "10.0.0.1"; 
+    	local_s_portc    = 50001;	
+    	remote_s_portc   = 50000;
+    	local_s_portd    = 50011;	
+    	remote_s_portd   = 50010;
+	tr_s_preference = "nfapi";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+     log_config :
+     {
+       global_log_level                      ="debug";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="debug";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="debug";
+       rlc_log_verbosity                     ="high";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="high";
+    };
+
+
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf
index bc2b3b219c316d8750846a61a16d96aeb90e926a..03241ec694a8ea75b99cb2b06a5ba360eb002a7b 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.50PRB.nfapi.conf
@@ -105,6 +105,40 @@ eNBs =
       ue_TimersAndConstants_n310			      = 20;
       ue_TimersAndConstants_n311			      = 1;
       ue_TransmissionMode                                    = 1;
+
+      //Parameters for SIB18
+      rxPool_sc_CP_Len                                       = "normal";
+      rxPool_sc_Period                                       = "sf40";
+      rxPool_data_CP_Len                                     = "normal";
+      rxPool_ResourceConfig_prb_Num                          = 20;
+      rxPool_ResourceConfig_prb_Start                        = 5;
+      rxPool_ResourceConfig_prb_End                          = 44;
+      rxPool_ResourceConfig_offsetIndicator_present          = "prSmall";
+      rxPool_ResourceConfig_offsetIndicator_choice           = 0;
+      rxPool_ResourceConfig_subframeBitmap_present           = "prBs40";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_buf              = "00000000000000000000";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_size             = 5;
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused      = 0;
+/*    rxPool_dataHoppingConfig_hoppingParameter                       = 0;
+      rxPool_dataHoppingConfig_numSubbands                            = "ns1";
+      rxPool_dataHoppingConfig_rbOffset                               = 0;
+      rxPool_commTxResourceUC-ReqAllowed                              = "TRUE";
+*/
+      // Parameters for SIB19
+      discRxPool_cp_Len                                               = "normal"
+      discRxPool_discPeriod                                           = "rf32"
+      discRxPool_numRetx                                              = 1;
+      discRxPool_numRepetition                                        = 2;
+      discRxPool_ResourceConfig_prb_Num                               = 5;
+      discRxPool_ResourceConfig_prb_Start                             = 3;
+      discRxPool_ResourceConfig_prb_End                               = 21;
+      discRxPool_ResourceConfig_offsetIndicator_present               = "prSmall";
+      discRxPool_ResourceConfig_offsetIndicator_choice                = 0;
+      discRxPool_ResourceConfig_subframeBitmap_present                = "prBs40";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf          = "f0ffffffff";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_size         = 5;
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused  = 0;
+
       }
     );
 
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 7dcfd432de82387e1010543292ec1e5a1679323b..c269bcbe3bf01539aca22b1893ccda4793eb7334 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -121,7 +121,9 @@ extern int transmission_mode;
 
 extern int oaisim_flag;
 
-uint16_t sf_ahead=4;
+//uint16_t sf_ahead=4;
+extern uint16_t sf_ahead;
+
 
 //pthread_t                       main_eNB_thread;
 
@@ -353,8 +355,19 @@ static void* tx_thread(void* param) {
 static void* eNB_thread_rxtx( void* param ) {
 
   static int eNB_thread_rxtx_status;
-  eNB_proc_t *eNB_proc  = (eNB_proc_t*)param;
-  eNB_rxtx_proc_t *proc = &eNB_proc->proc_rxtx[0];
+  //eNB_proc_t *eNB_proc  = (eNB_proc_t*)param;
+  eNB_rxtx_proc_t *proc;
+
+  // Working
+  if(nfapi_mode ==2){
+	  proc = (eNB_rxtx_proc_t*)param;
+  }
+  else{
+	  eNB_proc_t *eNB_proc  = (eNB_proc_t*)param;
+	  proc = &eNB_proc->proc_rxtx[0];
+  }
+
+
   PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
   //RU_proc_t *ru_proc = NULL;
 
@@ -476,6 +489,8 @@ void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t
 
 int wakeup_txfh(eNB_rxtx_proc_t *proc,RU_proc_t *ru_proc) {
   
+	if(ru_proc == NULL)
+		return(0);
   struct timespec wait;
   wait.tv_sec=0;
   wait.tv_nsec=5000000L;
@@ -963,8 +978,17 @@ void init_eNB_proc(int inst) {
       init_td_thread(eNB);
     }
     //////////////////////////////////////need to modified////////////////*****
-	pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, proc );
-	pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, tx_thread, proc);
+	//pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, proc );
+
+	//pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, proc_rxtx );
+
+
+    // Panos: Should we also include here the case where single_thread_flag = 1 ?
+	if(nfapi_mode!=2){
+		pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, proc );
+		pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, tx_thread, proc);
+	}
+
 
     LOG_I(PHY,"eNB->single_thread_flag:%d\n", eNB->single_thread_flag);
 
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 8e469d526030c052bff0cac3efe7d5f595b6ad69..50b868ae1d1205747d5730548977db3782e0786e 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -118,6 +118,8 @@ int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
 
 uint8_t nfapi_mode = 0; // Default to monolithic mode
 
+uint16_t sf_ahead=4;
+
 pthread_cond_t sync_cond;
 pthread_mutex_t sync_mutex;
 int sync_var=-1; //!< protected by mutex \ref sync_mutex.
@@ -1149,6 +1151,13 @@ int main( int argc, char **argv )
     pthread_mutex_init(&sync_mutex, NULL);
   }
   
+  if (nfapi_mode)
+  {
+    printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
+    pthread_cond_init(&sync_cond,NULL);
+    pthread_mutex_init(&sync_mutex, NULL);
+  }
+
   const char *nfapi_mode_str = "<UNKNOWN>";
 
   switch(nfapi_mode) {
diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h
index aff969908f2d738114afe6bfef26fb8e588c5498..bd6596f75c73c651ddcfcd743229f783f7e4b174 100644
--- a/targets/RT/USER/lte-softmodem.h
+++ b/targets/RT/USER/lte-softmodem.h
@@ -74,6 +74,8 @@
 #define CONFIG_HLP_DLMCS         "Set the maximum downlink MCS\n"
 #define CONFIG_HLP_STMON         "Enable processing timing measurement of lte softmodem on per subframe basis \n"
 #define CONFIG_HLP_PRB           "Set the PRB, valid values: 6, 25, 50, 100  \n"    
+#define CONFIG_HLP_EMULIFACE     "Set the interface name for the multicast transport for emulation mode (e.g. eth0, lo, etc.)  \n"
+//#define CONFIG_HLP_NUMUES		 "Set the number of UEs for the emulation"
 #define CONFIG_HLP_MSLOTS        "Skip the missed slots/subframes \n"    
 #define CONFIG_HLP_ULMCS         "Set the maximum uplink MCS\n"
 #define CONFIG_HLP_TDD           "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n"
@@ -135,7 +137,10 @@
 {"ue-nb-ant-tx",     	       CONFIG_HLP_UENANTT,    0,		u8ptr:&nb_antenna_tx,		    defuintval:1,   TYPE_UINT8,    0},     \
 {"ue-scan-carrier",  	       CONFIG_HLP_UESCAN,     PARAMFLAG_BOOL,	iptr:&UE_scan_carrier,  	    defintval:0,    TYPE_INT,	   0},     \
 {"ue-max-power",     	       NULL,		      0,		iptr:&(tx_max_power[0]),	    defintval:90,   TYPE_INT,	   0},     \
-{"r"  ,                        CONFIG_HLP_PRB,        0,                u8ptr:&(frame_parms[0]->N_RB_DL),   defintval:25,   TYPE_UINT8,    0},     \
+{"emul-iface",                 CONFIG_HLP_EMULIFACE,  0,                strptr:&emul_iface,                  defstrval:"lo", TYPE_STRING,   100}, \
+{"L2-emul",                 	NULL,  				  0,                u8ptr:&nfapi_mode,                  defuintval:3, TYPE_UINT8,   0}, \
+{"num-ues",     	       		   NULL,		      	  0,				u8ptr:&(NB_UE_INST),	    defuintval:1,   	TYPE_UINT8,	   0},     \
+{"r"  ,                        CONFIG_HLP_PRB,        0,                u8ptr:&(frame_parms[0]->N_RB_DL),   defintval:25,   TYPE_UINT8,    0}     \
 }
 
 #define DEFAULT_DLF 2680000000
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index 2c83ea9a04e22671ba45fd6ced7b1ddbbc0656fe..84e77c1ef829f5da1946a37a11ba86db27bc59c5 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -37,6 +37,7 @@
 #include "LAYER2/MAC/defs.h"
 #include "RRC/LITE/extern.h"
 #endif
+#include "PHY_INTERFACE/phy_stub_UE.h"
 #include "PHY_INTERFACE/extern.h"
 
 #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
@@ -46,6 +47,9 @@
 #include "SCHED/extern.h"
 #include "LAYER2/MAC/extern.h"
 #include "LAYER2/MAC/proto.h"
+#include <inttypes.h>
+//#include "openair2/PHY_INTERFACE/phy_stub_UE.h"
+
 
 #include "UTIL/LOG/log_extern.h"
 #include "UTIL/OTG/otg_tx.h"
@@ -54,76 +58,100 @@
 #include "UTIL/LOG/vcd_signal_dumper.h"
 #include "UTIL/OPT/opt.h"
 
+
 #include "T.h"
 
 extern double cpuf;
+extern uint8_t  nfapi_mode;
 
 #define FRAME_PERIOD    100000000ULL
 #define DAQ_PERIOD      66667ULL
 #define FIFO_PRIORITY   40
 
 typedef enum {
-    pss=0,
-    pbch=1,
-    si=2
+  pss=0,
+  pbch=1,
+  si=2
 } sync_mode_t;
 
 void init_UE_threads(int);
+void init_UE_threads_stub(int);
+void init_UE_single_thread_stub(int);
 void *UE_thread(void *arg);
 void init_UE(int nb_inst,int,int,int);
+void init_UE_stub(int nb_inst,int,int,char*);
+void init_UE_stub_single_thread(int nb_inst,int,int,char*);
+int init_timer_thread(void);
+extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
+extern void multicast_link_start(void (*rx_handlerP) (unsigned int, char *),
+                          unsigned char _multicast_group, char *multicast_ifname);
+extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind);
+extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind);
+extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind);
+extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind);
+extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind);
+extern int multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP);
+
+//extern int tx_req_UE_MAC1();
+
+void ue_stub_rx_handler(unsigned int, char *);
 
 int32_t **rxdata;
 int32_t **txdata;
 
+int timer_subframe;
+int timer_frame;
+SF_ticking *phy_stub_ticking;
+
 #define KHz (1000UL)
 #define MHz (1000*KHz)
 
 typedef struct eutra_band_s {
-    int16_t band;
-    uint32_t ul_min;
-    uint32_t ul_max;
-    uint32_t dl_min;
-    uint32_t dl_max;
-    lte_frame_type_t frame_type;
+  int16_t band;
+  uint32_t ul_min;
+  uint32_t ul_max;
+  uint32_t dl_min;
+  uint32_t dl_max;
+  lte_frame_type_t frame_type;
 } eutra_band_t;
 
 typedef struct band_info_s {
-    int nbands;
-    eutra_band_t band_info[100];
+  int nbands;
+  eutra_band_t band_info[100];
 } band_info_t;
 
 band_info_t bands_to_scan;
 
 static const eutra_band_t eutra_bands[] = {
-    { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
-    { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
-    { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
-    { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
-    { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
-    { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
-    { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
-    { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
-    { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
-    {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
-    {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
-    {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
-    {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
-    {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},
-    {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},
-    {20,  832    * MHz,  862    * MHz,  791    * MHz,  821    * MHz, FDD},
-    {22, 3510    * MHz, 3590    * MHz, 3410    * MHz, 3490    * MHz, FDD},
-    {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
-    {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
-    {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
-    {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
-    {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
-    {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
-    {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
-    {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
-    {41, 2496    * MHz, 2690    * MHz, 2496    * MHz, 2690    * MHz, TDD},
-    {42, 3400    * MHz, 3600    * MHz, 3400    * MHz, 3600    * MHz, TDD},
-    {43, 3600    * MHz, 3800    * MHz, 3600    * MHz, 3800    * MHz, TDD},
-    {44, 703    * MHz, 803    * MHz, 703    * MHz, 803    * MHz, TDD},
+  { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
+  { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
+  { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
+  { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
+  { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
+  { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
+  { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
+  { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
+  { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
+  {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
+  {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
+  {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
+  {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
+  {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},
+  {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},
+  {20,  832    * MHz,  862    * MHz,  791    * MHz,  821    * MHz, FDD},
+  {22, 3510    * MHz, 3590    * MHz, 3410    * MHz, 3490    * MHz, FDD},
+  {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
+  {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
+  {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
+  {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
+  {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
+  {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
+  {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
+  {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
+  {41, 2496    * MHz, 2690    * MHz, 2496    * MHz, 2690    * MHz, TDD},
+  {42, 3400    * MHz, 3600    * MHz, 3400    * MHz, 3600    * MHz, TDD},
+  {43, 3600    * MHz, 3800    * MHz, 3600    * MHz, 3800    * MHz, TDD},
+  {44, 703    * MHz, 803    * MHz, 703    * MHz, 803    * MHz, TDD},
 };
 
 
@@ -147,16 +175,21 @@ PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
     ue = (PHY_VARS_UE *)malloc(sizeof(PHY_VARS_UE));
     memset(ue,0,sizeof(PHY_VARS_UE));
     memcpy(&(ue->frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS));
-  }					
+  }
   else ue = PHY_vars_UE_g[UE_id][0];
 
 
   ue->Mod_id      = UE_id;
   ue->mac_enabled = 1;
-  // initialize all signal buffers
-  init_lte_ue_signal(ue,1,abstraction_flag);
-  // intialize transport
-  init_lte_ue_transport(ue,abstraction_flag);
+
+  // Panos: In phy_stub_UE (MAC-to-MAC) mode these init functions don't need to get called. Is this correct?
+  if (nfapi_mode!=3)
+    {
+      // initialize all signal buffers
+      init_lte_ue_signal(ue,1,abstraction_flag);
+      // intialize transport
+      init_lte_ue_transport(ue,abstraction_flag);
+    }
 
   return(ue);
 }
@@ -169,35 +202,35 @@ char uecap_xer[1024];
 void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name) {
 
 #ifdef DEADLINE_SCHEDULER
-    if (sched_runtime!=0) {
-        struct sched_attr attr= {0};
-        attr.size = sizeof(attr);
-        attr.sched_policy = SCHED_DEADLINE;
-        attr.sched_runtime  = sched_runtime;
-        attr.sched_deadline = sched_deadline;
-        attr.sched_period   = 0;
-        AssertFatal(sched_setattr(0, &attr, 0) == 0,
-                    "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
-        LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n",
-              name, (unsigned long)gettid(), sched_getcpu());
-    }
+  if (sched_runtime!=0) {
+    struct sched_attr attr= {0};
+    attr.size = sizeof(attr);
+    attr.sched_policy = SCHED_DEADLINE;
+    attr.sched_runtime  = sched_runtime;
+    attr.sched_deadline = sched_deadline;
+    attr.sched_period   = 0;
+    AssertFatal(sched_setattr(0, &attr, 0) == 0,
+		"[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
+    LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n",
+	  name, (unsigned long)gettid(), sched_getcpu());
+  }
 #else
-    if (CPU_COUNT(cpuset) > 0)
-        AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), "");
-    struct sched_param sp;
-    sp.sched_priority = sched_fifo;
-    AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
-                "Can't set thread priority, Are you root?\n");
-    /* Check the actual affinity mask assigned to the thread */
-    cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE);
-    if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) {
-      char txt[512]={0};
-      for (int j = 0; j < CPU_SETSIZE; j++)
-        if (CPU_ISSET(j, cset))
-	  sprintf(txt+strlen(txt), " %d ", j);
-      printf("CPU Affinity of thread %s is %s\n", name, txt);
-    }
-    CPU_FREE(cset);
+  if (CPU_COUNT(cpuset) > 0)
+    AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), "");
+  struct sched_param sp;
+  sp.sched_priority = sched_fifo;
+  AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
+	      "Can't set thread priority, Are you root?\n");
+  /* Check the actual affinity mask assigned to the thread */
+  cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE);
+  if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) {
+    char txt[512]={0};
+    for (int j = 0; j < CPU_SETSIZE; j++)
+      if (CPU_ISSET(j, cset))
+	sprintf(txt+strlen(txt), " %d ", j);
+    printf("CPU Affinity of thread %s is %s\n", name, txt);
+  }
+  CPU_FREE(cset);
 #endif
 
 }
@@ -209,11 +242,11 @@ void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correcti
   int         ret;
 
   LOG_I(PHY,"UE : Calling Layer 2 for initialization\n");
-    
+
   l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
 	     0,// cba_group_active
 	     0); // HO flag
-  
+
   for (inst=0;inst<nb_inst;inst++) {
 
     LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
@@ -251,6 +284,76 @@ void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correcti
 #endif
 }
 
+// Panos: Initiating all UEs within a single set of threads for PHY_STUB. Future extensions -> multiple
+// set of threads for multiple UEs.
+void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface) {
+
+  int         inst;
+
+  LOG_I(PHY,"UE : Calling Layer 2 for initialization, nb_inst: %d \n", nb_inst);
+
+  l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
+	     0,// cba_group_active
+	     0); // HO flag
+
+  for (inst=0;inst<nb_inst;inst++) {
+
+    LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
+    PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
+  }
+  init_timer_thread();
+  init_UE_single_thread_stub(nb_inst);
+
+
+  printf("UE threads created \n");
+
+  LOG_I(PHY,"Starting multicast link on %s\n",emul_iface);
+  if(nfapi_mode!=3)
+  multicast_link_start(ue_stub_rx_handler,0,emul_iface);
+
+
+}
+
+
+
+
+
+void init_UE_stub(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface) {
+
+  int         inst;
+
+  LOG_I(PHY,"UE : Calling Layer 2 for initialization\n");
+
+  l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
+	     0,// cba_group_active
+	     0); // HO flag
+
+  for (inst=0;inst<nb_inst;inst++) {
+
+    LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
+    PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
+  }
+  init_timer_thread();
+
+  for (inst=0;inst<nb_inst;inst++) {
+
+    LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
+    init_UE_threads_stub(inst);
+  }
+
+  printf("UE threads created \n");
+
+  LOG_I(PHY,"Starting multicast link on %s\n",emul_iface);
+  if(nfapi_mode !=3)
+     multicast_link_start(ue_stub_rx_handler,0,emul_iface);
+
+
+
+}
+
+
+
+
 /*!
  * \brief This is the UE synchronize thread.
  * It performs band scanning and synchonization.
@@ -275,14 +378,14 @@ static void *UE_thread_synch(void *arg)
   UE->is_synchronized = 0;
   printf("UE_thread_sync in with PHY_vars_UE %p\n",arg);
 
-   cpu_set_t cpuset;
+  cpu_set_t cpuset;
   CPU_ZERO(&cpuset);
   if ( threads.iq != -1 )
     CPU_SET(threads.iq, &cpuset);
   // this thread priority must be lower that the main acquisition thread
   sprintf(threadname, "sync UE %d\n", UE->Mod_id);
   init_thread(100000, 500000, FIFO_PRIORITY-1, &cpuset, threadname);
-  
+
   printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch);
   ind = 0;
   found = 0;
@@ -303,7 +406,7 @@ static void *UE_thread_synch(void *arg)
 
       ind++;
     } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
-  
+
     if (found == 0) {
       LOG_E(PHY,"Can't find EUTRA band for frequency %d",UE->frame_parms.dl_CarrierFreq);
       exit_fun("Can't find EUTRA band for frequency");
@@ -317,7 +420,7 @@ static void *UE_thread_synch(void *arg)
       openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = UE->frame_parms.dl_CarrierFreq;
       openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = UE->frame_parms.ul_CarrierFreq;
       openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
-      if (uplink_frequency_offset[CC_id][i] != 0) // 
+      if (uplink_frequency_offset[CC_id][i] != 0) //
 	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
       else //FDD
 	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
@@ -339,15 +442,15 @@ static void *UE_thread_synch(void *arg)
     }
   }
 
-  while (sync_var<0)     
-    pthread_cond_wait(&sync_cond, &sync_mutex);   
-  pthread_mutex_unlock(&sync_mutex);   
+  while (sync_var<0)
+    pthread_cond_wait(&sync_cond, &sync_mutex);
+  pthread_mutex_unlock(&sync_mutex);
 
-  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");   
+  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");
 
-  if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {     
-    LOG_E(HW,"Could not start the device\n");     
-    oai_exit=1;   
+  if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
+    LOG_E(HW,"Could not start the device\n");
+    oai_exit=1;
   }
 
   while (oai_exit==0) {
@@ -356,202 +459,202 @@ static void *UE_thread_synch(void *arg)
       // the thread waits here most of the time
       pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
     AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
-    
+
     switch (sync_mode) {
     case pss:
       LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
       lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
       current_offset += 20000000; // increase by 20 MHz
-      
+
       if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
 	current_band++;
-                current_offset=0;
-            }
-
-            if (current_band==bands_to_scan.nbands) {
-                current_band=0;
-                oai_exit=1;
-            }
-
-            for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
-                downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
-                uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
-
-                openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
-                openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
-                openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
-                if (UE->UE_scan_carrier) {
-                    openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
-                }
-	    }
+	current_offset=0;
+      }
+
+      if (current_band==bands_to_scan.nbands) {
+	current_band=0;
+	oai_exit=1;
+      }
+
+      for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+	downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
+	uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
+
+	openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
+	openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
+	openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
+	if (UE->UE_scan_carrier) {
+	  openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
+	}
+      }
+
+      break;
 
-	    break;
- 
     case pbch:
 
 #if DISABLE_LOG_X
-            printf("[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
+      printf("[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
 #else
-            LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
+      LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
 #endif
-            if (initial_sync( UE, UE->mode ) == 0) {
-
-                hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
-                LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
-                       hw_slot_offset,
-                       freq_offset,
-                       UE->rx_total_gain_dB,
-                       downlink_frequency[0][0]+freq_offset,
-                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset,
-                       UE->UE_scan_carrier );
-
-
-                    // rerun with new cell parameters and frequency-offset
-                    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
-                        openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
-			if (UE->UE_scan_carrier == 1) {
-                        if (freq_offset >= 0)
-                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
-                        else
-                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
-                        openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
-                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
-                        downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
-                        freq_offset=0;
-                    }
+      if (initial_sync( UE, UE->mode ) == 0) {
+
+	hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
+	LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
+	       hw_slot_offset,
+	       freq_offset,
+	       UE->rx_total_gain_dB,
+	       downlink_frequency[0][0]+freq_offset,
+	       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset,
+	       UE->UE_scan_carrier );
+
+
+	// rerun with new cell parameters and frequency-offset
+	for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+	  openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
+	  if (UE->UE_scan_carrier == 1) {
+	    if (freq_offset >= 0)
+	      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
+	    else
+	      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
+	    openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
+	      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
+	    downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
+	    freq_offset=0;
 	  }
+	}
+
+	// reconfigure for potentially different bandwidth
+	switch(UE->frame_parms.N_RB_DL) {
+	case 6:
+	  openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
+	  openair0_cfg[UE->rf_map.card].rx_bw          =.96e6;
+	  openair0_cfg[UE->rf_map.card].tx_bw          =.96e6;
+	  //            openair0_cfg[0].rx_gain[0] -= 12;
+	  break;
+	case 25:
+	  openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
+	  openair0_cfg[UE->rf_map.card].rx_bw          =2.5e6;
+	  openair0_cfg[UE->rf_map.card].tx_bw          =2.5e6;
+	  //            openair0_cfg[0].rx_gain[0] -= 6;
+	  break;
+	case 50:
+	  openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
+	  openair0_cfg[UE->rf_map.card].rx_bw          =5.0e6;
+	  openair0_cfg[UE->rf_map.card].tx_bw          =5.0e6;
+	  //            openair0_cfg[0].rx_gain[0] -= 3;
+	  break;
+	case 100:
+	  openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
+	  openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
+	  openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
+	  //            openair0_cfg[0].rx_gain[0] -= 0;
+	  break;
+	}
+
+	UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
+	//UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
+	//UE->rfdevice.trx_stop_func(&UE->rfdevice);
+	sleep(1);
+	init_frame_parms(&UE->frame_parms,1);
+	/*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
+	  LOG_E(HW,"Could not start the device\n");
+	  oai_exit=1;
+	  }*/
+
+	if (UE->UE_scan_carrier == 1) {
+
+	  UE->UE_scan_carrier = 0;
+	} else {
+	  AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+	  UE->is_synchronized = 1;
+	  AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+
+	  if( UE->mode == rx_dump_frame ) {
+	    FILE *fd;
+	    if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) {  // this guarantees SIB1 is present
+	      if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) {
+		fwrite((void*)&UE->common_vars.rxdata[0][0],
+		       sizeof(int32_t),
+		       10*UE->frame_parms.samples_per_tti,
+		       fd);
+		LOG_I(PHY,"Dummping Frame ... bye bye \n");
+		fclose(fd);
+		exit(0);
+	      } else {
+		LOG_E(PHY,"Cannot open file for writing\n");
+		exit(0);
+	      }
+	    } else {
+	      AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+	      UE->is_synchronized = 0;
+	      AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
 
-                    // reconfigure for potentially different bandwidth
-                    switch(UE->frame_parms.N_RB_DL) {
-                    case 6:
-                        openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
-                        openair0_cfg[UE->rf_map.card].rx_bw          =.96e6;
-                        openair0_cfg[UE->rf_map.card].tx_bw          =.96e6;
-                        //            openair0_cfg[0].rx_gain[0] -= 12;
-                        break;
-                    case 25:
-                        openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
-                        openair0_cfg[UE->rf_map.card].rx_bw          =2.5e6;
-                        openair0_cfg[UE->rf_map.card].tx_bw          =2.5e6;
-                        //            openair0_cfg[0].rx_gain[0] -= 6;
-                        break;
-                    case 50:
-                        openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
-                        openair0_cfg[UE->rf_map.card].rx_bw          =5.0e6;
-                        openair0_cfg[UE->rf_map.card].tx_bw          =5.0e6;
-                        //            openair0_cfg[0].rx_gain[0] -= 3;
-                        break;
-                    case 100:
-                        openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
-                        openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
-                        openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
-                        //            openair0_cfg[0].rx_gain[0] -= 0;
-                        break;
-                    }
-
-                    UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
-                    //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
-                    //UE->rfdevice.trx_stop_func(&UE->rfdevice);
-                    sleep(1);
-                    init_frame_parms(&UE->frame_parms,1);
-                    /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
-                        LOG_E(HW,"Could not start the device\n");
-                        oai_exit=1;
-                    }*/
-
-		if (UE->UE_scan_carrier == 1) {
-
-		  UE->UE_scan_carrier = 0;
-                } else {
-                    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
-                    UE->is_synchronized = 1;
-                    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
-
-                    if( UE->mode == rx_dump_frame ) {
-                        FILE *fd;
-                        if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) {  // this guarantees SIB1 is present
-                            if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) {
-                                fwrite((void*)&UE->common_vars.rxdata[0][0],
-                                       sizeof(int32_t),
-                                       10*UE->frame_parms.samples_per_tti,
-                                       fd);
-                                LOG_I(PHY,"Dummping Frame ... bye bye \n");
-                                fclose(fd);
-                                exit(0);
-                            } else {
-                                LOG_E(PHY,"Cannot open file for writing\n");
-                                exit(0);
-                            }
-                        } else {
-                            AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
-                            UE->is_synchronized = 0;
-                            AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
-
-                        }
-                    }
-                }
-            } else {
-                // initial sync failed
-                // calculate new offset and try again
-                if (UE->UE_scan_carrier == 1) {
-                    if (freq_offset >= 0)
-                        freq_offset += 100;
-                    freq_offset *= -1;
-
-                    if (abs(freq_offset) > 7500) {
-                        LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" );
-                        FILE *fd;
-                        if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) {
-                            fwrite((void*)&UE->common_vars.rxdata[0][0],
-                                   sizeof(int32_t),
-                                   10*UE->frame_parms.samples_per_tti,
-                                   fd);
-                            LOG_I(PHY,"Dummping Frame ... bye bye \n");
-                            fclose(fd);
-                            exit(0);
-                        }
-                        AssertFatal(1==0,"No cell synchronization found, abandoning");
-                        return &UE_thread_synch_retval; // not reached
-                    }
-                }
+	    }
+	  }
+	}
+      } else {
+	// initial sync failed
+	// calculate new offset and try again
+	if (UE->UE_scan_carrier == 1) {
+	  if (freq_offset >= 0)
+	    freq_offset += 100;
+	  freq_offset *= -1;
+
+	  if (abs(freq_offset) > 7500) {
+	    LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" );
+	    FILE *fd;
+	    if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) {
+	      fwrite((void*)&UE->common_vars.rxdata[0][0],
+		     sizeof(int32_t),
+		     10*UE->frame_parms.samples_per_tti,
+		     fd);
+	      LOG_I(PHY,"Dummping Frame ... bye bye \n");
+	      fclose(fd);
+	      exit(0);
+	    }
+	    AssertFatal(1==0,"No cell synchronization found, abandoning");
+	    return &UE_thread_synch_retval; // not reached
+	  }
+	}
 #if DISABLE_LOG_X
-                printf("[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
-                       freq_offset,
-                       UE->rx_total_gain_dB,
-                       downlink_frequency[0][0]+freq_offset,
-                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
+	printf("[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
+	       freq_offset,
+	       UE->rx_total_gain_dB,
+	       downlink_frequency[0][0]+freq_offset,
+	       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
 #else
-                LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
-                       freq_offset,
-                       UE->rx_total_gain_dB,
-                       downlink_frequency[0][0]+freq_offset,
-                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
+	LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
+	      freq_offset,
+	      UE->rx_total_gain_dB,
+	      downlink_frequency[0][0]+freq_offset,
+	      downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
 #endif
 
-                for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
-                    openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset;
-                    openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset;
-                    openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
-                    if (UE->UE_scan_carrier==1)
-                        openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
-                }
-                UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
-            }// initial_sync=0
-            break;
-        case si:
-        default:
-            break;
-        }
-
-        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
-        // indicate readiness
-        UE->proc.instance_cnt_synch--;
-        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
-
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
-    }  // while !oai_exit
-
-    return &UE_thread_synch_retval;
+	for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+	  openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset;
+	  openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset;
+	  openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
+	  if (UE->UE_scan_carrier==1)
+	    openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
+	}
+	UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
+      }// initial_sync=0
+      break;
+    case si:
+    default:
+      break;
+    }
+
+    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+    // indicate readiness
+    UE->proc.instance_cnt_synch--;
+    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
+  }  // while !oai_exit
+
+  return &UE_thread_synch_retval;
 }
 
 /*!
@@ -563,146 +666,730 @@ static void *UE_thread_synch(void *arg)
  */
 
 static void *UE_thread_rxn_txnp4(void *arg) {
-    static __thread int UE_thread_rxtx_retval;
-    struct rx_tx_thread_data *rtd = arg;
-    UE_rxtx_proc_t *proc = rtd->proc;
-    PHY_VARS_UE    *UE   = rtd->UE;
-    int ret;
-
-    proc->instance_cnt_rxtx=-1;
-    proc->subframe_rx=proc->sub_frame_start;
-
-    char threadname[256];
-    sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
-    cpu_set_t cpuset;
-    CPU_ZERO(&cpuset);
-
-    if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 )
-        CPU_SET(threads.one, &cpuset);
-    if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 )
-        CPU_SET(threads.two, &cpuset);
-    if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 )
-        CPU_SET(threads.three, &cpuset);
-            //CPU_SET(threads.three, &cpuset);
-    init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
-                threadname);
-
-    while (!oai_exit) {
-        if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
-          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
-          exit_fun("nothing to add");
-        }
-        while (proc->instance_cnt_rxtx < 0) {
-          // most of the time, the thread is waiting here
-          pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
-        }
-        if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
-          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
-          exit_fun("nothing to add");
-        }
-
-        initRefTimes(t2);
-        initRefTimes(t3);
-        pickTime(current);
-        updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");
-
-        // Process Rx data for one sub-frame
-        lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);
-        if ((sf_type == SF_DL) ||
-                (UE->frame_parms.frame_type == FDD) ||
-                (sf_type == SF_S)) {
-
-            if (UE->frame_parms.frame_type == TDD) {
-                LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
-                      threadname,
-                      UE->frame_parms.tdd_config,
-                      (sf_type==SF_DL? "SF_DL" :
-                       (sf_type==SF_UL? "SF_UL" :
-                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
-            } else {
-                LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
-                      threadname,
-                      (UE->frame_parms.frame_type==FDD? "FDD":
-                       (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
-                      (sf_type==SF_DL? "SF_DL" :
-                       (sf_type==SF_UL? "SF_UL" :
-                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
-            }
+  static __thread int UE_thread_rxtx_retval;
+  struct rx_tx_thread_data *rtd = arg;
+  UE_rxtx_proc_t *proc = rtd->proc;
+  PHY_VARS_UE    *UE   = rtd->UE;
+  int ret;
+
+  proc->instance_cnt_rxtx=-1;
+  proc->subframe_rx=proc->sub_frame_start;
+
+  char threadname[256];
+  sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
+  cpu_set_t cpuset;
+  CPU_ZERO(&cpuset);
+
+  if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 )
+    CPU_SET(threads.one, &cpuset);
+  if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 )
+    CPU_SET(threads.two, &cpuset);
+  if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 )
+    CPU_SET(threads.three, &cpuset);
+  //CPU_SET(threads.three, &cpuset);
+  init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
+	      threadname);
+
+  while (!oai_exit) {
+    if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
+      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
+      exit_fun("nothing to add");
+    }
+    while (proc->instance_cnt_rxtx < 0) {
+      // most of the time, the thread is waiting here
+      pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
+    }
+    if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
+      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
+      exit_fun("nothing to add");
+    }
+
+    initRefTimes(t2);
+    initRefTimes(t3);
+    pickTime(current);
+    updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");
+
+    // Process Rx data for one sub-frame
+    lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);
+    if ((sf_type == SF_DL) ||
+	(UE->frame_parms.frame_type == FDD) ||
+	(sf_type == SF_S)) {
+
+      if (UE->frame_parms.frame_type == TDD) {
+	LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
+	      threadname,
+	      UE->frame_parms.tdd_config,
+	      (sf_type==SF_DL? "SF_DL" :
+	       (sf_type==SF_UL? "SF_UL" :
+		(sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
+      } else {
+	LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
+	      threadname,
+	      (UE->frame_parms.frame_type==FDD? "FDD":
+	       (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
+	      (sf_type==SF_DL? "SF_DL" :
+	       (sf_type==SF_UL? "SF_UL" :
+		(sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
+      }
 #ifdef UE_SLOT_PARALLELISATION
-            phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
+      phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
 #else
-            phy_procedures_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
+      phy_procedures_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
 #endif
-        }
+    }
 
 #if UE_TIMING_TRACE
-        start_meas(&UE->generic_stat);
+    start_meas(&UE->generic_stat);
 #endif
-        if (UE->mac_enabled==1) {
-
-            ret = ue_scheduler(UE->Mod_id,
-			       proc->frame_rx,
-			       proc->subframe_rx,
-			       proc->frame_tx,
-			       proc->subframe_tx,
-			       subframe_select(&UE->frame_parms,proc->subframe_tx),
-			       0,
-			       0/*FIXME CC_id*/);
-            if ( ret != CONNECTION_OK) {
-                char *txt;
-                switch (ret) {
-                case CONNECTION_LOST:
-                    txt="RRC Connection lost, returning to PRACH";
-                    break;
-                case PHY_RESYNCH:
-                    txt="RRC Connection lost, trying to resynch";
-                    break;
-                case RESYNCH:
-                    txt="return to PRACH and perform a contention-free access";
-                    break;
-                default:
-                    txt="UNKNOWN RETURN CODE";
-                };
-                LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
-                       UE->Mod_id, proc->frame_rx, proc->subframe_tx,txt );
-            }
-        }
+    if (UE->mac_enabled==1) {
+
+      ret = ue_scheduler(UE->Mod_id,
+			 proc->frame_rx,
+			 proc->subframe_rx,
+			 proc->frame_tx,
+			 proc->subframe_tx,
+			 subframe_select(&UE->frame_parms,proc->subframe_tx),
+			 0,
+			 0/*FIXME CC_id*/);
+      if ( ret != CONNECTION_OK) {
+	char *txt;
+	switch (ret) {
+	case CONNECTION_LOST:
+	  txt="RRC Connection lost, returning to PRACH";
+	  break;
+	case PHY_RESYNCH:
+	  txt="RRC Connection lost, trying to resynch";
+	  break;
+	case RESYNCH:
+	  txt="return to PRACH and perform a contention-free access";
+	  break;
+	default:
+	  txt="UNKNOWN RETURN CODE";
+	};
+	LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
+	       UE->Mod_id, proc->frame_rx, proc->subframe_tx,txt );
+      }
+    }
 #if UE_TIMING_TRACE
-        stop_meas(&UE->generic_stat);
+    stop_meas(&UE->generic_stat);
 #endif
 
 
-        // Prepare the future Tx data
+    // Prepare the future Tx data
+
+    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
+	(UE->frame_parms.frame_type == FDD) )
+      if (UE->mode != loop_through_memory)
+	phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
+
+
+
+    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
+	(UE->frame_parms.frame_type == TDD))
+      if (UE->mode != loop_through_memory)
+	phy_procedures_UE_S_TX(UE,0,0,no_relay);
+    updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");
 
-        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
-	    (UE->frame_parms.frame_type == FDD) )
-            if (UE->mode != loop_through_memory)
-                phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
+    if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
+      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
+      exit_fun("noting to add");
+    }
+    proc->instance_cnt_rxtx--;
+    if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
+      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
+      exit_fun("noting to add");
+    }
+  }
+
+  // thread finished
+  free(arg);
+  return &UE_thread_rxtx_retval;
+}
+
+
+
+unsigned int emulator_absSF;
+
+void ue_stub_rx_handler(unsigned int num_bytes, char *rx_buffer) {
+
+  PHY_VARS_UE *UE;
+  UE = PHY_vars_UE_g[0][0];
+
+  UE_tport_t *pdu = (UE_tport_t*)rx_buffer;
+  SLSCH_t *slsch = (SLSCH_t*)&pdu->slsch;
+  SLDCH_t *sldch = (SLDCH_t*)&pdu->sldch;
+
+  switch (((UE_tport_header_t*)rx_buffer)->packet_type) {
+  case TTI_SYNC:
+    emulator_absSF = ((UE_tport_header_t*)rx_buffer)->absSF;
+    wakeup_thread(&UE->timer_mutex,&UE->timer_cond,&UE->instance_cnt_timer,"timer_thread");
+    break;
+  case SLSCH:
+
+
+    LOG_I(PHY,"Emulator SFN.SF %d.%d, Got SLSCH packet\n",emulator_absSF/10,emulator_absSF%10);
+    LOG_I(PHY,"Received %d bytes on UE-UE link for SFN.SF %d.%d, sending SLSCH payload (%d bytes) to MAC\n",num_bytes,
+	  pdu->header.absSF/10,pdu->header.absSF%10,
+	  slsch->payload_length);
+    printf("SLSCH:");
+    for (int i=0;i<sizeof(SLSCH_t);i++) printf("%x ",((uint8_t*)slsch)[i]);
+    printf("\n");
+
+    ue_send_sl_sdu(0,
+		   0,
+		   pdu->header.absSF/10,
+		   pdu->header.absSF%10,
+		   pdu->payload,
+		   slsch->payload_length,
+		   0,
+		   SL_DISCOVERY_FLAG_NO);
+    break;
+
+  case SLDCH:
+
+
+    LOG_I(PHY,"Emulator SFN.SF %d.%d, Got SLDCH packet\n",emulator_absSF/10,emulator_absSF%10);
+    LOG_I(PHY,"Received %d bytes on UE-UE link for SFN.SF %d.%d, sending SLDCH payload (%d bytes) to MAC\n",num_bytes,
+          pdu->header.absSF/10,pdu->header.absSF%10,
+          sldch->payload_length);
+    printf("SLDCH:");
+    for (int i=0;i<sizeof(SLDCH_t);i++) printf("%x ",((uint8_t*)sldch)[i]);
+    printf("\n");
+
+    ue_send_sl_sdu(0,
+                   0,
+                   pdu->header.absSF/10,
+                   pdu->header.absSF%10,
+                   sldch->payload,
+                   sldch->payload_length,
+                   0,
+                   SL_DISCOVERY_FLAG_YES);
+    break;
+
+  }
+}
+
+
+/*!
+ * \brief This is the UE thread for RX subframe n and TX subframe n+4.
+ * This thread performs the phy_procedures_UE_RX() on every received slot.
+ * then, if TX is enabled it performs TX for n+4.
+ * \param arg is a pointer to a \ref PHY_VARS_UE structure.
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+
+static void *UE_phy_stub_single_thread_rxn_txnp4(void *arg) {
+
+	thread_top_init("UE_phy_stub_thread_rxn_txnp4",1,870000L,1000000L,1000000L);
+
+	module_id_t Mod_id = 0;
+	//int init_ra_UE = -1; // This counter is used to initiate the RA of each UE in different SFrames
+  static __thread int UE_thread_rxtx_retval;
+  struct rx_tx_thread_data *rtd = arg;
+  UE_rxtx_proc_t *proc = rtd->proc;
+
+  // Initializations for nfapi-L2-emulator mode
+  dl_config_req = NULL;
+  ul_config_req = NULL;
+  hi_dci0_req	= NULL;
+  tx_request_pdu_list = NULL;
+
+  PHY_VARS_UE    *UE;   //= rtd->UE;
+  int ret;
+  //  double t_diff;
+
+  char threadname[256];
+  //sprintf(threadname,"UE_%d_proc", UE->Mod_id);
+
+  //proc->instance_cnt_rxtx=-1;
+
+  phy_stub_ticking->ticking_var = -1;
+  proc->subframe_rx=proc->sub_frame_start;
+
+
+  //PANOS: CAREFUL HERE!
+  wait_sync("UE_phy_stub_single_thread_rxn_txnp4");
+
+  while (!oai_exit) {
+
+    if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
+      LOG_E( MAC, "[SCHED][UE] error locking mutex for UE RXTX\n" );
+      exit_fun("nothing to add");
+    }
+    while (phy_stub_ticking->ticking_var < 0) {
+      // most of the time, the thread is waiting here
+      //pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx )
+      LOG_D(MAC,"Waiting for ticking_var\n");
+      pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
+    }
+    phy_stub_ticking->ticking_var--;
+    if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
+      LOG_E( MAC, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
+      exit_fun("nothing to add");
+    }
+    LOG_D(MAC," Panos-D [UE_phy_stub_thread_rxn_txnp4 1] Frame: %d, Subframe: %d \n" "\n" "\n", timer_frame, timer_subframe);
+
+
+    proc->subframe_rx=timer_subframe;
+    proc->frame_rx = timer_frame;
+    proc->subframe_tx=(timer_subframe+4)%10;
+    proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
+    //oai_subframe_ind(proc->frame_rx, proc->subframe_rx);
+
+
+    oai_subframe_ind(timer_frame, timer_subframe);
+
+    // Panos: Guessing that the next 4 lines are not needed for the phy_stub mode.
+    /*initRefTimes(t2);
+      initRefTimes(t3);
+      pickTime(current);
+      updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");*/
+
+
+    	//Panos: Not sure whether we should put the memory allocation here and not sure how much memory
+        //we should allocate for each subframe cycle.
+    	UL_INFO = (UL_IND_t*)malloc(sizeof(UL_IND_t));
+
+    	UL_INFO->rx_ind.rx_indication_body.rx_pdu_list = (nfapi_rx_indication_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_rx_indication_pdu_t));
+    	UL_INFO->rx_ind.rx_indication_body.number_of_pdus = 0;
+
+
+    	UL_INFO->crc_ind.crc_indication_body.crc_pdu_list = (nfapi_crc_indication_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_crc_indication_pdu_t));
+    	UL_INFO->crc_ind.crc_indication_body.number_of_crcs = 0;
+
+    	UL_INFO->harq_ind.harq_indication_body.harq_pdu_list = (nfapi_harq_indication_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_harq_indication_pdu_t));
+    	UL_INFO->harq_ind.harq_indication_body.number_of_harqs = 0;
+
+    	UL_INFO->sr_ind.sr_indication_body.sr_pdu_list = (nfapi_sr_indication_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_sr_indication_pdu_t));
+    	UL_INFO->sr_ind.sr_indication_body.number_of_srs = 0;
+
+
+
+
+    for (Mod_id=0; Mod_id<NB_UE_INST; Mod_id++) {
+    	//LOG_D(MAC, "UE_phy_stub_single_thread_rxn_txnp4, NB_UE_INST:%d, Mod_id:%d \n", NB_UE_INST, Mod_id);
+    	UE = PHY_vars_UE_g[Mod_id][0];
+    lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);
+    if ((sf_type == SF_DL) ||
+	(UE->frame_parms.frame_type == FDD) ||
+	(sf_type == SF_S)) {
+
+      if (UE->frame_parms.frame_type == TDD) {
+	LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
+	      threadname,
+	      UE->frame_parms.tdd_config,
+	      (sf_type==SF_DL? "SF_DL" :
+	       (sf_type==SF_UL? "SF_UL" :
+		(sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
+      } else {
+	LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
+	      threadname,
+	      (UE->frame_parms.frame_type==FDD? "FDD":
+	       (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
+	      (sf_type==SF_DL? "SF_DL" :
+	       (sf_type==SF_UL? "SF_UL" :
+		(sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
+      }
+
+
+      phy_procedures_UE_SL_RX(UE,proc);
+
+      if (dl_config_req!=NULL && tx_request_pdu_list!=NULL){
+    	  //if(dl_config_req!= NULL) {
+    	  dl_config_req_UE_MAC(dl_config_req, Mod_id);
 
+      }
+
+      if (hi_dci0_req!=NULL && hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
+    	  hi_dci0_req_UE_MAC(hi_dci0_req, Mod_id);
+      }
+
+      if(nfapi_mode!=3)
+      phy_procedures_UE_SL_TX(UE,proc);
 
+    }
 
-        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
-                (UE->frame_parms.frame_type == TDD))
-            if (UE->mode != loop_through_memory)
-                phy_procedures_UE_S_TX(UE,0,0,no_relay);
-        updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");
+#if UE_TIMING_TRACE
+    start_meas(&UE->generic_stat);
+#endif
 
-        if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
-          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
-          exit_fun("noting to add");
-        }
-        proc->instance_cnt_rxtx--;
-        if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
-          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
-          exit_fun("noting to add");
-        }
+    if (UE->mac_enabled==1) {
+
+      ret = ue_scheduler(UE->Mod_id,
+			 proc->frame_rx,
+			 proc->subframe_rx,
+			 proc->frame_tx,
+			 proc->subframe_tx,
+			 subframe_select(&UE->frame_parms,proc->subframe_tx),
+			 0,
+			 0/*FIXME CC_id*/);
+      if ( ret != CONNECTION_OK) {
+	char *txt;
+	switch (ret) {
+	case CONNECTION_LOST:
+	  txt="RRC Connection lost, returning to PRACH";
+	  break;
+	case PHY_RESYNCH:
+	  txt="RRC Connection lost, trying to resynch";
+	  break;
+	case RESYNCH:
+	  txt="return to PRACH and perform a contention-free access";
+	  break;
+	default:
+	  txt="UNKNOWN RETURN CODE";
+	};
+	LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
+	       UE->Mod_id, proc->frame_rx, proc->subframe_tx,txt );
+      }
     }
+#if UE_TIMING_TRACE
+    stop_meas(&UE->generic_stat);
+#endif
+
+
+    // Prepare the future Tx data
+
+    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
+	(UE->frame_parms.frame_type == FDD) )
+      if (UE->mode != loop_through_memory){
+
+    // We make the start of RA between consecutive UEs differ by 20 frames
+	//if ((UE_mac_inst[Mod_id].UE_mode[0] == PRACH  && Mod_id == 0) || (UE_mac_inst[Mod_id].UE_mode[0] == PRACH && Mod_id>0 && proc->frame_rx >= UE_mac_inst[Mod_id-1].ra_frame + 20) ) {
+	if (UE_mac_inst[Mod_id].UE_mode[0] == PRACH  && Mod_id == next_Mod_id && proc->frame_rx >= next_ra_frame) {
+
+	  // check if we have PRACH opportunity
 
-// thread finished
-    free(arg);
-    return &UE_thread_rxtx_retval;
+	  if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx) &&  UE_mac_inst[Mod_id].SI_Decoded == 1) {
+
+	  // The one working strangely...
+      //if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx && Mod_id == (module_id_t) init_ra_UE) ) {
+
+	    PRACH_RESOURCES_t *prach_resources = ue_get_rach(Mod_id, 0, proc->frame_tx, 0, proc->subframe_tx);
+	    if(prach_resources!=NULL ) {
+	    	UE_mac_inst[Mod_id].ra_frame = proc->frame_rx;
+	      LOG_D(MAC, "UE_phy_stub_thread_rxn_txnp4 before RACH, Mod_id: %d \n", Mod_id );
+	      fill_rach_indication_UE_MAC(Mod_id, proc->frame_tx ,proc->subframe_tx, UL_INFO, prach_resources->ra_PreambleIndex, prach_resources->ra_RNTI);
+	      Msg1_transmitted(Mod_id, 0, proc->frame_tx, 0);
+	      UE_mac_inst[Mod_id].UE_mode[0] = RA_RESPONSE;
+	      next_Mod_id = Mod_id + 1;
+	      next_ra_frame = (proc->frame_rx + 20)%1000;
+	    }
+
+	    //ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode);
+	  }
+	} // mode is PRACH
+	// Panos: Substitute call to phy_procedures Tx with call to phy_stub functions in order to trigger
+	// UE Tx procedures directly at the MAC layer, based on the received ul_config requests from the vnf (eNB).
+	// Generate UL_indications which correspond to UL traffic.
+	if(ul_config_req!=NULL){ //&& UE_mac_inst[Mod_id].ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
+		ul_config_req_UE_MAC(ul_config_req, timer_frame, timer_subframe, Mod_id);
+	}
+      }
+
+    phy_procedures_UE_SL_RX(UE,proc);
+
+
+    } //for (Mod_id=0; Mod_id<NB_UE_INST; Mod_id++)
+
+
+    if (UL_INFO->crc_ind.crc_indication_body.number_of_crcs>0)
+      {
+    	  //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf));
+    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.2, SFN/SF of PNF counter:%d.%d, number_of_crcs: %d \n", timer_frame, timer_subframe, UL_INFO->crc_ind.crc_indication_body.number_of_crcs);
+    	  oai_nfapi_crc_indication(&UL_INFO->crc_ind);
+    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.21 \n");
+    	  UL_INFO->crc_ind.crc_indication_body.number_of_crcs = 0;
+      }
+      if (UL_INFO->rx_ind.rx_indication_body.number_of_pdus>0)
+      {
+    	  //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf));
+    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.3, SFN/SF of PNF counter:%d.%d, number_of_pdus: %d \n", timer_frame, timer_subframe, UL_INFO->rx_ind.rx_indication_body.number_of_pdus);
+    	  oai_nfapi_rx_ind(&UL_INFO->rx_ind);
+    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.31 \n");
+    	  UL_INFO->rx_ind.rx_indication_body.number_of_pdus = 0;
+      }
+      if(UL_INFO->harq_ind.harq_indication_body.number_of_harqs>0)
+      {
+    	  //LOG_D(MAC, "ul_config_req_UE_MAC 2.4, SFN/SF of PNF counter:%d.%d, number_of_harqs: %d \n", timer_frame, timer_subframe, UL_INFO->harq_ind.harq_indication_body.number_of_harqs);
+    	  oai_nfapi_harq_indication(&UL_INFO->harq_ind);
+    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.41 \n");
+    	  UL_INFO->harq_ind.harq_indication_body.number_of_harqs =0;
+
+      }
+      if(UL_INFO->sr_ind.sr_indication_body.number_of_srs>0)
+      {
+    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.5, SFN/SF of PNF counter:%d.%d, number_of_srs: %d \n", timer_frame, timer_subframe, UL_INFO->sr_ind.sr_indication_body.number_of_srs);
+    	  oai_nfapi_sr_indication(&UL_INFO->sr_ind);
+    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.51 \n");
+    	  UL_INFO->sr_ind.sr_indication_body.number_of_srs = 0;
+      }
+
+      // Free UL_INFO messages
+      //if(UL_INFO->crc_ind.crc_indication_body.crc_pdu_list != NULL){
+    	  free(UL_INFO->crc_ind.crc_indication_body.crc_pdu_list);
+    	  UL_INFO->crc_ind.crc_indication_body.crc_pdu_list = NULL;
+      //}
+      //if(UL_INFO->rx_ind.rx_indication_body.rx_pdu_list != NULL){
+    	  free(UL_INFO->rx_ind.rx_indication_body.rx_pdu_list);
+    	  UL_INFO->rx_ind.rx_indication_body.rx_pdu_list = NULL;
+      //}
+      //if(UL_INFO->harq_ind.harq_indication_body.harq_pdu_list !=NULL){
+    	  free(UL_INFO->harq_ind.harq_indication_body.harq_pdu_list);
+    	  UL_INFO->harq_ind.harq_indication_body.harq_pdu_list = NULL;
+      //}
+      //if(UL_INFO->sr_ind.sr_indication_body.sr_pdu_list!=NULL){
+    	  free(UL_INFO->sr_ind.sr_indication_body.sr_pdu_list);
+    	  UL_INFO->sr_ind.sr_indication_body.sr_pdu_list = NULL;
+      //}
+
+      free(UL_INFO);
+      UL_INFO = NULL;
+
+      // De-allocate memory of nfapi requests copies before next subframe round
+      if(dl_config_req!=NULL){
+    	  if(dl_config_req->vendor_extension)
+    		  free(dl_config_req->vendor_extension);
+    	  if(dl_config_req->dl_config_request_body.dl_config_pdu_list!=NULL){
+    		  free(dl_config_req->dl_config_request_body.dl_config_pdu_list);
+    		  dl_config_req->dl_config_request_body.dl_config_pdu_list = NULL;
+    	  }
+    	  free(dl_config_req);
+    	  dl_config_req = NULL;
+      }
+      if(tx_request_pdu_list!=NULL){
+    	  free(tx_request_pdu_list);
+    	  tx_request_pdu_list = NULL;
+      }
+      if(ul_config_req!=NULL){
+    	  if(ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
+    		  free(ul_config_req->ul_config_request_body.ul_config_pdu_list);
+    		  ul_config_req->ul_config_request_body.ul_config_pdu_list = NULL;
+    	  }
+    	  free(ul_config_req);
+    	  ul_config_req = NULL;
+      }
+
+      if(hi_dci0_req!=NULL){
+    	  if(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
+    		  free(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list);
+    		  hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list = NULL;
+    	  }
+    	  free(hi_dci0_req);
+    	  hi_dci0_req = NULL;
+      }
+
+
+
+  }
+  // thread finished
+  free(arg);
+  return &UE_thread_rxtx_retval;
 }
 
+
+
+
+/*!
+ * \brief This is the UE thread for RX subframe n and TX subframe n+4.
+ * This thread performs the phy_procedures_UE_RX() on every received slot.
+ * then, if TX is enabled it performs TX for n+4.
+ * \param arg is a pointer to a \ref PHY_VARS_UE structure.
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+
+static void *UE_phy_stub_thread_rxn_txnp4(void *arg) {
+
+	thread_top_init("UE_phy_stub_thread_rxn_txnp4",1,870000L,1000000L,1000000L);
+
+	module_id_t Mod_id = 0;
+  static __thread int UE_thread_rxtx_retval;
+  struct rx_tx_thread_data *rtd = arg;
+  UE_rxtx_proc_t *proc = rtd->proc;
+  PHY_VARS_UE    *UE   = rtd->UE;
+  int ret;
+  //  double t_diff;
+
+  char threadname[256];
+  sprintf(threadname,"UE_%d_proc", UE->Mod_id);
+
+
+  //proc->instance_cnt_rxtx=-1;
+
+  phy_stub_ticking->ticking_var = -1;
+  proc->subframe_rx=proc->sub_frame_start;
+
+  //PANOS: CAREFUL HERE!
+  wait_sync("UE_phy_stub_thread_rxn_txnp4");
+
+  while (!oai_exit) {
+
+    if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
+      LOG_E( MAC, "[SCHED][UE] error locking mutex for UE RXTX\n" );
+      exit_fun("nothing to add");
+    }
+    while (phy_stub_ticking->ticking_var < 0) {
+      // most of the time, the thread is waiting here
+      //pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx )
+      LOG_D(MAC,"Waiting for ticking_var\n");
+      pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
+    }
+    phy_stub_ticking->ticking_var--;
+    if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
+      LOG_E( MAC, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
+      exit_fun("nothing to add");
+    }
+    LOG_D(MAC," Panos-D [UE_phy_stub_thread_rxn_txnp4 1] Frame: %d, Subframe: %d \n" "\n" "\n", timer_frame, timer_subframe);
+
+
+    proc->subframe_rx=timer_subframe;
+    proc->frame_rx = timer_frame;
+    proc->subframe_tx=(timer_subframe+4)%10;
+    proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
+
+
+    // Process Rx data for one sub-frame
+    lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);
+    if ((sf_type == SF_DL) ||
+	(UE->frame_parms.frame_type == FDD) ||
+	(sf_type == SF_S)) {
+
+      if (UE->frame_parms.frame_type == TDD) {
+	LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
+	      threadname,
+	      UE->frame_parms.tdd_config,
+	      (sf_type==SF_DL? "SF_DL" :
+	       (sf_type==SF_UL? "SF_UL" :
+		(sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
+      } else {
+	LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
+	      threadname,
+	      (UE->frame_parms.frame_type==FDD? "FDD":
+	       (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
+	      (sf_type==SF_DL? "SF_DL" :
+	       (sf_type==SF_UL? "SF_UL" :
+		(sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
+      }
+
+
+      phy_procedures_UE_SL_RX(UE,proc);
+
+       oai_subframe_ind(timer_frame, timer_subframe);
+
+      if(dl_config_req!= NULL) {
+
+	dl_config_req_UE_MAC(dl_config_req, Mod_id);
+
+      }
+      //if(UE_mac_inst[Mod_id].hi_dci0_req!= NULL){
+      if (hi_dci0_req!=NULL && hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
+    	  LOG_I( MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind 4 \n");
+    	  hi_dci0_req_UE_MAC(hi_dci0_req, Mod_id);
+    	  //if(UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
+    		  free(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list);
+    		  hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list = NULL;
+    	  //}
+    	  free(hi_dci0_req);
+    	  hi_dci0_req = NULL;
+      }
+
+      else if(hi_dci0_req!=NULL){
+      		free(hi_dci0_req);
+      		hi_dci0_req = NULL;
+      	}
+
+      if (nfapi_mode != 3)
+        phy_procedures_UE_SL_TX(UE,proc);
+
+    }
+
+#if UE_TIMING_TRACE
+    start_meas(&UE->generic_stat);
+#endif
+    if (UE->mac_enabled==1) {
+
+      ret = ue_scheduler(UE->Mod_id,
+			 proc->frame_rx,
+			 proc->subframe_rx,
+			 proc->frame_tx,
+			 proc->subframe_tx,
+			 subframe_select(&UE->frame_parms,proc->subframe_tx),
+			 0,
+			 0);
+      if ( ret != CONNECTION_OK) {
+	char *txt;
+	switch (ret) {
+	case CONNECTION_LOST:
+	  txt="RRC Connection lost, returning to PRACH";
+	  break;
+	case PHY_RESYNCH:
+	  txt="RRC Connection lost, trying to resynch";
+	  break;
+	case RESYNCH:
+	  txt="return to PRACH and perform a contention-free access";
+	  break;
+	default:
+	  txt="UNKNOWN RETURN CODE";
+	};
+	LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
+	       UE->Mod_id, proc->frame_rx, proc->subframe_tx,txt );
+      }
+    }
+#if UE_TIMING_TRACE
+    stop_meas(&UE->generic_stat);
+#endif
+
+
+    // Prepare the future Tx data
+
+    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
+	(UE->frame_parms.frame_type == FDD) )
+      if (UE->mode != loop_through_memory){
+
+	if ((UE_mac_inst[Mod_id].UE_mode[0] == PRACH) ) {
+	  //LOG_D(MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 before RACH \n");
+
+	  // check if we have PRACH opportunity
+
+	  if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx)) {
+	    PRACH_RESOURCES_t *prach_resources = ue_get_rach(Mod_id, 0, proc->frame_tx, 0, proc->subframe_tx);
+	    if(prach_resources!=NULL) {
+	      fill_rach_indication_UE_MAC(Mod_id, proc->frame_tx ,proc->subframe_tx, UL_INFO, prach_resources->ra_PreambleIndex, prach_resources->ra_RNTI);
+	      Msg1_transmitted(Mod_id, 0, proc->frame_tx, 0);
+	      UE_mac_inst[Mod_id].UE_mode[0] = RA_RESPONSE;
+	    }
+
+	    //ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode);
+	  }
+	} // mode is PRACH
+	// Panos: Substitute call to phy_procedures Tx with call to phy_stub functions in order to trigger
+	// UE Tx procedures directly at the MAC layer, based on the received ul_config requests from the vnf (eNB).
+	// Generate UL_indications which correspond to UL traffic.
+	if(ul_config_req!= NULL && ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
+		//LOG_I(MAC, "UE_phy_stub_thread_rxn_txnp4 ul_config_req is not NULL \n");
+		ul_config_req_UE_MAC(ul_config_req, timer_frame, timer_subframe, Mod_id);
+		if(ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
+			free(ul_config_req->ul_config_request_body.ul_config_pdu_list);
+			ul_config_req->ul_config_request_body.ul_config_pdu_list = NULL;
+		}
+		free(ul_config_req);
+		ul_config_req = NULL;
+	}
+	else if(ul_config_req!=NULL){
+		free(ul_config_req);
+		ul_config_req = NULL;
+	}
+      }
+
+    phy_procedures_UE_SL_RX(UE,proc);
+
+  }
+  // thread finished
+  free(arg);
+  return &UE_thread_rxtx_retval;
+}
+
+
+
 /*!
  * \brief This is the main UE thread.
  * This thread controls the other three UE threads:
@@ -716,81 +1403,81 @@ static void *UE_thread_rxn_txnp4(void *arg) {
 void *UE_thread(void *arg) {
 
 
-    PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
-    //  int tx_enabled = 0;
-    int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32)));
-    openair0_timestamp timestamp,timestamp1;
-    void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
-    int start_rx_stream = 0;
-    int i;
-    int th_id;
+  PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
+  //  int tx_enabled = 0;
+  int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32)));
+  openair0_timestamp timestamp,timestamp1;
+  void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
+  int start_rx_stream = 0;
+  int i;
+  int th_id;
 
-    static uint8_t thread_idx = 0;
+  static uint8_t thread_idx = 0;
 
-    cpu_set_t cpuset;
-    CPU_ZERO(&cpuset);
-    if ( threads.iq != -1 )
-        CPU_SET(threads.iq, &cpuset);
-    init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,
-                "UHD Threads");
+  cpu_set_t cpuset;
+  CPU_ZERO(&cpuset);
+  if ( threads.iq != -1 )
+    CPU_SET(threads.iq, &cpuset);
+  init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,
+	      "UHD Threads");
 
 #ifdef NAS_UE
-    MessageDef *message_p;
-    message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
-    itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
+  MessageDef *message_p;
+  message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
+  itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
 #endif
 
-    int sub_frame=-1;
-    //int cumulated_shift=0;
+  int sub_frame=-1;
+  //int cumulated_shift=0;
 
-    
-    while (!oai_exit) {
-        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
-        int instance_cnt_synch = UE->proc.instance_cnt_synch;
-        int is_synchronized    = UE->is_synchronized;
-        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
 
-        if (is_synchronized == 0) {
-            if (instance_cnt_synch < 0) {  // we can invoke the synch
-                // grab 10 ms of signal and wakeup synch thread
-                for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
-                    rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
+  while (!oai_exit) {
+    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+    int instance_cnt_synch = UE->proc.instance_cnt_synch;
+    int is_synchronized    = UE->is_synchronized;
+    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
 
-                if (UE->mode != loop_through_memory)
-                    AssertFatal( UE->frame_parms.samples_per_tti*10 ==
-                                 UE->rfdevice.trx_read_func(&UE->rfdevice,
-                                                            &timestamp,
-                                                            rxp,
-                                                            UE->frame_parms.samples_per_tti*10,
-                                                            UE->frame_parms.nb_antennas_rx), "");
-		AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
-                instance_cnt_synch = ++UE->proc.instance_cnt_synch;
-                if (instance_cnt_synch == 0) {
-                    AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
-                } else {
-                    LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
-                    exit_fun("nothing to add");
-                }
-		AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
-            } else {
+    if (is_synchronized == 0) {
+      if (instance_cnt_synch < 0) {  // we can invoke the synch
+	// grab 10 ms of signal and wakeup synch thread
+	for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
+	  rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
+
+	if (UE->mode != loop_through_memory)
+	  AssertFatal( UE->frame_parms.samples_per_tti*10 ==
+		       UE->rfdevice.trx_read_func(&UE->rfdevice,
+						  &timestamp,
+						  rxp,
+						  UE->frame_parms.samples_per_tti*10,
+						  UE->frame_parms.nb_antennas_rx), "");
+	AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+	instance_cnt_synch = ++UE->proc.instance_cnt_synch;
+	if (instance_cnt_synch == 0) {
+	  AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
+	} else {
+	  LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
+	  exit_fun("nothing to add");
+	}
+	AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+      } else {
 #if OAISIM
-              (void)dummy_rx; /* avoid gcc warnings */
-              usleep(500);
+	(void)dummy_rx; /* avoid gcc warnings */
+	usleep(500);
 #else
-                // grab 10 ms of signal into dummy buffer
-                if (UE->mode != loop_through_memory) {
-                    for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
-                        rxp[i] = (void*)&dummy_rx[i][0];
-                    for (int sf=0; sf<10; sf++)
-                        //	    printf("Reading dummy sf %d\n",sf);
-                          UE->rfdevice.trx_read_func(&UE->rfdevice,
-                                              &timestamp,
-                                              rxp,
-                                              UE->frame_parms.samples_per_tti,
-                                              UE->frame_parms.nb_antennas_rx);
-                }
+	// grab 10 ms of signal into dummy buffer
+	if (UE->mode != loop_through_memory) {
+	  for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
+	    rxp[i] = (void*)&dummy_rx[i][0];
+	  for (int sf=0; sf<10; sf++)
+	    //	    printf("Reading dummy sf %d\n",sf);
+	    UE->rfdevice.trx_read_func(&UE->rfdevice,
+				       &timestamp,
+				       rxp,
+				       UE->frame_parms.samples_per_tti,
+				       UE->frame_parms.nb_antennas_rx);
+	}
 #endif
-            }
+	}
 
         } // UE->is_synchronized==0
         else {
@@ -959,6 +1646,7 @@ void *UE_thread(void *arg) {
     return NULL;
 }
 
+
 /*!
  * \brief Initialize the UE theads.
  * Creates the UE threads:
@@ -972,117 +1660,677 @@ void *UE_thread(void *arg) {
  * and the locking between them.
  */
 void init_UE_threads(int inst) {
-    struct rx_tx_thread_data *rtd;
-    PHY_VARS_UE *UE;
+  struct rx_tx_thread_data *rtd;
+  PHY_VARS_UE *UE;
 
-    AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
-    AssertFatal(PHY_vars_UE_g[inst]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
-    AssertFatal(PHY_vars_UE_g[inst][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");
-    UE = PHY_vars_UE_g[inst][0];
+  AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
+  AssertFatal(PHY_vars_UE_g[inst]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
+  AssertFatal(PHY_vars_UE_g[inst][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");
+  UE = PHY_vars_UE_g[inst][0];
 
-    pthread_attr_init (&UE->proc.attr_ue);
-    pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
+  pthread_attr_init (&UE->proc.attr_ue);
+  pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
 
-    pthread_mutex_init(&UE->proc.mutex_synch,NULL);
-    pthread_cond_init(&UE->proc.cond_synch,NULL);
+  pthread_mutex_init(&UE->proc.mutex_synch,NULL);
+  pthread_cond_init(&UE->proc.cond_synch,NULL);
 
-    // the threads are not yet active, therefore access is allowed without locking
-    int nb_threads=RX_NB_TH;
-    for (int i=0; i<nb_threads; i++) {
-        rtd = calloc(1, sizeof(struct rx_tx_thread_data));
-        if (rtd == NULL) abort();
-        rtd->UE = UE;
-        rtd->proc = &UE->proc.proc_rxtx[i];
+  // the threads are not yet active, therefore access is allowed without locking
+  int nb_threads=RX_NB_TH;
+  for (int i=0; i<nb_threads; i++) {
+    rtd = calloc(1, sizeof(struct rx_tx_thread_data));
+    if (rtd == NULL) abort();
+    rtd->UE = UE;
+    rtd->proc = &UE->proc.proc_rxtx[i];
 
-        pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
-        pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
-        UE->proc.proc_rxtx[i].sub_frame_start=i;
-        UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
-        printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
-        pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd);
+    pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
+    pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
+    UE->proc.proc_rxtx[i].sub_frame_start=i;
+    UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
+    printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
+    pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd);
 
 #ifdef UE_SLOT_PARALLELISATION
-        //pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot0_dl_processing,NULL);
-        //pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot0_dl_processing,NULL);
-        //pthread_create(&UE->proc.proc_rxtx[i].pthread_slot0_dl_processing,NULL,UE_thread_slot0_dl_processing, rtd);
+    //pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot0_dl_processing,NULL);
+    //pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot0_dl_processing,NULL);
+    //pthread_create(&UE->proc.proc_rxtx[i].pthread_slot0_dl_processing,NULL,UE_thread_slot0_dl_processing, rtd);
 
-        pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot1_dl_processing,NULL);
-        pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot1_dl_processing,NULL);
-        pthread_create(&UE->proc.proc_rxtx[i].pthread_slot1_dl_processing,NULL,UE_thread_slot1_dl_processing, rtd);
+    pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot1_dl_processing,NULL);
+    pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot1_dl_processing,NULL);
+    pthread_create(&UE->proc.proc_rxtx[i].pthread_slot1_dl_processing,NULL,UE_thread_slot1_dl_processing, rtd);
 #endif
 
-    }
-    pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
+  }
+  pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
 }
 
 
+
+/*!
+ * \brief Initialize the UE theads.
+ * Creates the UE threads:
+ * - UE_thread_rxtx0
+ * - UE_thread_synch
+ * - UE_thread_fep_slot0
+ * - UE_thread_fep_slot1
+ * - UE_thread_dlsch_proc_slot0
+ * - UE_thread_dlsch_proc_slot1
+ * and the locking between them.
+ */
+void init_UE_single_thread_stub(int nb_inst) {
+  struct rx_tx_thread_data *rtd;
+  PHY_VARS_UE *UE;
+
+  for (int i=0; i<nb_inst; i++){
+	  AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
+	  AssertFatal(PHY_vars_UE_g[i]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
+	  AssertFatal(PHY_vars_UE_g[i][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");
+  }
+  UE = PHY_vars_UE_g[0][0];
+
+  pthread_attr_init (&UE->proc.attr_ue);
+  pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
+
+  // Panos: Don't need synch for phy_stub mode
+  //pthread_mutex_init(&UE->proc.mutex_synch,NULL);
+  //pthread_cond_init(&UE->proc.cond_synch,NULL);
+
+  // the threads are not yet active, therefore access is allowed without locking
+  // Panos: In phy_stub_UE mode due to less heavy processing operations we don't need two threads
+  //int nb_threads=RX_NB_TH;
+  int nb_threads=1;
+  for (int i=0; i<nb_threads; i++) {
+    rtd = calloc(1, sizeof(struct rx_tx_thread_data));
+    if (rtd == NULL) abort();
+    rtd->UE = UE;
+    rtd->proc = &UE->proc.proc_rxtx[i];
+
+    pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
+    pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
+    UE->proc.proc_rxtx[i].sub_frame_start=i;
+    UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
+    printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
+    pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_phy_stub_single_thread_rxn_txnp4, rtd);
+
+  }
+  // Panos: Remove thread for UE_sync in phy_stub_UE mode.
+  //pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
+}
+
+
+
+
+/*!
+ * \brief Initialize the UE theads.
+ * Creates the UE threads:
+ * - UE_thread_rxtx0
+ * - UE_thread_synch
+ * - UE_thread_fep_slot0
+ * - UE_thread_fep_slot1
+ * - UE_thread_dlsch_proc_slot0
+ * - UE_thread_dlsch_proc_slot1
+ * and the locking between them.
+ */
+void init_UE_threads_stub(int inst) {
+  struct rx_tx_thread_data *rtd;
+  PHY_VARS_UE *UE;
+
+  AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
+  AssertFatal(PHY_vars_UE_g[inst]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
+  AssertFatal(PHY_vars_UE_g[inst][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");
+  UE = PHY_vars_UE_g[inst][0];
+
+  pthread_attr_init (&UE->proc.attr_ue);
+  pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
+
+  // Panos: Don't need synch for phy_stub mode
+  //pthread_mutex_init(&UE->proc.mutex_synch,NULL);
+  //pthread_cond_init(&UE->proc.cond_synch,NULL);
+
+  // the threads are not yet active, therefore access is allowed without locking
+  // Panos: In phy_stub_UE mode due to less heavy processing operations we don't need two threads
+  //int nb_threads=RX_NB_TH;
+  int nb_threads=1;
+  for (int i=0; i<nb_threads; i++) {
+    rtd = calloc(1, sizeof(struct rx_tx_thread_data));
+    if (rtd == NULL) abort();
+    rtd->UE = UE;
+    rtd->proc = &UE->proc.proc_rxtx[i];
+
+    pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
+    pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
+    UE->proc.proc_rxtx[i].sub_frame_start=i;
+    UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
+    printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
+    pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_phy_stub_thread_rxn_txnp4, rtd);
+
+
+  }
+  // Panos: Remove thread for UE_sync in phy_stub_UE mode.
+  //pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
+}
+
+
+
+
 #ifdef OPENAIR2
 void fill_ue_band_info(void) {
 
-    UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability;
-    int i,j;
-
-    bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;
-
-    for (i=0; i<bands_to_scan.nbands; i++) {
-
-        for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++)
-            if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
-                memcpy(&bands_to_scan.band_info[i],
-                       &eutra_bands[j],
-                       sizeof(eutra_band_t));
-
-                printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n",
-                       bands_to_scan.band_info[i].band,
-                       UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA,
-                       bands_to_scan.band_info[i].dl_min,
-                       bands_to_scan.band_info[i].dl_max,
-                       bands_to_scan.band_info[i].ul_min,
-                       bands_to_scan.band_info[i].ul_max,
-                       (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD");
-                break;
-            }
-    }
+  UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability;
+  int i,j;
+
+  bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;
+
+  for (i=0; i<bands_to_scan.nbands; i++) {
+
+    for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++)
+      if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
+	memcpy(&bands_to_scan.band_info[i],
+	       &eutra_bands[j],
+	       sizeof(eutra_band_t));
+
+	printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n",
+	       bands_to_scan.band_info[i].band,
+	       UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA,
+	       bands_to_scan.band_info[i].dl_min,
+	       bands_to_scan.band_info[i].dl_max,
+	       bands_to_scan.band_info[i].ul_min,
+	       bands_to_scan.band_info[i].ul_max,
+	       (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD");
+	break;
+      }
+  }
 }
 #endif
 
 int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg) {
 
-    int i, CC_id;
-    LTE_DL_FRAME_PARMS *frame_parms;
-    openair0_rf_map *rf_map;
-
-    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
-      rf_map = &phy_vars_ue[CC_id]->rf_map;
-      
-      AssertFatal( phy_vars_ue[CC_id] !=0, "");
-      frame_parms = &(phy_vars_ue[CC_id]->frame_parms);
-      
-      // replace RX signal buffers with mmaped HW versions
-      rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) );
-      txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) );
-      
-      for (i=0; i<frame_parms->nb_antennas_rx; i++) {
-	LOG_I(PHY, "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",
-	      CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
-	free( phy_vars_ue[CC_id]->common_vars.rxdata[i] );
-	rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
-	phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD
+  int i, CC_id;
+  LTE_DL_FRAME_PARMS *frame_parms;
+  openair0_rf_map *rf_map;
+
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    rf_map = &phy_vars_ue[CC_id]->rf_map;
+
+    AssertFatal( phy_vars_ue[CC_id] !=0, "");
+    frame_parms = &(phy_vars_ue[CC_id]->frame_parms);
+
+    // replace RX signal buffers with mmaped HW versions
+    rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) );
+    txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) );
+
+    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
+      LOG_I(PHY, "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",
+	    CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
+      free( phy_vars_ue[CC_id]->common_vars.rxdata[i] );
+      rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
+      phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD
+    }
+
+    for (i=0; i<frame_parms->nb_antennas_tx; i++) {
+      LOG_I(PHY, "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",
+	    CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
+      free( phy_vars_ue[CC_id]->common_vars.txdata[i] );
+      txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
+      phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i];
+    }
+
+    // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x]
+    // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x]
+    // be careful when releasing memory!
+    // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
+  }
+  return 0;
+}
+
+
+
+
+/*static void* timer_thread( void* param ) {
+  thread_top_init("timer_thread",1,870000L,1000000L,1000000L);
+  timer_subframe =9;
+  timer_frame    =1023;
+  //phy_stub_ticking = (SF_ticking*)malloc(sizeof(SF_ticking));
+  phy_stub_ticking->ticking_var = -1;
+  PHY_VARS_UE *UE;
+  UE = PHY_vars_UE_g[0][0];
+  double t_diff;
+  int external_timer = 0;
+
+
+  //struct timespec pselect_start;
+
+
+  //struct timespec sf_duration;
+  //sf_duration.tv_sec = 0;
+  //sf_duration.tv_nsec = 1e6;
+
+
+  wait_sync("timer_thread");
+
+  //pthread_mutex_init(&phy_stub_ticking->mutex_ticking,NULL);
+  //pthread_cond_init(&phy_stub_ticking->cond_ticking,NULL);
+
+  //  struct timespec start = {0};
+  //  struct timespec end = {0};
+  //sleepValue.tv_nsec = 1000000;
+  opp_enabled = 1;
+
+  // first check if we are receiving timing indications
+  if(nfapi_mode==4) {
+  usleep(10000);
+  if (UE->instance_cnt_timer > 0) {
+    external_timer = 1;
+    int absSFm1 = ((emulator_absSF+10239)%10240);
+    timer_frame = absSFm1/10;
+    timer_subframe = absSFm1%10;
+    pthread_mutex_lock(&UE->timer_mutex);
+    UE->instance_cnt_timer = -1;
+    pthread_mutex_unlock(&UE->timer_mutex);
+    LOG_I(PHY,"Running with external timer\n");
+  }
+  else LOG_I(PHY,"Running with internal timer\n");
+  }
+
+  struct timespec t_start;
+  struct timespec t_now;
+  struct timespec t_sleep;
+  uint64_t T_0;
+  uint64_t T_now;
+  uint64_t T_next_SF;
+  uint64_t T_sleep;
+  uint64_t sf_cnt = 0; //Total Subframe counter
+
+  clock_gettime(CLOCK_MONOTONIC, &t_start);
+  T_0 = (uint64_t) t_start.tv_sec*1000000000 + t_start.tv_nsec;
+  LOG_I(MAC, "Panos-D: timer_thread(), T_0 value: %" PRId64 "\n", T_0);
+  //printf("%" PRId64 "\n", t);
+
+  while (!oai_exit) {
+
+    // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
+    // They are set on the first rx/tx in the underly FH routines.
+    if (timer_subframe==9) {
+      timer_subframe=0;
+      timer_frame++;
+      timer_frame&=1023;
+    } else {
+      timer_subframe++;
+    }
+    //printf("[timer_thread] Frame: %d, Subframe: %d \n", timer_frame, timer_subframe);
+    //LOG_I(MAC," Panos-D [timer_thread] Frame: %d, Subframe: %d \n", timer_frame, timer_subframe);
+    //AssertFatal( 0 == pthread_cond_signal(&phy_stub_ticking->cond_ticking), "");
+    AssertFatal(pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) ==0,"");
+    phy_stub_ticking->ticking_var++;
+    // This should probably be a call to pthread_cond_broadcast when we introduce support for multiple UEs (threads)
+    if(phy_stub_ticking->ticking_var == 0){
+      //AssertFatal(phy_stub_ticking->ticking_var == 0,"phy_stub_ticking->ticking_var = %d",
+      		//phy_stub_ticking->ticking_var);
+      if (pthread_cond_signal(&phy_stub_ticking->cond_ticking) != 0) {
+	//LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id);
+	LOG_E( PHY, "timer_thread ERROR pthread_cond_signal for UE_thread\n");
+	exit_fun("nothing to add");
       }
-		
-      for (i=0; i<frame_parms->nb_antennas_tx; i++) {
-	LOG_I(PHY, "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",
-	      CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
-	free( phy_vars_ue[CC_id]->common_vars.txdata[i] );
-	txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
-	phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i];
+    }
+    else
+    	LOG_I(MAC, "Panos-D: timer_thread() Timing problem! \n");
+
+    AssertFatal(pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) ==0,"");
+    start_meas(&UE->timer_stats);
+
+
+    //clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); // get initial time-stamp
+    if (external_timer == 0) {
+    	sf_cnt++;
+    	T_next_SF = T_0 + sf_cnt*1000000;
+    	do{
+    	clock_gettime(CLOCK_MONOTONIC, &t_now);
+    	T_now =(uint64_t) t_now.tv_sec*1000000000 + t_now.tv_nsec;
+    	}while(T_now < T_next_SF);
+      //usleep(1000);
+      UE_tport_t pdu;
+      pdu.header.packet_type = TTI_SYNC;
+      pdu.header.absSF = (timer_frame*10)+timer_subframe;
+      if (nfapi_mode!=3){
+      multicast_link_write_sock(0,
+	  			&pdu,
+				sizeof(UE_tport_header_t));
+				}
+
+    }
+    else {
+      wait_on_condition(&UE->timer_mutex,&UE->timer_cond,&UE->instance_cnt_timer,"timer_thread");
+      release_thread(&UE->timer_mutex,&UE->instance_cnt_timer,"timer_thread");
+    }
+    //clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);   // get final time-stamp
+
+    //double t_ns = (double)(end.tv_sec - start.tv_sec) * 1.0e9 +
+    //              (double)(end.tv_nsec - start.tv_nsec);
+    //printf("Panos-D: [timer_thread] REAL TIME difference: %f", t_ns);
+
+
+    stop_meas(&UE->timer_stats);
+    t_diff = get_time_meas_us(&UE->timer_stats);
+
+    //printf("Panos-D: Absolute time: %lld, diff: %lld, diff_now: %lld \n",UE->timer_stats.p_time, UE->timer_stats.diff, UE->timer_stats.diff_now);
+    //LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
+    //if (t_diff > 1100)
+
+
+    //    LOG_E(MAC," Panos-D Absolute time: %f\n", t_diff);
+	    //LOG_E(MAC," Panos-D Absolute time: %f\n", t_diff);
+
+    //printf("Panos-D: Absolute time: %f", t_diff);
+
+
+    stop_meas(&UE->timer_stats);
+    t_diff = get_time_meas_us(&UE->timer_stats);
+    //printf("Panos-D: Absolute time: %lld, diff: %lld, diff_now: %lld \n",UE->timer_stats.p_time, UE->timer_stats.diff, UE->timer_stats.diff_now);
+    //LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
+    //if (t_diff > 1100) LOG_E(MAC," Panos-D Absolute time: %f\n", t_diff);
+    //printf("Panos-D: Absolute time: %f", t_diff);
+
+    //UE->proc.ticking_var++;
+    // pthread_cond_signal() //Send signal to ue_thread()?
+    // We also need to somehow pass the information of SFN/SF
+  }
+  free(phy_stub_ticking);
+  pthread_cond_destroy(&phy_stub_ticking->cond_ticking);
+  pthread_mutex_destroy(&phy_stub_ticking->mutex_ticking);
+  return 0;
+
+}*/
+
+
+
+
+
+
+
+
+
+// Panos: This timer thread is used only in the phy_stub mode as an independent timer
+// which will be ticking and provide the SFN/SF values that will be used from the UE threads
+// playing the role of nfapi-pnf.
+
+//02/02/2018
+static void* timer_thread( void* param ) {
+  thread_top_init("timer_thread",1,870000L,1000000L,1000000L);
+  timer_subframe =9;
+  timer_frame    =1023;
+  //phy_stub_ticking = (SF_ticking*)malloc(sizeof(SF_ticking));
+  phy_stub_ticking->ticking_var = -1;
+  PHY_VARS_UE *UE;
+  UE = PHY_vars_UE_g[0][0];
+  //double t_diff;
+  int external_timer = 0;
+
+
+  wait_sync("timer_thread");
+
+  opp_enabled = 1;
+
+  // first check if we are receiving timing indications
+  if(nfapi_mode==4) {
+  usleep(10000);
+  if (UE->instance_cnt_timer > 0) {
+    external_timer = 1;
+    int absSFm1 = ((emulator_absSF+10239)%10240);
+    timer_frame = absSFm1/10;
+    timer_subframe = absSFm1%10;
+    pthread_mutex_lock(&UE->timer_mutex);
+    UE->instance_cnt_timer = -1;
+    pthread_mutex_unlock(&UE->timer_mutex);
+    LOG_I(PHY,"Running with external timer\n");
+  }
+  else LOG_I(PHY,"Running with internal timer\n");
+  }
+
+  struct timespec t_start;
+  struct timespec t_now;
+  struct timespec t_sleep;
+  uint64_t T_0;
+  uint64_t T_now;
+  uint64_t T_next_SF;
+  uint64_t T_sleep;
+  uint64_t sf_cnt = 0; //Total Subframe counter
+
+  clock_gettime(CLOCK_MONOTONIC, &t_start);
+  T_0 = (uint64_t) t_start.tv_sec*1000000000 + t_start.tv_nsec;
+  LOG_D(MAC, "timer_thread(), T_0 value: %" PRId64 "\n", T_0);
+
+  while (!oai_exit) {
+
+    // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
+    // They are set on the first rx/tx in the underly FH routines.
+    if (timer_subframe==9) {
+      timer_subframe=0;
+      timer_frame++;
+      timer_frame&=1023;
+    } else {
+      timer_subframe++;
+    }
+
+    //AssertFatal( 0 == pthread_cond_signal(&phy_stub_ticking->cond_ticking), "");
+    AssertFatal(pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) ==0,"");
+    phy_stub_ticking->ticking_var++;
+    // This should probably be a call to pthread_cond_broadcast when we introduce support for multiple UEs (threads)
+    if(phy_stub_ticking->ticking_var == 0){
+      //AssertFatal(phy_stub_ticking->ticking_var == 0,"phy_stub_ticking->ticking_var = %d",
+      		//phy_stub_ticking->ticking_var);
+      if (pthread_cond_signal(&phy_stub_ticking->cond_ticking) != 0) {
+	//LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id);
+	LOG_E( PHY, "timer_thread ERROR pthread_cond_signal for UE_thread\n");
+	exit_fun("nothing to add");
       }
-      
-      // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x]
-      // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x]
-      // be careful when releasing memory!
-      // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
     }
-    return 0;
+    else
+    	LOG_D(MAC, "timer_thread() Timing problem! ticking_var value:%d \n \n \n", phy_stub_ticking->ticking_var);
+
+    AssertFatal(pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) ==0,"");
+    start_meas(&UE->timer_stats);
+
+
+    //clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); // get initial time-stamp
+    if (external_timer == 0) {
+    	clock_gettime(CLOCK_MONOTONIC, &t_now);
+    	sf_cnt++;
+    	T_next_SF = T_0 + sf_cnt*1000000;
+    	T_now =(uint64_t) t_now.tv_sec*1000000000 + t_now.tv_nsec;
+    	if(T_now > T_next_SF){
+    		t_sleep.tv_sec =0;
+    	    t_sleep.tv_nsec =0;
+    	}
+    	else{
+    		T_sleep = T_next_SF - T_now;
+    		t_sleep.tv_sec =0;
+    		t_sleep.tv_nsec = (__syscall_slong_t) T_sleep;
+    	}
+      nanosleep(&t_sleep, (struct timespec *)NULL);
+      UE_tport_t pdu;
+      pdu.header.packet_type = TTI_SYNC;
+      pdu.header.absSF = (timer_frame*10)+timer_subframe;
+      if (nfapi_mode!=3){
+      multicast_link_write_sock(0,
+				&pdu,
+				sizeof(UE_tport_header_t));
+      }
+
+    }
+    else {
+      wait_on_condition(&UE->timer_mutex,&UE->timer_cond,&UE->instance_cnt_timer,"timer_thread");
+      release_thread(&UE->timer_mutex,&UE->instance_cnt_timer,"timer_thread");
+    }
+
+
+    /*stop_meas(&UE->timer_stats);
+    t_diff = get_time_meas_us(&UE->timer_stats);
+
+    stop_meas(&UE->timer_stats);
+    t_diff = get_time_meas_us(&UE->timer_stats);*/
+  }
+  free(phy_stub_ticking);
+  pthread_cond_destroy(&phy_stub_ticking->cond_ticking);
+  pthread_mutex_destroy(&phy_stub_ticking->mutex_ticking);
+  return 0;
+
 }
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*static void* timer_thread( void* param ) {
+  thread_top_init("timer_thread",1,870000L,1000000L,1000000L);
+  timer_subframe =9;
+  timer_frame    =1023;
+  //phy_stub_ticking = (SF_ticking*)malloc(sizeof(SF_ticking));
+  phy_stub_ticking->ticking_var = -1;
+  PHY_VARS_UE *UE;
+  UE = PHY_vars_UE_g[0][0];
+  double t_diff;
+  int external_timer = 0;
+
+  wait_sync("timer_thread");
+
+  //pthread_mutex_init(&phy_stub_ticking->mutex_ticking,NULL);
+  //pthread_cond_init(&phy_stub_ticking->cond_ticking,NULL);
+
+  //  struct timespec start = {0};
+  //  struct timespec end = {0};
+  //sleepValue.tv_nsec = 1000000;
+  opp_enabled = 1;
+
+  // first check if we are receiving timing indications
+  if(nfapi_mode==4) {
+  usleep(10000);
+  if (UE->instance_cnt_timer > 0) {
+    external_timer = 1;
+    int absSFm1 = ((emulator_absSF+10239)%10240);
+    timer_frame = absSFm1/10;
+    timer_subframe = absSFm1%10;
+    pthread_mutex_lock(&UE->timer_mutex);
+    UE->instance_cnt_timer = -1;
+    pthread_mutex_unlock(&UE->timer_mutex);
+    LOG_I(PHY,"Running with external timer\n");
+  }
+  else LOG_I(PHY,"Running with internal timer\n");
+  }
+
+  while (!oai_exit) {
+
+    // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
+    // They are set on the first rx/tx in the underly FH routines.
+    if (timer_subframe==9) {
+      timer_subframe=0;
+      timer_frame++;
+      timer_frame&=1023;
+    } else {
+      timer_subframe++;
+    }
+    //printf("[timer_thread] Frame: %d, Subframe: %d \n", timer_frame, timer_subframe);
+    //LOG_I(MAC," Panos-D [timer_thread] Frame: %d, Subframe: %d \n", timer_frame, timer_subframe);
+    //AssertFatal( 0 == pthread_cond_signal(&phy_stub_ticking->cond_ticking), "");
+    AssertFatal(pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) ==0,"");
+    phy_stub_ticking->ticking_var++;
+    // This should probably be a call to pthread_cond_broadcast when we introduce support for multiple UEs (threads)
+    if(phy_stub_ticking->ticking_var == 0){
+      //AssertFatal(phy_stub_ticking->ticking_var == 0,"phy_stub_ticking->ticking_var = %d",
+      //		phy_stub_ticking->ticking_var);
+      if (pthread_cond_signal(&phy_stub_ticking->cond_ticking) != 0) {
+	//LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id);
+	LOG_E( PHY, "timer_thread ERROR pthread_cond_signal for UE_thread\n");
+	exit_fun("nothing to add");
+      }
+    }
+
+    AssertFatal(pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) ==0,"");
+    start_meas(&UE->timer_stats);
+
+
+    //clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); // get initial time-stamp
+    if (external_timer == 0) {
+      usleep(1000);
+      UE_tport_t pdu;
+      pdu.header.packet_type = TTI_SYNC;
+      pdu.header.absSF = (timer_frame*10)+timer_subframe;
+      multicast_link_write_sock(0,
+				&pdu,
+				sizeof(UE_tport_header_t));
+
+    }
+    else {
+      wait_on_condition(&UE->timer_mutex,&UE->timer_cond,&UE->instance_cnt_timer,"timer_thread");
+      release_thread(&UE->timer_mutex,&UE->instance_cnt_timer,"timer_thread");
+    }
+    //clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);   // get final time-stamp
+
+    //double t_ns = (double)(end.tv_sec - start.tv_sec) * 1.0e9 +
+    //              (double)(end.tv_nsec - start.tv_nsec);
+    //printf("Panos-D: [timer_thread] REAL TIME difference: %f", t_ns);
+
+
+    stop_meas(&UE->timer_stats);
+    t_diff = get_time_meas_us(&UE->timer_stats);
+
+    //printf("Panos-D: Absolute time: %lld, diff: %lld, diff_now: %lld \n",UE->timer_stats.p_time, UE->timer_stats.diff, UE->timer_stats.diff_now);
+    //LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
+    //if (t_diff > 1100)
+
+
+    //    LOG_E(MAC," Panos-D Absolute time: %f\n", t_diff);
+	    //LOG_E(MAC," Panos-D Absolute time: %f\n", t_diff);
+
+    //printf("Panos-D: Absolute time: %f", t_diff);
+
+
+    stop_meas(&UE->timer_stats);
+    t_diff = get_time_meas_us(&UE->timer_stats);
+    //printf("Panos-D: Absolute time: %lld, diff: %lld, diff_now: %lld \n",UE->timer_stats.p_time, UE->timer_stats.diff, UE->timer_stats.diff_now);
+    //LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
+    //if (t_diff > 1100) LOG_E(MAC," Panos-D Absolute time: %f\n", t_diff);
+    //printf("Panos-D: Absolute time: %f", t_diff);
+
+    //UE->proc.ticking_var++;
+    // pthread_cond_signal() //Send signal to ue_thread()?
+    // We also need to somehow pass the information of SFN/SF
+  }
+  free(phy_stub_ticking);
+  pthread_cond_destroy(&phy_stub_ticking->cond_ticking);
+  pthread_mutex_destroy(&phy_stub_ticking->mutex_ticking);
+  return 0;
+
+}*/
+
+
+
+
+
+
+
+
+int init_timer_thread(void) {
+  //PHY_VARS_UE *UE=PHY_vars_UE_g[0];
+	PHY_VARS_UE *UE=PHY_vars_UE_g[0][0];
+  phy_stub_ticking = (SF_ticking*)malloc(sizeof(SF_ticking));
+  pthread_mutex_init(&UE->timer_mutex,NULL);
+  pthread_cond_init(&UE->timer_cond,NULL);
+  UE->instance_cnt_timer = -1;
+  pthread_mutex_init(&phy_stub_ticking->mutex_ticking,NULL);
+  pthread_cond_init(&phy_stub_ticking->cond_ticking,NULL);
+  pthread_create(&phy_stub_ticking->pthread_timer, NULL, &timer_thread, NULL);
+  return 0;
+}
diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c
index a571aebe23a2b606317f7111727c7d95857cdc11..c178dd3c2378c9ff253990680c7a3a00fc792896 100644
--- a/targets/RT/USER/lte-uesoftmodem.c
+++ b/targets/RT/USER/lte-uesoftmodem.c
@@ -114,6 +114,17 @@ unsigned char                   scope_enb_num_ue = 2;
 static pthread_t                forms_thread; //xforms
 #endif //XFORMS
 
+pthread_cond_t nfapi_sync_cond;
+pthread_mutex_t nfapi_sync_mutex;
+int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
+
+uint8_t nfapi_mode = 0;
+
+uint16_t sf_ahead=2;
+
+char *emul_iface;
+
+
 pthread_cond_t sync_cond;
 pthread_mutex_t sync_mutex;
 int sync_var=-1; //!< protected by mutex \ref sync_mutex.
@@ -205,6 +216,7 @@ uint64_t num_missed_slots=0; // counter for the number of missed slots
 
 extern void reset_opp_meas(void);
 extern void print_opp_meas(void);
+extern void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface);
 
 extern PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
 			  uint8_t UE_id,
@@ -576,7 +588,8 @@ static void get_options(void) {
     // Read it in and store in asn1c data structures
     sprintf(uecap_xer,"%stargets/PROJECTS/GENERIC-LTE-EPC/CONF/UE_config.xml",getenv("OPENAIR_HOME"));
     printf("%s\n",uecap_xer);
-    uecap_xer_in=1;
+    if(nfapi_mode!=3)
+    	uecap_xer_in=1;
   } /* UE with config file  */
 }
 
@@ -742,6 +755,32 @@ void terminate_task(task_id_t task_id, module_id_t mod_id)
 
 #endif
 
+
+
+static inline void wait_nfapi_init(char *thread_name) {
+
+  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
+  pthread_mutex_lock( &nfapi_sync_mutex );
+
+  while (nfapi_sync_var<0)
+    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
+
+  pthread_mutex_unlock(&nfapi_sync_mutex);
+
+  printf( "NFAPI: got sync (%s)\n", thread_name);
+}
+
+int stop_L1L2(module_id_t enb_id)
+{
+	return 0;
+}
+
+
+int restart_L1L2(module_id_t enb_id)
+{
+	return 0;
+}
+
 int main( int argc, char **argv )
 {
   int i;
@@ -753,6 +792,10 @@ int main( int argc, char **argv )
   uint8_t  abstraction_flag=0;
   uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
 
+  // Default value for the number of UEs. It will hold,
+  // if not changed from the command line option --num-ues
+  NB_UE_INST=1;
+
 #if defined (XFORMS)
   int ret;
 #endif
@@ -780,7 +823,21 @@ int main( int argc, char **argv )
 
   printf("Reading in command-line options\n");
 
-  get_options (); 
+  get_options ();
+
+  printf("NFAPI_MODE value: %d \n", nfapi_mode);
+
+  // Panos: Not sure if the following is needed here
+  /*if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
+      if (UE_flag == 0) {
+        fprintf(stderr,"Getting configuration failed\n");
+        exit(-1);
+      }
+      else {
+        printf("Setting nfapi mode to UE_STUB_OFFNET\n");
+        nfapi_mode = 4;
+      }
+    }*/
 
 
 #if T_TRACER
@@ -846,6 +903,14 @@ int main( int argc, char **argv )
 #endif
 #endif
 
+//TTN for D2D
+#ifdef Rel14
+  printf ("RRC control socket\n");
+  rrc_control_socket_init();
+  printf ("PDCP PC5S socket\n");
+  pdcp_pc5_socket_init();
+#endif
+
 #if !defined(ENABLE_ITTI)
   // to make a graceful exit when ctrl-c is pressed
   signal(SIGSEGV, signal_handler);
@@ -872,20 +937,66 @@ int main( int argc, char **argv )
 
   printf("Before CC \n");
 
-  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {  
-      NB_UE_INST=1;     
-      NB_INST=1;     
-      PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));     
-      PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);    
+
+
+  // Panos: From old version
+  /*if (UE_flag==1) {
+	  PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**)*NB_UE_INST);
+	  for (int i=0; i<NB_UE_INST; i++) {
+		  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+
+			  PHY_vars_UE_g[i] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
+			  PHY_vars_UE_g[i][CC_id] = init_ue_vars(frame_parms[CC_id], i,abstraction_flag);
+
+			  UE[CC_id] = PHY_vars_UE_g[i][CC_id];
+			  printf("PHY_vars_UE_g[inst][%d] = %p\n",CC_id,UE[CC_id]);
+
+			  if (phy_test==1)
+				  UE[CC_id]->mac_enabled = 0;
+			  else
+				  UE[CC_id]->mac_enabled = 1;
+		  }
+	  }
+  }*/
+
+
+
+  //NB_UE_INST=1;
+  NB_INST=1;
+  if(nfapi_mode == 3){
+	  PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**)*NB_UE_INST);
+	  	  for (int i=0; i<NB_UE_INST; i++) {
+	  		  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+	  			PHY_vars_UE_g[i] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
+	  			PHY_vars_UE_g[i][CC_id] = init_ue_vars(frame_parms[CC_id], i,abstraction_flag);
+
+	  			UE[CC_id] = PHY_vars_UE_g[i][CC_id];
+	  			printf("PHY_vars_UE_g[inst][%d] = %p\n",CC_id,UE[CC_id]);
+
+	  			if (phy_test==1)
+	  				UE[CC_id]->mac_enabled = 0;
+	  			else
+	  				UE[CC_id]->mac_enabled = 1;
+	  		}
+	  	  }
+  }
+  else{
+
+
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+      //NB_UE_INST=1;
+      NB_INST=1;
+      PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
+      PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
       PHY_vars_UE_g[0][CC_id] = init_ue_vars(frame_parms[CC_id], 0,abstraction_flag);
       UE[CC_id] = PHY_vars_UE_g[0][CC_id];
       printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
-      
+
       if (phy_test==1)
 	UE[CC_id]->mac_enabled = 0;
-      else 
+      else
 	UE[CC_id]->mac_enabled = 1;
-      
+
       if (UE[CC_id]->mac_enabled == 0) {  //set default UL parameters for testing mode
 	for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
 	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
@@ -897,13 +1008,13 @@ int main( int argc, char **argv )
 	  UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
 	}
       }
-      
+
       UE[CC_id]->UE_scan = UE_scan;
       UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
       UE[CC_id]->mode    = mode;
       printf("UE[%d]->mode = %d\n",CC_id,mode);
-      
-      if (UE[CC_id]->mac_enabled == 1) { 
+
+      if (UE[CC_id]->mac_enabled == 1) {
 	UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1234;
 	UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1234;
       }else {
@@ -912,7 +1023,7 @@ int main( int argc, char **argv )
       }
       UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0] + rx_gain_off;
       UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
-      
+
       if (frame_parms[CC_id]->frame_type==FDD) {
 	UE[CC_id]->N_TA_offset = 0;
       }
@@ -923,14 +1034,16 @@ int main( int argc, char **argv )
 	  UE[CC_id]->N_TA_offset = 624/2;
 	else if (frame_parms[CC_id]->N_RB_DL == 25)
 	  UE[CC_id]->N_TA_offset = 624/4;
-     
+
     }
-    init_openair0(); 
+    init_openair0();
   }
 
+
   printf("Runtime table\n");
   fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
   cpuf=get_cpu_freq_GHz();
+  }
   
   
   
@@ -980,6 +1093,9 @@ int main( int argc, char **argv )
       printf("cannot create ITTI tasks\n");
       exit(-1); // need a softer mode
     }
+    if(nfapi_mode==3){ //Panos: Here we should add another nfapi_mode for the case of Supervised LTE-D2D
+    	UE_config_stub_pnf();
+    }
     printf("ITTI tasks created\n");
 #endif
 
@@ -1029,9 +1145,46 @@ int main( int argc, char **argv )
   
   rt_sleep_ns(10*100000000ULL);
 
+  const char *nfapi_mode_str = "<UNKNOWN>";
+
+    switch(nfapi_mode)
+    {
+      case 0:
+        nfapi_mode_str = "MONOLITHIC";
+        break;
+      case 1:
+        nfapi_mode_str = "PNF";
+        break;
+      case 2:
+        nfapi_mode_str = "VNF";
+        break;
+      case 3:
+        nfapi_mode_str = "UE_STUB_PNF";
+        break;
+      case 4:
+        nfapi_mode_str = "UE_STUB_OFFNET";
+        break;
+      default:
+        nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
+        break;
+    }
+    printf("NFAPI MODE:%s\n", nfapi_mode_str);
+
+
   // start the main threads
     int eMBMS_active = 0;
-    init_UE(1,eMBMS_active,uecap_xer_in,0);
+
+    if (nfapi_mode==3) // UE-STUB-PNF
+    {
+    	config_sync_var=0;
+    	wait_nfapi_init("main?");
+    	//Panos: Temporarily we will be using single set of threads for multiple UEs.
+    	//init_UE_stub(1,eMBMS_active,uecap_xer_in,emul_iface);
+    	init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
+    }
+    else {
+    	init_UE(1,eMBMS_active,uecap_xer_in,0);
+    }
 
     if (phy_test==0) {
       printf("Filling UE band info\n");
@@ -1039,10 +1192,12 @@ int main( int argc, char **argv )
       dl_phy_sync_success (0, 0, 0, 1);
     }
 
-    number_of_cards = 1;
-    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
-      PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
-      PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
+    if (nfapi_mode!=3){
+    	number_of_cards = 1;
+    	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    		PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
+    		PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
+    	}
     }
 
 
@@ -1058,13 +1213,16 @@ int main( int argc, char **argv )
       UE[CC_id]->hw_timing_advance = 160;
 #endif
     }
-    if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) {
-      printf("Error setting up eNB buffer\n");
-      exit(-1);
+    if(nfapi_mode!=3) {
+    	if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) {
+    		printf("Error setting up eNB buffer\n");
+    		exit(-1);
+    	}
     }
     
     
     
+
     if (input_fd) {
       printf("Reading in from file to antenna buffer %d\n",0);
       if (fread(UE[0]->common_vars.rxdata[0],