diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index aa11892fa6a90593c848a84833f861dd7025fd80..15c44aed22a46638543af94ca08ac8c5a99798c5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -34,4 +34,5 @@ job1:
    - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no "  --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR
    - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no "  --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR
    - cat $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml
-  when: manual  
+  only:
+   - triggers
diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 3169c6cc98d7bdafffdb9d7dd431a00c8f4bdc75..81ddf3750309b94118758a5e037a29698af7906e 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -119,6 +119,7 @@ endmacro(add_list_string_option)
 ####################################################
 # compilation flags
 #############################################
+#set(CMAKE_BUILD_TYPE "Debug")
 if (CMAKE_BUILD_TYPE STREQUAL "")
    set(CMAKE_BUILD_TYPE "RelWithDebInfo")
 endif()
@@ -235,6 +236,7 @@ add_boolean_option(DEBUG_OMG           False "???")
 add_boolean_option(XFORMS              False "This adds the possibility to see the signal oscilloscope")
 add_boolean_option(PRINT_STATS         False "This adds the possibility to see the status")
 add_boolean_option(T_TRACER            False "Activate the T tracer, a debugging/monitoring framework" )
+add_boolean_option(UE_AUTOTEST_TRACE   False "Activate UE autotest specific logs")
 
 add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering")
 
@@ -475,7 +477,7 @@ include_directories ("${X2AP_DIR}")
 # Hardware dependant options
 ###################################
 add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4")
-add_list1_option(NB_ANTENNAS_TX "2" "Number of antennas in transmission" "1" "2" "4")
+add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4")
 add_list1_option(NB_ANTENNAS_TXRX "2" "Number of antennas in ????" "1" "2" "4")
 
 add_list2_option(RF_BOARD "EXMIMO" "RF head type" "None" "EXMIMO" "OAI_USRP" "OAI_BLADERF" "CPRIGW" "OAI_LMSSDR")
@@ -621,7 +623,7 @@ add_boolean_option(MESSAGE_CHART_GENERATOR False         "For generating sequenc
 add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchanges in sequence diagrams")
 add_boolean_option(MESSAGE_CHART_GENERATOR_PHY     False "trace some PHY exchanges in sequence diagrams")
 
-add_boolean_option(ENB_AGENT                   True         "enable eNB agent to inteface with a SDN contrller")
+add_boolean_option(FLEXRAN_AGENT_SB_IF             False         "enable FlexRAN agent to inteface with a SDN controller")
 
 ########################
 # Include order
@@ -817,8 +819,10 @@ include_directories("${OPENAIR_DIR}/targets/ARCH/COMMON")
 include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/USERSPACE/LIB/")
 include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/DEFS")
 include_directories("${OPENAIR2_DIR}/ENB_APP")
+include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC")
 include_directories("${OPENAIR2_DIR}/UTIL/OSA")
 include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/inc")
+include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/inc")
 include_directories("${OPENAIR2_DIR}/UTIL/MEM")
 include_directories("${OPENAIR2_DIR}/UTIL/LISTS")
 include_directories("${OPENAIR2_DIR}/UTIL/FIFO")
@@ -837,6 +841,94 @@ include_directories("${OPENAIR_DIR}")
 
 # Utilities Library
 ################
+if (FLEXRAN_AGENT_SB_IF)
+  # set the version of protobuf messages, V3 not supported yet
+  add_list1_option(FLPT_VERSION V2 "FLPT MSG  protobuf  grammar version" V2 V3)
+  
+  if (${FLPT_VERSION} STREQUAL "V2")
+    set (FLPTDIR V2)
+  elseif (${FLPT_VERSION} STREQUAL "V3")
+    set (FLPTDIR V3)
+  endif(${FLPT_VERSION} STREQUAL "V2")
+  
+  set(FLPT_MSG_DIR ${OPENAIR2_DIR}/ENB_APP/MESSAGES/${FLPTDIR} )
+  set(FLPT_MSG_FILES
+    ${FLPT_MSG_DIR}/header.proto
+    ${FLPT_MSG_DIR}/flexran.proto
+    ${FLPT_MSG_DIR}/stats_common.proto
+    ${FLPT_MSG_DIR}/stats_messages.proto
+    ${FLPT_MSG_DIR}/time_common.proto
+    ${FLPT_MSG_DIR}/controller_commands.proto
+    ${FLPT_MSG_DIR}/mac_primitives.proto
+    ${FLPT_MSG_DIR}/config_messages.proto
+    ${FLPT_MSG_DIR}/config_common.proto
+    ${FLPT_MSG_DIR}/control_delegation.proto
+    )
+
+  set(FLPT_C_DIR ${protobuf_generated_dir}/${FLPTDIR})
+  #message("calling protoc_call=${protoc_call} FLPT_C_DIR=${FLPT_C_DIR} FLPT_MSG_FILES=${FLPT_MSG_FILES}")
+  execute_process(COMMAND ${protoc_call} ${FLPT_C_DIR} ${FLPT_MSG_DIR} ${FLPT_MSG_FILES})
+  file(GLOB FLPT_source ${FLPT_C_DIR}/*.c)
+  set(FLPT_OAI_generated
+    ${FLPT_C_DIR}/header.pb-c.c
+    ${FLPT_C_DIR}/flexran.pb-c.c
+    ${FLPT_C_DIR}/stats_common.pb-c.c
+    ${FLPT_C_DIR}/stats_messages.pb-c.c
+    ${FLPT_C_DIR}/time_common.pb-c.c
+    ${FLPT_C_DIR}/controller_commands.pb-c.c
+    ${FLPT_C_DIR}/mac_primitives.pb-c.c
+    ${FLPT_C_DIR}/config_messages.pb-c.c
+    ${FLPT_C_DIR}/config_common.pb-c.c
+    ${FLPT_C_DIR}/control_delegation.pb-c.c
+    )
+  
+  file(GLOB flpt_h ${FLPT_C_DIR}/*.h)
+  set(flpt_h ${flpt_h} )
+  
+  add_library(FLPT_MSG
+    ${FLPT_OAI_generated}
+    ${FLPT_source}
+    )
+  set(FLPT_MSG_LIB FLPT_MSG)
+  #message("prpt c dir is : ${FLPT_C_DIR}")
+  include_directories (${FLPT_C_DIR})
+
+  add_library(ASYNC_IF
+    ${OPENAIR2_DIR}/UTIL/ASYNC_IF/socket_link.c
+    ${OPENAIR2_DIR}/UTIL/ASYNC_IF/link_manager.c
+    ${OPENAIR2_DIR}/UTIL/ASYNC_IF/message_queue.c
+    ${OPENAIR2_DIR}/UTIL/ASYNC_IF/ringbuffer_queue.c
+    )
+  set(ASYNC_IF_LIB ASYNC_IF)
+  include_directories(${OPENAIR2_DIR}/UTIL/ASYNC_IF)
+
+ add_library(FLEXRAN_AGENT
+    ${OPENAIR2_DIR}/ENB_APP/flexran_agent_handler.c
+    ${OPENAIR2_DIR}/ENB_APP/flexran_agent_common.c
+    ${OPENAIR2_DIR}/ENB_APP/flexran_agent_common_internal.c
+    ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
+    ${OPENAIR2_DIR}/ENB_APP/flexran_agent.c
+    ${OPENAIR2_DIR}/ENB_APP/flexran_agent_task_manager.c
+    ${OPENAIR2_DIR}/ENB_APP/flexran_agent_net_comm.c
+    ${OPENAIR2_DIR}/ENB_APP/flexran_agent_async.c
+    ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
+    )
+  set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT)
+  #include_directories(${OPENAIR2_DIR}/ENB_APP)
+  
+  set(PROTOBUF_LIB "protobuf-c")
+  
+  FIND_PATH(LIBYAML_INCLUDE_DIR NAMES yaml.h)
+  FIND_LIBRARY(LIBYAML_LIBRARIES NAMES yaml libyaml)
+  
+  INCLUDE(FindPackageHandleStandardArgs)
+  FIND_PACKAGE_HANDLE_STANDARD_ARGS(Yaml DEFAULT_MSG LIBYAML_LIBRARIES LIBYAML_INCLUDE_DIR)
+  MARK_AS_ADVANCED(LIBYAML_INCLUDE_DIR LIBYAML_LIBRARIES)
+
+  #set(PROTOBUF_LIB "protobuf") #for Cpp
+endif()
+
+
 add_library(HASHTABLE
   ${OPENAIR_DIR}/common/utils/hashtable/hashtable.c
   ${OPENAIR_DIR}/common/utils/hashtable/obj_hashtable.c
@@ -930,6 +1022,7 @@ set(SCHED_SRC
   ${OPENAIR1_DIR}/SCHED/phy_mac_stub.c
   ${OPENAIR1_DIR}/SCHED/pucch_pc.c
   ${OPENAIR1_DIR}/SCHED/pusch_pc.c
+  ${OPENAIR1_DIR}/SCHED/srs_pc.c
 )
 add_library(SCHED_LIB ${SCHED_SRC})
 
@@ -978,11 +1071,14 @@ set(PHY_SRC
   ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_mbsfn.c
   ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_ul.c
   ${OPENAIR1_DIR}/PHY/MODULATION/ul_7_5_kHz.c
+  ${OPENAIR1_DIR}/PHY/MODULATION/beamforming.c
+  ${OPENAIR1_DIR}/PHY/MODULATION/compute_bf_weights.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_time.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_timefreq.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c
+  ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_est_freq_offset.c
@@ -1095,7 +1191,17 @@ set (MAC_SRC
   ${MAC_DIR}/eNB_scheduler_RA.c
   ${MAC_DIR}/pre_processor.c
   ${MAC_DIR}/config.c
-  )
+ )
+
+if (FLEXRAN_AGENT_SB_IF)
+
+set (MAC_SRC ${MAC_SRC}
+  ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue.c
+  ${MAC_DIR}/flexran_agent_scheduler_dataplane.c
+  ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue_remote.c
+)
+
+endif()
 
 set (ENB_APP_SRC
   ${OPENAIR2_DIR}/ENB_APP/enb_app.c
@@ -1108,6 +1214,14 @@ add_library(L2
   ${ENB_APP_SRC})
 #  ${OPENAIR2_DIR}/RRC/L2_INTERFACE/openair_rrc_L2_interface.c)
 
+if (FLEXRAN_AGENT_SB_IF)
+
+#Test for adding a shared library
+add_library(default_sched SHARED ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue.c)
+add_library(remote_sched SHARED ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue_remote.c)
+
+endif()
+
 # L3 Libs
 ##########################
 
@@ -1468,6 +1582,23 @@ add_library(LFDS
   ${lfds}/lfds611_abstraction/lfds611_abstraction_malloc.c
 )
 
+set(lfds7 ${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/src/)
+file(GLOB lfds7_queue ${lfds7}/lfds700_queue/*.c)
+file(GLOB lfds7_ring ${lfds7}/lfds700_ringbuffer/*.c)
+file(GLOB lfds7_qbss ${lfds7}/lfds700_queue_bounded_singleconsumer_singleproducer/*.c)
+file(GLOB lfds7_stack ${lfds7}/lfds700_stack/*.c)
+file(GLOB lfds7_freelist ${lfds7}/lfds700_freelist/*.c)
+file(GLOB lfds7_btree ${lfds7}/lfds700_btree_addonly_unbalanced/*.c)
+file(GLOB lfds7_hash ${lfds7}/lfds700_hash_addonly/*.c)
+file(GLOB lfds7_ordered_list ${lfds7}/lfds700_list_addonly_ordered_singlylinked/*.c)
+file(GLOB lfds7_unordered_list ${lfds7}/lfds700_list_addonly_singlylinked_unordered/*.c)
+file(GLOB lfds7_misc ${lfds7}/lfds700_misc/*.c)
+
+include_directories(${lfds7})
+add_library(LFDS7
+  ${lfds7_queue} ${lfds7_ring} ${lfds7_qbss} ${lfds7_stack} ${lfds7_freelist} ${lfds7_btree} ${lfds7_hash} ${lfds7_ordered_list} ${lfds7_unordered_list} ${lfds7_misc}
+)
+
 # Simulation library
 ##########################
 add_library(SIMU
@@ -1644,11 +1775,11 @@ add_executable(lte-softmodem
 
 target_link_libraries (lte-softmodem -ldl
   -Wl,--start-group
-  RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} 
+  RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
   -Wl,--end-group )
 
 target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES})
-target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ) 
+target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ${PROTOBUF_LIB}  ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
 target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES})
 target_link_libraries (lte-softmodem ${T_LIB})
 
@@ -1678,11 +1809,11 @@ add_executable(lte-softmodem-nos1
   )
 target_link_libraries (lte-softmodem-nos1
   -Wl,--start-group
-  RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB}
+  RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
   -Wl,--end-group )
 
 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}  ${option_HW_lib}  ${option_TP_lib} ${XFORMS_LIBRARIES} )
+target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES}  ${option_HW_lib} ${option_TP_lib} ${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})
 
@@ -1823,20 +1954,24 @@ add_executable(oaisim_nos1
 target_include_directories(oaisim_nos1 PUBLIC  ${OPENAIR_TARGETS}/SIMU/USER)
 target_link_libraries (oaisim_nos1
   -Wl,--start-group
-  RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB}  ${MIH_LIB}
+  RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB}  ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
   -Wl,--end-group )
 
 target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
-target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES}  ${NETTLE_LIBRARIES}  ${option_HW_lib}  ${option_TP_lib}
-  ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES})
+target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES}  ${NETTLE_LIBRARIES}  ${option_HW_lib} ${option_TP_lib}
+  ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
 #Force link with forms, regardless XFORMS option
 target_link_libraries (oaisim_nos1 forms)
+
+#message("protobuflib is  ${PROTOBUF_LIB}")
+
 target_link_libraries (oaisim_nos1 ${T_LIB})
 
+
 # Unitary tests for each piece of L1: example, mbmssim is MBMS L1 simulator
 #####################################
 
-foreach(myExe dlsim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim)
+foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim)
   add_executable(${myExe}
     ${OPENAIR_BIN_DIR}/messages_xml.h
     ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c
@@ -1844,7 +1979,8 @@ foreach(myExe dlsim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syn
     ${T_SOURCE}
     )
   target_link_libraries (${myExe}
-    -Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} -Wl,--end-group
+
+    -Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} LFDS7 -Wl,--end-group
     pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${T_LIB}
     )
 endforeach(myExe)
@@ -1917,6 +2053,7 @@ if (${T_TRACER})
   add_dependencies(oaisim generate_T)
   add_dependencies(oaisim_nos1 generate_T)
   add_dependencies(dlsim generate_T)
+  add_dependencies(dlsim_tm7 generate_T)
   add_dependencies(ulsim generate_T)
   add_dependencies(pbchsim generate_T)
   add_dependencies(scansim generate_T)
diff --git a/cmake_targets/autotests/openair.py b/cmake_targets/autotests/openair.py
index 5cea3aa121f177238dd72ed93c97543983067457..7ad118ef1bba19a1d9e6f186ecbd341dfb7d8f5f 100644
--- a/cmake_targets/autotests/openair.py
+++ b/cmake_targets/autotests/openair.py
@@ -75,7 +75,7 @@ class openair(core):
         return (stdout, stderr)
 
     def connect(self, username, password, prompt='PEXPECT_OAI'):
-     max_retries=100
+     max_retries=10
      i=0
      while i <= max_retries:  
         self.prompt1 = prompt
@@ -97,9 +97,9 @@ class openair(core):
             # need to look for twice the string of the prompt
             self.oai.prompt()
             self.oai.prompt()
-            self.oai.sendline('uptime')
-            self.oai.prompt()
-            print self.oai.before
+#            self.oai.sendline('uptime')
+#            self.oai.prompt()
+#           print self.oai.before
             break
         except Exception, e:
             error=''
@@ -171,7 +171,7 @@ class openair(core):
                sys.exit(1)
 
     def disconnect(self):
-        print 'disconnecting the ssh connection to ' + self.address + '\n'
+#        print 'disconnecting the ssh connection to ' + self.address + '\n'
         self.oai.send('exit')
 #        self.cancel()
 
diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py
index ada0cf09326c1d774ab9b71e76144dc5c8c33a28..9f08a00d1aa0f7ad0605145cb87b67e7ff071f25 100755
--- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py
+++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py
@@ -20,10 +20,14 @@
 # *      contact@openairinterface.org
 # */
 
-# \author Rohit Gupta
+# \author Rohit Gupta - Benoit ROBERT (benoit.robert@syrtem.com)
 # \version 0.1
 # @ingroup _test
 
+# \Changelog
+# 2016-11-18 : 
+#   - Add progess bar during test execution update_progress()
+
 import tempfile
 import threading
 import sys
@@ -37,6 +41,8 @@ import math #from time import clock
 import xml.etree.ElementTree as ET
 import re
 
+#from dict2xml import dict2xml as xmlify
+
 from colorama import Fore, Back, Style
 
 import numpy as np
@@ -57,6 +63,36 @@ import ssh
 from ssh import SSHSession
 import argparse
 
+
+# update_progress() : Displays or updates a console progress bar
+## Accepts a float between 0 and 1. Any int will be converted to a float.
+## A value under 0 represents a 'halt'.
+## A value at 1 or bigger represents 100%
+def update_progress(progress, prefix_string):
+    barLength = 20 # Modify this to change the length of the progress bar
+    status = ""
+    #print "progress = "+ str(progress)
+    if isinstance(progress, int):
+        progress = float(progress)
+    if not isinstance(progress, float):
+        progress = 0
+        status = "error: progress var must be float\r\n"
+    if progress < 0:
+        progress = 0
+        status = "Halt...\r\n"
+    if progress >= 1:
+        progress = 1
+        status = "Done...\r\n"
+    block = int(round(barLength*progress))
+    text = "\r"+prefix_string+" [{0}] {1}% {2}".format( "="*block + " "*(barLength-block), progress*100, status)
+    sys.stdout.write(text)
+    sys.stdout.flush()
+
+
+def exit_prog(exit_val):
+  print(Style.RESET_ALL),
+  sys.exit(exit_val)
+
 # \brief write a string to a file
 # \param filename name of file
 # \param string string to write
@@ -271,7 +307,7 @@ def update_config_file(oai, config_string, logdirRepo, python_script):
 # \param logdir_local_base local directory
 # \param operation operation to perform (get_all, put_all) transfers recursively for directories
 def SSHSessionWrapper(machine, username, key_file, password, logdir_remote, logdir_local_base, operation):
-  max_tries = 100
+  max_tries = 10
   i=0
   while i <= max_tries:
     i = i +1
@@ -306,30 +342,50 @@ def SSHSessionWrapper(machine, username, key_file, password, logdir_remote, logd
 # \param CleanUpAluLteBox program to terminate AlU Bell Labs LTE Box
 # \param ExmimoRfStop String to stop EXMIMO card (specified in test_case_list.xml)
 def cleanOldPrograms(oai, programList, CleanUpAluLteBox, ExmimoRfStop, logdir, logdirOAI5GRepo):
-  cmd = 'sudo -E killall -s INT -q -r ' + programList + ' ; sleep 5 ; sudo -E killall -9 -q -r ' + programList
+  cmd = 'killall -9 ' + programList
   result = oai.send(cmd, True)
-  print "Killing old programs..." + result
+#  print "\t\t > "+cmd
+#  print "\t\t < "+result
+
+#  print "Killing old programs on ..." + result
   programArray = programList.split()
   programListJoin = '|'.join(programArray)
   cmd = " ( date ;echo \"Starting cleaning old programs.. \" ; dmesg|tail ; echo \"Current disk space.. \" ; df -h )>& " + logdir + "/oai_test_setup_cleanup.log.`hostname` 2>&1 ; sync"
   result=oai.send_recv(cmd)
+#  print "\t\t > "+cmd
+#  print "\t\t < "+result
+
   cmd = cleanupOldProgramsScript + ' ' + '\''+programListJoin+'\''
   #result = oai.send_recv(cmd)
   #print result
   result = oai.send_expect_false(cmd, 'Match found', False)
-  print "Looking for old programs..." + result
+#  print "\t\t > "+cmd
+#  print "\t\t < "+result
+
+#  print "Looking for old programs..." + result
   res=oai.send_recv(CleanUpAluLteBox, True)
+#  print "\t\t > "+CleanUpAluLteBox
+#  print "\t\t < "+res
   cmd= " echo \"Starting EXmimoRF Stop... \"  >> " + logdir + "/oai_test_setup_cleanup.log.`hostname` 2>&1  ; sync ";
-  oai.send_recv(cmd)
+  result = oai.send_recv(cmd)
+#  print "\t\t > "+cmd
+#  print "\t\t < "+result
   cmd  = "( " + "cd " + logdirOAI5GRepo + " ; source oaienv ;  "  +  ExmimoRfStop + " ) >> " + logdir + "/oai_test_setup_cleanup.log.`hostname` 2>&1  ; sync "
-  print "cleanoldprograms cmd = " + cmd
+#  print "cleanoldprograms cmd = " + cmd
   res=oai.send_recv(cmd, False, timeout=600)
+#  print "\t\t > "+cmd
+#  print "\t\t < "+res
+
   cmd= " echo \"Stopping EXmimoRF Stop... \" >> " + logdir + "/oai_test_setup_cleanup.log.`hostname` 2>&1  ; sync ";
-  oai.send_recv(cmd)
+  result = oai.send_recv(cmd)
+#  print "\t\t > "+cmd
+#  print "\t\t < "+result
 
   #res = oai.send_recv(ExmimoRfStop, False)
   cmd = " ( date ;echo \"Finished cleaning old programs.. \" ; dmesg | tail)>> $HOME/.oai_test_setup_cleanup.log.`hostname` 2>&1 ; sync"
   res=oai.send_recv(cmd)
+#  print "\t\t > "+cmd
+#  print "\t\t < "+res
 
 # \brief Class thread to launch a generic command on remote machine
 # \param threadID number of thread (for book keeping)
@@ -355,10 +411,10 @@ class oaiThread (threading.Thread):
         try:
           oai = openair('localdomain',self.machine)
           oai.connect(self.username, self.password)
-          print "Starting " + self.threadname + " on machine " + self.machine
+          # print "Starting " + self.threadname + " on machine " + self.machine
           result = oai.send_recv(self.cmd, self.sudo, self.timeout)
-          print "result = " + result
-          print "Exiting " + self.threadname
+          #print "result = " + result
+          #print "Exiting " + self.threadname
           oai.disconnect()
         except Exception, e:
            error=''
@@ -1269,6 +1325,8 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
   if testcase_verdict != 'PASS':      # if something went wrong to not run test cases
     max_ntries=0
 
+  indent="\t\t"
+
   runs_results = []
   nb_runs       = 0
   nb_run_pass   = 0
@@ -1288,9 +1346,11 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
     #
     # RUN initialization
     # ----------------------------------------------------
-    print (Fore.WHITE + indent + "> RUN_"+str(run).zfill(2)+"                  : " ),
- 
-    sys.stdout.flush()
+    
+    prefix_string = Fore.WHITE + indent + "> RUN_"+str(run).zfill(2)+"              :"
+
+#    print (Fore.WHITE + indent + "> RUN_"+str(run).zfill(2)+"                  : " ),
+#    sys.stdout.flush()
 
     run_start_time=datetime.datetime.now()
 
@@ -1406,8 +1466,34 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
     threads.append(thread_UE)
     thread_eNB.start()
     thread_UE.start()
+
+    run_work_inprogress_flag = True
+    progress_step = timeout_thread/20
+    progress_count = 0
+
+    while (run_work_inprogress_flag):
+
+
+      update_progress(float(progress_count)/float(timeout_thread),prefix_string)
+
+      time.sleep(progress_step)
+
+      progress_count += progress_step
+
+#      sys.stdout.write ('#')
+#      sys.stdout.flush()
+
+      run_work_inprogress_flag = False
+      for t in threads:
+          if t.isAlive():
+            run_work_inprogress_flag = True
+
+    
+    update_progress(1,prefix_string)
+
     for t in threads:
-       t.join()
+      t.join()
+
 
     #
     # 
@@ -1422,10 +1508,12 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
 
     fname = logdir_local_run+ '/UE_exec'     + '_' + str(run) + '_.log'
     cell_synch_status = analyser.check_cell_synchro(fname)
+    print (Fore.WHITE + indent + "> Check Cell synchro  :"),
+      
     if cell_synch_status == 'CELL_SYNCH':
-      print '!!!!!!!!!!!!!!  Cell synchronized !!!!!!!!!!!'
+      print ( Fore.GREEN + cell_synch_status)
     else :
-      print '!!!!!!!!!!!!!!  Cell NOT  NOT synchronized !!!!!!!!!!!'
+      print ( Fore.RED + cell_synch_status)
       metric_checks_flag = 0
 
     ue_seg_fault_status = analyser.check_exec_seg_fault(fname)
@@ -1444,6 +1532,9 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
       # UE side metrics
       metricList=testcase.findall('UE_metric')
       for metric in metricList:
+        
+        metric_verdict = 'PASS'
+
         metric_def = {}
         metric_def['id']            = metric.get('id') 
         metric_def['description']   = metric.get('description') 
@@ -1464,15 +1555,19 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
     
         metric_extracted = analyser.do_extract_metrics(args)
 
-        print "\t  > Metric "+metric_def['id']+" :"
-        print "\t\t> min       = "+ str( metric_extracted['metric_min'] )
-        print "\t\t> min_index = "+ str( metric_extracted['metric_min_index'] )
-        print "\t\t> max       = "+ str( metric_extracted['metric_max'] )
-        print "\t\t> max_index = "+ str( metric_extracted['metric_max_index'] )
-        print "\t\t> mean      = "+ str( metric_extracted['metric_mean'] )
-        print "\t\t> median    = "+ str( metric_extracted['metric_median'] )      
+        print (Fore.WHITE + indent + "> Metric              : "+metric_def['id']),
+        print ("(min="+str( metric_extracted['metric_min'])+", max="+str( metric_extracted['metric_max'])+", mean="+str( metric_extracted['metric_mean'])+", median="+str( metric_extracted['metric_median'])+")")
+
+#        print "\t  > Metric "+metric_def['id']+" :"
+#        print "\t\t> min       = "+ str( metric_extracted['metric_min'] )
+#        print "\t\t> min_index = "+ str( metric_extracted['metric_min_index'] )
+#        print "\t\t> max       = "+ str( metric_extracted['metric_max'] )
+#        print "\t\t> max_index = "+ str( metric_extracted['metric_max_index'] )
+#        print "\t\t> mean      = "+ str( metric_extracted['metric_mean'] )
+#        print "\t\t> median    = "+ str( metric_extracted['metric_median'] )      
 
-        verdict = analyser.do_check_verdict(metric_def, metric_extracted)
+        if metric_def['pass_fail_stat'] :
+          metric_verdict = analyser.do_check_verdict(metric_def, metric_extracted)
    
         metric_fig = logdir_local_run+ '/UE_metric_'+ metric_def['id']+'_' + str(run) + '_.png'
         analyser.do_img_metrics(metric_def, metric_extracted, metric_fig)
@@ -1500,6 +1595,13 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
 
         runs_metrics.append(run_metrics)
 
+        if metric_verdict != 'PASS':
+          verdict = metric_verdict
+
+      # End Metrics LOOP
+      # ---------------------
+
+
       # Traffic analysis
       if UE_traffic_exec != "":
 
@@ -1553,9 +1655,9 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
     run_stop_time=datetime.datetime.now()
     run_duration = run_stop_time-run_start_time
 #   print (Fore.WHITE + ("duration=" :"),
-    print (Fore.WHITE + indent + "> RUN duration            : "+ str(run_duration) +"s" )
+    print (Fore.WHITE + indent + "> RUN duration        : "+ str(run_duration) +"s" )
 
-    print (Fore.WHITE + indent + "> RUN verdict             :"),
+    print (Fore.WHITE + indent + "> RUN verdict         :"),
 
     if verdict == 'PASS':
       nb_run_pass   += 1
@@ -1585,6 +1687,8 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
   # END RUN LOOP
   #----------------------------------------------------
 
+  indent="\t"
+
   # Test case duration
   # ----------------------------------  
   testcase_time_stop = datetime.datetime.now()
@@ -1624,11 +1728,9 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
   else:
     print (Fore.YELLOW+'INCONCLUSIVE')
 
-  duration= testcase_time_stop - testcase_time_start
-  xmlFile = logdir_local_testcase + '/test.' + testcasename + '.xml'
-  xml="\n<testcase classname=\'"+ testcaseclass +  "\' name=\'" + testcasename + "."+tags +  "\' Run_result=\'" + test_result_string + "\' time=\'" + str(duration) + " s \' RESULT=\'" + testcase_verdict + "\'></testcase> \n"
-  write_file(xmlFile, xml, mode="w")
+  print(Style.RESET_ALL)
 
+  duration= testcase_time_stop - testcase_time_start
 
   test_result = dict(testcase_name=testcasename,
                      testcaseclass=testcaseclass, 
@@ -1647,7 +1749,17 @@ def handle_testcaseclass_softmodem_noS1 (testcase, oldprogramList, logdirOAI5GRe
                      testcase_eNBMachine =eNBMachine,
                      testcase_UEMachine =UEMachine,
                      runs_results = runs_results)
-  #test_results.append(test_result)
+  test_results.append(test_result)
+
+  xmlFile = logdir_local_testcase + '/test.' + testcasename + '.xml'
+  xml="\n<testcase classname=\'"+ testcaseclass +  "\' name=\'" + testcasename + "."+tags +  "\' Run_result=\'" + test_result_string + "\' time=\'" + str(duration) + " s \' RESULT=\'" + testcase_verdict + "\'></testcase> \n"
+  write_file(xmlFile, xml, mode="w")
+
+#  xmlFile_ng = logdir_local_testcase + '/test.' + testcasename + '_ng.xml'
+#  xml_ng = xmlify(test_result, wrap=testcasename, indent="  ")
+#  write_file(xmlFile_ng, xml_ng, mode="w")
+
+
 
   return testcase_verdict
 
@@ -1666,12 +1778,12 @@ def search_test_case_group(testcasename, testcasegroup, test_case_exclude):
           if entry.find('+') >=0:
             match = re.search(entry, testcasename)
             if match:
-               print "\nSkipping test case as it is found in black list: " + testcasename
+               #print "\nSkipping test case as it is found in black list: " + testcasename
                return False
           else:
              match = entry.find(testcasename)
              if match >=0:
-                print "\nSkipping test case as it is found in black list: " + testcasename
+                #print "\nSkipping test case as it is found in black list: " + testcasename
                 return False
     if testcasegroup == '':
          return True
@@ -1759,6 +1871,7 @@ if openairdir_local is None:
    print "Environment variable OPENAIR_DIR not set correctly"
    sys.exit()
 locallogdir = openairdir_local + '/cmake_targets/autotests/log'
+reportdir = openairdir_local + '/cmake_targets/autotests/report'
 MachineList = ''
 MachineListGeneric=''
 MachineDescDic={}
@@ -1767,12 +1880,19 @@ flag_start_testcase=False
 nruns_lte_softmodem=''
 flag_skip_git_head_check=False
 flag_skip_oai_install=False
+flag_skip_machine_preparation=False
+flag_skip_sanity_check=False
+flag_generate_html_report = False
 Timeout_cmd=''
 xmlInputFile=''
-print "Number of arguments argc = " + str(len(sys.argv))
+
+#print "Number of arguments argc = " + str(len(sys.argv))
 #for index in range(1,len(sys.argv) ):
 #  print "argv_" + str(index) + " : " + sys.argv[index]
 
+oai_list = []
+
+
 i=1
 while i < len (sys.argv):
     arg=sys.argv[i]
@@ -1832,9 +1952,15 @@ while i < len (sys.argv):
         i = i +1
     elif arg == '--skip-oai-install':
         flag_skip_oai_install=True
+    elif arg == '--skip-machine-preparation':
+        flag_skip_machine_preparation=True
+    elif arg == '--skip-sanity-check':
+        flag_skip_sanity_check=True
     elif arg == '--test-suite' :
         xmlInputFile = sys.argv[i+1]
         i = i +1
+    elif arg == '--generate-html-report':
+        flag_generate_html_report=True
     elif arg == '-h' :
         print "-s:  This flag *MUST* be set to start the test cases"
         print "-r:  Remove the log directory in autotests"
@@ -1852,90 +1978,65 @@ while i < len (sys.argv):
         print "--skip-git-head-check: skip checking of GitHead remote/local branch (only for debugging)"
         print "--timeout_cmd: Override the default parameter (timeout_cmd) in test_case_list.xml. This parameter is in seconds and should be > 120"
         print "--skip-oai-install: Skips the openairinterface5g installer"
+        print "--skip-machine-preparation: skipp the whole system preparation -> direct to test cases"
+        print "--skip-sanity-check: skipp the machine sanity checks"
         print "--test-suite: Select a XML test-suite file"
+        print "--generate-html-report: Generate an HTML report of the test campaign (supported only for noS1 testsuite !!)"
         sys.exit()
     else :
         print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options"
         sys.exit()
     i= i + 1     
 
-try:  
-   os.environ["OPENAIR1_DIR"]
-except KeyError: 
-   print "Please set the environment variable OPENAIR1_DIR in the .bashrc"
-   sys.exit(1)
-
-try:  
-   os.environ["OPENAIR2_DIR"]
-except KeyError: 
-   print "Please set the environment variable OPENAIR2_DIR in the .bashrc"
-   sys.exit(1)
-
-try:  
-   os.environ["OPENAIR_TARGETS"]
-except KeyError: 
-   print "Please set the environment variable OPENAIR_TARGETS in the .bashrc"
-   sys.exit(1)
-
-print "Killing zombie ssh sessions from earlier sessions..."
-cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"| awk \'{print $2}\' | sudo xargs kill -9  '
-
-os.system(cmd)
+logdir = '/tmp/' + 'OAITestFrameWork-' + user + '/'
+logdirOAI5GRepo = logdir + 'openairinterface5g/'
+logdirOpenaircnRepo = logdir + 'openair-cn/'
+patchdir = logdirOAI5GRepo + 'cmake_targets/autotests/patches/'
+NFSResultsDir = '/mnt/sradio'
+cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash'
 
-try:
-  analyser = __import__("lib_autotest_analyser")
-except ImportError as err:
-  print('Import error: ' + str(err))
-  exit(0)
+#Now we parse the xml file for basic configuration
+if xmlInputFile == '':
+  xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_list.xml"
+xmlTree = ET.parse(xmlInputFile)
+xmlRoot = xmlTree.getroot()
 
+#
+# Read test session configuration
+# ---------------------------------------------------------------------------------
+print (Fore.YELLOW + '\nStep 0.1 - Read test session configuration')
+print (Fore.YELLOW + '-------------------------------------------------')
 
-if flag_start_testcase == False:
-  print "You need to start the testcase by passing option -s. Use -h to see all options. Aborting now..."
-  sys.exit(1)
+test_session_start_time = datetime.datetime.now()
+print (Fore.WHITE + '  - start time                    : '+ str(test_session_start_time))
 
-# get the oai object
 host = os.uname()[1]
-#oai = openair('localdomain','calisson')
-oai_list = []
+print (Fore.WHITE + '  - MTC host                      : '+host)
+
 
-#start_time = time.time()  # datetime.datetime.now()
 if user=='':
   user = getpass.getuser()
+print (Fore.WHITE + '  - user                          : '+user)
+
 if pw=='':
   pw = getpass.getpass()
+print (Fore.WHITE + '  - password                      : '+pw)
 
-print "Killing zombie ssh sessions from earlier sessions..."
-cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 '
-cmd = cmd + '; ps aux |grep \"/usr/bin/ssh -q -l ' + user + '\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 '
-os.system(cmd)
-
-print "host = " + host 
-print "user = " + user
-if xmlInputFile == '':
-  xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_list.xml"
-NFSResultsDir = '/mnt/sradio'
-cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash'
-logdir = '/tmp/' + 'OAITestFrameWork-' + user + '/'
-logdirOAI5GRepo = logdir + 'openairinterface5g/'
-logdirOpenaircnRepo = logdir + 'openair-cn/'
-patchdir = logdirOAI5GRepo + 'cmake_targets/autotests/patches/'
-
-if flag_remove_logdir == True:
-   print "Removing directory: " + locallogdir
-   os.system(' rm -fr ' + locallogdir + '; mkdir -p ' +  locallogdir  )
-else:
-   os.system('mkdir -p  ' + locallogdir)
-
-paramiko_logfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/log/paramiko.log')
-res=os.system(' echo > ' + paramiko_logfile)
-paramiko.util.log_to_file(paramiko_logfile)
-
-#pw=getpass.getpass()
+print (Fore.WHITE + '  - cmd line flags                : ')
+print (Fore.WHITE + '    +  -s                         : '+str(flag_start_testcase))
+print (Fore.WHITE + '    +  -r                         : '+str(flag_remove_logdir))
+print (Fore.WHITE + '    +  -c                         : '+str(cleanUpRemoteMachines))
+print (Fore.WHITE + '    +  --skip-git-head-check      : '+str(flag_skip_git_head_check))
+print (Fore.WHITE + '    +  --skip-oai-install         : '+str(flag_skip_oai_install))
+print (Fore.WHITE + '    +  --skip-machine-preparation : '+str(flag_skip_machine_preparation))
+print (Fore.WHITE + '    +  --skip-sanity-check        : '+str(flag_skip_sanity_check))
 
-#Now we parse the xml file for basic configuration
-xmlTree = ET.parse(xmlInputFile)
-xmlRoot = xmlTree.getroot()
 
+print (Fore.WHITE + '  - Test setup basic config       : (* -> overwrite by cmd line parameter)')
+print (Fore.WHITE + '    +  test setup config file     : '+str(xmlInputFile))
+print (Fore.WHITE + '    +  remote setup dir           : '+str(logdir))
+print (Fore.WHITE + '    +  remote OAI5G repo          : '+str(logdirOAI5GRepo))
+print (Fore.WHITE + '    +  remote OpenAirCN repo      : '+str(logdirOpenaircnRepo))
 
 
 if MachineList =='':
@@ -1948,6 +2049,8 @@ if GitOAI5GRepo == '':
 
 if GitOAI5GRepoBranch == '':
    GitOAI5GRepoBranch = xmlRoot.findtext('GitOAI5GRepoBranch',default='')
+if GitOAI5GHeadVersion == '':
+   GitOAI5GHeadVersion = xmlRoot.findtext('GitOAI5GHeadVersion',default='')
 
 GitOpenaircnRepoBranch = xmlRoot.findtext('GitOpenair-cnRepoBranch',default='')
 CleanUpOldProgs = xmlRoot.findtext('CleanUpOldProgs',default='')
@@ -1960,25 +2063,27 @@ ExmimoRfStop = xmlRoot.findtext('ExmimoRfStop',default='')
 if nruns_lte_softmodem == '':
    nruns_lte_softmodem = xmlRoot.findtext('nruns_lte-softmodem',default='')
 
-OAI5GpatchFileList=xmlRoot.findall('OAI5GPatchFile')
+print (Fore.WHITE + '    +  MachineList                : '+ MachineList)
+print (Fore.WHITE + '    +  GitOpenair-cnRepo          : '+  GitOpenaircnRepo)
+print (Fore.WHITE + '    +  GitOAI5GRepo               : '+ GitOAI5GRepo)
+print (Fore.WHITE + '    +  GitOAI5GBranch             : '+ GitOAI5GRepoBranch)
+print (Fore.WHITE + '    +  GitOpenaircnRepoBranch     : '+ GitOpenaircnRepoBranch)
+print (Fore.WHITE + '    +  NFSResultsShare            : '+ NFSResultsShare)
+print (Fore.WHITE + '    +  nruns_lte_softmodem        : '+ nruns_lte_softmodem)
+print (Fore.WHITE + '    +  Timeout_cmd                : '+ Timeout_cmd)
 
-print "MachineList = " + MachineList
-print "GitOpenair-cnRepo = " + GitOpenaircnRepo
-print "GitOAI5GRepo = " + GitOAI5GRepo
-print "GitOAI5GBranch = " + GitOAI5GRepoBranch
-print "GitOpenaircnRepoBranch = " + GitOpenaircnRepoBranch
-print "NFSResultsShare = " + NFSResultsShare
-print "nruns_lte_softmodem = " + nruns_lte_softmodem
-print "Timeout_cmd = " + Timeout_cmd
 
 if GitOAI5GHeadVersion == '':
-  cmd = "git show-ref --heads -s "+ GitOAI5GRepoBranch
+  cmd = "git log --pretty=format:\'%H\' -n 1" # origin/"+ GitOAI5GRepoBranch
+#  cmd = "git show-ref --heads -s "+ GitOAI5GRepoBranch
   GitOAI5GHeadVersion = subprocess.check_output ([cmd], shell=True)
   GitOAI5GHeadVersion=GitOAI5GHeadVersion.replace("\n","")
 
-print "GitOAI5GHeadVersion = " + GitOAI5GHeadVersion
-print "CleanUpOldProgs = " + CleanUpOldProgs
-print "Timeout_execution = " + str(Timeout_execution)
+ # Print commiter and date : git log -1 --pretty=format:"%an %ad" 
+
+print (Fore.WHITE + '    +  GitOAI5GHeadVersion        : '+  GitOAI5GHeadVersion)
+#print "CleanUpOldProgs = " + CleanUpOldProgs
+print (Fore.WHITE + '    +  Timeout_execution (s)      : '+  str(Timeout_execution))
 
 if GitOAI5GHeadVersion == '':
   print "Error getting the OAI5GBranch Head version...Exiting"
@@ -1986,214 +2091,401 @@ if GitOAI5GHeadVersion == '':
 
 NFSTestsResultsDir = NFSResultsShare + '/'+ GitOAI5GRepoBranch + '/' + GitOAI5GHeadVersion
 
-print "NFSTestsResultsDir = " + NFSTestsResultsDir
+#print "NFSTestsResultsDir = " + NFSTestsResultsDir
+
+OAI5GpatchFileList=xmlRoot.findall('OAI5GPatchFile')
+
+
 
 MachineList = MachineList.split()
 MachineListGeneric = MachineListGeneric.split()
 
-#index=0
+
+MachineDescDic
+
+
+#
+# 'Check Mater Test Controller sanity (MTC)'
+# ---------------------------------------------------------------------------------
+print (Fore.YELLOW + '\nStep 0.2 - Check Mater Test Controller sanity (MTC)')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+try:
+  print (Fore.WHITE + '  - check OpenAirInterface environment variable OPENAIR1_DIR... '),
+  os.environ["OPENAIR1_DIR"]
+except KeyError:
+    print (Fore.RED + 'FAILED')
+    print "Please set the environment variable OPENAIR1_DIR in the .bashrc or run 'source oaienv' "
+    exit_prog(1)
+print (Fore.GREEN + 'OK')
+
+try:
+  print (Fore.WHITE + '  - check OpenAirInterface environment variable OPENAIR2_DIR... '),
+  os.environ["OPENAIR2_DIR"]
+except KeyError: 
+  print (Fore.RED + 'FAILED')
+  print "Please set the environment variable OPENAIR2_DIR in the .bashrc or run 'source oaienv' "
+  exit_prog(1)
+print (Fore.GREEN + 'OK')
+
+try:  
+   os.environ["OPENAIR_TARGETS"]
+except KeyError: 
+   print "Please set the environment variable OPENAIR_TARGETS in the .bashrc or run 'source oaienv' "
+   sexit_prog(1)
+
+print (Fore.WHITE + '  - kill zombie ssh sessions from earlier sessions...         '),
+cmd='ps aux |grep \"/usr/bin/ssh -q -l ' + user + '\"| tr -s \" \" :| cut -f 2 -d :| xargs kill -9 '
+os.system(cmd)
+print (Fore.GREEN + 'DONE')
+
+if flag_start_testcase == False:
+  print "You need to start the testcase by passing option -s. Use -h to see all options. Aborting now..."
+  exit_prog(1)
+
+  
+#print "Killing zombie ssh sessions from earlier sessions..."
+#cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 '
+#cmd = cmd + '; ps aux |grep \"/usr/bin/ssh -q -l ' + user + '\"| tr -s \" \" :| cut -f 2 -d :| xargs kill -9 '
+#os.system(cmd)
+#print cmd
+
+try:
+  analyser = __import__("lib_autotest_analyser")
+except ImportError as err:
+  print('Import error: ' + str(err))
+  exit(0)
+
+if flag_remove_logdir == True:
+   print "Removing directory: " + locallogdir
+   os.system(' rm -fr ' + locallogdir + '; mkdir -p ' +  locallogdir  )
+   
+if not os.path.exists(locallogdir):
+	os.system('mkdir -p ' +  locallogdir  )
+
+
+paramiko_logfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/log/paramiko.log')
+res=os.system(' echo > ' + paramiko_logfile)
+paramiko.util.log_to_file(paramiko_logfile)
+
+
+#
+# 'REMOTE MACHINE SANITY CHEKS'
+# ---------------------------------------------------------------------------------
+print (Fore.YELLOW + '\nStep 0.3 - REMOTE MACHINE SANITY CHEKS')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+
 for machine in MachineList: 
   oai_list.append( openair('localdomain',machine))
   MachineDescDic[machine]={}
-  #index = index + 1
 
 
-print "\nTesting the sanity of machines used for testing..."
-if localshell == 0:
+if not flag_skip_sanity_check:
+
+  if localshell == 0:
     try:
-        index=0
-        for machine in MachineList:
-           print '\n******* Note that the user <'+user+'> should be a sudoer *******\n'
-           print '******* Connecting to the machine <'+machine+'> to perform the test *******\n'
-           if not pw :
-              print "username: " + user 
-              #pw = getpass.getpass() 
-              #print "password: " + pw            
-           else :
-              print "username: " + user 
-              #print "password: " + pw 
-           # issues in ubuntu 12.04
-           oai_list[index].connect(user,pw)
-           print '\nChecking for sudo permissions on machine <'+machine+'>...'
-           result = oai_list[index].send_expect_false('sudo -S -v','may not run sudo',True)
-           print "Sudo permissions..." + result
-           
-           print '\nCleaning Older running programs : ' + CleanUpOldProgs
-           cleanOldPrograms(oai_list[index], CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop, '$HOME', '/tmp')
-
-           #result = oai_list[index].send('mount ' + NFSResultsDir, True)
-           #print "Mounting NFS Share " + NFSResultsDir + "..." + result
-
-           # Check if NFS share is mounted correctly.
-           #print 'Checking if NFS Share<' + NFSResultsDir + '> is mounted correctly...'
-           #cmd = 'if grep -qs '+NFSResultsDir+ ' /proc/mounts; then  echo \'' + NFSResultsDir  + ' is mounted\' ; fi'
-           #search_expr = NFSResultsDir + ' is mounted'
-           #print "cmd = " + cmd
-           #print "search_expr = " + search_expr
-           #result = oai_list[index].send_expect(cmd, search_expr)
-           #print "Mount NFS_Results_Dir..." + result
-           index = index + 1
-           
-           #oai.connect2(user,pw) 
-           #oai.get_shell()
+      index=0
+      for machine in MachineList:
+        print (Fore.WHITE + "  - Check sanity for remote machine "+machine)
+
+        oai_list[index].connect(user,pw)
+        print (Fore.WHITE + "    > Checking for sudo permissions for user "+user+ " : "),
+        result = oai_list[index].send_expect_false('sudo -S -v','may not run sudo',True)
+        if (result == 'OK'):
+          print (Fore.GREEN + result )
+        else:
+          print (Fore.RED + result )
+         
+        print (Fore.WHITE + "    > Cleaning Older running programs : "),
+        cleanOldPrograms(oai_list[index], CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop, '$HOME', '/tmp')
+        print (Fore.WHITE + " Done")
+
+        #result = oai_list[index].send('mount ' + NFSResultsDir, True)
+        #print "Mounting NFS Share " + NFSResultsDir + "..." + result
+
+        # Check if NFS share is mounted correctly.
+        #print 'Checking if NFS Share<' + NFSResultsDir + '> is mounted correctly...'
+        #cmd = 'if grep -qs '+NFSResultsDir+ ' /proc/mounts; then  echo \'' + NFSResultsDir  + ' is mounted\' ; fi'
+        #search_expr = NFSResultsDir + ' is mounted'
+        #print "cmd = " + cmd
+        #print "search_expr = " + search_expr
+        #result = oai_list[index].send_expect(cmd, search_expr)
+        #print "Mount NFS_Results_Dir..." + result
+        index = index + 1
+
+        #oai.connect2(user,pw) 
+        #oai.get_shell()
     except :
         print 'Fail to connect to the machine: '+ machine 
         sys.exit(1)
+  else:
+      pw = ''
+      oai_list[0].connect_localshell()
 else:
-    pw = ''
-    oai_list[0].connect_localshell()
+  print (Fore.RED + "  Skipping Machine sanity check...")
+
+#
+# 'REMOTE MACHINE TEST SETUP CONFIGURATION'
+# ---------------------------------------------------------------------------------
+print (Fore.YELLOW + '\nStep 0.4 - REMOTE MACHINE PREPARATION')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+if not flag_skip_machine_preparation:
+  index=0
+  threads_init_setup=[]
+  for oai in oai_list:
+    try:
+        print "setting up machine: " + MachineList[index]
+        #print oai_list[oai].send_recv('echo \''+pw+'\' |sudo -S -v')
+        #print oai_list[oai].send_recv('sudo su')
+        #print oai_list[oai].send_recv('who am i') 
+        #cleanUpPrograms(oai_list[oai]
+        cmd = 'sudo -S -E rm -fr ' + logdir + ' ; mkdir -p ' + logdir 
+        result = oai.send_recv(cmd)
+        print cmd
+
+        setuplogfile  = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
+        setup_script  = locallogdir  + '/setup_script_' + MachineList[index] +  '_.txt'
+
+        #Sometimes git fails so the script below retries in that case
+        localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/git-retry.sh')
+        remotefile = logdir + '/git-retry.sh'
+        paramList=[]
+        port=22
+        paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
+        sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
+        sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
+
+        cmd = ' ( \n'
+        #cmd = cmd  + 'rm -fR ' +  logdir + '\n'
+        #cmd = cmd + 'mkdir -p ' + logdir + '\n'
+        cmd = cmd + 'cd '+ logdir   + '\n'
+        cmd = cmd + 'sudo apt-get install -y git \n'
+        cmd = cmd + 'chmod 700 ' + logdir + '/git-retry.sh \n' 
+        cmd = cmd + logdir + '/git-retry.sh clone  '+ GitOAI5GRepo  +' \n'
+        cmd = cmd + logdir + '/git-retry.sh clone '+ GitOpenaircnRepo + ' \n'
+        cmd = cmd +  'cd ' + logdirOAI5GRepo  + '\n'
+        cmd = cmd + 'git checkout ' + GitOAI5GRepoBranch   + '\n'
+        if GitOAI5GHeadVersion :
+          cmd = cmd + 'git checkout ' + GitOAI5GHeadVersion   + '\n'
+        cmd = cmd + 'git_head=`git ls-remote |grep \'' + GitOAI5GRepoBranch + '\'` \n'
+        cmd = cmd + 'git_head=($git_head) \n'
+        cmd = cmd + 'git_head=${git_head[0]} \n'
+        cmd = cmd + 'echo \"GitOAI5GHeadVersion_remote = $git_head\" \n'
+        cmd = cmd + 'echo \"GitOAI5GHeadVersion_local = ' + GitOAI5GHeadVersion + '\" \n'
+        if flag_skip_git_head_check==True:
+           cmd = cmd + 'echo \"skipping GitHead check...\" \n '
+        else:
+           cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi \n'
+        cmd = cmd + 'source oaienv'   + '\n'
+        if flag_skip_oai_install == False:
+           cmd = cmd + 'source $OPENAIR_DIR/cmake_targets/tools/build_helper \n'
+           cmd = cmd + 'echo \"Installing core OAI dependencies...Start\" \n'
+           cmd = cmd + '$OPENAIR_DIR/cmake_targets/build_oai -I --install-optional-packages \n'
+           cmd = cmd + 'echo \"Installing core OAI dependencies...Finished\" \n'
+           #cmd = cmd + 'echo \"Installing BLADERF OAI dependencies...Start\" \n'
+           #cmd = cmd + 'check_install_bladerf_driver \n'
+           #cmd = cmd + 'echo \"Installing BLADERF OAI dependencies...Finished\" \n'
+           #cmd = cmd + 'echo \"Installing USRP OAI dependencies...Start\" \n'
+           #cmd = cmd + 'check_install_usrp_uhd_driver \n'
+           #cmd = cmd + 'echo \"Installing USRP OAI dependencies...Finished\" \n'
+        cmd = cmd +  'cd ' + logdirOpenaircnRepo  + '\n'
+        cmd = cmd +  'git checkout ' + GitOpenaircnRepoBranch  + '\n'
+        cmd = cmd +  'env |grep OPENAIR'  + '\n'
+        cmd = cmd + ' cd ' + logdir   + '\n'
+        cmd = cmd + 'mkdir -p ' + patchdir + '\n'
+        cmd = cmd + ' ) > ' +  setuplogfile + ' 2>&1 \n'
+        #cmd = cmd + 'echo \' ' + cmd  + '\' > ' + setup_script + ' 2>&1 \n '
+        #result = oai_list[index].send_recv(cmd, False, 300 )
+        write_file(setup_script, cmd, mode="w")
+        tempThread = oaiThread(index, 'thread_setup_'+str(index)+'_' + MachineList[index] , MachineList[index] , user, pw, cmd, False, 3000)
+        threads_init_setup.append(tempThread )
+        tempThread.start()
+        index = index + 1
+    except Exception, e:
+           print 'There is error in one of the commands to setup the machine '+ MachineList[index] 
+           error=''
+           error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: '  + str(e.__class__) + " : " + str( e)
+           error = error + traceback.format_exc()
+           print error
+           sys.exit(1)
 
-#We now prepare the machines for testing
-index=0
-threads_init_setup=[]
-for oai in oai_list:
-  try:
-      print "setting up machine: " + MachineList[index]
-      #print oai_list[oai].send_recv('echo \''+pw+'\' |sudo -S -v')
-      #print oai_list[oai].send_recv('sudo su')
-      #print oai_list[oai].send_recv('who am i') 
-      #cleanUpPrograms(oai_list[oai]
-      cmd = 'sudo -S -E rm -fr ' + logdir + ' ; mkdir -p ' + logdir 
-      result = oai.send_recv(cmd)
+  #Now we wait for all the threads to complete
+  index = 0
+  for t in threads_init_setup:
+    t.join()
+
+    port = 22
+    paramList=[]
+    sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
+
+    #Now we copy patch files and apply them
+    print( Fore.WHITE + "  - Installating patch files on machine " + MachineList[index])
+    for patchFile in OAI5GpatchFileList:
+      localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/patches/')+patchFile.get('name')
+      remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/patches/'+patchFile.get('name')
+      if patchFile.get('machine') == MachineList[index] or patchFile.get('machine') == None:     
+        if os.path.isfile(localfile):
+          print( Fore.WHITE + "\t> PATCH FILE :"+localfile)
+          paramList=[]
+          paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
+          sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
+          cmd =  '  cd ' + logdirOAI5GRepo + ' ;git apply cmake_targets/autotests/patches/'+patchFile.get('name')
+          res = oai_list[index].send_recv(cmd)
+          #print res
      
-      setuplogfile  = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
-      setup_script  = locallogdir  + '/setup_script_' + MachineList[index] +  '_.txt'
-
-      #Sometimes git fails so the script below retries in that case
-      localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/git-retry.sh')
-      remotefile = logdir + '/git-retry.sh'
-      paramList=[]
-      port=22
-      paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
-      sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
-      sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
-
-
-      cmd = ' ( \n'
-      #cmd = cmd  + 'rm -fR ' +  logdir + '\n'
-      #cmd = cmd + 'mkdir -p ' + logdir + '\n'
-      cmd = cmd + 'cd '+ logdir   + '\n'
-      cmd = cmd + 'sudo apt-get install -y git \n'
-      cmd = cmd + 'chmod 700 ' + logdir + '/git-retry.sh \n' 
-      cmd = cmd + logdir + '/git-retry.sh clone  '+ GitOAI5GRepo  +' \n'
-      cmd = cmd + logdir + '/git-retry.sh clone '+ GitOpenaircnRepo + ' \n'
-      cmd = cmd +  'cd ' + logdirOAI5GRepo  + '\n'
-      cmd = cmd + 'git checkout ' + GitOAI5GRepoBranch   + '\n'                      
-      #cmd = cmd + 'git checkout ' + GitOAI5GHeadVersion   + '\n'
-      cmd = cmd + 'git_head=`git ls-remote |grep \'' + GitOAI5GRepoBranch + '\'` \n'
-      cmd = cmd + 'git_head=($git_head) \n'
-      cmd = cmd + 'git_head=${git_head[0]} \n'
-      cmd = cmd + 'echo \"GitOAI5GHeadVersion_remote = $git_head\" \n'
-      cmd = cmd + 'echo \"GitOAI5GHeadVersion_local = ' + GitOAI5GHeadVersion + '\" \n'
-      if flag_skip_git_head_check==True:
-         cmd = cmd + 'echo \"skipping GitHead check...\" \n '
-      else:
-         cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi \n'
-      cmd = cmd + 'source oaienv'   + '\n'
-      if flag_skip_oai_install == False:
-         cmd = cmd + 'source $OPENAIR_DIR/cmake_targets/tools/build_helper \n'
-         cmd = cmd + 'echo \"Installing core OAI dependencies...Start\" \n'
-         cmd = cmd + '$OPENAIR_DIR/cmake_targets/build_oai -I --install-optional-packages \n'
-         cmd = cmd + 'echo \"Installing core OAI dependencies...Finished\" \n'
-         #cmd = cmd + 'echo \"Installing BLADERF OAI dependencies...Start\" \n'
-         #cmd = cmd + 'check_install_bladerf_driver \n'
-         #cmd = cmd + 'echo \"Installing BLADERF OAI dependencies...Finished\" \n'
-         #cmd = cmd + 'echo \"Installing USRP OAI dependencies...Start\" \n'
-         #cmd = cmd + 'check_install_usrp_uhd_driver \n'
-         #cmd = cmd + 'echo \"Installing USRP OAI dependencies...Finished\" \n'
-      cmd = cmd +  'cd ' + logdirOpenaircnRepo  + '\n'
-      cmd = cmd +  'git checkout ' + GitOpenaircnRepoBranch  + '\n'
-      cmd = cmd +  'env |grep OPENAIR'  + '\n'
-      cmd = cmd + ' cd ' + logdir   + '\n'
-      cmd = cmd + 'mkdir -p ' + patchdir + '\n'
-      cmd = cmd + ' ) > ' +  setuplogfile + ' 2>&1 \n'
-      #cmd = cmd + 'echo \' ' + cmd  + '\' > ' + setup_script + ' 2>&1 \n '
-      #result = oai_list[index].send_recv(cmd, False, 300 )
-      write_file(setup_script, cmd, mode="w")
-      tempThread = oaiThread(index, 'thread_setup_'+str(index)+'_' + MachineList[index] , MachineList[index] , user, pw, cmd, False, 3000)
-      threads_init_setup.append(tempThread )
-      tempThread.start()
-      index = index + 1
-  except Exception, e:
-         print 'There is error in one of the commands to setup the machine '+ MachineList[index] 
-         error=''
-         error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: '  + str(e.__class__) + " : " + str( e)
-         error = error + traceback.format_exc()
-         print error
-         sys.exit(1)
+    paramList=[]
 
-#Now we wait for all the threads to complete
-index = 0
-for t in threads_init_setup:
-   t.join()
-   setuplogfile  = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
-   setup_script  = locallogdir  + '/setup_script_' + MachineList[index] +  '_.txt'
-   localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt'
-   remotefile = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
-   port = 22
-
-   #Now we copy patch files and apply them
-   print "Installating patch files on machine " + MachineList[index]
-   for patchFile in OAI5GpatchFileList:
-     localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/patches/')+patchFile.get('name')
-     remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/patches/'+patchFile.get('name')
-     if patchFile.get('machine') == MachineList[index] or patchFile.get('machine') == None:     
-       if os.path.isfile(localfile):
-         print "\t> PATCH FILE :"+localfile
-         paramList=[]
-         paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
-         sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
-         cmd =  '  cd ' + logdirOAI5GRepo + ' ;git apply cmake_targets/autotests/patches/'+patchFile.get('name')
-         res = oai_list[index].send_recv(cmd)
-   
-   paramList=[]
-
-   setuplogfile  = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
-   setup_script  = locallogdir  + '/setup_script_' + MachineList[index] +  '_.txt'
-   localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt'
-   remotefile = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
-   sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
-   paramList.append ( {"operation":'get', "localfile":localfile, "remotefile":remotefile} )
-   #sftp_module (user, pw, MachineList[index], port, localfile, remotefile, sftp_log, "get")
-
-   #Now we copy test_case_list.xml on the remote machines
-   localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/test_case_list.xml')
-   remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/test_case_list.xml'
-   paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
-   sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
-   sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
-
-   cmd =  '  cd ' + logdirOAI5GRepo + ' ; source oaienv ; env|grep OPENAIR \n'
-   res = oai_list[index].send_recv(cmd)
-   index  = index +1
-   if os.path.exists(localfile) == 0:
+    setuplogfile  = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
+    setup_script  = locallogdir  + '/setup_script_' + MachineList[index] +  '_.txt'
+    localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt'
+    remotefile = logdir  + '/setup_log_' + MachineList[index] + '_.txt'
+    sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log')
+    paramList.append ( {"operation":'get', "localfile":localfile, "remotefile":remotefile} )
+    #sftp_module (user, pw, MachineList[index], port, localfile, remotefile, sftp_log, "get")
+
+    #Now we copy test_case_list.xml on the remote machines
+    localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/test_case_list.xml')
+    remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/test_case_list.xml'
+    # paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} )
+    #     sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
+
+    sftp_module (user, pw, MachineList[index], port, paramList, sftp_log)
+
+
+    cmd =  '  cd ' + logdirOAI5GRepo + ' ; source oaienv ; env|grep OPENAIR \n'
+    res = oai_list[index].send_recv(cmd)
+    index  = index +1
+    if os.path.exists(localfile) == 0:
       print "Setup log file <" + localfile + "> missing for machine <" + MachineList[index] + ">.  Please check the setup log files. Exiting now"
       sys.exit(1)
 
-#Now we process all the test cases
-#Now we check if there was error in setup files
+  #Now we process all the test cases
+  #Now we check if there was error in setup files
 
-status, out = commands.getstatusoutput('grep ' +  ' -il \'error\' ' + locallogdir + '/setup_log*')
-if (out != '') :
-  print "There is error in setup of machines"
-  print "status  = " + str(status) + "\n Check files for error = " + out
-  print "Exiting now..."
-  sys.exit(1)
+  status, out = commands.getstatusoutput('grep ' +  ' -il \'error\' ' + locallogdir + '/setup_log*')
+  if (out != '') :
+    print "There is error in setup of machines"
+    print "status  = " + str(status) + "\n Check files for error = " + out
+    print "Exiting now..."
+    sys.exit(1)
+
+  cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop, '$HOME' , logdirOAI5GRepo)
+  if cleanUpRemoteMachines == True:
+    print "Error while cleaning Remote machines"
+    print "Exiting now..."
+    sys.exit(0)
+
+
+else:
+  print (Fore.RED + "  Skipping Machine preparation...")
+
+# **************************************************************************
+# **************************************************************************
+#           STEP 2 - TEST SELECTION AND PARAMETRIZATION
+# **************************************************************************
+# **************************************************************************
+
+print (Fore.YELLOW + '\nStep 2 - TEST SELECTION')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+print (Fore.WHITE + "  Parsing test case list for test selection...")
+print (Fore.WHITE + "  - TestCaseExclusionList      : "+TestCaseExclusionList)
+print (Fore.WHITE + "  - testcasegroup              : "+testcasegroup)
 
-cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop, '$HOME' , logdirOAI5GRepo)
-if cleanUpRemoteMachines == True:
-  sys.exit(0)
 
-threadListGlobal=[]
 testcaseList=xmlRoot.findall('testCase')
-#print testcaseList
+
+nb_total_testcases              = 0
+nb_total_testcases_softmodem    = 0
+nb_total_testcases_softmodem_noS1 = 0
+nb_total_testcases_compilation  = 0
+nb_total_testcases_execution    = 0
+
+nb_run_testcases                = 0
+nb_run_testcases_softmodem      = 0
+nb_run_testcases_softmodem_noS1 = 0
+nb_run_testcases_compilation    = 0
+nb_run_testcases_execution      = 0
+
+
+for testcase in testcaseList:
+  try:
+    testcasename = testcase.get('id')
+    testcaseclass = testcase.findtext('class',default='')
+    desc = testcase.findtext('desc',default='')
+    nb_total_testcases+=1
+
+    run_flag = search_test_case_group(testcasename, testcasegroup, TestCaseExclusionList)
+    if (run_flag):
+      nb_run_testcases+=1
+
+    if testcaseclass == 'lte-softmodem' :
+      nb_total_testcases_softmodem+=1
+      if (run_flag): nb_run_testcases_softmodem+=1
+    elif testcaseclass == 'lte-softmodem-noS1':  
+      nb_total_testcases_softmodem_noS1+=1
+      if (run_flag): nb_run_testcases_softmodem_noS1+=1
+    elif testcaseclass == 'compilation':
+      nb_total_testcases_compilation+=1 
+      if (run_flag): nb_run_testcases_compilation+=1
+    elif testcaseclass == 'execution': 
+      nb_total_testcases_execution+=1
+      if (run_flag): nb_run_testcases_execution+=1
+    else :
+      print "Unknown test case class: " + testcaseclass
+      sys.exit()
+
+  except Exception, e:
+     error=''
+     error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: '  + str(e.__class__) + " : " + str( e)
+     error = error + '\n testcasename = ' + testcasename + '\n testcaseclass = ' + testcaseclass + '\n desc = ' + 'desc' + '\n'  
+     error = error + traceback.format_exc()
+     print error
+     print "Continuing to next test case..."
+
+print (Fore.WHITE + "  Parsing done...")
+
+print (Fore.WHITE + "  - Total number of test cases        : "+str(nb_total_testcases))
+print (Fore.WHITE + "  - Total number class softmodem      : "+str(nb_total_testcases_softmodem))
+print (Fore.WHITE + "  - Total number class softmodem-noS1 : "+str(nb_total_testcases_softmodem_noS1))
+print (Fore.WHITE + "  - Total number class compilation    : "+str(nb_total_testcases_compilation))
+print (Fore.WHITE + "  - Total number class execution      : "+str(nb_total_testcases_execution))
+print
+print (Fore.WHITE + "  - Selected number of test cases     : "+str(nb_run_testcases))
+print (Fore.WHITE + "  - Selected class softmodem          : "+str(nb_run_testcases_softmodem))
+print (Fore.WHITE + "  - Selected class softmodem_noS1     : "+str(nb_run_testcases_softmodem_noS1))
+print (Fore.WHITE + "  - Selected class compilation        : "+str(nb_run_testcases_compilation))
+print (Fore.WHITE + "  - Selected class execution          : "+str(nb_run_testcases_execution))
+
+
+# **************************************************************************
+# **************************************************************************
+#           STEP 3 - TEST CAMPAIGNS
+# **************************************************************************
+# **************************************************************************
+
+test_results = []
+
+
+print (Fore.YELLOW + '\nStep 3 - TEST CAMPAIGNS')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+print (Fore.WHITE + "  Start test campaign...")
+
+threadListGlobal=[]
+run_count = 0
 for testcase in testcaseList:
   try:
     testcasename = testcase.get('id')
     testcaseclass = testcase.findtext('class',default='')
     desc = testcase.findtext('desc',default='')
     #print "Machine list top level = " + ','.join(MachineList)
+
     if search_test_case_group(testcasename, testcasegroup, TestCaseExclusionList) == True:
+      run_count+=1
+      print (Fore.WHITE + "  ("+str(run_count).zfill(3)+"/"+str(nb_run_testcases).zfill(3)+") - test case "+testcasename+" : "),
       if testcaseclass == 'lte-softmodem' :
         #First we wait for all the test cases in generic test case class to finish as they are running in parallel
         threadListGlobal = wait_testcaseclass_generic_threads(threadListGlobal, Timeout_execution)
@@ -2266,6 +2558,22 @@ for param in threadListGlobal:
    thread_id = param["thread_id"]
    thread_id.join()
 
+
+# **************************************************************************
+# **************************************************************************
+#           STEP 4 - TEST REPORT PRODUCTION
+# **************************************************************************
+# **************************************************************************
+
+
+
+test_session_stop_time = datetime.datetime.now()
+
+print (Fore.YELLOW + '\nStep 4 - TEST REPORT PRODUCTION')
+print (Fore.YELLOW + '-------------------------------------------------')
+
+# XML test report
+# --------------------------------------------------------------------
 print "Creating xml file for overall results..."
 cmd = "cat $OPENAIR_DIR/cmake_targets/autotests/log/*/*.xml > $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml "
 res=os.system(cmd)
@@ -2284,4 +2592,43 @@ res = oai_localhost.send_recv(cmd)
  
 oai_localhost.disconnect()
 
+
+# HTML test report
+# --------------------------------------------------------------------
+if flag_generate_html_report:
+  
+  print "Creating html test report..."
+
+  report_dir = reportdir + '/'+ test_session_start_time.strftime("%Y-%m-%d_%H-%M")+"_"+host
+
+  cmd = 'mkdir -p ' + report_dir
+  result = os.system(cmd)
+
+  cmd = 'cp -r '+locallogdir+' '+report_dir
+  result = os.system(cmd)
+
+  context = {
+      'report_path' : report_dir,
+      'test_session_start_time' : test_session_start_time,
+      'test_session_stop_time'  : test_session_stop_time,
+      'test_session_duration'   : test_session_stop_time-test_session_start_time,    
+      'mtc_host'                : host,
+      'user'                    : user,
+      'password'                : pw,
+      'test_results'            : test_results,  
+  }
+
+  for test_result in test_results:
+    cmd = 'mkdir -p ' + report_dir + '/'+ test_result['testcase_name']
+    result = os.system(cmd)
+
+    report_file = report_dir + '/'+ test_result['testcase_name'] + '/'+ test_result['testcase_name']+ '_report.html'
+
+    analyser.create_test_report_detailed_html(test_result, report_file )
+
+   # print test_result
+
+  analyser.create_report_html(context)
+
+
 sys.exit()
diff --git a/cmake_targets/autotests/templates/index.html b/cmake_targets/autotests/templates/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..10a15fb53da1438dae34eee9cf16dd6eaabd111c
--- /dev/null
+++ b/cmake_targets/autotests/templates/index.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8"/>
+    <title>OAI5G UE Autotest Report</title>
+    <script type="text/javascript">
+    function showhide(id) {
+      var e = document.getElementById(id);
+     e.style.display = (e.style.display == 'block') ? 'none' : 'block';
+    }
+</script>
+</head>
+<style>
+table, th, td {
+    border: 1px solid black;
+    border-collapse: collapse;
+    padding: 5px;
+}
+</style>
+<body>
+<center>
+<h2>OAI5G UE Autotest Report</h2>
+</center>
+
+<p>
+  <table border>
+    <caption>Test session configuration</caption>
+    <tr><td>Start time</td><td>{{test_session_start_time}}</td></tr>
+    <tr><td>Stop time</td><td>{{test_session_stop_time}}</td></tr>
+    <tr><td>Duration</td><td>{{test_session_duration}}</td></tr>    
+    <tr><td>MTC host</td><td>{{mtc_host}}</td></tr>
+    <tr><td>User</td><td>{{user}}</td></tr>
+    <tr><td>Password</td><td>{{password}}</td></tr>
+  </table>
+</p>
+
+
+<h3>Test Setup</h3>
+To be complete
+
+<br></br>
+<h3>UE phy-test performances tests results</h3>
+<h4>Objectives</h4>
+<p>Checks that OAI UE can achieve at least 75 percent of the theoretical throughput.</p>
+<p>Tests are done for all MCS (0 to 28) for 5MHz and 10MHz bandwidth.</p>
+<h4>Results</h4>
+
+<table>
+<TR><TH>ID</TH><TH>TAG</TH><TH>VERDICT</TH><TH>NB RUNS</TH><TH>PASS</TH><TH>FAILED</TH><TH>INCON</TH><TH>SKIPPED</TH><TH>SEG FAULT</TH><TH>TC Timeout</TH><TH>Start</TH><TH>Stop</TH><TH>Duration</TH><TH>Details</TH></TR>
+{% for result in test_results|sort(attribute='testcase_name') %}
+<TR>
+   <TD >{{result.testcase_name}}</TD>
+   <TD align="right">{{result.tags}}</TD>
+   {% if result.testcase_verdict == "PASS" %}
+      <TD align="center" style="background-color:green">{{result.testcase_verdict}}</TD>
+   {% elif result.testcase_verdict == "FAIL" %}
+      <TD align="center" style="background-color:red">{{result.testcase_verdict}}</TD>
+   {% else %}
+      <TD align="center" style="background-color:orange">{{result.testcase_verdict}}</TD>
+   {% endif %}
+   <TD align='center'>{{result.nruns}}</TD>
+   <TD align='center'>{{result.nb_run_pass}}</TD>
+   <TD align='center'>{{result.nb_run_failed}}</TD>
+   <TD align='center'>{{result.nb_run_inc}}</TD>  
+   <TD align='center'>{{result.nb_run_skip}}</TD>  
+   <TD align='center'>{{result.nb_seg_fault}}</TD>  
+   <TD >{{result.testcase_timeout}}</TD>
+   <TD >{{result.testcase_time_start.strftime('%Y-%m-%d %H:%M:%S')}}</TD>
+   <TD >{{result.testcase_time_stop.strftime('%Y-%m-%d %H:%M:%S')}}</TD>
+   <TD >{{result.testcase_duration}}</TD>
+   <TD ><a href="{{ result.testcase_name }}/{{ result.testcase_name }}_report.html">{{ result.testcase_name }}_report.html</a></TD>  
+</TR>
+{% endfor %}
+</table>
+
+
+<br></br>
+<h3>UE phy-test stability tests results</h3>
+<h4>Objectives</h4>
+<p>To be complete</p>
+<h4>Results</h4>
+To be complete
+
+</table>
+</body>
+</html>
+
diff --git a/cmake_targets/autotests/templates/testcase_report.html b/cmake_targets/autotests/templates/testcase_report.html
new file mode 100644
index 0000000000000000000000000000000000000000..007ab56909b9827dab6991427e25babe01f17c15
--- /dev/null
+++ b/cmake_targets/autotests/templates/testcase_report.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8"/>
+    <title>OAI5G UE test case report</title>
+    <script type="text/javascript">
+    function showhide(id) {
+      var e = document.getElementById(id);
+     e.style.display = (e.style.display == 'block') ? 'none' : 'block';
+    }
+</script>
+</head>
+<style>
+table, th, td {
+    border: 1px solid black;
+    border-collapse: collapse;
+    padding: 5px;
+}
+</style>
+<body>
+<center>
+<h2>OAI5G UE test case report details</h2>
+</center>
+
+<h3>Test Case description</h3>
+<p>
+  <table border>
+
+    <tr><td>ID</td><td>{{testcase_name}}</td></tr>
+    <tr><td>TAG</td><td>{{tags}}</td></tr>
+    <tr><td>class</td><td>{{testcaseclass}}</td></tr>
+    <tr><td>description</td><td></td></tr>
+    <tr><td>timeout</td><td>{{testcase_timeout}}</td></tr>
+    <tr><td>number of runs</td><td>{{nruns}}</td></tr>
+    <tr><td>eNB machine</td><td>{{testcase_eNBMachine}}</td></tr>
+    <tr><td>UE machine</td><td>{{testcase_UEMachine}}</td></tr>
+
+  </table>
+</p>
+
+
+<h3>Test Case execution</h3>
+<p>
+  <table border>
+
+    <tr><td>testcase_time_start</td><td>{{testcase_time_start}}</td></tr>
+    <tr><td>testcase_time_stop</td><td>{{testcase_time_stop}}</td></tr>
+    <tr><td>testcase_duration</td><td>{{testcase_duration}}</td></tr>
+    <tr><td>Nb runs</td><td>{{nruns}}</td></tr>
+    <tr><td>Nb PASS</td><td>{{nb_run_pass}}</td></tr>
+    <tr><td>Nb FAILED</td><td>{{nb_run_failed}}</td></tr>
+    <tr><td>Nb INCONCLUSIVE</td><td>{{nb_run_inc}}</td></tr>
+    <tr>
+    <td>testcase_verdict</td>
+     {% if testcase_verdict == "PASS" %}
+        <TD align="center" style="background-color:green">{{testcase_verdict}}</TD>
+     {% elif testcase_verdict == "FAIL" %}
+        <TD align="center" style="background-color:red">{{testcase_verdict}}</TD>
+     {% else %}
+        <TD align="center" style="background-color:orange">{{testcase_verdict}}</TD>
+     {% endif %}
+    </tr>
+    <tr><td>Nb Seg Fault</td><td>{{nb_seg_fault}}</td></tr>
+
+  </table>
+</p>
+
+
+
+<h3>Test Case runs results</h3>
+
+{% for run_results in runs_results|sort(attribute='run_id') %}
+<h4>RUN {{run_results.run_id}} </h4>
+	<table border>
+		<tr><td>run_start_time </td><td>{{run_results.run_start_time}}</td></tr>
+    <tr><td>run_stop_time</td><td>{{run_results.run_stop_time}}</td></tr>
+    <tr><td>run_duration</td><td>{{run_results.run_duration}}</td></tr>
+		<tr>
+      <td>run_verdict</td>
+       {% if run_results.run_verdict == "PASS" %}
+          <TD align="center" style="background-color:green">{{run_results.run_verdict}}</TD>
+       {% elif run_results.run_verdict == "FAIL" %}
+          <TD align="center" style="background-color:red">{{run_results.run_verdict}}</TD>
+       {% else %}
+          <TD align="center" style="background-color:orange">{{run_results.run_verdict}}</TD>
+       {% endif %}
+    </tr>
+    <tr><td>Seg Fault Satus</td>
+      {% if run_results.ue_seg_fault_status == "NO_SEG_FAULT" %}
+        <TD align="center" style="background-color:green">{{run_results.ue_seg_fault_status}}</TD>
+      {% elif run_results.ue_seg_fault_status == "SEG_FAULT" %}
+        <TD align="center" style="background-color:red">{{run_results.ue_seg_fault_status}}</TD>
+      {% else %}
+          <TD align="center" style="background-color:orange">unknown</TD>
+       {% endif %}
+    </tr>
+	</table>
+
+	{% for run_metrics in run_results.runs_metrics %}
+	<br></br>
+	<table border>
+    <tr><td>metric_id</td><td>{{run_metrics.metric_id}}</td></tr>
+    <tr><td>Description</td><td>{{run_metrics.metric_desc}}</td></tr>
+    <tr><td>Unit of measure</td><td>{{run_metrics.metric_uom}}</td></tr>    
+		<tr><td>metric_min</td><td>{{run_metrics.metric_min}}</td></tr>
+		<tr><td>metric_max</td><td>{{run_metrics.metric_max}}</td></tr>
+		<tr><td>metric_mean</td><td>{{run_metrics.metric_mean}}</td></tr>
+		<tr><td>metric_median</td><td>{{run_metrics.metric_median}}</td></tr>
+    <tr><td colspan="2"></td></tr>
+    {% if run_metrics.pass_fail_stat is defined %}
+      <tr><td>Pass/fail stat</td><td>{{run_metrics.pass_fail_stat}}</td></tr>
+    {% endif %}
+    {% if run_metrics.pass_fail_min_limit is defined %}
+       <tr><td>Pass/fail min limit</td><td>{{run_metrics.pass_fail_min_limit}}</td></tr>
+    {% endif %}
+    {% if run_metrics.pass_fail_max_limit is defined %}
+      <tr><td>Pass/fail max limit</td><td>{{run_metrics.pass_fail_max_limit}}</td></tr>    
+    {% endif %}
+    <tr><td colspan="2"></td></tr>
+		<tr><td>metric_fig</td><td><IMG src={{run_metrics.metric_fig}}></td></tr>
+	</table>
+
+	{% endfor %}
+
+  {% if run_results.run_traffic.traffic_count != 0 %}
+  <br></br>
+  <table border>
+    <TR><TH>Iperf metric</TH><TH>min</TH><TH>max</TH><TH>mean</TH><TH>median</TH><TR>
+    <TR><td>Bandwidth </td><td>{{run_results.run_traffic.bw_min}}</td><td>{{run_results.run_traffic.bw_max}}</td><td>{{run_results.run_traffic.bw_mean}}</td><td>{{run_results.run_traffic.bw_median}}</td><TR>
+    <TR><td>Jitter</td><td>{{run_results.run_traffic.jitter_min}}</td><td>{{run_results.run_traffic.jitter_max}}</td><td>{{run_results.run_traffic.jitter_mean}}</td><td>{{run_results.run_traffic.jitter_median}}</td><TR>
+    <TR><td>Loss rate</td><td>{{run_results.run_traffic.rl_min}}</td><td>{{run_results.run_traffic.rl_max}}</td><td>{{run_results.run_traffic.rl_mean}}</td><td>{{run_results.run_traffic.rl_median}}</td><TR> 
+    <TR><td colspan="5"></td></TR>
+    <TR><td>Iperf duration</td><td>{{run_results.run_traffic.iperf_duration}}</td><td></td><td>Pass/Fail criteria (min duration)</td><td>{{run_results.run_traffic.dur_pass_fail_crit}}</td><TR> 
+    <TR><td colspan="5"></td></TR>
+    <tr><td>traffic_fig</td><td colspan="4"><IMG src={{run_results.run_traffic.traffic_fig}}></td></tr>
+  </table>
+  {% endif %}
+
+{% endfor %}
+
+</body>
+</html>
diff --git a/cmake_targets/autotests/testsuite_ue_noS1.xml b/cmake_targets/autotests/testsuite_ue_noS1.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c5403feab237aeba20fe2b196d27e0db7983573a
--- /dev/null
+++ b/cmake_targets/autotests/testsuite_ue_noS1.xml
@@ -0,0 +1,3214 @@
+<testCaseList>
+
+<MachineList>imb182-desktop yanbo-M4HM87P-00</MachineList> <!-- ued-PRM-130 -->
+ <NFSResultsShare>/mnt/sradio/TEST_RESULTS/</NFSResultsShare>
+ <GitOAI5GRepo> https://gitlab.eurecom.fr/oai1B/openairinterface5g.git</GitOAI5GRepo>
+ <!-- <GitOAI5GRepo>https://gitlab.eurecom.fr/oai/openairinterface5g.git</GitOAI5GRepo> -->
+ <!-- <GitOAI5GRepo>git@gitlab.com:TCL_Communications/openairinterface5g.git</GitOAI5GRepo> -->
+ <GitOpenair-cnRepo>https://gitlab.eurecom.fr/oai/openair-cn.git</GitOpenair-cnRepo> -->
+ <GitOAI5GRepoBranch>develop1B</GitOAI5GRepoBranch>
+ <GitOAI5GHeadVersion>develop1B_integration_w49</GitOAI5GHeadVersion> -->
+ <!-- <GitOAI5GHeadVersion>425b6fd525d9c4b0b3c2357926bbac5685e4b1e5</GitOAI5GHeadVersion> -->
+ <!-- <GitOAI5GHeadVersion>23822ea203e00f2100fa41c7ee3084ec55b884fe</GitOAI5GHeadVersion> --> 
+ <GitOAI5GHeadVersion></GitOAI5GHeadVersion>
+ <OAI5GPatchDir></OAI5GPatchDir>
+
+ <OAI5GPatchFile name="autotest_ue_cell_synch_event.patch"/>
+ <OAI5GPatchFile name="autotest_ue_dlsch_bitrate_metric.patch"/>
+ <OAI5GPatchFile name="autotest_ue_offsets_metric.patch"/>
+ <OAI5GPatchFile name="build_oai.patch"/>
+ <OAI5GPatchFile name="CmakeLists.patch"/>
+ 
+ <!--
+ <OAI5GPatchFile name="phy_test_dl_harq_reset.patch"/>
+ <OAI5GPatchFile name="phy_test__target_dl_mcs.patch"/>
+ <OAI5GPatchFile name="pdcp_fifo_netlink.patch"/>
+-->
+
+ <GitOpenair-cnRepoBranch>develop</GitOpenair-cnRepoBranch>
+ <CleanUpOldProgs>oaisim oaisim_nos1 lte-softmodem lte-softmodem-nos1 mme_gw run_epc auth_request run_hss oai_hss mme spgw hss hss_sim configure_cots* wvdial  iperf iperf_script iperf_script_phone ping tshark rrh_gw iperf3 iperf3_script iperf3_script_phone pppd</CleanUpOldProgs>	
+ <CleanUpAluLteBox>sudo -S -E /opt/ltebox/tools/stop_ltebox</CleanUpAluLteBox>
+<ExmimoRfStop>$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_huaweiE398_ue.py --reset-ue;  sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py --stop-ue; uname -a; sudo -E dmesg</ExmimoRfStop>
+ <Timeout_execution>36000</Timeout_execution>
+ <TestCaseExclusionList></TestCaseExclusionList>
+ <nruns_lte-softmodem></nruns_lte-softmodem>
+ <MachineListGeneric>yanbo-M4HM87P-00</MachineListGeneric>
+
+
+<!-- USRP Testcases performances  030000 030030 030100 030900 030930 031000 031030 031600 031630 031700 031730 031800 031900 031930 032000 032100 032200 032300 032400 032500 032600 032700 032710 032730 032740 032800 032810 032830 032840 032870 036000 036100 036130 036170 -->
+
+<!-- USRP Testcases performances  030000 030030  030900 030930 031000 031030 031600 031630 031700 031730 031900 031930 032700 032730 032800 036000 036100 036130 032740 032710 -->
+
+<!-- Stability 032740 032710 -->
+
+
+    <!-- USRP Band 7 5MHz SISO Iperf downlink performances : 030030 030930 031030 031630 031730 031930 032730 032830 -->
+
+
+
+
+<!-- PHY-TEST DOWNLINK PERFORMANCE -->
+
+
+ <testCase id="030000" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 0 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "510"/>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS00</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="030001" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 0 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "510"/>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS00</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="030100" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 1 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+                description="UE downlink physical throughput"  
+                regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+                unit_of_meas = "kbps"
+                pass_fail_stat = "mean_value"
+                min_limit = "678"/>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS01</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="030101" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 1 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "678"/>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS01</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+
+
+
+<testCase id="030900" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 9 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "3006"/>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS09</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="030901" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 9 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "3006"/>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS09</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="031600" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 16 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "3726"/>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS16</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="031601" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 16 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "3726"/>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS16</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="031000" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 10 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS10</tags>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "3006"/>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="031001" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 10 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS10</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "3006"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="031700" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 17 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS17</tags>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "5802"/>    
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="031701" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 17 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS17</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "5802"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="031800" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 18 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS18</tags>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "5994"/>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="031801" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 18 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS18</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "5994"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="031900" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 19 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS19</tags>
+     <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "6858"/>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="031901" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 19 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS19</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+     <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "6858"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+<testCase id="032000" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 20 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS20</tags>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "7434"/>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032001" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 20 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS20</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "7434"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+    <testCase id="032100" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 21 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS21</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "8010"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032101" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 21 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS21</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+     <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "8010"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="032200" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 22 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS22</tags>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "8586"/>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032201" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 22 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS22</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "8586"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="032300" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 23 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS23</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "9432"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032301" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 23 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS23</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "9432"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="032400" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 24 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS24</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "10152"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032401" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 24 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS24</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "10152"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+<testCase id="032500" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 25 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS25</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+     <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "10584"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032501" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 25 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS25</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+     <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "10584"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="032600" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 26 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS26</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "11448"/>       
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032601" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 26 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS26</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "11448"/>    
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+<testCase id="032700" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS27</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "11880"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032701" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS27</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "11880"/>    
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032801" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS28</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+   <UE_metric  id="UE_DLSCH_BITRATE" 
+        description="UE downlink physical throughput"  
+        regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+        unit_of_meas = "kbps"
+        pass_fail_stat = "mean_value"
+        min_limit = "13752"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+<testCase id="032710" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>3600</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_STAB.BAND7.5MHZ.MCS27</tags>
+    <nruns>1</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "11880"/>    
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="032711" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_STAB.BAND7.5MHZ.MCS27</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "11880"/>    
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+ <testCase id="036000" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test </eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS27</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "22193"/>    
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+ <testCase id="036001" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 27 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r50 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS27</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "22193"/>    
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+ <testCase id="036100" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 28 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS28</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "25687"/>    
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+ <testCase id="035201" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 19 --single-thread-disable --phy-test</eNB_main_exec_args>
+    <eNB_traffic_exec></eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r50 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25 --phy-test</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec></UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true></UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.PHYTEST_PERF.BAND7.10MHZ.MCS19</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "12835"/>
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+ <testCase id="036130" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 28 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 30M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.10MHZ.MCS28</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+
+
+ <testCase id="030031" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 0</eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 512K</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>  
+    <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS00</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+ <testCase id="030931" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 9 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS09</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+ <testCase id="031031" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 10 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS10</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+
+
+ <testCase id="031631" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 16 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS16</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+
+ <testCase id="031731" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 17 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS17</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+
+
+
+
+ <testCase id="031931" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 19 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 10M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS19</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+
+ <testCase id="032740" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>3600</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>2800</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.DATA_IPERF_STAB.BAND7.5MHZ.MCS27</tags>
+    <nruns>1</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+ <testCase id="032731" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>ued-PRM-130</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w EXMIMO --noS1 --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2660000000 -r25 --ue-scan-carrier --ue-txgain 15 --ue-rxgain 5 -S -A 6 -F myriadRF_FMX --ue-max-power -25</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_UEDV1.NOS1.DATA_IPERF.BAND7.5MHZ.MCS27</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+    <!-- USRP Band 7 5MHz SISO Iperf downlink performances -->
+    <!-- 030030 030930 031030 031630 031730 031930 032730 032830 -->
+
+    <testCase id="030030" >
+        <class>lte-softmodem-noS1</class>
+        <desc></desc>
+        <eNB>imb182-desktop</eNB>
+        <UE>yanbo-M4HM87P-00</UE>
+        <TimeOut_cmd>300</TimeOut_cmd>
+        <eNB_working_dir>/tmp</eNB_working_dir>
+        <eNB_config_file></eNB_config_file>
+        <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+        <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+        <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+        <eNB_pre_exec_args></eNB_pre_exec_args>
+        <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+        <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 0 </eNB_main_exec_args>
+        <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 512K</eNB_traffic_exec>
+        <eNB_traffic_exec_args></eNB_traffic_exec_args>
+        <eNB_search_expr_true></eNB_search_expr_true>
+        <eNB_search_expr_false></eNB_search_expr_false>
+        <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+        <UE_working_dir>/tmp</UE_working_dir>
+        <UE_config_file></UE_config_file>
+        <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+        <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+        <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+        <UE_pre_exec_args></UE_pre_exec_args>
+        <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S</UE_main_exec>
+        <UE_main_exec_args></UE_main_exec_args>
+        <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+        <UE_traffic_exec_args></UE_traffic_exec_args>
+        <UE_search_expr_true>200</UE_search_expr_true>
+        <UE_search_expr_false></UE_search_expr_false>
+        <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+        <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS00</tags>
+        <nruns>3</nruns><max_ntries>6</max_ntries>
+        <UE_metric  id="UE_DLSCH_BITRATE" 
+                description="UE downlink physical throughput"  
+                regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+                unit_of_meas = "kbps"/> 
+        <UE_metric  id="UE_FREQ_OFFSET" 
+                description="UE downlink frequency channel offset"  
+                regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+                unit_of_meas = "Hz"/> 
+        <UE_metric  id="UE_RX_OFFSET" 
+                description="UE downlink rx sample offset"  
+                regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+                unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+    <testCase id="030930" >
+        <class>lte-softmodem-noS1</class>
+        <desc></desc>
+        <eNB>imb182-desktop</eNB>
+        <UE>yanbo-M4HM87P-00</UE>
+        <TimeOut_cmd>300</TimeOut_cmd>
+        <eNB_working_dir>/tmp</eNB_working_dir>
+        <eNB_config_file></eNB_config_file>
+        <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+        <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+        <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+        <eNB_pre_exec_args></eNB_pre_exec_args>
+        <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+        <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 9 </eNB_main_exec_args>
+        <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+        <eNB_traffic_exec_args></eNB_traffic_exec_args>
+        <eNB_search_expr_true></eNB_search_expr_true>
+        <eNB_search_expr_false></eNB_search_expr_false>
+        <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+        <UE_working_dir>/tmp</UE_working_dir>
+        <UE_config_file></UE_config_file>
+        <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+        <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+        <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+        <UE_pre_exec_args></UE_pre_exec_args>
+        <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S</UE_main_exec>
+        <UE_main_exec_args></UE_main_exec_args>
+        <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+        <UE_traffic_exec_args></UE_traffic_exec_args>
+        <UE_search_expr_true>200</UE_search_expr_true>
+        <UE_search_expr_false></UE_search_expr_false>
+        <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+        <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS09</tags>
+        <nruns>3</nruns><max_ntries>6</max_ntries>
+        <UE_metric  id="UE_DLSCH_BITRATE" 
+                description="UE downlink physical throughput"  
+                regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+                unit_of_meas = "kbps"/> 
+        <UE_metric  id="UE_FREQ_OFFSET" 
+                description="UE downlink frequency channel offset"  
+                regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+                unit_of_meas = "Hz"/> 
+        <UE_metric  id="UE_RX_OFFSET" 
+                description="UE downlink rx sample offset"  
+                regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+                unit_of_meas = ""/> 
+    </testCase> 
+    
+    
+ <testCase id="031030" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 10 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS10</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+ <testCase id="031630" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 16 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS16</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+    
+    
+ <testCase id="031730" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 17 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS17</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+    
+     <testCase id="031930" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 19 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S</UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS19</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+    
+    
+     <testCase id="032730" >
+    <class>lte-softmodem-noS1</class>
+    <desc></desc>
+    <eNB>imb182-desktop</eNB>
+    <UE>yanbo-M4HM87P-00</UE>
+    <TimeOut_cmd>300</TimeOut_cmd>
+    <eNB_working_dir>/tmp</eNB_working_dir>
+    <eNB_config_file></eNB_config_file>
+    <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+    <eNB_compile_prog_args>-c -w USRP --eNB --noS1 </eNB_compile_prog_args>
+    <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+    <eNB_pre_exec_args></eNB_pre_exec_args>
+    <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+    <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 27 </eNB_main_exec_args>
+    <eNB_traffic_exec>sleep 30;iperf -c 10.0.1.9 -i 1 -u -b 15M</eNB_traffic_exec>
+    <eNB_traffic_exec_args></eNB_traffic_exec_args>
+    <eNB_search_expr_true></eNB_search_expr_true>
+    <eNB_search_expr_false></eNB_search_expr_false>
+    <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+    <UE_working_dir>/tmp</UE_working_dir>
+    <UE_config_file></UE_config_file>
+    <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+    <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+    <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+    <UE_pre_exec_args></UE_pre_exec_args>
+    <UE_main_exec>sleep 5; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S </UE_main_exec>
+    <UE_main_exec_args></UE_main_exec_args>
+    <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+    <UE_traffic_exec_args></UE_traffic_exec_args>
+    <UE_search_expr_true>200</UE_search_expr_true>
+    <UE_search_expr_false></UE_search_expr_false>
+    <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+    <tags>UE_USRP.NOS1.DATA_IPERF.BAND7.5MHZ.MCS27</tags>
+    <nruns>3</nruns><max_ntries>6</max_ntries>
+    <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"/> 
+    <UE_metric  id="UE_FREQ_OFFSET" 
+            description="UE downlink frequency channel offset"  
+            regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+            unit_of_meas = "Hz"/> 
+    <UE_metric  id="UE_RX_OFFSET" 
+            description="UE downlink rx sample offset"  
+            regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+            unit_of_meas = ""/> 
+    </testCase> 
+
+
+
+
+
+
+
+
+
+
+
+    <testCase id="032800" >
+        <class>lte-softmodem-noS1</class>
+        <desc></desc>
+        <eNB>imb182-desktop</eNB>
+        <UE>yanbo-M4HM87P-00</UE>
+        <TimeOut_cmd>300</TimeOut_cmd>
+        <eNB_working_dir>/tmp</eNB_working_dir>
+        <eNB_config_file></eNB_config_file>
+        <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+        <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+        <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+        <eNB_pre_exec_args></eNB_pre_exec_args>
+        <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+        <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28 --single-thread-disable --phy-test</eNB_main_exec_args>
+        <eNB_traffic_exec></eNB_traffic_exec>
+        <eNB_traffic_exec_args></eNB_traffic_exec_args>
+        <eNB_search_expr_true></eNB_search_expr_true>
+        <eNB_search_expr_false></eNB_search_expr_false>
+        <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+        <UE_working_dir>/tmp</UE_working_dir>
+        <UE_config_file></UE_config_file>
+        <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+        <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+        <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+        <UE_pre_exec_args></UE_pre_exec_args>
+        <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+        <UE_main_exec_args></UE_main_exec_args>
+        <UE_traffic_exec></UE_traffic_exec>
+        <UE_traffic_exec_args></UE_traffic_exec_args>
+        <UE_search_expr_true></UE_search_expr_true>
+        <UE_search_expr_false></UE_search_expr_false>
+        <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+        <UE_metric  id="UE_DLSCH_BITRATE" 
+            description="UE downlink physical throughput"  
+            regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+            unit_of_meas = "kbps"
+            pass_fail_stat = "mean_value"
+            min_limit = "13752"/>
+        <UE_metric  id="UE_FREQ_OFFSET" 
+                description="UE downlink frequency channel offset"  
+                regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+                unit_of_meas = "Hz"/> 
+        <UE_metric  id="UE_RX_OFFSET" 
+                description="UE downlink rx sample offset"  
+                regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+                unit_of_meas = ""/> 
+        <tags>UE_USRP.NOS1.PHYTEST_PERF.BAND7.5MHZ.MCS28</tags>
+        <nruns>3</nruns><max_ntries>6</max_ntries>
+    </testCase> 
+
+    <testCase id="032810" >
+        <class>lte-softmodem-noS1</class>
+        <desc></desc>
+        <eNB>imb182-desktop</eNB>
+        <UE>yanbo-M4HM87P-00</UE>
+        <TimeOut_cmd>18000</TimeOut_cmd>
+        <eNB_working_dir>/tmp</eNB_working_dir>
+        <eNB_config_file></eNB_config_file>
+        <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+        <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+        <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+        <eNB_pre_exec_args></eNB_pre_exec_args>
+        <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+        <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28 --single-thread-disable --phy-test</eNB_main_exec_args>
+        <eNB_traffic_exec></eNB_traffic_exec>
+        <eNB_traffic_exec_args></eNB_traffic_exec_args>
+        <eNB_search_expr_true></eNB_search_expr_true>
+        <eNB_search_expr_false></eNB_search_expr_false>
+        <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+        <UE_working_dir>/tmp</UE_working_dir>
+        <UE_config_file></UE_config_file>
+        <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+        <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+        <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+        <UE_pre_exec_args></UE_pre_exec_args>
+        <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S --phy-test</UE_main_exec>
+        <UE_main_exec_args></UE_main_exec_args>
+        <UE_traffic_exec></UE_traffic_exec>
+        <UE_traffic_exec_args></UE_traffic_exec_args>
+        <UE_search_expr_true></UE_search_expr_true>
+        <UE_search_expr_false></UE_search_expr_false>
+        <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+        <UE_metric  id="UE_DLSCH_BITRATE" 
+                description="UE downlink physical throughput"  
+                regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+                unit_of_meas = "kbps"
+                pass_fail_stat = "mean_value"
+                min_limit = "11880"/>    
+        <UE_metric  id="UE_FREQ_OFFSET" 
+                description="UE downlink frequency channel offset"  
+                regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+                unit_of_meas = "Hz"/> 
+        <UE_metric  id="UE_RX_OFFSET" 
+                description="UE downlink rx sample offset"  
+                regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+                unit_of_meas = ""/> 
+        <tags>UE_USRP.NOS1.PHYTEST_STAB.BAND7.5MHZ.MCS28</tags>
+        <nruns>1</nruns><max_ntries>6</max_ntries>
+    </testCase> 
+    
+
+    <testCase id="032830" >
+        <class>lte-softmodem-noS1</class>
+        <desc></desc>
+        <eNB>imb182-desktop</eNB>
+        <UE>yanbo-M4HM87P-00</UE>
+        <TimeOut_cmd>300</TimeOut_cmd>
+        <eNB_working_dir>/tmp</eNB_working_dir>
+        <eNB_config_file></eNB_config_file>
+        <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+        <eNB_compile_prog_args>-c -w USRP --eNB --noS1 </eNB_compile_prog_args>
+        <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+        <eNB_pre_exec_args></eNB_pre_exec_args>
+        <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+        <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28 </eNB_main_exec_args>
+        <eNB_traffic_exec>sleep 30;iperf -c 10.0.1.9 -i 1 -u -b 13700K</eNB_traffic_exec> <!-- PHY max TP 18.336Mbps -> 75% = 13.70Mbps -->
+        <eNB_traffic_exec_args></eNB_traffic_exec_args>
+        <eNB_search_expr_true></eNB_search_expr_true>
+        <eNB_search_expr_false></eNB_search_expr_false>
+        <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+        <UE_working_dir>/tmp</UE_working_dir>
+        <UE_config_file></UE_config_file>
+        <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+        <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+        <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+        <UE_pre_exec_args></UE_pre_exec_args>
+        <UE_main_exec>sleep 5; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S </UE_main_exec>
+        <UE_main_exec_args></UE_main_exec_args>
+        <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+        <UE_traffic_exec_args></UE_traffic_exec_args>
+        <UE_search_expr_true>200</UE_search_expr_true>
+        <UE_search_expr_false></UE_search_expr_false>
+        <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+        <UE_metric  id="UE_DLSCH_BITRATE" 
+                description="UE downlink physical throughput"  
+                regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+                unit_of_meas = "kbps"/> 
+        <UE_metric  id="UE_FREQ_OFFSET" 
+                description="UE downlink frequency channel offset"  
+                regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+                unit_of_meas = "Hz"/> 
+        <UE_metric  id="UE_RX_OFFSET" 
+                description="UE downlink rx sample offset"  
+                regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+                unit_of_meas = ""/> 
+        <UE_traffic_metric
+                mode="UDP"
+                duration_min="200"
+
+        />
+        <tags>UE_USRP.NOS1.DATA_IPERF_DL.BAND7.5MHZ.MCS28</tags>
+        <nruns>3</nruns><max_ntries>6</max_ntries>
+    </testCase> 
+
+
+    <testCase id="032840" >
+        <class>lte-softmodem-noS1</class>
+        <desc></desc>
+        <eNB>imb182-desktop</eNB>
+        <UE>yanbo-M4HM87P-00</UE>
+        <TimeOut_cmd>3600</TimeOut_cmd>
+        <tags>UE_USRP.NOS1.DATA_IPERF_STAB_DL.BAND7.5MHZ.MCS28</tags>
+        <nruns>1</nruns><max_ntries>6</max_ntries>
+
+        <eNB_working_dir>/tmp</eNB_working_dir>
+        <eNB_config_file></eNB_config_file>
+        <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+        <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+        <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+        <eNB_pre_exec_args></eNB_pre_exec_args>
+        <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+        <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28 </eNB_main_exec_args>
+        <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1 -u -b 2M</eNB_traffic_exec>
+        <eNB_traffic_exec_args></eNB_traffic_exec_args>
+        <eNB_search_expr_true></eNB_search_expr_true>
+        <eNB_search_expr_false></eNB_search_expr_false>
+        <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+        <UE_working_dir>/tmp</UE_working_dir>
+        <UE_config_file></UE_config_file>
+        <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+        <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+        <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+        <UE_pre_exec_args></UE_pre_exec_args>
+        <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S</UE_main_exec>
+        <UE_main_exec_args></UE_main_exec_args>
+        <UE_traffic_exec>iperf -s -i 1 -u</UE_traffic_exec>
+        <UE_traffic_exec_args></UE_traffic_exec_args>
+        <UE_search_expr_true>2800</UE_search_expr_true>
+        <UE_search_expr_false></UE_search_expr_false>
+        <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+        <UE_metric  id="UE_DLSCH_BITRATE" 
+                description="UE downlink physical throughput"  
+                regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+                unit_of_meas = "kbps"/> 
+        <UE_metric  id="UE_FREQ_OFFSET" 
+                description="UE downlink frequency channel offset"  
+                regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+                unit_of_meas = "Hz"/> 
+        <UE_metric  id="UE_RX_OFFSET" 
+                description="UE downlink rx sample offset"  
+                regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+                unit_of_meas = ""/> 
+
+    </testCase> 
+
+
+
+    <testCase id="032870" >
+        <class>lte-softmodem-noS1</class>
+        <desc></desc>
+        <eNB>imb182-desktop</eNB>
+        <UE>yanbo-M4HM87P-00</UE>
+        <TimeOut_cmd>300</TimeOut_cmd>
+        <eNB_working_dir>/tmp</eNB_working_dir>
+        <eNB_config_file></eNB_config_file>
+        <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+        <eNB_compile_prog_args>-c -w USRP --eNB --noS1 </eNB_compile_prog_args>
+        <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+        <eNB_pre_exec_args></eNB_pre_exec_args>
+        <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+        <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf -W -m 28 </eNB_main_exec_args>
+        <eNB_traffic_exec>sleep 30;iperf -c 10.0.1.9 -i 1</eNB_traffic_exec> <!-- PHY max TP 18.336Mbps -> 75% = 13.70Mbps -->
+        <eNB_traffic_exec_args></eNB_traffic_exec_args>
+        <eNB_search_expr_true></eNB_search_expr_true>
+        <eNB_search_expr_false></eNB_search_expr_false>
+        <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+        <UE_working_dir>/tmp</UE_working_dir>
+        <UE_config_file></UE_config_file>
+        <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+        <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+        <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+        <UE_pre_exec_args></UE_pre_exec_args>
+        <UE_main_exec>sleep 5; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r25 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125 -S </UE_main_exec>
+        <UE_main_exec_args></UE_main_exec_args>
+        <UE_traffic_exec>iperf -s -i 1</UE_traffic_exec>
+        <UE_traffic_exec_args></UE_traffic_exec_args>
+        <UE_search_expr_true>200</UE_search_expr_true>
+        <UE_search_expr_false></UE_search_expr_false>
+        <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+        <UE_metric  id="UE_DLSCH_BITRATE" 
+                description="UE downlink physical throughput"  
+                regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+                unit_of_meas = "kbps"/> 
+        <UE_metric  id="UE_FREQ_OFFSET" 
+                description="UE downlink frequency channel offset"  
+                regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+                unit_of_meas = "Hz"/> 
+        <UE_metric  id="UE_RX_OFFSET" 
+                description="UE downlink rx sample offset"  
+                regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+                unit_of_meas = ""/> 
+        <UE_traffic_metric
+                mode="TCP"
+                duration_min="200"
+                bandwidth_min="13.7"
+        />
+        <tags>UE_USRP.NOS1.DATA_IPERF_TCP_DL.BAND7.5MHZ.MCS28</tags>
+        <nruns>3</nruns><max_ntries>6</max_ntries>
+    </testCase> 
+
+
+    <testCase id="036170" >
+        <class>lte-softmodem-noS1</class>
+        <desc></desc>
+        <eNB>imb182-desktop</eNB>
+        <UE>yanbo-M4HM87P-00</UE>
+        <TimeOut_cmd>300</TimeOut_cmd>
+        <eNB_working_dir>/tmp</eNB_working_dir>
+        <eNB_config_file></eNB_config_file>
+        <eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
+        <eNB_compile_prog_args>-c -w USRP --eNB --noS1</eNB_compile_prog_args>
+        <eNB_pre_exec>source $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 eNB</eNB_pre_exec>
+        <eNB_pre_exec_args></eNB_pre_exec_args>
+        <eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1</eNB_main_exec>
+        <eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf -W -m 28 </eNB_main_exec_args>
+        <eNB_traffic_exec>sleep 80;iperf -c 10.0.1.9 -i 1</eNB_traffic_exec>
+        <eNB_traffic_exec_args></eNB_traffic_exec_args>
+        <eNB_search_expr_true></eNB_search_expr_true>
+        <eNB_search_expr_false></eNB_search_expr_false>
+        <eNB_terminate_missing_procs>False</eNB_terminate_missing_procs>
+
+        <UE_working_dir>/tmp</UE_working_dir>
+        <UE_config_file></UE_config_file>
+        <UE_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</UE_compile_prog>
+        <UE_compile_prog_args>-c --UE -w USRP --noS1 --eNB --ue-autotest-trace </UE_compile_prog_args>
+        <UE_pre_exec>source ./targets/bin/init_nas_nos1 UE</UE_pre_exec>
+        <UE_pre_exec_args></UE_pre_exec_args>
+        <UE_main_exec>sleep 20; ./cmake_targets/autotests/tools/run_gdb ./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C2660000000 -r50 --ue-scan-carrier --ue-txgain 85 -A 20 --ue-rxgain 125  -S</UE_main_exec>
+        <UE_main_exec_args></UE_main_exec_args>
+        <UE_traffic_exec>iperf -s -i 1</UE_traffic_exec>
+        <UE_traffic_exec_args></UE_traffic_exec_args>
+        <UE_search_expr_true>200</UE_search_expr_true>
+        <UE_search_expr_false></UE_search_expr_false>
+        <UE_terminate_missing_procs>False</UE_terminate_missing_procs>
+        <tags>UE_USRP.NOS1.DATA_IPERF_TCP_DL.BAND7.10MHZ.MCS28</tags>
+        <nruns>3</nruns><max_ntries>6</max_ntries>
+        <UE_metric  id="UE_DLSCH_BITRATE" 
+                description="UE downlink physical throughput"  
+                regex='(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)' 
+                unit_of_meas = "kbps"/> 
+        <UE_metric  id="UE_FREQ_OFFSET" 
+                description="UE downlink frequency channel offset"  
+                regex='(UE_FREQ_OFFSET) =\s+(-?\d+) Hz.+frame = (\d+)\)' 
+                unit_of_meas = "Hz"/> 
+        <UE_metric  id="UE_RX_OFFSET" 
+                description="UE downlink rx sample offset"  
+                regex='(UE_RX_OFFSET) =\s+(-?\d+).+frame = (\d+)\)' 
+                unit_of_meas = ""/> 
+        <UE_traffic_metric
+                mode="TCP"
+                duration_min="200"
+                bandwidth_min="27.5"
+        />
+    </testCase> 
+
+
+
+
+
+
+
+  </testCaseList>
+
diff --git a/cmake_targets/autotests/tools/autotest_analyser.py b/cmake_targets/autotests/tools/autotest_analyser.py
index a75727ad65cfddf5a8ed2a561831e1859d555b6c..61759a15454bd77bc793ad14aaba2093f8e65b17 100755
--- a/cmake_targets/autotests/tools/autotest_analyser.py
+++ b/cmake_targets/autotests/tools/autotest_analyser.py
@@ -35,12 +35,15 @@ import getopt
 import sys
 from subprocess import call
 
+import encoder
+
+sys.path.append(os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/'))
 
 
 #test_cases = ('030001', '030901', '031001', '031601', '031701', '031801', '031901', '032001', '032101', '032201', '032301', '032501', '032601', '032801')
-test_cases = ('030030' , '030030' ) 
+test_cases = ('032800' , '032730' ) 
 
-nb_run = 3
+nb_run = 2
 
 def error_opt(msg):
     print("Option error: " + msg)
@@ -58,14 +61,27 @@ def main(args):
 
 
 
+	# metric = {}
+	# metric['id'] 			= 'UE_DLSCH_BITRATE'
+	# metric['description'] 	= 'UE downlink physical throughput'	
+	# metric['regex'] 		= '(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)'
+	# metric['unit_of_meas']	= 'kbps'
+	# metric['min_limit']		= 14668.8
+
+
+#AUTOTEST Metric : RRC Measurments RSRP[0]=-97.60 dBm/RE, RSSI=-72.83 dBm, RSRQ[0] 9.03 dB, N0 -125 dBm/RE, NF 7.2 dB (frame = 4490)
+
 	metric = {}
-	metric['id'] 			= 'UE_DLSCH_BITRATE'
-	metric['description'] 	= 'UE downlink physical throughput'	
-	metric['regex'] 		= '(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)'
+	metric['id'] 		= 'UE_DL_RRC_MEAS'
+	metric['description'] 	= 'UE downlink RRC Measurments'	
+	metric['nb_metric']	= 5
+#	metric['regex'] 	= 'AUTOTEST Metric : RRC Measurments (RSRP\[0\])=(-?\d+\.?\d*)\s+(.+),\s+(RSRQ\[0\])=(-?\d+\.?\d*)\s+(.+),,\s+(N0)=(-?\d+\.?\d*)\s+(.+),,\s+(NF)=(-?\d+\.?\d*)\s+(.+)\s+\(frame = (\d+)\) '
+	metric['regex'] 	= 'AUTOTEST Metric : RRC Measurments (RSRP\[0\])=(-?\d+\.?\d*)\s+(.+)\,\s+(RSSI)=(-?\d+\.?\d*)\s+(.+)\,\s+(RSRQ\[0\])=(-?\d+\.?\d*)\s+(.+)\,\s+(N0)=(-?\d+\.?\d*)\s+(.+)\,\s+(NF)=(-?\d+\.?\d*)\s+(.+)\s+\(frame = (\d+)\)'
 	metric['unit_of_meas']	= 'kbps'
 	metric['min_limit']		= 14668.8
 
 
+
 #report_path = log_path+'/report/'
 
 #os.system(' mkdir -p ' + report_path)
@@ -74,58 +90,44 @@ def main(args):
 
 #return(0)
 
-	for test_case in test_cases:
-
-#		print test_case
-		if test_case == '030001':
-			metric['min_limit']		= 500.0
-		if test_case == '030901':
-			metric['min_limit']		= 640.0
-		if test_case == '031001':
-			metric['min_limit']		= 3200.0
-		if test_case == '031601':
-			metric['min_limit']		= 5920.0
-		if test_case == '031701':
-			metric['min_limit']		= 6000.0
-		if test_case == '031801':
-			metric['min_limit']		= 6200.0
-		if test_case == '031901':
-			metric['min_limit']		= 7000.0
-		if test_case == '032001':
-			metric['min_limit']		= 7800.0
-		if test_case == '032101':
-			metric['min_limit']		= 8000.0
-		if test_case == '032201':
-			metric['min_limit']		= 9000.0
-		if test_case == '032301':
-			metric['min_limit']		= 10000.0
-		if test_case == '032501':
-			metric['min_limit']		= 11000.0
-		if test_case == '032601':
-			metric['min_limit']		= 12000.0
-		if test_case == '032801':
-			metric['min_limit']		= 12500.0
-
-		if test_case == '035201':
-			metric['min_limit']		= 14668.8
-		if test_case == '036001':
-			metric['min_limit']		= 25363.2
-
+	test_results = []
 
+	for test_case in test_cases:
 
 		for i in range(0, nb_run):
-			fname = 'log//'+test_case+'/run_'+str(i)+'/UE_exec_'+str(i)+'_.log'
+			fname = '..//log//'+test_case+'/run_'+str(i)+'/UE_exec_'+str(i)+'_.log'
 			args = {'metric' : metric,
 					'file' : fname }
 
-			cell_synch_status = analyser.check_cell_synchro(fname)
-			if cell_synch_status == 'CELL_SYNCH':
-			  print '!!!!!!!!!!!!!!  Cell synchronized !!!!!!!!!!!'
-			  metric_checks_flag = 0
-			else :
-			  print '!!!!!!!!!!!!!!  Cell NOT  NOT synchronized !!!!!!!!!!!'
+			# cell_synch_status = analyser.check_cell_synchro(fname)
+			# if cell_synch_status == 'CELL_SYNCH':
+			#   print '!!!!!!!!!!!!!!  Cell synchronized !!!!!!!!!!!'
+			#   metric_checks_flag = 0
+			# else :
+			#   print '!!!!!!!!!!!!!!  Cell NOT  NOT synchronized !!!!!!!!!!!'
 	
-#			metric_extracted = analyser.do_extract_metrics(args)
+#			metrics_extracted = analyser.do_extract_metrics_new(args)
+
+
+			# de-xmlfy test report
+			xml_file = '..//log//'+test_case+'/test.'+test_case+'_ng.xml'
+			print xml_file
+
+		# 	test_result =
+
+
+  # 			test_results.append(test_result)
+
+  # xmlFile = logdir_local_testcase + '/test.' + testcasename + '.xml'
+  # xml="\n<testcase classname=\'"+ testcaseclass +  "\' name=\'" + testcasename + "."+tags +  "\' Run_result=\'" + test_result_string + "\' time=\'" + str(duration) + " s \' RESULT=\'" + testcase_verdict + "\'></testcase> \n"
+  # write_file(xmlFile, xml, mode="w")
+
+  # xmlFile_ng = logdir_local_testcase + '/test.' + testcasename + '_ng.xml'
+  # xml_ng = xmlify(test_result, wrap=testcasename, indent="  ")
+  # write_file(xmlFile_ng, xml_ng, mode="w")
+
+
+
 
 #			print "min       = "+ str( metric_extracted['metric_min'] )
 #			print "min_index = "+ str( metric_extracted['metric_min_index'] )
@@ -143,16 +145,27 @@ def main(args):
 #			print fname
 #			analyser.do_img_metrics(metric, metric_extracted, fname)
 
-#			fname = 'log//'+test_case+'/run_'+str(i)+'/UE_traffic_'+str(i)+'_.log'
+			# fname = 'log//'+test_case+'/run_'+str(i)+'/UE_traffic_'+str(i)+'_.log'
 			
-#			args = {'file' : fname }
+			# args = {'file' : fname }
 
-#			traffic_metrics = analyser.do_extract_traffic_metrics(args)
+			# traffic_metrics = analyser.do_extract_traffic_metrics(args)
 
-#			fname= 'report/iperf_'+test_case+'_'+str(i)+'.png'
+			# fname= 'report/iperf_'+test_case+'_'+str(i)+'.png'
 			
-#			print fname
-#			analyser.do_img_traffic(traffic_metrics, fname)
+			# print fname
+			# analyser.do_img_traffic(traffic_metrics, fname)
+
+
+	for test_result in test_results:
+	  cmd = 'mkdir -p ' + report_dir + '/'+ test_result['testcase_name']
+	  result = os.system(cmd)
+
+	  report_file = report_dir + '/'+ test_result['testcase_name'] + '/'+ test_result['testcase_name']+ '_report.html'
+
+	  analyser.create_test_report_detailed_html(test_result, report_file )
+
+	  print test_result
 
 
 
diff --git a/cmake_targets/autotests/tools/lib_autotest_analyser.py b/cmake_targets/autotests/tools/lib_autotest_analyser.py
index 92dcc31e48dcae0ccd989a2e4e5d116bffee0add..333bbd656e3b2542460b7d72d4ce6892f13cf06a 100644
--- a/cmake_targets/autotests/tools/lib_autotest_analyser.py
+++ b/cmake_targets/autotests/tools/lib_autotest_analyser.py
@@ -41,7 +41,7 @@ from jinja2 import Environment, FileSystemLoader
 PATH = os.path.dirname(os.path.abspath(__file__))
 TEMPLATE_ENVIRONMENT = Environment(
     autoescape=False,
-    loader=FileSystemLoader(os.path.join(PATH, 'templates')),
+    loader=FileSystemLoader(os.path.join(PATH, '../templates')),
     trim_blocks=False)
 
 
@@ -103,6 +103,129 @@ def do_extract_metrics(args):
 			}
 	return(ret)
 
+
+def do_extract_metrics_new(args):
+
+#	print ""
+#	print "do_extract_metrics ... "
+
+	fname 	= args['file']
+	metric 	= args['metric']
+	print(fname)
+	print 'metric id = ' + metric['id']
+	print 'metric regex = ' + metric['regex']
+
+
+
+	count 		= 0
+	mmin 		= 0
+	mmin_index 	= 0
+	mmax  		= 0
+	mmax_index 	= 0
+	mean 		= 0
+	median 		= 0
+	
+	toto = [('id', 'S20'), ('metric', np.float), ('frame', np.int)]
+	print toto
+
+
+	np_format = []
+
+	for x in range(0, metric['nb_metric']):
+	 	np_format.append( ('id'+str(x), 'S20') )
+	 	np_format.append( ('metric'+str(x), np.float) )
+	 	np_format.append( ('uom'+str(x), 'S20') )
+	np_format.append( ('frame', np.int)) 
+
+	print np_format
+
+	output = np.fromregex(fname,metric['regex'], np_format)
+	print output
+	count =  output['frame'].size
+	print count
+	if count > 0:
+
+
+		fontP = FontProperties()
+		fontP.set_size('small')
+
+		fig = plt.figure(1)
+		plt.figure(figsize=(10,10))
+
+		plot_xmax = np.amax(output['frame'])+np.amin(output['frame'])
+
+		for x in range(0, metric['nb_metric']):	
+
+			metric_name = output['id'+str(x)][0]
+			metric_uom = output['uom'+str(x)][0]
+
+			mmin 	= np.amin(output['metric'+str(x)])
+			mmax 	= np.amax(output['metric'+str(x)])
+			mmean 	= np.mean(output['metric'+str(x)])
+			mmedian = np.median(output['metric'+str(x)])
+
+			plot_loc = 100*metric['nb_metric']+10+x+1
+
+			sbplt = plt.subplot(plot_loc)
+			sbplt.plot(output['frame'], output['metric'+str(x)], color='b' )
+			sbplt.set_title( metric_name+' ('+metric_uom+')')
+			if mmin < 0:
+				sbplot_ymin=mmin+mmin/10
+			else:
+				sbplot_ymin=0
+			sbplt.set_ylim(ymin=sbplot_ymin)	
+			if mmax > 0:
+				sbplot_ymax=mmax+mmax/10
+			else:
+				sbplot_ymax=0
+			sbplt.set_ylim(ymax=sbplot_ymax)
+
+			sbplt.set_xlim(xmax=plot_xmax)
+			sbplt.set_xlim(xmin=0)
+			text='min: '+str(mmin)+'\nmax: '+str(mmax)+'\nmean: '+str(mmean)+'\nmedian: '+str(mmedian)
+			sbplt.text( plot_xmax+10,sbplot_ymin,text)
+			sbplt.set_xlabel('frame')
+			sbplt.set_ylabel(metric_name)
+
+		plt.tight_layout()
+
+		fname = "toto.png"
+
+#		lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
+		mng = plt.get_current_fig_manager()
+		plt.savefig(fname, bbox_inches='tight')
+		plt.close()
+
+
+
+
+
+
+
+
+
+		mmin  		= np.amin(output['metric']);
+		mmin_index 	= np.argmin(output['metric']);
+		mmax  		= np.amax(output['metric']);
+		mmax_index 	= np.argmax(output['metric']); 			
+		mean 		= np.mean(output['metric']);
+		median 		= np.median(output['metric']);
+
+#		print ( ( (metric['min_limit'] > output['metric']).sum() / float(output['metric'].size) ) * 100 )
+
+	ret = {	'metric_count'		: count,
+		'metric_buf' 		: output,
+		
+
+		'metric_min' 		: mmin, 
+		'metric_min_index' 	: mmin_index,
+		'metric_max' 		: mmax,
+		'metric_max_index' 	: mmax_index,
+		'metric_mean' 		: mean,
+		'metric_median' 	: median,
+		}
+	return(ret)
+
 #
 #
 #
@@ -182,24 +305,30 @@ def do_img_metrics(metric_def, metric_data, fname):
 #		print output['metric'].size
 
 		plt.scatter(output['frame'], output['metric'], color='b', alpha=0.33, s = 1 , label=metric_def['id'])
-		plt.plot([0, output['frame'][metric_data['metric_count']-1]],[ metric_def['min_limit'],metric_def['min_limit']], 'r-', lw=2, label='min limit') # Red straight line
+		
+		if 'min_limit' in metric_def:
+			plt.plot([0, output['frame'][metric_data['metric_count']-1]],[ metric_def['min_limit'],metric_def['min_limit']], 'r-', lw=2, label='min limit') # Red straight line
 
-		plt.title('Physical throughput ('+metric_def['unit_of_meas']+')')
+		plt.title(metric_def['id'] +' ('+metric_def['unit_of_meas']+')')
 		plt.xlabel('frame')
 		plt.ylabel(metric_def['id'])
 		
 		# Set graphic minimum Y axis
 		# -------------------------
-		if metric_data['metric_min'] == 0 :
-			plt.ylim(ymin=-metric_def['min_limit']/10)
+		if metric_data['metric_min'] < 0:
+			plt.ylim(ymin=metric_data['metric_min']+metric_data['metric_min']/10)
 		else :	
 			plt.ylim(ymin=0)
 
 		y_axis_max = 0
-		if metric_data['metric_max'] >  metric_def['min_limit']:
-			y_axis_max =metric_data['metric_max']+metric_data['metric_max']/10
+		if 'min_limit' in metric_def:
+			if metric_data['metric_max'] >  metric_def['min_limit']:
+				y_axis_max =metric_data['metric_max']+metric_data['metric_max']/10
+			else:
+				y_axis_max =metric_def['min_limit']+metric_def['min_limit']/10
 		else:
-			y_axis_max =metric_def['min_limit']+metric_def['min_limit']/10
+			y_axis_max =metric_data['metric_max']+metric_data['metric_max']/10
+
 
 		plt.ylim(ymax=y_axis_max)
 
@@ -219,9 +348,6 @@ def do_img_metrics(metric_def, metric_data, fname):
 
 def do_extract_traffic_metrics(args):
 
-	print ""
-	print "do_extract_traffic_metrics ... "
-
 	fname 	= args['file']
 
 #	print(fname)
@@ -325,7 +451,8 @@ def do_img_traffic(traffic_data, fname):
 		ax1.set_xlim(xmax=np.amax(output['interval_stop']))
 		text='min: '+str(traffic_data['bw_min'])+'\nmax: '+str(traffic_data['bw_max'])+'\nmean: '+str(traffic_data['bw_mean'])+'\nmedian: '+str(traffic_data['bw_median'])
 		ax1.text( np.amax(output['interval_stop'])+10,0,text)
-
+		ax1.set_xlabel('time (s)')
+		ax1.set_ylabel(' ')
 
 		ax2=plt.subplot(312)
 		plt.plot(output['interval_stop'], output['jitter'], color='b' )
@@ -334,6 +461,8 @@ def do_img_traffic(traffic_data, fname):
 		ax2.set_ylim(ymin=-1)
 		text='min: '+str(traffic_data['jitter_min'])+'\nmax: '+str(traffic_data['jitter_max'])+'\nmean: '+str(traffic_data['jitter_mean'])+'\nmedian: '+str(traffic_data['jitter_median'])
 		ax2.text( np.amax(output['interval_stop'])+10,0,text)
+		ax2.set_xlabel('time (s)')
+		ax2.set_ylabel(' ')
 
 		ax3=plt.subplot(313)
 		plt.plot(output['interval_stop'], output['rate_lost'], color='b')
@@ -342,10 +471,11 @@ def do_img_traffic(traffic_data, fname):
 		ax3.set_ylim(ymin=-1)
 		text='min: '+str(traffic_data['rl_min'])+'\nmax: '+str(traffic_data['rl_max'])+'\nmean: '+str(traffic_data['rl_mean'])+'\nmedian: '+str(traffic_data['rl_median'])
 		ax3.text( np.amax(output['interval_stop'])+10,0,text)
-
+		ax3.set_xlabel('time (s)')
+		ax3.set_ylabel(' ')
 
 #		plt.title('Physical throughput ('+metric_def['unit_of_meas']+')')
-		plt.xlabel('time (s)')
+#		plt.xlabel('time (s)')
 #		plt.ylabel(metric_def['id'])
 		
 		# Set graphic minimum Y axis
@@ -365,7 +495,7 @@ def do_img_traffic(traffic_data, fname):
 
 		plt.tight_layout()
 
-		lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
+#		lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
 		mng = plt.get_current_fig_manager()
 		plt.savefig(fname, bbox_inches='tight')
 		plt.close()
@@ -395,7 +525,7 @@ def check_cell_synchro(fname):
 
 			m = re.search('AUTOTEST Cell Sync \:', line)
 			if m :
-				print line
+				#print line
 				return 'CELL_SYNCH'
 
 	return 'CELL_NOT_SYNCH'
@@ -407,7 +537,7 @@ def check_exec_seg_fault(fname):
 		for line in f:
 			m = re.search('Segmentation fault', line)
 			if m :
-				print line
+				#print line
 				return 'SEG_FAULT'
 
 	return 'NO_SEG_FAULT'
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index b77a9baa566252bef3498d6ebc79a4918b704bbc..0a64c0a672b416bdb2ed991ce60d051c42c3a026 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -35,6 +35,7 @@ source $THIS_SCRIPT_PATH/tools/build_helper
 
 MSC_GEN="False"
 XFORMS="True"
+FLEXRAN_AGENT_SB_IF="True"
 PRINT_STATS="False"
 VCD_TIMING="False"
 DEADLINE_SCHEDULER_FLAG_USER="False"
@@ -53,6 +54,7 @@ BUILD_DOXYGEN=0
 T_TRACER="False"
 DISABLE_HARDWARE_DEPENDENCY="False"
 CMAKE_BUILD_TYPE=""
+UE_AUTOTEST_TRACE="False"
 trap handle_ctrl_c INT
 
 function print_help() {
@@ -83,6 +85,8 @@ Options
    Makes the UE specific parts (ue_ip, usim, nvram) 
 --RRH
    Makes the RRH
+-a | --agent
+   Enables agent for software-defined control of the eNB
 -r | --3gpp-release
    default is Rel10,
    Rel8 limits the implementation to 3GPP Release 8 version
@@ -127,6 +131,8 @@ Options
    Enables the T tracer.
 --disable-hardware-dependency
    Disable HW dependency during installation
+--ue-autotest-trace
+    Enable specific traces for UE autotest framework
 Usage (first build):
  oaisim (eNB + UE): ./build_oai -I  --oaisim -x --install-system-files
  Eurecom EXMIMO + COTS UE : ./build_oai -I  --eNB -x --install-system-files
@@ -169,6 +175,10 @@ function main() {
             eNB=1
             echo_info "Will compile eNB"
             shift;;
+       -a | --agent)
+	    FLEXRAN_AGENT=1
+	    echo_info "Will compile eNB with agent support"
+	    shift;;
        --UE)
             UE=1
             echo_info "Will compile UE"
@@ -278,6 +288,10 @@ function main() {
             echo_info "Disabling hardware dependency for compiling software"
             DISABLE_HARDWARE_DEPENDENCY="True"
             shift 1;;
+        --ue-autotest-trace)
+            UE_AUTOTEST_TRACE="True"
+            echo_info "Enabling autotest specific trace for UE"
+            shift 1;;
         -h | --help)
             print_help
             exit 1;;
@@ -321,7 +335,7 @@ function main() {
   #By default: EXMIMO: enable
   if [ "$FORCE_DEADLINE_SCHEDULER_FLAG_USER" = "" ]; then
      if [ "$HW" = "EXMIMO" ] ; then 
-        DEADLINE_SCHEDULER_FLAG_USER="False"
+        DEADLINE_SCHEDULER_FLAG_USER="True"
      elif [ "$HW" = "ETHERNET" ] ; then 
         DEADLINE_SCHEDULER_FLAG_USER="False"
      elif [ "$HW" = "OAI_USRP" ] ; then 
@@ -439,6 +453,9 @@ function main() {
     echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file
     echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >>  $cmake_file
     echo "set ( XFORMS $XFORMS )"                  >>  $cmake_file
+    if [ "$FLEXRAN_AGENT" = "1" ] ; then
+	echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )"      >>  $cmake_file
+    fi
     echo "set ( RRC_ASN1_VERSION \"${REL}\")"      >>  $cmake_file
     echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )"     >>  $cmake_file
     echo "set ( RF_BOARD \"${HW}\")"               >>  $cmake_file
@@ -447,6 +464,7 @@ function main() {
     echo "set (DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )"    >>$cmake_file
     echo "set (CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )"      >>$cmake_file
     echo "set ( T_TRACER $T_TRACER )"              >>  $cmake_file
+    echo "set (UE_AUTOTEST_TRACE $UE_AUTOTEST_TRACE)"        >>  $cmake_file
     echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
     cd  $DIR/$lte_build_dir/build
     cmake ..
@@ -581,6 +599,9 @@ function main() {
     echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file
     echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >>  $cmake_file
     echo "set ( XFORMS $XFORMS )" >>  $cmake_file
+    if [ "$FLEXRAN_AGENT" = "1" ] ; then
+	echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )"      >>  $cmake_file
+    fi
     echo "set ( PRINT_STATS $PRINT_STATS )" >>  $cmake_file
     echo "set ( RRC_ASN1_VERSION \"${REL}\")" >>  $cmake_file
     echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >>  $cmake_file
@@ -649,6 +670,9 @@ function main() {
     cp $DIR/oaisim_mme_build_oai/CMakeLists.template $cmake_file
     echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file
     echo "set ( XFORMS $XFORMS )" >>  $cmake_file
+    if [ "$FLEXRAN_AGENT" = "1" ] ; then
+	echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )"      >>  $cmake_file
+    fi
     echo "set ( RRC_ASN1_VERSION \"${REL}\")" >>  $cmake_file
     echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >>  $cmake_file
     echo "set ( T_TRACER $T_TRACER )"        >>  $cmake_file
diff --git a/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template b/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
index 6d8fc6d26a77c3420673b341b2ebcfec22a7fe73..8e1670ea43e9208190d895d1948467e580c602bc 100644
--- a/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
+++ b/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
@@ -1,6 +1,5 @@
 cmake_minimum_required(VERSION 2.8)
 
-set (  CMAKE_BUILD_TYPE "RelWithDebInfo" )
 set (  ADDR_CONF False )
 set (  DEBUG_OMG False )
 set (  DISABLE_XER_PRINT False )
@@ -48,7 +47,7 @@ set (  NEW_FFT True )
 set (  NO_RRM True )
 set (  OAI_EMU True )
 set (  OAISIM True )
-set (  OAI_NW_DRIVER_TYPE_ETHERNET True )
+set (  OAI_NW_DRIVER_TYPE_ETHERNET False )
 set (  OAI_NW_DRIVER_USE_NETLINK True )
 set (  OPENAIR1 True )
 set (  OPENAIR2 True )
diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper
index c5f2b877048c10b4a0e19cb238a99a6ac5c603dc..448d54f334db51dd3ce702312e94e90ca66f201e 100755
--- a/cmake_targets/tools/build_helper
+++ b/cmake_targets/tools/build_helper
@@ -163,6 +163,42 @@ compilations() {
 # External packages installers
 ############################################
 
+install_protobuf_from_source(){
+    protobuf_install_log=$OPENAIR_DIR/cmake_targets/log/protobuf_install_log.txt
+    echo_info "\nInstalling Google Protobuf from sources. The log file for Protobuf installation is here: $protobuf_install_log "
+    (
+    cd /tmp
+    echo "Downloading protobuf"
+    rm -rf /tmp/protobuf-2.6.1.tar.gz* /tmp/protobuf-2.6.1
+    wget https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz
+    tar -xzvf protobuf-2.6.1.tar.gz
+    cd protobuf-2.6.1/
+    ./configure
+    echo "Compiling protobuf"
+    make -j`nproc`
+    $SUDO make install
+    $SUDO ldconfig
+    ) >& $protobuf_install_log
+}
+
+install_protobuf_c_from_source(){
+    protobuf_c_install_log=$OPENAIR_DIR/cmake_targets/log/protobuf_c_install_log.txt
+    echo_info "\nInstalling Google Protobuf_C from sources. The log file for Protobuf_C installation is here: $protobuf_c_install_log "
+    (
+    cd /tmp
+    echo "Downloading protobuf-c"
+    rm -rf /tmp/protobuf-c
+    git clone https://github.com/protobuf-c/protobuf-c.git
+    cd protobuf-c
+    ./autogen.sh
+    ./configure
+    echo "Compiling protobuf-c"
+    make -j`nproc`
+    $SUDO make install
+    $SUDO ldconfig
+    ) >& $protobuf_c_install_log
+}
+
 check_install_usrp_uhd_driver(){
         #first we remove old installation
         $SUDO apt-get remove -y uhd || true
@@ -324,6 +360,7 @@ check_install_oai_software() {
 	xmlstarlet \
 	python-pip \
 	pydb \
+	libyaml-dev \
 	wget
 
     $SUDO update-alternatives --set liblapack.so /usr/lib/atlas-base/atlas/liblapack.so
@@ -337,6 +374,10 @@ check_install_oai_software() {
     $SUDO apt-get install -y libgnutls-dev
     
     install_asn1c_from_source
+    $SUDO rm -fr /opt/ssh
+    $SUDO git clone https://gist.github.com/2190472.git /opt/ssh
+    install_protobuf_from_source
+    install_protobuf_c_from_source
 }
 
 ### Remove Nettle installation which was done from sources
@@ -361,6 +402,7 @@ remove_nettle_from_source() {
     cd nettle-2.5/
     ./configure --disable-openssl --enable-shared --prefix=/usr 
     $SUDO make uninstall || true 
+    $SUDO ldconfig
     ) >& $nettle_uninstall_log
 }
 
@@ -384,6 +426,7 @@ remove_gnutls_from_source(){
     cd gnutls-3.1.23/
     ./configure --prefix=/usr
     $SUDO make uninstall || true
+    $SUDO ldconfig
     )>& $gnutls_uninstall_log
 }
 
@@ -398,6 +441,7 @@ install_asn1c_from_source(){
     make -j`nproc`
     $SUDO make install
     cd -
+    $SUDO ldconfig
     ) > $asn1_install_log 2>&1
 }
 
diff --git a/cmake_targets/tools/generate_protobuf b/cmake_targets/tools/generate_protobuf
new file mode 100755
index 0000000000000000000000000000000000000000..5c1b523f8cf338d8e29f18b25e6ceaf12d74ceac
--- /dev/null
+++ b/cmake_targets/tools/generate_protobuf
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+function main()
+{
+mkdir -p $1
+
+#echo generate protobuf messages inside $1 $2
+
+c_out=$1
+shift
+proto_path=$1
+shift
+
+protoc-c  --c_out=$c_out --proto_path=$proto_path $*
+#protoc    --cpp_out=$c_out --proto_path=$proto_path $*
+
+}
+
+main "$@"
diff --git a/cmake_targets/tools/make_agent_cache b/cmake_targets/tools/make_agent_cache
new file mode 100755
index 0000000000000000000000000000000000000000..d2eab20fc0ba0e74792582df44f9dd69d5407e4a
--- /dev/null
+++ b/cmake_targets/tools/make_agent_cache
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+CACHE_DIR=/mnt/oai_agent_cache
+
+if [ ! -d $CACHE_DIR ]; then
+    echo "Creating cache dir in $CACHE_DIR"
+    sudo mkdir $CACHE_DIR
+fi
+
+if grep -qs "$CACHE_DIR" /proc/mounts; then
+    echo "Agent cache is already mounted"
+else
+    echo "Agent cache was not mounted"
+    echo "Mounting..."
+    sudo mount -o size=100m -t tmpfs none "$CACHE_DIR"
+    if [ $? -eq 0 ]; then
+	echo "Mount success"
+    else
+	echo "Something went wrong with the mount"
+    fi
+fi
diff --git a/common/utils/Makefile.inc b/common/utils/Makefile.inc
index b7a1c82379da96c817f5fc96213eeb59d260db99..33c126b8d73230a685451ff9d86136c608c1982d 100644
--- a/common/utils/Makefile.inc
+++ b/common/utils/Makefile.inc
@@ -5,14 +5,14 @@ linux := $(shell if [ `uname` = "Linux" ] ; then echo "1" ; else echo "0" ; fi)
 
 
 CFLAGS += -std=gnu99 
-#CFLAGS += -Wall -g -ggdb -Wstrict-prototypes -fno-strict-aliasing 
+CFLAGS += -Wall -g -ggdb -Wstrict-prototypes -fno-strict-aliasing 
 
 # Need to force this option because default kernel module builder is wrong
 CFLAGS += $(call cc-option,-mpreferred-stack-boundary=4)
 
 #For performance, if some option doesn't exist in all gcc versions, use $(call cc-option,MY_OPTION)
-CFLAGS += -O2
-CFLAGS +=  -funroll-loops 
+#CFLAGS += -O2
+#CFLAGS +=  -funroll-loops 
 CFLAGS += -Wno-packed-bitfield-compat 
 
 # This is the minimum CPU faetures for OAI
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 2d2ee3c48908994512ca1049064013ab741c9db4..d1807080bcc1b5f370b91d5cd0c76759f0bacfd5 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -423,6 +423,27 @@ ID = LEGACY_ENB_APP_TRACE
     GROUP = ALL:LEGACY_ENB_APP:LEGACY_GROUP_TRACE:LEGACY
     FORMAT = string,log
 
+ID = LEGACY_FLEXRAN_AGENT_INFO
+    DESC = FLEXRAN_AGENT legacy logs - info level
+    GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_INFO:LEGACY
+    FORMAT = string,log
+ID = LEGACY_FLEXRAN_AGENT_ERROR
+    DESC = FLEXRAN_AGENT legacy logs - error level
+    GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_ERROR:LEGACY
+    FORMAT = string,log
+ID = LEGACY_FLEXRAN_AGENT_WARNING
+    DESC = FLEXRAN_AGENT legacy logs - warning level
+    GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_WARNING:LEGACY
+    FORMAT = string,log
+ID = LEGACY_FLEXRAN_AGENT_DEBUG
+    DESC = FLEXRAN_AGENT legacy logs - debug level
+    GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_DEBUG:LEGACY
+    FORMAT = string,log
+ID = LEGACY_FLEXRAN_AGENT_TRACE
+    DESC = FLEXRAN_AGENT legacy logs - trace level
+    GROUP = ALL:LEGACY_FLEXRAN_AGENT:LEGACY_GROUP_TRACE:LEGACY
+    FORMAT = string,log
+
 ID = LEGACY_SCTP_INFO
     DESC = SCTP legacy logs - info level
     GROUP = ALL:LEGACY_SCTP:LEGACY_GROUP_INFO:LEGACY
@@ -1246,6 +1267,14 @@ ID = VCD_VARIABLE_UE0_SFN7
     DESC = VCD variable UE0_SFN7
     GROUP = ALL:VCD:ENB:VCD_VARIABLE
     FORMAT = ulong,value
+ID = VCD_VARIABLE_UE0_TRX_READ_NS
+    DESC = VCD variable UE0_TRX_READ_NS
+    GROUP = ALL:VCD:ENB:VCD_VARIABLE
+    FORMAT = ulong,value
+ID = VCD_VARIABLE_UE0_TRX_WRITE_NS
+    DESC = VCD variable UE0_TRX_WRITE_NS
+    GROUP = ALL:VCD:ENB:VCD_VARIABLE
+    FORMAT = ulong,value
 
 #functions
 
@@ -1289,6 +1318,50 @@ ID = VCD_FUNCTION_UE_THREAD_RXTX1
     DESC = VCD function UE_THREAD_RXTX1
     GROUP = ALL:VCD:UE:VCD_FUNCTION
     FORMAT = int,value
+ID = VCD_FUNCTION_TRX_READ_SF9
+    DESC = VCD function TRX_READ_SF9
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_TRX_WRITE_SF9
+    DESC = VCD function TRX_WRITE_SF9
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_UE_SIGNAL_COND_RXTX
+    DESC = VCD function UE_SIGNAL_COND_RXTX
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_UE_WAIT_COND_RXTX0
+    DESC = VCD function UE_WAIT_COND_RXTX0
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_UE_WAIT_COND_RXTX1
+    DESC = VCD function UE_WAIT_COND_RXTX1
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0
+    DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT1
+    DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT1
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0
+    DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT1
+    DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT1
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0
+    DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT1
+    DESC = VCD function UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT1
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
 ID = VCD_FUNCTION_eNB_TX
     DESC = VCD function eNB_TX
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
@@ -1381,8 +1454,8 @@ ID = VCD_FUNCTION_PHY_PROCEDURES_ENB_RX_UESPEC1
     DESC = VCD function PHY_PROCEDURES_ENB_RX_UESPEC1
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
-ID = VCD_FUNCTION_PHY_PROCEDURES_ENB_SLOT_FEP
-    DESC = VCD function PHY_PROCEDURES_ENB_SLOT_FEP
+ID = VCD_FUNCTION_ENB_SLOT_FEP
+    DESC = VCD function ENB_SLOT_FEP
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
 ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX
@@ -1393,6 +1466,26 @@ ID = VCD_FUNCTION_PHY_PROCEDURES_UE_RX
     DESC = VCD function PHY_PROCEDURES_UE_RX
     GROUP = ALL:VCD:UE:VCD_FUNCTION
     FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC
+    DESC = VCD function PHY_PROCEDURES_UE_TX_ULSCH_UESPEC
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_PUCCH
+    DESC = VCD function PHY_PROCEDURES_UE_TX_PUCCH
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_ULSCH_COMMON
+    DESC = VCD function PHY_PROCEDURES_UE_TX_ULSCH_COMMON
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_PRACH
+    DESC = VCD function PHY_PROCEDURES_UE_TX_PRACH
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PHY_PROCEDURES_UE_TX_ULSCH_RAR
+    DESC = VCD function PHY_PROCEDURES_UE_TX_ULSCH_RAR
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
 ID = VCD_FUNCTION_PHY_PROCEDURES_ENB_LTE
     DESC = VCD function PHY_PROCEDURES_ENB_LTE
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
@@ -1481,6 +1574,22 @@ ID = VCD_FUNCTION_RX_PHICH
     DESC = VCD function RX_PHICH
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
+ID = VCD_FUNCTION_PDSCH_PROC
+    DESC = VCD function PDSCH_PROC
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PDSCH_PROC_SI
+    DESC = VCD function PDSCH_PROC_SI
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PDSCH_PROC_P
+    DESC = VCD function PDSCH_PROC_P
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_PDSCH_PROC_RA
+    DESC = VCD function PDSCH_PROC_RA
+    GROUP = ALL:VCD:UE:VCD_FUNCTION
+    FORMAT = int,value
 ID = VCD_FUNCTION_PHY_UE_CONFIG_SIB2
     DESC = VCD function PHY_UE_CONFIG_SIB2
     GROUP = ALL:VCD:UE:VCD_FUNCTION
@@ -1585,6 +1694,14 @@ ID = VCD_FUNCTION_ENB_DLSCH_SCRAMBLING
     DESC = VCD function ENB_DLSCH_SCRAMBLING
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
+ID = VCD_FUNCTION_ENB_BEAM_PRECODING
+    DESC = VCD function ENB_BEAM_PRECODING
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+ID = VCD_FUNCTION_ENB_OFDM_MODULATION
+    DESC = VCD function ENB_OFDM_MODULATION
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
 ID = VCD_FUNCTION_MACPHY_INIT
     DESC = VCD function MACPHY_INIT
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
@@ -1697,6 +1814,10 @@ ID = VCD_FUNCTION_RLC_DATA_REQ
     DESC = VCD function RLC_DATA_REQ
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
+ID = VCD_FUNCTION_RLC_DATA_IND
+    DESC = VCD function RLC_DATA_IND
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
 ID = VCD_FUNCTION_MAC_RLC_STATUS_IND
     DESC = VCD function MAC_RLC_STATUS_IND
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
diff --git a/common/utils/collection/tree.h b/common/utils/collection/tree.h
index 8e4e35c408c5a3945447caae1beabea6f34ad2b9..c9df686fbb135d17c24a8e2ad72ebd75e9ada647 100755
--- a/common/utils/collection/tree.h
+++ b/common/utils/collection/tree.h
@@ -1,4 +1,8 @@
-/*
+/*	$NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $	*/
+/*	$OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $	*/
+/* $FreeBSD$ */
+
+/*-
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * All rights reserved.
  *
@@ -26,6 +30,8 @@
 #ifndef	_SYS_TREE_H_
 #define	_SYS_TREE_H_
 
+#include <sys/cdefs.h>
+
 /*
  * This file defines data structures for different types of trees:
  * splay trees and red-black trees.
@@ -63,7 +69,7 @@ struct name {								\
 
 #define SPLAY_INIT(root) do {						\
 	(root)->sph_root = NULL;					\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 #define SPLAY_ENTRY(type)						\
 struct {								\
@@ -81,32 +87,32 @@ struct {								\
 	SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);	\
 	SPLAY_RIGHT(tmp, field) = (head)->sph_root;			\
 	(head)->sph_root = tmp;						\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 	
 #define SPLAY_ROTATE_LEFT(head, tmp, field) do {			\
 	SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);	\
 	SPLAY_LEFT(tmp, field) = (head)->sph_root;			\
 	(head)->sph_root = tmp;						\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 #define SPLAY_LINKLEFT(head, tmp, field) do {				\
 	SPLAY_LEFT(tmp, field) = (head)->sph_root;			\
 	tmp = (head)->sph_root;						\
 	(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);		\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 #define SPLAY_LINKRIGHT(head, tmp, field) do {				\
 	SPLAY_RIGHT(tmp, field) = (head)->sph_root;			\
 	tmp = (head)->sph_root;						\
 	(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);	\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 #define SPLAY_ASSEMBLE(head, node, left, right, field) do {		\
 	SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field);	\
 	SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
 	SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field);	\
 	SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field);	\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 /* Generates prototypes and inline functions */
 
@@ -207,7 +213,7 @@ name##_SPLAY(struct name *head, struct type *elm)			\
 	SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
 	__left = __right = &__node;					\
 \
-	while ((__comp = (cmp)(elm, (head)->sph_root))) {		\
+	while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) {		\
 		if (__comp < 0) {					\
 			__tmp = SPLAY_LEFT((head)->sph_root, field);	\
 			if (__tmp == NULL)				\
@@ -286,7 +292,7 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \
 	     (x) != NULL;						\
 	     (x) = SPLAY_NEXT(name, head, x))
 
-/* Macros that define a red-back tree */
+/* Macros that define a red-black tree */
 #define RB_HEAD(name, type)						\
 struct name {								\
 	struct type *rbh_root; /* root of the tree */			\
@@ -297,7 +303,7 @@ struct name {								\
 
 #define RB_INIT(root) do {						\
 	(root)->rbh_root = NULL;					\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 #define RB_BLACK	0
 #define RB_RED		1
@@ -320,24 +326,24 @@ struct {								\
 	RB_PARENT(elm, field) = parent;					\
 	RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;		\
 	RB_COLOR(elm, field) = RB_RED;					\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 #define RB_SET_BLACKRED(black, red, field) do {				\
 	RB_COLOR(black, field) = RB_BLACK;				\
 	RB_COLOR(red, field) = RB_RED;					\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 #ifndef RB_AUGMENT
-#define RB_AUGMENT(x)
+#define RB_AUGMENT(x)	do {} while (0)
 #endif
 
 #define RB_ROTATE_LEFT(head, elm, tmp, field) do {			\
 	(tmp) = RB_RIGHT(elm, field);					\
-	if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) {		\
+	if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) {	\
 		RB_PARENT(RB_LEFT(tmp, field), field) = (elm);		\
 	}								\
 	RB_AUGMENT(elm);						\
-	if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {		\
+	if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) {	\
 		if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))	\
 			RB_LEFT(RB_PARENT(elm, field), field) = (tmp);	\
 		else							\
@@ -349,15 +355,15 @@ struct {								\
 	RB_AUGMENT(tmp);						\
 	if ((RB_PARENT(tmp, field)))					\
 		RB_AUGMENT(RB_PARENT(tmp, field));			\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 #define RB_ROTATE_RIGHT(head, elm, tmp, field) do {			\
 	(tmp) = RB_LEFT(elm, field);					\
-	if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) {		\
+	if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) {	\
 		RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);		\
 	}								\
 	RB_AUGMENT(elm);						\
-	if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {		\
+	if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) {	\
 		if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))	\
 			RB_LEFT(RB_PARENT(elm, field), field) = (tmp);	\
 		else							\
@@ -369,28 +375,66 @@ struct {								\
 	RB_AUGMENT(tmp);						\
 	if ((RB_PARENT(tmp, field)))					\
 		RB_AUGMENT(RB_PARENT(tmp, field));			\
-} while (0)
+} while (/*CONSTCOND*/ 0)
 
 /* Generates prototypes and inline functions */
-#define RB_PROTOTYPE(name, type, field, cmp)				\
-void name##_RB_INSERT_COLOR(struct name *, struct type *);	\
-void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
-struct type *name##_RB_REMOVE(struct name *, struct type *);		\
-struct type *name##_RB_INSERT(struct name *, struct type *);		\
-struct type *name##_RB_FIND(struct name *, struct type *);		\
-struct type *name##_RB_NEXT(struct type *);				\
-struct type *name##_RB_MINMAX(struct name *, int);			\
-									\
+#define	RB_PROTOTYPE(name, type, field, cmp)				\
+	RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
+#define	RB_PROTOTYPE_STATIC(name, type, field, cmp)			\
+	RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)		\
+	RB_PROTOTYPE_INSERT_COLOR(name, type, attr);			\
+	RB_PROTOTYPE_REMOVE_COLOR(name, type, attr);			\
+	RB_PROTOTYPE_INSERT(name, type, attr);				\
+	RB_PROTOTYPE_REMOVE(name, type, attr);				\
+	RB_PROTOTYPE_FIND(name, type, attr);				\
+	RB_PROTOTYPE_NFIND(name, type, attr);				\
+	RB_PROTOTYPE_NEXT(name, type, attr);				\
+	RB_PROTOTYPE_PREV(name, type, attr);				\
+	RB_PROTOTYPE_MINMAX(name, type, attr);
+#define RB_PROTOTYPE_INSERT_COLOR(name, type, attr)			\
+	attr void name##_RB_INSERT_COLOR(struct name *, struct type *)
+#define RB_PROTOTYPE_REMOVE_COLOR(name, type, attr)			\
+	attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *)
+#define RB_PROTOTYPE_REMOVE(name, type, attr)				\
+	attr struct type *name##_RB_REMOVE(struct name *, struct type *)
+#define RB_PROTOTYPE_INSERT(name, type, attr)				\
+	attr struct type *name##_RB_INSERT(struct name *, struct type *)
+#define RB_PROTOTYPE_FIND(name, type, attr)				\
+	attr struct type *name##_RB_FIND(struct name *, struct type *)
+#define RB_PROTOTYPE_NFIND(name, type, attr)				\
+	attr struct type *name##_RB_NFIND(struct name *, struct type *)
+#define RB_PROTOTYPE_NEXT(name, type, attr)				\
+	attr struct type *name##_RB_NEXT(struct type *)
+#define RB_PROTOTYPE_PREV(name, type, attr)				\
+	attr struct type *name##_RB_PREV(struct type *)
+#define RB_PROTOTYPE_MINMAX(name, type, attr)				\
+	attr struct type *name##_RB_MINMAX(struct name *, int)
 
 /* Main rb operation.
  * Moves node close to the key of elm to top
  */
-#define RB_GENERATE(name, type, field, cmp)				\
-void									\
+#define	RB_GENERATE(name, type, field, cmp)				\
+	RB_GENERATE_INTERNAL(name, type, field, cmp,)
+#define	RB_GENERATE_STATIC(name, type, field, cmp)			\
+	RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr)		\
+	RB_GENERATE_INSERT_COLOR(name, type, field, attr)		\
+	RB_GENERATE_REMOVE_COLOR(name, type, field, attr)		\
+	RB_GENERATE_INSERT(name, type, field, cmp, attr)		\
+	RB_GENERATE_REMOVE(name, type, field, attr)			\
+	RB_GENERATE_FIND(name, type, field, cmp, attr)			\
+	RB_GENERATE_NFIND(name, type, field, cmp, attr)			\
+	RB_GENERATE_NEXT(name, type, field, attr)			\
+	RB_GENERATE_PREV(name, type, field, attr)			\
+	RB_GENERATE_MINMAX(name, type, field, attr)
+
+#define RB_GENERATE_INSERT_COLOR(name, type, field, attr)		\
+attr void								\
 name##_RB_INSERT_COLOR(struct name *head, struct type *elm)		\
 {									\
 	struct type *parent, *gparent, *tmp;				\
-	while ((parent = RB_PARENT(elm, field)) &&			\
+	while ((parent = RB_PARENT(elm, field)) != NULL &&		\
 	    RB_COLOR(parent, field) == RB_RED) {			\
 		gparent = RB_PARENT(parent, field);			\
 		if (parent == RB_LEFT(gparent, field)) {		\
@@ -428,9 +472,10 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm)		\
 		}							\
 	}								\
 	RB_COLOR(head->rbh_root, field) = RB_BLACK;			\
-}									\
-									\
-void									\
+}
+
+#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr)		\
+attr void								\
 name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
 {									\
 	struct type *tmp;						\
@@ -454,7 +499,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
 				if (RB_RIGHT(tmp, field) == NULL ||	\
 				    RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
 					struct type *oleft;		\
-					if ((oleft = RB_LEFT(tmp, field)))\
+					if ((oleft = RB_LEFT(tmp, field)) \
+					    != NULL)			\
 						RB_COLOR(oleft, field) = RB_BLACK;\
 					RB_COLOR(tmp, field) = RB_RED;	\
 					RB_ROTATE_RIGHT(head, tmp, oleft, field);\
@@ -486,7 +532,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
 				if (RB_LEFT(tmp, field) == NULL ||	\
 				    RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
 					struct type *oright;		\
-					if ((oright = RB_RIGHT(tmp, field)))\
+					if ((oright = RB_RIGHT(tmp, field)) \
+					    != NULL)			\
 						RB_COLOR(oright, field) = RB_BLACK;\
 					RB_COLOR(tmp, field) = RB_RED;	\
 					RB_ROTATE_LEFT(head, tmp, oright, field);\
@@ -504,9 +551,10 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
 	}								\
 	if (elm)							\
 		RB_COLOR(elm, field) = RB_BLACK;			\
-}									\
-									\
-struct type *								\
+}
+
+#define RB_GENERATE_REMOVE(name, type, field, attr)			\
+attr struct type *							\
 name##_RB_REMOVE(struct name *head, struct type *elm)			\
 {									\
 	struct type *child, *parent, *old = elm;			\
@@ -518,7 +566,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm)			\
 	else {								\
 		struct type *left;					\
 		elm = RB_RIGHT(elm, field);				\
-		while ((left = RB_LEFT(elm, field)))			\
+		while ((left = RB_LEFT(elm, field)) != NULL)		\
 			elm = left;					\
 		child = RB_RIGHT(elm, field);				\
 		parent = RB_PARENT(elm, field);				\
@@ -551,7 +599,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm)			\
 			left = parent;					\
 			do {						\
 				RB_AUGMENT(left);			\
-			} while ((left = RB_PARENT(left, field)));	\
+			} while ((left = RB_PARENT(left, field)) != NULL); \
 		}							\
 		goto color;						\
 	}								\
@@ -572,9 +620,10 @@ color:									\
 		name##_RB_REMOVE_COLOR(head, parent, child);		\
 	return (old);							\
 }									\
-									\
+
+#define RB_GENERATE_INSERT(name, type, field, cmp, attr)		\
 /* Inserts a node into the RB tree */					\
-struct type *								\
+attr struct type *							\
 name##_RB_INSERT(struct name *head, struct type *elm)			\
 {									\
 	struct type *tmp;						\
@@ -599,15 +648,14 @@ name##_RB_INSERT(struct name *head, struct type *elm)			\
 			RB_RIGHT(parent, field) = elm;			\
 		RB_AUGMENT(parent);					\
 	} else								\
-  {                                                                     \
 		RB_ROOT(head) = elm;					\
-  }                                                                     \
 	name##_RB_INSERT_COLOR(head, elm);				\
 	return (NULL);							\
-}									\
-									\
+}
+
+#define RB_GENERATE_FIND(name, type, field, cmp, attr)			\
 /* Finds the node with the same key as elm */				\
-struct type *								\
+attr struct type *							\
 name##_RB_FIND(struct name *head, struct type *elm)			\
 {									\
 	struct type *tmp = RB_ROOT(head);				\
@@ -622,9 +670,33 @@ name##_RB_FIND(struct name *head, struct type *elm)			\
 			return (tmp);					\
 	}								\
 	return (NULL);							\
-}									\
-									\
-struct type *								\
+}
+
+#define RB_GENERATE_NFIND(name, type, field, cmp, attr)			\
+/* Finds the first node greater than or equal to the search key */	\
+attr struct type *							\
+name##_RB_NFIND(struct name *head, struct type *elm)			\
+{									\
+	struct type *tmp = RB_ROOT(head);				\
+	struct type *res = NULL;					\
+	int comp;							\
+	while (tmp) {							\
+		comp = cmp(elm, tmp);					\
+		if (comp < 0) {						\
+			res = tmp;					\
+			tmp = RB_LEFT(tmp, field);			\
+		}							\
+		else if (comp > 0)					\
+			tmp = RB_RIGHT(tmp, field);			\
+		else							\
+			return (tmp);					\
+	}								\
+	return (res);							\
+}
+
+#define RB_GENERATE_NEXT(name, type, field, attr)			\
+/* ARGSUSED */								\
+attr struct type *							\
 name##_RB_NEXT(struct type *elm)					\
 {									\
 	if (RB_RIGHT(elm, field)) {					\
@@ -643,9 +715,33 @@ name##_RB_NEXT(struct type *elm)					\
 		}							\
 	}								\
 	return (elm);							\
-}									\
-									\
-struct type *								\
+}
+
+#define RB_GENERATE_PREV(name, type, field, attr)			\
+/* ARGSUSED */								\
+attr struct type *							\
+name##_RB_PREV(struct type *elm)					\
+{									\
+	if (RB_LEFT(elm, field)) {					\
+		elm = RB_LEFT(elm, field);				\
+		while (RB_RIGHT(elm, field))				\
+			elm = RB_RIGHT(elm, field);			\
+	} else {							\
+		if (RB_PARENT(elm, field) &&				\
+		    (elm == RB_RIGHT(RB_PARENT(elm, field), field)))	\
+			elm = RB_PARENT(elm, field);			\
+		else {							\
+			while (RB_PARENT(elm, field) &&			\
+			    (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
+				elm = RB_PARENT(elm, field);		\
+			elm = RB_PARENT(elm, field);			\
+		}							\
+	}								\
+	return (elm);							\
+}
+
+#define RB_GENERATE_MINMAX(name, type, field, attr)			\
+attr struct type *							\
 name##_RB_MINMAX(struct name *head, int val)				\
 {									\
 	struct type *tmp = RB_ROOT(head);				\
@@ -666,7 +762,9 @@ name##_RB_MINMAX(struct name *head, int val)				\
 #define RB_INSERT(name, x, y)	name##_RB_INSERT(x, y)
 #define RB_REMOVE(name, x, y)	name##_RB_REMOVE(x, y)
 #define RB_FIND(name, x, y)	name##_RB_FIND(x, y)
+#define RB_NFIND(name, x, y)	name##_RB_NFIND(x, y)
 #define RB_NEXT(name, x, y)	name##_RB_NEXT(y)
+#define RB_PREV(name, x, y)	name##_RB_PREV(y)
 #define RB_MIN(name, x)		name##_RB_MINMAX(x, RB_NEGINF)
 #define RB_MAX(name, x)		name##_RB_MINMAX(x, RB_INF)
 
@@ -675,4 +773,29 @@ name##_RB_MINMAX(struct name *head, int val)				\
 	     (x) != NULL;						\
 	     (x) = name##_RB_NEXT(x))
 
+#define RB_FOREACH_FROM(x, name, y)					\
+	for ((x) = (y);							\
+	    ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL);	\
+	     (x) = (y))
+
+#define RB_FOREACH_SAFE(x, name, head, y)				\
+	for ((x) = RB_MIN(name, head);					\
+	    ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL);	\
+	     (x) = (y))
+
+#define RB_FOREACH_REVERSE(x, name, head)				\
+	for ((x) = RB_MAX(name, head);					\
+	     (x) != NULL;						\
+	     (x) = name##_RB_PREV(x))
+
+#define RB_FOREACH_REVERSE_FROM(x, name, y)				\
+	for ((x) = (y);							\
+	    ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL);	\
+	     (x) = (y))
+
+#define RB_FOREACH_REVERSE_SAFE(x, name, head, y)			\
+	for ((x) = RB_MAX(name, head);					\
+	    ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL);	\
+	     (x) = (y))
+
 #endif	/* _SYS_TREE_H_ */
diff --git a/common/utils/itti/timer.c b/common/utils/itti/timer.c
index 5486c76d83e14c444309274aebc3187fcd55667a..c180cfcda40d8fea03c785061530ab0d7eabc983 100644
--- a/common/utils/itti/timer.c
+++ b/common/utils/itti/timer.c
@@ -86,8 +86,8 @@ int timer_handle_signal(siginfo_t *info)
   timer_p = (struct timer_elm_s *)info->si_ptr;
 
   // LG: To many traces for msc timer:
-  // TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer);
-
+  TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer);
+  
   task_id = timer_p->task_id;
   instance = timer_p->instance;
   message_p = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED);
@@ -120,6 +120,10 @@ int timer_handle_signal(siginfo_t *info)
     return -1;
   }
 
+#if defined(ENB_AGENT_SB_IF)
+
+#endif 
+
   return 0;
 }
 
diff --git a/maketags b/maketags
index 4dff87bf765f082cd58fafc5b4252367ee34fd45..361adc5d67eed32c67bc41ab1d59eb946aded209 100755
--- a/maketags
+++ b/maketags
@@ -1,3 +1,4 @@
 #!/bin/sh
 echo "building ctags for openair1 and openair2 ..."
 ctags -e -R  --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair2/RRC/CELLULAR/ --exclude=openair2/NAS/DRIVER/CELLULAR/ --exclude=openair2/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common
+
diff --git a/openair1/PHY/CODING/lte_segmentation.c b/openair1/PHY/CODING/lte_segmentation.c
index 746344a6acb6e29e3c124e7b0cc81244de2ccd55..04056c4c9eb919e5bccfdb1ee05e72e2ea8003a7 100644
--- a/openair1/PHY/CODING/lte_segmentation.c
+++ b/openair1/PHY/CODING/lte_segmentation.c
@@ -60,7 +60,7 @@ int lte_segmentation(unsigned char *input_buffer,
   }
 
   if ((*C)>MAX_NUM_DLSCH_SEGMENTS) {
-    msg("lte_segmentation.c: too many segments %d\n",*C);
+      LOG_E(PHY,"lte_segmentation.c: too many segments %d, B %d, L %d, Bprime %d\n",*C,B,L,Bprime);
     return(-1);
   }
 
diff --git a/openair1/PHY/INIT/defs.h b/openair1/PHY/INIT/defs.h
index 1874c4e8c7d85d9417381869cd998e0674cc2e26..27303cb57dc91deb0e58968e1d23197ab03de19a 100644
--- a/openair1/PHY/INIT/defs.h
+++ b/openair1/PHY/INIT/defs.h
@@ -206,7 +206,19 @@ void phy_config_dedicated_ue(module_id_t Mod_id,
                              uint8_t CH_index,
                              struct PhysicalConfigDedicated *physicalConfigDedicated);
 
+/*!
+\fn void phy_config_harq_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index,
+               uint16_t max_harq_tx)
+\brief Configure UE UL max harq Tx.
+\details Invoked upon reception of RRCConnectionSetup or RRCConnectionReconfiguration from eNB.
+@param Mod_id Instance ID for eNB
+@param CC_id Component Carrier index
+@param CH_index Index of eNB for this configuration
+@param max_harq_tx max harq tx information
 
+ */
+void phy_config_harq_ue(module_id_t Mod_id,int CC_id,uint8_t CH_index,
+                           uint16_t max_harq_tx);
 /**
 \brief Configure UE MBSFN common parameters.
 \details Invoked upon reception of SIB13 from eNB.
@@ -292,7 +304,8 @@ void phy_init_lte_top(LTE_DL_FRAME_PARMS *lte_frame_parms);
 
 //void copy_lte_parms_to_phy_framing(LTE_DL_FRAME_PARMS *frame_parm, PHY_FRAMING *phy_framing);
 
-void lte_param_init(unsigned char N_tx, 
+void lte_param_init(unsigned char N_tx_port_eNB,
+		    unsigned char N_tx, 
 		    unsigned char N_rx,
 		    unsigned char transmission_mode,
 		    uint8_t extended_prefix_flag,
@@ -327,7 +340,8 @@ void phy_cleanup(void);
 int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf);
 void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms);
 
-void lte_param_init(unsigned char N_tx, 
+void lte_param_init(unsigned char N_tx_port_eNB, 
+                    unsigned char N_tx_phy,
 		    unsigned char N_rx,
 		    unsigned char transmission_mode,
 		    uint8_t extended_prefix_flag,
@@ -338,7 +352,6 @@ void lte_param_init(unsigned char N_tx,
 		    uint8_t threequarter_fs,
                     uint8_t osf,
 		    uint32_t perfect_ce);
-
 /** @} */
 #endif
 
diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c
index 2f023f8235bf79160142eb89eebe17bd0b404212..db3c8d6b7204d44d814d4fe8a077099e4129e1b1 100644
--- a/openair1/PHY/INIT/lte_init.c
+++ b/openair1/PHY/INIT/lte_init.c
@@ -46,13 +46,12 @@ void phy_config_mib(LTE_DL_FRAME_PARMS *fp,
                     uint8_t p_eNB,
                     PHICH_CONFIG_COMMON *phich_config)
 {
-
   fp->N_RB_DL                            = N_RB_DL;
   fp->Nid_cell                           = Nid_cell;
   fp->nushift                            = Nid_cell%6;
   fp->Ncp                                = Ncp;
   fp->frame_type                         = frame_type;
-  fp->nb_antennas_tx_eNB                 = p_eNB;
+  fp->nb_antenna_ports_eNB               = p_eNB;
   fp->phich_config_common.phich_resource = phich_config->phich_resource;
   fp->phich_config_common.phich_duration = phich_config->phich_duration;
 }
@@ -482,6 +481,26 @@ void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *eNB)
 
       }
 
+      if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated) {
+        if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
+
+          eNB->soundingrs_ul_config_dedicated[UE_id].duration             = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.duration;
+          eNB->soundingrs_ul_config_dedicated[UE_id].cyclicShift          = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;
+          eNB->soundingrs_ul_config_dedicated[UE_id].freqDomainPosition   = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
+          eNB->soundingrs_ul_config_dedicated[UE_id].srs_Bandwidth        = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
+          eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex      = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
+          eNB->soundingrs_ul_config_dedicated[UE_id].srs_HoppingBandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;
+          eNB->soundingrs_ul_config_dedicated[UE_id].transmissionComb     = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
+
+
+          LOG_D(PHY,"soundingrs_ul_config_dedicated.srs_ConfigIndex %d\n",eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex);
+
+        }
+
+        LOG_D(PHY,"------------------------------------------------------------\n");
+
+      }
+
       eNB->physicalConfigDedicated[UE_id] = NULL;
     }
   }
@@ -664,6 +683,7 @@ void phy_config_dedicated_eNB(uint8_t Mod_id,
 	eNB->transmission_mode[UE_id] = 6;
 	break;
       case AntennaInfoDedicated__transmissionMode_tm7:
+        lte_gold_ue_spec_port5(eNB->lte_gold_uespec_port5_table[0],eNB->frame_parms.Nid_cell,rnti);
 	eNB->transmission_mode[UE_id] = 7;
 	break;
       default:
@@ -726,6 +746,14 @@ void phy_config_dedicated_scell_eNB(uint8_t Mod_id,
 }
 #endif
 
+void phy_config_harq_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
+                        uint16_t max_harq_tx )
+{
+
+  PHY_VARS_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id];
+  phy_vars_ue->ulsch[eNB_id]->Mlimit = max_harq_tx;
+}
+
 void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
                              struct PhysicalConfigDedicated *physicalConfigDedicated )
 {
@@ -742,7 +770,8 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
   phy_vars_ue->dlsch_received_last[eNB_id]=0;
   phy_vars_ue->dlsch_fer[eNB_id]=0;
 
-
+  phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1;
+  phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1;
 
   if (physicalConfigDedicated) {
     LOG_D(PHY,"[UE %d] Received physicalConfigDedicated from eNB %d\n",Mod_id, eNB_id);
@@ -806,7 +835,6 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
     if (physicalConfigDedicated->antennaInfo) {
       phy_vars_ue->transmission_mode[eNB_id] = 1+(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode);
       LOG_D(PHY,"Transmission Mode %d\n",phy_vars_ue->transmission_mode[eNB_id]);
-      LOG_D(PHY,"\n");
       switch(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode) {
       case AntennaInfoDedicated__transmissionMode_tm1:
 	phy_vars_ue->transmission_mode[eNB_id] = 1;
@@ -827,6 +855,7 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
 	phy_vars_ue->transmission_mode[eNB_id] = 6;
 	break;
       case AntennaInfoDedicated__transmissionMode_tm7:
+        lte_gold_ue_spec_port5(phy_vars_ue->lte_gold_uespec_port5_table, phy_vars_ue->frame_parms.Nid_cell, phy_vars_ue->pdcch_vars[eNB_id]->crnti);
 	phy_vars_ue->transmission_mode[eNB_id] = 7;
 	break;
       default:
@@ -852,6 +881,53 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
 
     }
 
+    if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated) {
+
+      phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srsConfigDedicatedSetup = 0;
+      if (physicalConfigDedicated->soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) {
+        phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srsConfigDedicatedSetup = 1;
+        phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].duration             = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.duration;
+        phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].cyclicShift          = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift;
+        phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].freqDomainPosition   = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition;
+        phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_Bandwidth        = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth;
+        phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_ConfigIndex      = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex;
+        phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_HoppingBandwidth = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;
+        phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].transmissionComb     = physicalConfigDedicated->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb;
+
+
+        LOG_D(PHY,"soundingrs_ul_config_dedicated.srs_ConfigIndex %d\n",phy_vars_ue->soundingrs_ul_config_dedicated[eNB_id].srs_ConfigIndex);
+      }
+
+      LOG_D(PHY,"------------------------------------------------------------\n");
+
+    }
+
+
+    if (physicalConfigDedicated->cqi_ReportConfig) {
+      if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic) {
+	// configure PUSCH CQI reporting
+	phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic;
+	if ((phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm12) && 
+	    (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm30) &&
+	    (phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic != rm31))
+	  LOG_E(PHY,"Unsupported Aperiodic CQI Feedback Mode : %d\n",phy_vars_ue->cqi_report_config[eNB_id].cqi_ReportModeAperiodic);
+      }
+      if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic) {
+	if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_setup) {
+	// configure PUCCH CQI reporting
+	  phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex;
+	  phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex     = physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex;
+	  if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex)
+	    phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = *physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.ri_ConfigIndex;	
+	}
+	else if (physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_release) {
+	  // handle release
+	  phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex = -1;
+	  phy_vars_ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex = -1;
+	}
+      }
+    }
+    
 #ifdef CBA
 
     if (physicalConfigDedicated->pusch_CBAConfigDedicated_vlola) {
@@ -868,6 +944,9 @@ void phy_config_dedicated_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,
     return;
   }
 
+  // fill cqi parameters for periodic CQI reporting
+  get_cqipmiri_params(phy_vars_ue,eNB_id);
+
 }
 
 void  phy_config_cba_rnti (module_id_t Mod_id,int CC_id,eNB_flag_t eNB_flag, uint8_t index, rnti_t cba_rnti, uint8_t cba_group_id, uint8_t num_active_cba_groups)
@@ -939,14 +1018,17 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS
   pdsch->llr128_2ndstream = (int16_t**)malloc16_clear( sizeof(int16_t*) );
   // FIXME! no further allocation for (int16_t*)pdsch->llr128 !!! expect SIGSEGV
 
-  pdsch->rxdataF_ext         = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
-  pdsch->rxdataF_comp0       = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
-  pdsch->rho                 = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) );
-  pdsch->dl_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
-  pdsch->dl_ch_rho_ext       = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
-  pdsch->dl_ch_rho2_ext       = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
-  pdsch->dl_ch_mag0          = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
-  pdsch->dl_ch_magb0         = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->rxdataF_ext            = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->rxdataF_uespec_pilots  = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->rxdataF_comp0          = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->rho                    = (int32_t**)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t*) );
+  pdsch->dl_ch_estimates_ext    = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->dl_bf_ch_estimates     = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->dl_bf_ch_estimates_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->dl_ch_rho_ext          = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->dl_ch_rho2_ext         = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->dl_ch_mag0             = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
+  pdsch->dl_ch_magb0            = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
 
   // the allocated memory size is fixed:
   AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" );
@@ -957,13 +1039,16 @@ void phy_init_lte_ue__PDSCH( LTE_UE_PDSCH* const pdsch, const LTE_DL_FRAME_PARMS
     for (int j=0; j<4; j++) { //fp->nb_antennas_tx; j++)
       const int idx = (j<<1)+i;
       const size_t num = 7*2*fp->N_RB_DL*12;
-      pdsch->rxdataF_ext[idx]         = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
-      pdsch->rxdataF_comp0[idx]       = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
-      pdsch->dl_ch_estimates_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
-      pdsch->dl_ch_rho_ext[idx]       = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
-      pdsch->dl_ch_rho2_ext[idx]       = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
-      pdsch->dl_ch_mag0[idx]          = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
-      pdsch->dl_ch_magb0[idx]         = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+      pdsch->rxdataF_ext[idx]             = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+      pdsch->rxdataF_uespec_pilots[idx]   = (int32_t*)malloc16_clear( sizeof(int32_t) * fp->N_RB_DL*12);
+      pdsch->rxdataF_comp0[idx]           = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+      pdsch->dl_ch_estimates_ext[idx]     = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+      pdsch->dl_bf_ch_estimates[idx]      = (int32_t*)malloc16_clear( sizeof(int32_t) * fp->ofdm_symbol_size*7*2);
+      pdsch->dl_bf_ch_estimates_ext[idx]  = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+      pdsch->dl_ch_rho_ext[idx]           = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+      pdsch->dl_ch_rho2_ext[idx]          = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+      pdsch->dl_ch_mag0[idx]              = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
+      pdsch->dl_ch_magb0[idx]             = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
     }
   }
 }
@@ -1178,6 +1263,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
   LTE_eNB_SRS* const srs_vars       = eNB->srs_vars;
   LTE_eNB_PRACH* const prach_vars   = &eNB->prach_vars;
   int i, j, eNB_id, UE_id; 
+  int re;
 
   eNB->total_dlsch_bitrate = 0;
   eNB->total_transmitted_bits = 0;
@@ -1204,9 +1290,9 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
       eNB->physicalConfigDedicated[UE_id] = NULL;
     }
     
-    eNB->first_run_I0_measurements =
-      1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here.
+    eNB->first_run_I0_measurements = 1; ///This flag used to be static. With multiple eNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here.
   }
+
   //  for (eNB_id=0; eNB_id<3; eNB_id++) {
   {
     eNB_id=0;
@@ -1214,11 +1300,23 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
       
       // TX vars
       if (eNB->node_function != NGFI_RCC_IF4p5)
-	common_vars->txdata[eNB_id]  = (int32_t**)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) );
-      common_vars->txdataF[eNB_id] = (int32_t **)malloc16( fp->nb_antennas_tx*sizeof(int32_t*) );
-      
+	common_vars->txdata[eNB_id]  = (int32_t**)malloc16(fp->nb_antennas_tx*sizeof(int32_t*));
+      common_vars->txdataF[eNB_id] = (int32_t **)malloc16(NB_ANTENNA_PORTS_ENB*sizeof(int32_t*));
+      common_vars->txdataF_BF[eNB_id] = (int32_t **)malloc16(fp->nb_antennas_tx*sizeof(int32_t*));
+
+      for (i=0; i<14; i++) {
+        common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) );
+#ifdef DEBUG_PHY
+        msg("[openair][LTE_PHY][INIT] lte_common_vars->txdataF[%d][%d] = %p (%d bytes)\n",
+            eNB_id,i,common_vars->txdataF[eNB_id][i],
+            fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t));
+#endif
+      }
+
       for (i=0; i<fp->nb_antennas_tx; i++) {
+	common_vars->txdataF_BF[eNB_id][i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t) );
 	if (eNB->node_function != NGFI_RCC_IF4p5)
+
 	  // Allocate 10 subframes of I/Q TX signal data (time) if not
 	  common_vars->txdata[eNB_id][i]  = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
 	if (eNB->node_function == NGFI_RRU_IF4p5) 
@@ -1238,17 +1336,41 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
 #endif
       }
       
+      for (i=0; i<14; i++) { // 14 is the total number of antenna ports
+        common_vars->beam_weights[eNB_id][i] = (int32_t **)malloc16_clear(fp->nb_antennas_tx*sizeof(int32_t*));
+        for (j=0; j<fp->nb_antennas_tx; j++) {
+          common_vars->beam_weights[eNB_id][i][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t));
+	  // antenna ports 0-3 are mapped on antennas 0-3
+	  // antenna port 4 is mapped on antenna 0
+	  // antenna ports 5-14 are mapped on all antennas 
+	  if (((i<4) && (i==j)) || ((i==4) && (j==0))) {
+	    for (re=0; re<fp->ofdm_symbol_size; re++) 
+	      common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff; 
+	  }
+	  else if (i>4) {
+	    for (re=0; re<fp->ofdm_symbol_size; re++) 
+	      common_vars->beam_weights[eNB_id][i][j][re] = 0x00007fff/fp->nb_antennas_tx; 
+	  }  
+#ifdef DEBUG_PHY
+	  msg("[openair][LTE_PHY][INIT] lte_common_vars->beam_weights[%d][%d][%d] = %p (%d bytes)\n",
+	      eNB_id,i,j,common_vars->beam_weights[eNB_id][i][j],
+              fp->ofdm_symbol_size*sizeof(int32_t)); 
+#endif
+        }
+      }
+
       // RX vars
       if (eNB->node_function != NGFI_RCC_IF4p5) {
-	common_vars->rxdata[eNB_id]        = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
-	common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
+	common_vars->rxdata[eNB_id]        = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) );
+	common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) );
       }
-      common_vars->rxdataF[eNB_id]       = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) );
-      
+      common_vars->rxdataF[eNB_id]       = (int32_t**)malloc16(fp->nb_antennas_rx*sizeof(int32_t*) );
+
       for (i=0; i<fp->nb_antennas_rx; i++) {
 	if (eNB->node_function != NGFI_RCC_IF4p5) {
 	  // allocate 2 subframes of I/Q signal data (time) if not an RCC (no time-domain signals)
 	  common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
+
 	  if (eNB->node_function != NGFI_RRU_IF5)
 	    // allocate 2 subframes of I/Q signal data (time, 7.5 kHz offset)
 	    common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( 2*fp->samples_per_tti*2*sizeof(int32_t) );
@@ -1261,6 +1383,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
 	if (eNB->node_function != NGFI_RRU_IF5)
 	  printf("[openair][LTE_PHY][INIT] common_vars->rxdata_7_5kHz[%d][%d] = %p (%lu bytes)\n",eNB_id,i,common_vars->rxdata_7_5kHz[eNB_id][i],fp->samples_per_tti*2*sizeof(int32_t));
 #endif
+        common_vars->rxdataF[eNB_id][i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(fp->ofdm_symbol_size*fp->symbols_per_tti) );
       }
       
       if ((eNB->node_function != NGFI_RRU_IF4p5)&&(eNB->node_function != NGFI_RRU_IF5)) {
@@ -1278,7 +1401,8 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
 	
 	common_vars->sync_corr[eNB_id] = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_tti );
       }
-    } else { //UPLINK abstraction = 1
+    } // abstraction_flag = 0
+    else { //UPLINK abstraction = 1
       eNB->sinr_dB = (double*) malloc16_clear( fp->N_RB_DL*12*sizeof(double) );
     }
   } //eNB_id
@@ -1400,5 +1524,5 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
   } // node_function != NGFI_RRU_IF4p5
 
   return (0);
-}
 
+}
diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c
index 9aca71612c66c84b12ca410190667507fc7ac426..4625eba4303eb959494dc28cf34e59eebe42dcf4 100644
--- a/openair1/PHY/INIT/lte_param_init.c
+++ b/openair1/PHY/INIT/lte_param_init.c
@@ -33,7 +33,8 @@
 extern PHY_VARS_eNB *eNB;
 extern PHY_VARS_UE *UE;
 
-void lte_param_init(unsigned char N_tx, 
+void lte_param_init(unsigned char N_tx_port_eNB, 
+                    unsigned char N_tx_phy,
 		    unsigned char N_rx,
 		    unsigned char transmission_mode,
 		    uint8_t extended_prefix_flag,
@@ -70,9 +71,9 @@ void lte_param_init(unsigned char N_tx,
   frame_parms->Ncp_UL             = extended_prefix_flag;
   frame_parms->Nid_cell           = Nid_cell;
   frame_parms->nushift            = Nid_cell%6;
-  frame_parms->nb_antennas_tx     = N_tx;
+  frame_parms->nb_antennas_tx     = N_tx_phy;
   frame_parms->nb_antennas_rx     = N_rx;
-  frame_parms->nb_antennas_tx_eNB = N_tx;
+  frame_parms->nb_antenna_ports_eNB = N_tx_port_eNB;
   frame_parms->phich_config_common.phich_resource         = oneSixth;
   frame_parms->phich_config_common.phich_duration         = normal;
   frame_parms->tdd_config         = tdd_config;
@@ -81,7 +82,7 @@ void lte_param_init(unsigned char N_tx,
   //  frame_parms->Bsrs = 0;
   //  frame_parms->kTC = 0;44
   //  frame_parms->n_RRC = 0;
-  frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0;
+  frame_parms->mode1_flag = (transmission_mode == 1 || transmission_mode ==7)? 1 : 0;
 
   init_frame_parms(frame_parms,osf);
 
@@ -93,6 +94,9 @@ void lte_param_init(unsigned char N_tx,
   UE->frame_parms = *frame_parms;
   eNB->frame_parms = *frame_parms;
 
+  eNB->transmission_mode[0] = transmission_mode;
+  UE->transmission_mode[0] = transmission_mode;
+
   phy_init_lte_top(frame_parms);
   dump_frame_parms(frame_parms);
 
@@ -110,7 +114,8 @@ void lte_param_init(unsigned char N_tx,
   generate_phich_reg_mapping(&UE->frame_parms);
 
   // DL power control init
-  if (transmission_mode == 1) {
+  //if (transmission_mode == 1) {
+  if (transmission_mode == 1 || transmission_mode ==7) {
     eNB->pdsch_config_dedicated->p_a  = dB0; // 4 = 0dB
     ((eNB->frame_parms).pdsch_config_common).p_b = 0;
     UE->pdsch_config_dedicated->p_a  = dB0; // 4 = 0dB
diff --git a/openair1/PHY/INIT/lte_parms.c b/openair1/PHY/INIT/lte_parms.c
index 611a141656075197be7bd8b8a1789505a2dc285c..cd879b1a90e6634ef02de54d2adea067e6bdb7ee 100644
--- a/openair1/PHY/INIT/lte_parms.c
+++ b/openair1/PHY/INIT/lte_parms.c
@@ -184,7 +184,7 @@ void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms)
   printf("frame_parms->tdd_config=%d\n",frame_parms->tdd_config);
   printf("frame_parms->tdd_config_S=%d\n",frame_parms->tdd_config_S);
   printf("frame_parms->mode1_flag=%d\n",frame_parms->mode1_flag);
-  printf("frame_parms->nb_antennas_tx_eNB(nb_antenna_ports)=%d\n",frame_parms->nb_antennas_tx_eNB);
+  printf("frame_parms->nb_antenna_ports_eNB=%d\n",frame_parms->nb_antenna_ports_eNB);
   printf("frame_parms->nb_antennas_tx=%d\n",frame_parms->nb_antennas_tx);
   printf("frame_parms->nb_antennas_rx=%d\n",frame_parms->nb_antennas_rx);
   printf("frame_parms->ofdm_symbol_size=%d\n",frame_parms->ofdm_symbol_size);
diff --git a/openair1/PHY/LTE_ESTIMATION/bf_freq_domain_filters.m b/openair1/PHY/LTE_ESTIMATION/bf_freq_domain_filters.m
new file mode 100644
index 0000000000000000000000000000000000000000..e0c0a0f18fe243d68b793de911649721f805cdbd
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/bf_freq_domain_filters.m
@@ -0,0 +1,59 @@
+filt_len = 16;
+
+F = -3/4:1/4:7/4;
+F_l = zeros(8,filt_len);
+F_r = zeros(8,filt_len);
+F_m = zeros(8,filt_len);
+
+F2 =-3/5:1/5:8/5;
+
+for i=0:3
+  F_l(i+1,:)  = floor(16384*[F(8+i:-1:4) zeros(1,7-i) zeros(1,4)]);
+  F_r(i+1,:)  = floor(16384*[zeros(1,4+i) F(4:end-i) zeros(1,4)]);
+  F_m(i+1,:)  = floor(16384*[F(4-i:8) F(7:-1:1+i) zeros(1,4)]);
+end
+
+for i=0:1
+  F_l(i+5,:)  = floor(16384*[F(8:-1:4-i) zeros(1,7-i) zeros(1,4)]);
+  F_r(i+5,:)  = floor(16384*[zeros(1,5+i) F2(5+i) F2(7:end-i) zeros(1,4)]);
+  F_m(i+5,:)  = floor(16384*[F(4-i:8) F2(8-i) F2(6:-1:1+i) zeros(1,4)]);
+end
+
+for i=2:3
+  F_l(i+5,:)  = floor(16384*[F2(end:-1:7) F2(8-i) zeros(1,5) zeros(1,4)]);
+  F_r(i+5,:)  = floor(16384*[zeros(1,4+i) F(4:end-i) zeros(1,4)]);
+  F_m(i+5,:)  = floor(16384*[F2(4-i:6) F2(4+i) F(8:-1:1+i) zeros(1,4)]);
+end
+
+
+fd = fopen("filt16_32.h","w");
+
+for i=0:3
+  fprintf(fd,"short filt%d_l%d[%d] = {\n",filt_len,i,filt_len);
+  fprintf(fd,"%d,",F_l(i+1,1:end-1));
+  fprintf(fd,"%d};\n\n",F_l(i+1,end));
+  
+  fprintf(fd,"short filt%d_r%d[%d] = {\n",filt_len,i,filt_len);
+  fprintf(fd,"%d,",F_r(i+1,1:end-1));
+  fprintf(fd,"%d};\n\n",F_r(i+1,end));
+  
+  fprintf(fd,"short filt%d_m%d[%d] = {\n",filt_len,i,filt_len);
+  fprintf(fd,"%d,",F_m(i+1,1:end-1));
+  fprintf(fd,"%d};\n\n",F_m(i+1,end));
+end
+
+for i=0:3
+  fprintf(fd,"short filt%d_l%d_dc[%d] = {\n",filt_len,i,filt_len);
+  fprintf(fd,"%d,",F_l(i+5,1:end-1));
+  fprintf(fd,"%d};\n\n",F_l(i+5,end));
+  
+  fprintf(fd,"short filt%d_r%d_dc[%d] = {\n",filt_len,i,filt_len);
+  fprintf(fd,"%d,",F_r(i+5,1:end-1));
+  fprintf(fd,"%d};\n\n",F_r(i+5,end));
+  
+  fprintf(fd,"short filt%d_m%d_dc[%d] = {\n",filt_len,i,filt_len);
+  fprintf(fd,"%d,",F_m(i+5,1:end-1));
+  fprintf(fd,"%d};\n\n",F_m(i+5,end));
+end
+
+fclose(fd);
diff --git a/openair1/PHY/LTE_ESTIMATION/defs.h b/openair1/PHY/LTE_ESTIMATION/defs.h
index 0a38265461ec38194fde6a34768af43a276cb670..3af9c2471f140cacdb0a84d8829d976cba237be8 100644
--- a/openair1/PHY/LTE_ESTIMATION/defs.h
+++ b/openair1/PHY/LTE_ESTIMATION/defs.h
@@ -116,6 +116,12 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue,
                               uint8_t l,
                               uint8_t symbol);
 
+int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue,
+                                 module_id_t eNB_id,
+                                 uint8_t eNB_offset,
+                                 uint8_t Ns,
+                                 uint8_t p,
+                                 uint8_t symbol);
 
 int lte_dl_msbfn_channel_estimation(PHY_VARS_UE *phy_vars_ue,
                                     module_id_t eNB_id,
diff --git a/openair1/PHY/LTE_ESTIMATION/filt16_32.h b/openair1/PHY/LTE_ESTIMATION/filt16_32.h
new file mode 100644
index 0000000000000000000000000000000000000000..3487fd3466739acc608acaee9ad3721c5face987
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/filt16_32.h
@@ -0,0 +1,86 @@
+short filt16_l0[16] = {
+16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r0[16] = {
+0,0,0,0,0,4096,8192,12288,16384,20480,24576,28672,0,0,0,0};
+
+short filt16_m0[16] = {
+0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,-12288,0,0,0,0};
+
+short filt16_l1[16] = {
+20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r1[16] = {
+0,0,0,0,0,0,4096,8192,12288,16384,20480,24576,0,0,0,0};
+
+short filt16_m1[16] = {
+-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,0,0,0,0};
+
+short filt16_l2[16] = {
+24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r2[16] = {
+0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0};
+
+short filt16_m2[16] = {
+-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,0,0,0,0};
+
+short filt16_l3[16] = {
+28672,24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0};
+
+short filt16_r3[16] = {
+0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0};
+
+short filt16_m3[16] = {
+-12288,-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0};
+
+short filt16_l0_dc[16] = {
+16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r0_dc[16] = {
+0,0,0,0,0,3276,9830,13107,16384,19660,22937,26214,0,0,0,0};
+
+short filt16_m0_dc[16] = {
+0,4096,8192,12288,16384,13107,6553,3276,0,-3277,-6554,-9831,0,0,0,0};
+
+short filt16_l1_dc[16] = {
+16384,12288,8192,4096,0,-4096,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_r1_dc[16] = {
+0,0,0,0,0,0,6553,9830,13107,16384,19660,22937,0,0,0,0};
+
+short filt16_m1_dc[16] = {
+-4096,0,4096,8192,12288,16384,9830,6553,3276,0,-3277,-6554,0,0,0,0};
+
+short filt16_l2_dc[16] = {
+26214,22937,19660,16384,13107,9830,6553,0,0,0,0,0,0,0,0,0};
+
+short filt16_r2_dc[16] = {
+0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0};
+
+short filt16_m2_dc[16] = {
+-6554,-3277,0,3276,6553,6553,16384,12288,8192,4096,0,-4096,0,0,0,0};
+
+short filt16_l3_dc[16] = {
+26214,22937,19660,16384,13107,9830,3276,0,0,0,0,0,0,0,0,0};
+
+short filt16_r3_dc[16] = {
+0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0};
+
+short filt16_m3_dc[16] = {
+-9831,-6554,-3277,0,3276,6553,9830,16384,12288,8192,4096,0,0,0,0,0};
+
+short filt16_1[16] = {
+16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384};
+
+short filt16_2l0[16] = {
+16384,12288,8192,4096,-4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_2r0[16] = {
+0,4096,8192,12288,16384,20480,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_2l1[16] = {
+20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_2r1[16] = {
+-4096,0,4096,8192,12288,16384,0,0,0,0,0,0,0,0,0,0};
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c
new file mode 100644
index 0000000000000000000000000000000000000000..0b220c2c391897a8f5283c450fa75ab5d42232b0
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c
@@ -0,0 +1,750 @@
+/*******************************************************************************
+    OpenAirInterface
+    Copyright(c) 1999 - 2014 Eurecom
+
+    OpenAirInterface is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+
+    OpenAirInterface is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenAirInterface.The full GNU General Public License is
+   included in this distribution in the file called "COPYING". If not,
+   see <http://www.gnu.org/licenses/>.
+
+  Contact Information
+  OpenAirInterface Admin: openair_admin@eurecom.fr
+  OpenAirInterface Tech : openair_tech@eurecom.fr
+  OpenAirInterface Dev  : openair4g-devel@eurecom.fr
+
+  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+#ifdef USER_MODE
+#include <string.h>
+#endif
+#include "defs.h"
+#include "PHY/defs.h"
+#include "filt16_32.h"
+//#define DEBUG_BF_CH
+
+int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue,
+                                 uint8_t eNB_id,
+                                 uint8_t eNB_offset,
+                                 unsigned char Ns,
+                                 unsigned char p,
+                                 unsigned char symbol)
+{
+  
+  unsigned short rb,nb_rb=0;
+  unsigned char aarx,l,lprime,nsymb,skip_half=0,sss_symb,pss_symb=0,rb_alloc_ind,harq_pid,uespec_pilots=0;
+  int beamforming_mode, ch_offset;
+  uint8_t subframe;
+  int8_t uespec_nushift, uespec_poffset=0, pil_offset=0;
+  uint8_t pilot0,pilot1,pilot2,pilot3;
+
+  short ch[2], *pil, *rxF, *dl_bf_ch, *dl_bf_ch_prev;
+  short *fl, *fm, *fr, *fl_dc, *fm_dc, *fr_dc, *f1, *f2l, *f2r;
+
+  unsigned int *rballoc; 
+  int **rxdataF;
+  int32_t **dl_bf_ch_estimates;
+  int uespec_pilot[300];
+
+  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms;
+  LTE_UE_DLSCH_t **dlsch_ue       = phy_vars_ue->dlsch[eNB_id];
+  LTE_DL_UE_HARQ_t *dlsch0_harq; 
+
+  harq_pid    = dlsch_ue[0]->current_harq_pid; 
+  dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid];
+
+  if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) ||
+      ((frame_parms->Ncp == EXTENDED) && (symbol>=6)))
+    rballoc = dlsch0_harq->rb_alloc_odd;
+  else
+    rballoc = dlsch0_harq->rb_alloc_even;
+
+  rxdataF = phy_vars_ue->common_vars.rxdataF;
+
+  dl_bf_ch_estimates = phy_vars_ue->pdsch_vars[eNB_id]->dl_bf_ch_estimates;
+  beamforming_mode   = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0;
+
+  if (phy_vars_ue->high_speed_flag == 0) // use second channel estimate position for temporary storage
+    ch_offset     = frame_parms->ofdm_symbol_size;
+  else
+    ch_offset     = frame_parms->ofdm_symbol_size*symbol;
+
+  
+  uespec_nushift = frame_parms->Nid_cell%3;
+  subframe = Ns>>1;
+ 
+
+    //generate ue specific pilots
+    lprime = symbol/3-1;
+    lte_dl_ue_spec_rx(phy_vars_ue,uespec_pilot,Ns,5,lprime,0,dlsch0_harq->nb_rb);
+    //write_output("uespec_pilot_rx.m","uespec_pilot",uespec_pilot,300,1,1);
+
+    if (frame_parms->Ncp==0){
+      if (symbol==3 || symbol==6 || symbol==9 || symbol==12)
+        uespec_pilots = 1;
+    } else{
+      if (symbol==4 || symbol==7 || symbol==10)
+        uespec_pilots = 1;
+    }
+   
+    if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7))
+      uespec_poffset = 2;
+
+    if (phy_vars_ue->frame_parms.Ncp == 0) { // normal prefix
+      pilot0 = 3;
+      pilot1 = 6;
+      pilot2 = 9;
+      pilot3 = 12;
+    } else { // extended prefix
+      pilot0 = 4;
+      pilot1 = 7;
+      pilot2 = 10;
+    }
+
+    //define the filter
+    pil_offset = (uespec_nushift+uespec_poffset)%3;
+    // printf("symbol=%d,pil_offset=%d\n",symbol,pil_offset);
+    switch (pil_offset) {
+    case 0:
+      fl = filt16_l0;
+      fm = filt16_m0;
+      fr = filt16_r0;
+      fl_dc = filt16_l0;
+      fm_dc = filt16_m0;
+      fr_dc = filt16_r0;
+      f1 = filt16_1;
+      f2l = filt16_2l0;
+      f2r = filt16_2r0;
+      break;
+
+    case 1:
+      fl = filt16_l1;
+      fm = filt16_m1;
+      fr = filt16_r1;
+      fl_dc = filt16_l1;
+      fm_dc = filt16_m1;
+      fr_dc = filt16_r1;
+      f1 = filt16_1;
+      f2l = filt16_2l1;
+      f2r = filt16_2r1;
+      break;
+
+    case 2:
+      fl = filt16_l2;
+      fm = filt16_m2;
+      fr = filt16_r2;
+      fl_dc = filt16_l2;
+      fm_dc = filt16_m2;
+      fr_dc = filt16_r2;
+      f1 = filt16_1;
+      f2l = filt16_2l0;
+      f2r = filt16_2r0;
+      break;
+
+    case 3:
+      fl = filt16_l3;
+      fm = filt16_m3;
+      fr = filt16_r3;
+      fl_dc = filt16_l3;
+      fm_dc = filt16_m3;
+      fr_dc = filt16_r3;
+      f1 = filt16_1;
+      f2l = filt16_2l1;
+      f2r = filt16_2r1;
+      break;
+    }
+ // beamforming mode extension
+ /* }
+  else if (beamforming_mode==0)
+    msg("lte_dl_bf_channel_estimation:No beamforming is performed.\n");
+  else
+    msg("lte_dl_bf_channel_estimation:Beamforming mode not supported yet.\n");*/
+  
+
+  l=symbol;
+  nsymb = (frame_parms->Ncp==NORMAL) ? 14:12;
+
+  if (frame_parms->frame_type == TDD) {  //TDD
+    sss_symb = nsymb-1;
+    pss_symb = 2;
+  } else {
+    sss_symb = (nsymb>>1)-2;
+    pss_symb = (nsymb>>1)-1;
+  }
+
+
+  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+
+    rxF  = (short *)&rxdataF[aarx][pil_offset + frame_parms->first_carrier_offset + symbol*frame_parms->ofdm_symbol_size];
+    pil  = (short *)uespec_pilot;
+    dl_bf_ch = (short *)&dl_bf_ch_estimates[aarx][ch_offset];
+
+    memset(dl_bf_ch,0,4*(frame_parms->ofdm_symbol_size));
+    //memset(dl_bf_ch,0,2*(frame_parms->ofdm_symbol_size));
+
+    if (phy_vars_ue->high_speed_flag==0) {
+    // multiply previous channel estimate by ch_est_alpha
+      if (frame_parms->Ncp==0){
+        multadd_complex_vector_real_scalar(dl_bf_ch-(frame_parms->ofdm_symbol_size<<1),
+                                           phy_vars_ue->ch_est_alpha,dl_bf_ch-(frame_parms->ofdm_symbol_size<<1),
+                                           1,frame_parms->ofdm_symbol_size);
+      } else {
+        msg("lte_dl_bf_channel_estimation: beamforming channel estimation not supported for TM7 Extended CP.\n"); // phy_vars_ue->ch_est_beta should be defined equaling 1/3
+      }
+    }
+    //estimation and interpolation
+
+    if ((frame_parms->N_RB_DL&1) == 0) { // even number of RBs
+      for (rb=0; rb<frame_parms->N_RB_DL; rb++) {
+
+        if (rb < 32)
+          rb_alloc_ind = (rballoc[0]>>rb) & 1;
+        else if (rb < 64)
+          rb_alloc_ind = (rballoc[1]>>(rb-32)) & 1;
+        else if (rb < 96)
+          rb_alloc_ind = (rballoc[2]>>(rb-64)) & 1;
+        else if (rb < 100)
+          rb_alloc_ind = (rballoc[3]>>(rb-96)) & 1;
+        else
+          rb_alloc_ind = 0;
+
+        // For second half of RBs skip DC carrier
+        if (rb==(frame_parms->N_RB_DL>>1)) {
+          rxF       = (short *)&rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))];
+        }
+
+        if (rb_alloc_ind==1) {
+          if (uespec_pilots==1) {
+            if (beamforming_mode==7) {
+              if (frame_parms->Ncp==0) {
+
+                ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+                ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+                multadd_real_vector_complex_scalar(fl,ch,dl_bf_ch,16);
+                
+                ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+                ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+                multadd_real_vector_complex_scalar(fm,ch,dl_bf_ch,16);
+
+                ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+                ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+                multadd_real_vector_complex_scalar(fr,ch,dl_bf_ch,16);
+              } else {
+                msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):TM7 beamgforming channel estimation not supported for extented CP\n");
+                exit(-1);
+              }
+            } else {
+              msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c): transmission mode not supported.\n");
+            }
+          }
+          nb_rb++;
+        }
+
+        rxF+=24;
+        dl_bf_ch+=24;
+      }
+    } else {  // Odd number of RBs
+      for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) {
+        skip_half=0;
+
+        if (rb < 32)
+          rb_alloc_ind = (rballoc[0]>>rb) & 1;
+        else if (rb < 64)
+          rb_alloc_ind = (rballoc[1]>>(rb-32)) & 1;
+        else if (rb < 96)
+          rb_alloc_ind = (rballoc[2]>>(rb-64)) & 1;
+        else if (rb < 100)
+          rb_alloc_ind = (rballoc[3]>>(rb-96)) & 1;
+        else
+          rb_alloc_ind = 0;
+
+        // PBCH
+        if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) {
+          rb_alloc_ind = 0;
+        }
+
+        //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3
+        if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+          skip_half=1;
+        else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+          skip_half=2;
+
+        //SSS
+        if (((subframe==0)||(subframe==5)) &&
+            (rb>((frame_parms->N_RB_DL>>1)-3)) &&
+            (rb<((frame_parms->N_RB_DL>>1)+3)) &&
+            (l==sss_symb) ) {
+          rb_alloc_ind = 0;
+        }
+
+        //SSS
+        if (((subframe==0)||(subframe==5)) &&
+            (rb==((frame_parms->N_RB_DL>>1)-3)) &&
+            (l==sss_symb))
+          skip_half=1;
+        else if (((subframe==0)||(subframe==5)) &&
+                 (rb==((frame_parms->N_RB_DL>>1)+3)) &&
+                 (l==sss_symb))
+          skip_half=2;
+
+        //PSS in subframe 0/5 if FDD
+        if (frame_parms->frame_type == FDD) {  //FDD
+          if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+
+          if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+            skip_half=1;
+          else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+            skip_half=2;
+        }
+
+        if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6
+          if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+
+          if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+            skip_half=1;
+          else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+            skip_half=2;
+        }
+
+        //printf("symbol=%d,pil_offset=%d\ni,rb_alloc_ind=%d,uespec_pilots=%d,beamforming_mode=%d,Ncp=%d,skip_half=%d\n",symbol,pil_offset,rb_alloc_ind,uespec_pilots,beamforming_mode,frame_parms->Ncp,skip_half);
+        if (rb_alloc_ind==1) {
+          if (uespec_pilots==1) {
+            if (beamforming_mode==7) {
+              if (frame_parms->Ncp==0) {
+                if (skip_half==1) {
+                  if (pil_offset<2) {
+
+                    ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+                    ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+                    multadd_real_vector_complex_scalar(f2l,ch,dl_bf_ch,16); 
+                    pil+=2;
+                    
+                    ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+                    ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+                    multadd_real_vector_complex_scalar(f2r,ch,dl_bf_ch,16); 
+                    pil+=2;
+
+                  } else {
+
+                    ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+                    ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+                    multadd_real_vector_complex_scalar(f1,ch,dl_bf_ch,16);
+                    pil+=2;
+                  }
+                } else if (skip_half==2) {
+                  if (pil_offset<2) {
+
+                    ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+                    ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+                    multadd_real_vector_complex_scalar(f1,ch,dl_bf_ch,16); 
+                    pil+=2;
+                    
+                  } else {
+
+                    ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+                    ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+                    multadd_real_vector_complex_scalar(f2l,ch,dl_bf_ch,16);
+                    pil+=2;
+
+                    ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+                    ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+                    multadd_real_vector_complex_scalar(f2r,ch,dl_bf_ch,16); 
+                    pil+=2;
+
+                  }
+                } else {
+
+                  ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+                  ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+                  multadd_real_vector_complex_scalar(fl,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+                  printf("symbol=%d,rxF[0]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[0],rxF[1],pil[0],pil[1],ch[0],ch[1]);
+#endif
+                  pil+=2;
+                  
+                  ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+                  ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+                  multadd_real_vector_complex_scalar(fm,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+                  printf("symbol=%d,rxF[4]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[8],rxF[9],pil[0],pil[1],ch[0],ch[1]);
+#endif
+                  pil+=2;
+
+                  ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+                  ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+                  multadd_real_vector_complex_scalar(fr,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+                  printf("symbol=%d,rxF[8]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[16],rxF[17],pil[0],pil[1],ch[0],ch[1]);
+#endif
+                  pil+=2;
+
+               }  
+             } else {
+              msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):TM7 beamgforming channel estimation not supported for extented CP\n");
+              exit(-1);
+             }
+          
+           } else {
+            msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):transmission mode not supported.\n");
+           }
+         }       
+         nb_rb++;
+       }
+
+        rxF+=24;
+        dl_bf_ch+=24;
+      } // first half loop
+
+      // Do middle RB (around DC) 
+      if (rb < 32)
+        rb_alloc_ind = (rballoc[0]>>rb) & 1;
+      else if (rb < 64)
+        rb_alloc_ind = (rballoc[1]>>(rb-32)) & 1;
+      else if (rb < 96)
+        rb_alloc_ind = (rballoc[2]>>(rb-64)) & 1;
+      else if (rb < 100)
+        rb_alloc_ind = (rballoc[3]>>(rb-96)) & 1;
+      else
+        rb_alloc_ind = 0;
+
+      // PBCH
+      if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) {
+        rb_alloc_ind = 0;
+      }
+
+      //SSS
+      if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+        rb_alloc_ind = 0;
+      }
+
+      if (frame_parms->frame_type == FDD) {
+       //PSS
+        if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+          rb_alloc_ind = 0;
+        }
+      }
+
+      if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) {
+        //PSS
+        if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+          rb_alloc_ind = 0;
+        }
+      }
+
+      //printf("DC rb %d (%p)\n",rb,rxF);
+      if (rb_alloc_ind==1) {
+        if (pil_offset<2) {
+          ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+          ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+          multadd_real_vector_complex_scalar(fl_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+          //printf("symbol=%d,rxF[0]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[0],rxF[1],pil[0],pil[1],ch[0],ch[1]);
+#endif
+          pil+=2;;
+                  
+          ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+          ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+          multadd_real_vector_complex_scalar(fm_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+          //printf("symbol=%d,rxF[4]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[8],rxF[9],pil[0],pil[1],ch[0],ch[1]);
+#endif
+          pil+=2;;
+
+          rxF   = (short *)&rxdataF[aarx][symbol*(frame_parms->ofdm_symbol_size)];
+
+          ch[0] = (short)(((int)pil[0]*rxF[6] - (int)pil[1]*rxF[7])>>15);
+          ch[1] = (short)(((int)pil[0]*rxF[7] + (int)pil[1]*rxF[6])>>15);
+          multadd_real_vector_complex_scalar(fr_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+          //printf("symbol=%d,rxF[3]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[6],rxF[7],pil[0],pil[1],ch[0],ch[1]);
+#endif
+          pil+=2;;
+        } else {
+          ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+          ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+          multadd_real_vector_complex_scalar(fl_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+          //printf("symbol=%d,rxF[0]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[0],rxF[1],pil[0],pil[1],ch[0],ch[1]);
+#endif
+          pil+=2;;
+                  
+          rxF   = (short *)&rxdataF[aarx][symbol*(frame_parms->ofdm_symbol_size)];
+
+          ch[0] = (short)(((int)pil[0]*rxF[2] - (int)pil[1]*rxF[3])>>15);
+          ch[1] = (short)(((int)pil[0]*rxF[3] + (int)pil[1]*rxF[2])>>15);
+          multadd_real_vector_complex_scalar(fm_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+          //printf("symbol=%d,rxF[1]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[2],rxF[3],pil[0],pil[1],ch[0],ch[1]);
+#endif
+          pil+=2;;
+
+          ch[0] = (short)(((int)pil[0]*rxF[10] - (int)pil[1]*rxF[11])>>15);
+          ch[1] = (short)(((int)pil[0]*rxF[11] + (int)pil[1]*rxF[10])>>15);
+          multadd_real_vector_complex_scalar(fr_dc,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+          //printf("symbol=%d,rxF[5]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[10],rxF[11],pil[0],pil[1],ch[0],ch[1]);
+#endif
+          pil+=2;;
+        }
+      } // rballoc==1
+      else {
+        rxF       = (short *)&rxdataF[aarx][pil_offset+((symbol*(frame_parms->ofdm_symbol_size)))];
+      }
+
+      rxF+=14+2*pil_offset;
+      dl_bf_ch+=24;
+      rb++;
+
+      for (; rb<frame_parms->N_RB_DL; rb++) {
+        skip_half=0;
+
+        if (rb < 32)
+          rb_alloc_ind = (rballoc[0]>>rb) & 1;
+        else if (rb < 64)
+          rb_alloc_ind = (rballoc[1]>>(rb-32)) & 1;
+        else if (rb < 96)
+          rb_alloc_ind = (rballoc[2]>>(rb-64)) & 1;
+        else if (rb < 100)
+          rb_alloc_ind = (rballoc[3]>>(rb-96)) & 1;
+        else
+          rb_alloc_ind = 0;
+
+        // PBCH
+        if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) {
+          rb_alloc_ind = 0;
+        }
+
+        //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3
+        if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+          skip_half=1;
+        else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+          skip_half=2;
+
+        //SSS
+        if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+          rb_alloc_ind = 0;
+        }
+
+        //SSS
+        if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb))
+          skip_half=1;
+        else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb))
+          skip_half=2;
+
+        if (frame_parms->frame_type == FDD) {
+          //PSS
+          if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+
+          //PSS
+          if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+            skip_half=1;
+          else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+            skip_half=2;
+        }
+
+        if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6
+          if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+
+          if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+            skip_half=1;
+          else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+            skip_half=2;
+        }
+
+        if (rb_alloc_ind==1) {
+          if (uespec_pilots==1) {
+            if (beamforming_mode==7) {
+              if (frame_parms->Ncp==0) {
+                if (skip_half==1) {
+                  if (pil_offset<2) {
+
+                    ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+                    ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+                    multadd_real_vector_complex_scalar(f2l,ch,dl_bf_ch,16); 
+                    pil+=2;
+                    
+                    ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+                    ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+                    multadd_real_vector_complex_scalar(f2r,ch,dl_bf_ch,16); 
+                    pil+=2;
+          
+
+                  } else {
+
+                    ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+                    ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+                    multadd_real_vector_complex_scalar(f1,ch,dl_bf_ch,16);
+                    pil+=2;
+                  }
+                } else if (skip_half==2) {
+                   if (pil_offset<2) {
+
+                     ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+                     ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+                     multadd_real_vector_complex_scalar(f1,ch,dl_bf_ch,16); 
+                     pil+=2;
+                     
+                   } else {
+
+                     ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+                     ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+                     multadd_real_vector_complex_scalar(f2l,ch,dl_bf_ch,16);
+                     pil+=2;
+
+                     ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+                     ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+                     multadd_real_vector_complex_scalar(f2r,ch,dl_bf_ch,16); 
+                     pil+=2;
+
+                   }
+                } else {
+
+                  ch[0] = (short)(((int)pil[0]*rxF[0] - (int)pil[1]*rxF[1])>>15);
+                  ch[1] = (short)(((int)pil[0]*rxF[1] + (int)pil[1]*rxF[0])>>15);
+                  multadd_real_vector_complex_scalar(fl,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+                  printf("symbol=%d,rxF[0]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[0],rxF[1],pil[0],pil[1],ch[0],ch[1]);
+#endif
+                  pil+=2;
+                  
+                  ch[0] = (short)(((int)pil[0]*rxF[8] - (int)pil[1]*rxF[9])>>15);
+                  ch[1] = (short)(((int)pil[0]*rxF[9] + (int)pil[1]*rxF[8])>>15);
+                  multadd_real_vector_complex_scalar(fm,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+                  printf("symbol=%d,rxF[4]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[8],rxF[9],pil[0],pil[1],ch[0],ch[1]);
+#endif
+                  pil+=2;
+
+                  ch[0] = (short)(((int)pil[0]*rxF[16] - (int)pil[1]*rxF[17])>>15);
+                  ch[1] = (short)(((int)pil[0]*rxF[17] + (int)pil[1]*rxF[16])>>15);
+                  multadd_real_vector_complex_scalar(fr,ch,dl_bf_ch,16);
+#ifdef DEBUG_BF_CH
+                  printf("symbol=%d,rxF[8]=(%d,%d),pil=(%d,%d),ch=(%d,%d)\n",symbol,rxF[16],rxF[17],pil[0],pil[1],ch[0],ch[1]);
+#endif
+                  pil+=2;
+
+                }
+              } else {
+                msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):TM7 beamgforming channel estimation not supported for extented CP\n");
+                exit(-1);
+              }
+            
+            } else {
+              msg("lte_dl_bf_channel_estimation(lte_dl_bf_channel_estimation.c):transmission mode not supported.\n");
+            }
+          }
+          nb_rb++;
+        }
+
+        rxF+=24;
+        dl_bf_ch+=24;
+      } // second half of RBs
+    } // odd number of RBs  
+
+    // Temporal Interpolation
+    if (phy_vars_ue->perfect_ce == 0) {
+
+      dl_bf_ch = (short *)&dl_bf_ch_estimates[aarx][ch_offset];
+#ifdef DEBUG_BF_CH
+      printf("[dlsch_bf_ch_est.c]:symbol %d, dl_bf_ch (%d,%d)\n",symbol,dl_bf_ch[0],dl_bf_ch[1]);
+#endif
+
+      if (phy_vars_ue->high_speed_flag == 0) {
+        multadd_complex_vector_real_scalar(dl_bf_ch,
+                                           32767-phy_vars_ue->ch_est_alpha,
+                                           dl_bf_ch-(frame_parms->ofdm_symbol_size<<1),0,frame_parms->ofdm_symbol_size);
+        //printf("dlsch_bf_ch_est.c:symbol %d,dl_bf_ch (%d,%d)\n",symbol,*(dl_bf_ch-512*2),*(dl_bf_ch-512*2+1));
+      } else { // high_speed_flag == 1
+        if (beamforming_mode==7) {
+          if (frame_parms->Ncp==0) {
+            if (symbol == pilot0) {
+              //      printf("Interpolating %d->0\n",4-phy_vars_ue->lte_frame_parms.Ncp);
+              //      dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][(4-phy_vars_ue->lte_frame_parms.Ncp)*(frame_parms->ofdm_symbol_size)];
+              dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][pilot3*(frame_parms->ofdm_symbol_size)];
+#ifdef DEBUG_BF_CH
+              printf("[dlsch_bf_ch_est.c] symbol=%d, dl_bf_ch_prev=(%d,%d), dl_bf_ch=(%d,%d)\n", symbol, dl_bf_ch_prev[0], dl_bf_ch_prev[1], dl_bf_ch[0], dl_bf_ch[1]);
+#endif
+              // pilot spacing 5 symbols (1/5,2/5,3/5,4/5 combination)
+              multadd_complex_vector_real_scalar(dl_bf_ch_prev,26214,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+              multadd_complex_vector_real_scalar(dl_bf_ch,6554,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+              multadd_complex_vector_real_scalar(dl_bf_ch_prev,19661,dl_bf_ch-(3*2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+              multadd_complex_vector_real_scalar(dl_bf_ch,13107,dl_bf_ch-(3*2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+              multadd_complex_vector_real_scalar(dl_bf_ch_prev,13107,dl_bf_ch-(2*((frame_parms->ofdm_symbol_size)<<1)),1,frame_parms->ofdm_symbol_size);
+              multadd_complex_vector_real_scalar(dl_bf_ch,19661,dl_bf_ch-(2*((frame_parms->ofdm_symbol_size)<<1)),0,frame_parms->ofdm_symbol_size);
+
+              multadd_complex_vector_real_scalar(dl_bf_ch_prev,6554,dl_bf_ch-(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+              multadd_complex_vector_real_scalar(dl_bf_ch,26214,dl_bf_ch-(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+            } else if (symbol == pilot1) {
+              dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][pilot0*(frame_parms->ofdm_symbol_size)];
+#ifdef DEBUG_BF_CH
+              printf("[dlsch_bf_ch_est.c] symbol=%d, dl_bf_ch_prev=(%d,%d), dl_bf_ch=(%d,%d)\n", symbol, dl_bf_ch_prev[0], dl_bf_ch_prev[1], dl_bf_ch[0], dl_bf_ch[1]);
+#endif
+
+              // pilot spacing 3 symbols (1/3,2/3 combination)
+              multadd_complex_vector_real_scalar(dl_bf_ch_prev,21845,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+              multadd_complex_vector_real_scalar(dl_bf_ch,10923,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+              multadd_complex_vector_real_scalar(dl_bf_ch_prev,10923,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),1,frame_parms->ofdm_symbol_size);
+              multadd_complex_vector_real_scalar(dl_bf_ch,21845,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),0,frame_parms->ofdm_symbol_size);
+
+            } else if (symbol == pilot2) {
+              dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][pilot1*(frame_parms->ofdm_symbol_size)];
+#ifdef DEBUG_BF_CH
+              printf("[dlsch_bf_ch_est.c] symbol=%d, dl_bf_ch_prev=(%d,%d), dl_bf_ch=(%d,%d)\n", symbol, dl_bf_ch_prev[0], dl_bf_ch_prev[1], dl_bf_ch[0], dl_bf_ch[1]);
+#endif
+
+              multadd_complex_vector_real_scalar(dl_bf_ch_prev,21845,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+              multadd_complex_vector_real_scalar(dl_bf_ch,10923,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+              multadd_complex_vector_real_scalar(dl_bf_ch_prev,10923,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),1,frame_parms->ofdm_symbol_size);
+              multadd_complex_vector_real_scalar(dl_bf_ch,21845,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),0,frame_parms->ofdm_symbol_size);
+            } else { // symbol == pilot3
+            //      printf("Interpolating 0->%d\n",4-phy_vars_ue->lte_frame_parms.Ncp);
+            dl_bf_ch_prev = (short *)&dl_bf_ch_estimates[aarx][pilot2*(frame_parms->ofdm_symbol_size)];
+
+            // pilot spacing 3 symbols (1/3,2/3 combination)
+            multadd_complex_vector_real_scalar(dl_bf_ch_prev,21845,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),1,frame_parms->ofdm_symbol_size);
+            multadd_complex_vector_real_scalar(dl_bf_ch,10923,dl_bf_ch_prev+(2*(frame_parms->ofdm_symbol_size)),0,frame_parms->ofdm_symbol_size);
+
+            multadd_complex_vector_real_scalar(dl_bf_ch_prev,10923,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),1,frame_parms->ofdm_symbol_size);
+            multadd_complex_vector_real_scalar(dl_bf_ch,21845,dl_bf_ch_prev+(2*((frame_parms->ofdm_symbol_size)<<1)),0,frame_parms->ofdm_symbol_size);
+            }
+
+          } else {
+            msg("lte_dl_bf_channel_estimation:temporal interpolation not supported for TM7 extented CP.\n");
+          }
+        } else {
+          msg("lte_dl_bf_channel_estimation:temporal interpolation not supported for this beamforming mode.\n");
+        } 
+      }
+    }
+  } //aarx
+ 
+#ifdef DEBUG_BF_CH  
+    printf("[dlsch_bf_ch_est.c]: dl_bf_estimates[0][600] %d, %d \n",*(short *)&dl_bf_ch_estimates[0][600],*(short*)&phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates[0][600]);
+#endif
+
+  return(0);
+
+}
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c
index 65e2101d99113932677085c92e9e533e92e83f96..45ed0f11c0d1a359fd19db11ccbf019a68091e4b 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c
@@ -35,9 +35,6 @@ int lte_dl_channel_estimation(PHY_VARS_UE *ue,
                               unsigned char l,
                               unsigned char symbol)
 {
-
-
-
   int pilot[2][200] __attribute__((aligned(16)));
   unsigned char nu,aarx;
   unsigned short k;
@@ -735,7 +732,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *ue,
 
   // do ifft of channel estimate
   for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++)
-    for (p=0; p<ue->frame_parms.nb_antennas_tx_eNB; p++) {
+    for (p=0; p<ue->frame_parms.nb_antenna_ports_eNB; p++) {
       if (ue->common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx])
         idft((int16_t*) &ue->common_vars.dl_ch_estimates[eNB_offset][(p<<1)+aarx][8],
              (int16_t*) ue->common_vars.dl_ch_estimates_time[eNB_offset][(p<<1)+aarx],1);
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_est_freq_offset.c b/openair1/PHY/LTE_ESTIMATION/lte_est_freq_offset.c
index 6ebd8948cf7108ddfd09791c19361d119107b22f..d713cc01635a2e8a68c7c599ef450d9b8ab38bed 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_est_freq_offset.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_est_freq_offset.c
@@ -102,7 +102,7 @@ int lte_est_freq_offset(int **dl_ch_estimates,
 {
 
   int ch_offset, omega, dl_ch_shift;
-  struct complex16 *omega_cpx;
+  struct complex16 omega_cpx;
   double phase_offset;
   int freq_offset_est;
   unsigned char aa;
@@ -142,9 +142,8 @@ int lte_est_freq_offset(int **dl_ch_estimates,
     //    printf("Computing freq_offset\n");
     omega = dot_product(dl_ch,dl_ch_prev,(frame_parms->N_RB_DL/2 - 1)*12,dl_ch_shift);
     //omega = dot_product(dl_ch,dl_ch_prev,frame_parms->ofdm_symbol_size,15);
-    omega_cpx = (struct complex16*) &omega;
-
-    //    printf("omega (%d,%d)\n",omega_cpx->r,omega_cpx->i);
+    omega_cpx.r = ((struct complex16*) &omega)->r;
+    omega_cpx.i = ((struct complex16*) &omega)->i;
 
     dl_ch = (int16_t *)&dl_ch_estimates[aa][(((frame_parms->N_RB_DL/2) + 1)*12) + ch_offset];
 
@@ -155,10 +154,12 @@ int lte_est_freq_offset(int **dl_ch_estimates,
 
     // calculate omega = angle(conj(dl_ch)*dl_ch_prev))
     omega = dot_product(dl_ch,dl_ch_prev,((frame_parms->N_RB_DL/2) - 1)*12,dl_ch_shift);
-    omega_cpx->r += ((struct complex16*) &omega)->r;
-    omega_cpx->i += ((struct complex16*) &omega)->i;
+
+    omega_cpx.r += ((struct complex16*) &omega)->r;
+    omega_cpx.i += ((struct complex16*) &omega)->i;
+
     //    phase_offset += atan2((double)omega_cpx->i,(double)omega_cpx->r);
-    phase_offset += atan2((double)omega_cpx->i,(double)omega_cpx->r);
+    phase_offset += atan2((double)omega_cpx.i,(double)omega_cpx.r);
     //    LOG_I(PHY,"omega (%d,%d) -> %f\n",omega_cpx->r,omega_cpx->i,phase_offset);
   }
 
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c
index b7b36efa0b5fec203f7726ac3a40af0bbdbccb42..90ebd07f60f2f45f1f64779ba601c8e3b98040f2 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c
@@ -446,7 +446,7 @@ void lte_ue_measurements(PHY_VARS_UE *ue,
   // signal measurements
   for (eNB_id=0; eNB_id<ue->n_connected_eNB; eNB_id++) {
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
-      for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
+      for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
         ue->measurements.rx_spatial_power[eNB_id][aatx][aarx] =
           (signal_energy_nodc(&ue->common_vars.dl_ch_estimates[eNB_id][(aatx<<1) + aarx][0],
                               (N_RB_DL*12)));
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
index d8a627020db5f93cc6e320a88e1d57784f664b4d..d2bc2e27c0750b7e68a97c461f4fac2d29f1e519 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
@@ -78,7 +78,7 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
   int16_t ul_ch_estimates_re,ul_ch_estimates_im;
   int32_t rx_power_correction;
 
-  //uint8_t nb_antennas_rx = frame_parms->nb_antennas_tx_eNB;
+  //uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB;
   uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
   uint8_t cyclic_shift;
 
@@ -679,7 +679,7 @@ int32_t lte_srs_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms,
 
   int T_SFC,aa;
   int N_symb,symbol;
-  uint8_t nb_antennas_rx = frame_parms->nb_antennas_tx_eNB;
+  uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB;
 #ifdef DEBUG_SRS
   char fname[40], vname[40];
 #endif
diff --git a/openair1/PHY/LTE_REFSIG/defs.h b/openair1/PHY/LTE_REFSIG/defs.h
index a1d2d3aaf8461f98ec4d8ba6e1ae95debef1c085..9c12458ff0fe18d7048dfc502a25665a213d6e92 100644
--- a/openair1/PHY/LTE_REFSIG/defs.h
+++ b/openair1/PHY/LTE_REFSIG/defs.h
@@ -45,12 +45,15 @@ unsigned int lte_gold_generic(unsigned int *x1, unsigned int *x2, unsigned char
 
 void lte_gold(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_table[20][2][14],uint16_t Nid_cell);
 
+void lte_gold_ue_spec(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_uespec_table[2][20][2][21],uint16_t Nid_cell, uint16_t *n_idDMRS);
+
+void lte_gold_ue_spec_port5(uint32_t lte_gold_uespec_port5_table[20][38],uint16_t Nid_cell, uint16_t n_rnti);
+
 /*!\brief This function generates the LTE Gold sequence (36-211, Sec 7.2), specifically for DL UE-specific reference signals for antenna ports 7..14.
 @param frame_parms LTE DL Frame parameters
 @param lte_gold_uespec_table pointer to table where sequences are stored
 @param Nid_cell Cell Id (to compute sequences for local and adjacent cells)
 @param n_idDMRS Scrambling identity for TM10*/
-void lte_gold_ue_spec(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_uespec_table[2][20][2][21],uint16_t Nid_cell, uint16_t *n_idDMRS);
 
 void lte_gold_mbsfn(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_mbsfn_table[10][3][42],uint16_t Nid_MBSFN);
 
@@ -77,16 +80,18 @@ int lte_dl_cell_spec(PHY_VARS_eNB *phy_vars_eNB,
 @param output Output vector for OFDM symbol (Frequency Domain)
 @param amp Q15 amplitude
 @param Ns Slot number (0..19)
+@param lprime symbol (0,1)
 @param p antenna index
 @param SS_flag Flag to indicate special subframe
 */
-int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB,
+/*int lte_dl_ue_spec(PHY_VARS_eNB *phy_vars_eNB,
                    uint8_t UE_id,
                    int32_t *output,
                    short amp,
                    uint8_t Ns,
+		   uint8_t lprime,
                    uint8_t p,
-                   int SS_flag );
+                   int SS_flag);*/
 
 /*! \brief This function generates the MBSFN reference signal sequence (36-211, Sec 6.10.1.2)
 @param phy_vars_eNB Pointer to eNB variables
@@ -116,6 +121,24 @@ int lte_dl_cell_spec_rx(PHY_VARS_UE *phy_vars_ue,
                         unsigned char l,
                         unsigned char p);
 
+/*!\brief This function generates the ue-specific reference signal
+ * sequence (36-211, Sec 6.10.3.1) for beamforming channel estimation upon reception
+@param phy_vars_ue Pointer to UE variables
+@param output Output vector for OFDM symbol (Frequency Domain)
+@param Ns Slot number (0..19)
+@param p antenna port intex
+@param lprime symbol (0,1)
+@param SS_flag Flag to indicate special subframe
+@param nRB_PDSCH number of allocated PDSCH RBs
+*/
+int lte_dl_ue_spec_rx(PHY_VARS_UE *phy_vars_ue,
+                      int32_t *output,
+                      unsigned char Ns,
+                      unsigned char p,
+                      int lprime,
+                      int SS_flag,
+                      uint16_t nRB_PDSCH);
+
 int lte_dl_mbsfn_rx(PHY_VARS_UE *phy_vars_ue,
                     int *output,
                     int subframe,
diff --git a/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c b/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c
index fba122eef4f4b8d8ca036234e60d8e49ffd506a2..3cf88fbb7639366ae9e696a2be0e983fefdc43f0 100644
--- a/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c
+++ b/openair1/PHY/LTE_REFSIG/lte_dl_uespec.c
@@ -19,13 +19,13 @@
  *      contact@openairinterface.org
  */
 
-/*! \file PHY/LTE_REFSIG/lte_dl_uespec.c
+/*! \file PHY/LTE_REFSIG/lte_dl_ue_spec.c
 * \brief Top-level routines for generating UE-specific Reference signals from 36-211, V11.3.0 2013-06
-* \author R. Knopp
-* \date 2014
+* \author R. Knopp X. Jiang
+* \date 2015
 * \version 0.1
 * \company Eurecom
-* \email: knopp@eurecom.fr
+* \email: knopp@eurecom.fr xiwen.jiang@eurecom.fr
 * \note
 * \warning
 */
@@ -44,18 +44,21 @@
 
 int Wbar_NCP[8][4] = {{1,1,1,1},{1,-1,1,-1},{1,1,1,1},{1,-1,1,-1},{1,1,-1,-1},{-1,-1,1,1},{1,-1,-1,1},{-1,1,1,-1}};
 
+/*
 int lte_dl_ue_spec(PHY_VARS_eNB *eNB,
                    uint8_t UE_id,
                    int32_t *output,
                    short amp,
                    uint8_t Ns,
+		   uint8_t lprime,
                    uint8_t p,
-                   int SS_flag )
+                   int SS_flag)
 {
 
-  int32_t qpsk[4],nqpsk[4],*qpsk_p,*output_p;
-  int16_t a;
-  int w,lprime,ind,l,ind_dword,ind_qpsk_symb,nPRB;
+  int32_t qpsk[4],nqpsk[4];
+  int16_t k=0,a;
+  int mprime,ind,ind_dword,ind_qpsk_symb;
+  unsigned nushift,kprime;
   //  LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_eNB[UE_id][0];
 
   a = (amp*ONE_OVER_SQRT2_Q15)>>15;
@@ -77,146 +80,230 @@ int lte_dl_ue_spec(PHY_VARS_eNB *eNB,
   ((short *)&nqpsk[3])[0] = a;
   ((short *)&nqpsk[3])[1] = a;
 
-  if (p>=7) {
+  if (p==5) {
     if (SS_flag==0) {
       if (eNB->frame_parms.Ncp == NORMAL) {
-        // this is 3GPP 36-211 6.10.3.2, NORMAL CP, p>=7
+      // this is 3GPP 36-211 6.10.3.2, NORMAL CP, p=5
+      
+      nushift =  eNB->frame_parms.Nid_cell%3;
+
+      if(lprime==0){
+        kprime=nushift;
+      }else{
+        kprime=(nushift+2*lprime)%4;
+      }
+
+      k = kprime+eNB->frame_parms.first_carrier_offset;
+      printf("lte_dl_ue_spec:k=%d\n",k);
+ 
+      for (mprime=0;mprime<3*nRB_PDSCH-1;mprime++) {
+        ind = 3*lprime*nRB_PDSCH+mprime;
+        ind_dword = ind>>4;
+        ind_qpsk_symb = ind&0xf;
+
+        output[k] = qpsk[(phy_vars_UE->lte_gold_uespec_port5_table[Ns][ind_dword]>>(2*ind_qpsk_symb))&3];
+        //output[k] = 0xffffffff;
+
+        k += 4;
+        if (k >= eNB->frame_parms.ofdm_symbol_size) {
+          k++;  // skip DC carrier
+          k-=eNB->frame_parms.ofdm_symbol_size;
+        }
+
+       }
+      }
+    }
+  } else if (p>=7) {
+    printf("lte_dl_ue_spec:antenna ports >=7 not supported yet!\n");
+  } else {
+    LOG_E(PHY,"Illegal p %d UE specific pilots\n",p);
+  }
+
+  return(0);
+}
+*/
+
 
+int lte_dl_ue_spec_rx(PHY_VARS_UE *ue,
+                      int32_t *output,
+                      unsigned char Ns,
+                      unsigned char p, 
+                      int lprime,
+                      int SS_flag,
+                      uint16_t nRB_PDSCH)
+{
+  int32_t qpsk[4],nqpsk[4],*qpsk_p,*output_p;
+  int w,mprime,ind,l,ind_dword,ind_qpsk_symb,nPRB;
+  short pamp;
 
+  // Compute the correct pilot amplitude, sqrt_rho_b = Q3.13
+  pamp = ONE_OVER_SQRT2_Q15;
 
-        // position output pointer to 5th symbol in slot
-        output_p = output+(60*eNB->frame_parms.N_RB_DL);
+  // This includes complex conjugate for channel estimation
+  ((short *)&qpsk[0])[0] = pamp;
+  ((short *)&qpsk[0])[1] = -pamp;
+  ((short *)&qpsk[1])[0] = -pamp;
+  ((short *)&qpsk[1])[1] = -pamp;
+  ((short *)&qpsk[2])[0] = pamp;
+  ((short *)&qpsk[2])[1] = pamp;
+  ((short *)&qpsk[3])[0] = -pamp;
+  ((short *)&qpsk[3])[1] = pamp;
 
-        // shift to 2nd RE in PRB for p=7,8,11,13
-        if ((p==7) || (p==8) || (p==11) || (p==13)) output_p++;
+  ((short *)&nqpsk[0])[0] = -pamp;
+  ((short *)&nqpsk[0])[1] = pamp;
+  ((short *)&nqpsk[1])[0] = pamp;
+  ((short *)&nqpsk[1])[1] = pamp;
+  ((short *)&nqpsk[2])[0] = -pamp;
+  ((short *)&nqpsk[2])[1] = -pamp;
+  ((short *)&nqpsk[3])[0] = pamp;
+  ((short *)&nqpsk[3])[1] = -pamp;
 
+  if (p>=7) {
+    if (SS_flag==0) {
+      if (ue->frame_parms.Ncp == NORMAL) {
+        // this is 3GPP 36-211 6.10.3.2, NORMAL CP, p>=7
 
-        for (lprime=0; lprime<2; lprime++) {
+        output_p = output;
 
-          ind = 3*lprime*eNB->frame_parms.N_RB_DL;
-          l = lprime + ((Ns&1)<<1);
+        ind = 3*lprime*ue->frame_parms.N_RB_DL;
+        l = lprime + ((Ns&1)<<1);
 
-          // loop over pairs of PRBs, this is the periodicity of the W_bar_NCP sequence
-          // unroll the computations for the 6 pilots, select qpsk or nqpsk as function of W_bar_NCP
-          for (nPRB=0; nPRB<eNB->frame_parms.N_RB_DL; nPRB+=2) {
+        // loop over pairs of PRBs, this is the periodicity of the W_bar_NCP sequence
+        // unroll the computations for the 6 pilots, select qpsk or nqpsk as function of W_bar_NCP
+        for (nPRB=0; nPRB<ue->frame_parms.N_RB_DL; nPRB+=2) {
 
-            // First pilot
-            w = Wbar_NCP[p-7][l];
-            qpsk_p = (w==1) ? qpsk : nqpsk;
+          // First pilot
+          w = Wbar_NCP[p-7][l];
+          qpsk_p = (w==1) ? qpsk : nqpsk;
 
 
-            ind_dword     = ind>>4;
-            ind_qpsk_symb = ind&0xf;
+          ind_dword     = ind>>4;
+          ind_qpsk_symb = ind&0xf;
 
-            *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+          *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
 
 
 #ifdef DEBUG_DL_UESPEC
-            LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
-                  Ns,l,m,mprime_dword,mprime_qpsk_symb);
-            LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+          LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+                Ns,l,m,ind_dword,ind_qpsk_symb);
+          LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
 #endif
 
-            output_p+=5;
-            ind++;
+          output_p++;
+          ind++;
 
-            w =  Wbar_NCP[p-7][3-l];
-            qpsk_p = (w==1) ? qpsk : nqpsk;
+          w =  Wbar_NCP[p-7][3-l];
+          qpsk_p = (w==1) ? qpsk : nqpsk;
 
-            // Second pilot
-            ind_dword     = ind>>4;
-            ind_qpsk_symb = ind&0xf;
+          // Second pilot
+          ind_dword     = ind>>4;
+          ind_qpsk_symb = ind&0xf;
 
-            *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+          *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
 
 #ifdef DEBUG_DL_UESPEC
-            LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
-                  Ns,l,m,mprime_dword,mprime_qpsk_symb);
-            LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+          LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+                Ns,l,m,ind_dword,ind_qpsk_symb);
+          LOG_D(PHY,"index = %d\n",(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
 #endif
 
-            output_p+=5;
-            ind++;
+          output_p++;
+          ind++;
 
-            w = Wbar_NCP[p-7][l];
-            qpsk_p = (w==1) ? qpsk : nqpsk;
-            // Third pilot
-            ind_dword     = ind>>4;
-            ind_qpsk_symb = ind&0xf;
+          w = Wbar_NCP[p-7][l];
+          qpsk_p = (w==1) ? qpsk : nqpsk;
+          // Third pilot
+          ind_dword     = ind>>4;
+          ind_qpsk_symb = ind&0xf;
 
-            *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+          *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
 
 #ifdef DEBUG_DL_UESPEC
-            LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
-                  Ns,l,m,mprime_dword,mprime_qpsk_symb);
-            LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+          LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+                Ns,l,m,ind_dword,ind_qpsk_symb);
+          LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
 #endif
 
-            output_p+=2;
-            ind++;
+          output_p++;
+          ind++;
 
-            // Fourth pilot
-            w = Wbar_NCP[p-7][3-l];
-            qpsk_p = (w==1) ? qpsk : nqpsk;
+          // Fourth pilot
+          w = Wbar_NCP[p-7][3-l];
+          qpsk_p = (w==1) ? qpsk : nqpsk;
 
 
-            ind_dword     = ind>>4;
-            ind_qpsk_symb = ind&0xf;
+          ind_dword     = ind>>4;
+          ind_qpsk_symb = ind&0xf;
 
-            *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+          *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
 
 
 #ifdef DEBUG_DL_UESPEC
-            LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
-                  Ns,l,m,mprime_dword,mprime_qpsk_symb);
-            LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+          LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+                Ns,l,m,ind_dword,ind_qpsk_symb);
+          LOG_D(PHY,"index = %d\n",(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
 #endif
 
-            output_p+=5;
-            ind++;
+          output_p++;
+          ind++;
 
-            w =  Wbar_NCP[p-7][l];
-            qpsk_p = (w==1) ? qpsk : nqpsk;
+          w =  Wbar_NCP[p-7][l];
+          qpsk_p = (w==1) ? qpsk : nqpsk;
 
-            // Fifth pilot
-            ind_dword     = ind>>4;
-            ind_qpsk_symb = ind&0xf;
+          // Fifth pilot
+          ind_dword     = ind>>4;
+          ind_qpsk_symb = ind&0xf;
 
-            *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+          *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
 
 #ifdef DEBUG_DL_UESPEC
-            LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
-                  Ns,l,m,mprime_dword,mprime_qpsk_symb);
-            LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+          LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+                Ns,l,m,ind_dword,ind_qpsk_symb);
+          LOG_D(PHY,"index = %d\n",(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
 #endif
 
-            output_p+=5;
-            ind++;
+          output_p++;
+          ind++;
 
-            w = Wbar_NCP[p-7][3-l];
-            qpsk_p = (w==1) ? qpsk : nqpsk;
-            // Sixth pilot
-            ind_dword     = ind>>4;
-            ind_qpsk_symb = ind&0xf;
+          w = Wbar_NCP[p-7][3-l];
+          qpsk_p = (w==1) ? qpsk : nqpsk;
+          // Sixth pilot
+          ind_dword     = ind>>4;
+          ind_qpsk_symb = ind&0xf;
 
-            *output_p = qpsk_p[(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
+          *output_p = qpsk_p[(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3];
 
 #ifdef DEBUG_DL_UESPEC
-            LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
-                  Ns,l,m,mprime_dword,mprime_qpsk_symb);
-            LOG_D(PHY,"index = %d\n",(eNB->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+          LOG_D(PHY,"Ns %d, l %d, m %d,ind_dword %d, ind_qpsk_symbol %d\n",
+                Ns,l,m,ind_dword,ind_qpsk_symb);
+          LOG_D(PHY,"index = %d\n",(ue->lte_gold_uespec_table[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
 #endif
 
-            output_p+=2;
-            ind++;
-          }
+          output_p++;
+          ind++;
         }
       } else {
         LOG_E(PHY,"Special subframe not supported for UE specific pilots yet\n");
       }
     }
   } else if (p==5) {
-    LOG_E(PHY,"p=5 not supported for UE specific pilots yet\n");
+    if (SS_flag==0) {
+      output_p = output;
+
+      if (ue->frame_parms.Ncp == NORMAL) {
+        for (mprime=0;mprime<3*nRB_PDSCH;mprime++) {
+
+          ind = 3*lprime*nRB_PDSCH+mprime;
+          ind_dword = ind>>4;
+          ind_qpsk_symb = ind&0xf;
+
+          *output_p = qpsk[(ue->lte_gold_uespec_port5_table[Ns][ind_dword]>>(2*ind_qpsk_symb))&3];
+          //printf("lprime=%d,ind=%d,Ns=%d,output_p=(%d,%d)\n",lprime,ind,Ns,((short *)&output_p[0])[0],((short *)&output_p[0])[1]);
+          output_p++;
+      
+        }
+      }
+    }
   } else {
     LOG_E(PHY,"Illegal p %d UE specific pilots\n",p);
   }
@@ -224,60 +311,7 @@ int lte_dl_ue_spec(PHY_VARS_eNB *eNB,
   return(0);
 }
 
-/*
-int lte_dl_cell_spec_rx(PHY_VARS_UE *phy_vars_ue,
-      uint8_t eNB_offset,
-      int *output,
-      unsigned char Ns,
-      unsigned char l,
-      unsigned char p) {
-
-
-  unsigned char mprime,mprime_dword,mprime_qpsk_symb,m;
-  unsigned short k=0;
-  unsigned int qpsk[4];
-  short pamp;
 
-  // Compute the correct pilot amplitude, sqrt_rho_b = Q3.13
-  pamp = ONE_OVER_SQRT2_Q15;
-
-  // This includes complex conjugate for channel estimation
-
-  ((short *)&qpsk[0])[0] = pamp;
-  ((short *)&qpsk[0])[1] = -pamp;
-  ((short *)&qpsk[1])[0] = -pamp;
-  ((short *)&qpsk[1])[1] = -pamp;
-  ((short *)&qpsk[2])[0] = pamp;
-  ((short *)&qpsk[2])[1] = pamp;
-  ((short *)&qpsk[3])[0] = -pamp;
-  ((short *)&qpsk[3])[1] = pamp;
-
-  mprime = 110 - phy_vars_ue->frame_parms.N_RB_DL;
-
-  for (m=0;m<phy_vars_ue->frame_parms.N_RB_DL<<1;m++) {
-
-    mprime_dword     = mprime>>4;
-    mprime_qpsk_symb = mprime&0xf;
-
-    // this is r_mprime from 3GPP 36-211 6.10.1.2
-    output[k] = qpsk[(phy_vars_ue->lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3];
-#ifdef DEBUG_DL_CELL_SPEC
-    printf("Ns %d, l %d, m %d,mprime_dword %d, mprime_qpsk_symbol %d\n",
-     Ns,l,m,mprime_dword,mprime_qpsk_symb);
-    printf("index = %d (k %d)\n",(phy_vars_ue->lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k);
-#endif
-
-    mprime++;
-#ifdef DEBUG_DL_CELL_SPEC
-    if (m<4)
-    printf("Ns %d l %d output[%d] = (%d,%d)\n",Ns,l,k,((short *)&output[k])[0],((short *)&output[k])[1]);
-#endif
-    k++;
-  }
-  return(0);
-}
-
-*/
 
 #ifdef LTE_DL_CELL_SPEC_MAIN
 
@@ -303,51 +337,51 @@ main()
 
   lte_gold(Nid_cell,Ncp);
 
-  lte_dl_cell_spec(output00,
-                   ONE_OVER_SQRT2_Q15,
-                   50,
-                   Nid_cell,
-                   Ncp,
-                   0,
-                   0,
-                   0,
-                   0);
-
-  lte_dl_cell_spec(output10,
-                   ONE_OVER_SQRT2_Q15,
-                   50,
-                   Nid_cell,
-                   Ncp,
-                   0,
-                   1,
-                   0,
-                   0);
-
-  lte_dl_cell_spec(output01,
-                   ONE_OVER_SQRT2_Q15,
-                   50,
-                   Nid_cell,
-                   Ncp,
-                   0,
-                   0,
-                   1,
-                   0);
-
-  lte_dl_cell_spec(output11,
-                   ONE_OVER_SQRT2_Q15,
-                   50,
-                   Nid_cell,
-                   Ncp,
-                   0,
-                   1,
-                   1,
-                   0);
-
-
-  write_output("dl_cell_spec00.m","dl_cs00",output00,1024,1,1);
-  write_output("dl_cell_spec01.m","dl_cs01",output01,1024,1,1);
-  write_output("dl_cell_spec10.m","dl_cs10",output10,1024,1,1);
-  write_output("dl_cell_spec11.m","dl_cs11",output11,1024,1,1);
+  lte_dl_ue_spec(output00,
+                 ONE_OVER_SQRT2_Q15,
+                 50,
+                 Nid_cell,
+                 Ncp,
+                 0,
+                 0,
+                 0,
+                 0);
+
+  lte_dl_ue_spec(output10,
+                 ONE_OVER_SQRT2_Q15,
+                 50,
+                 Nid_cell,
+                 Ncp,
+                 0,
+                 1,
+                 0,
+                 0);
+
+  lte_dl_ue_spec(output01,
+                 ONE_OVER_SQRT2_Q15,
+                 50,
+                 Nid_cell,
+                 Ncp,
+                 0,
+                 0,
+                 1,
+                 0);
+
+  lte_dl_ue_spec(output11,
+                 ONE_OVER_SQRT2_Q15,
+                 50,
+                 Nid_cell,
+                 Ncp,
+                 0,
+                 1,
+                 1,
+                 0);
+
+
+  write_output("dl_ue_spec00.m","dl_cs00",output00,1024,1,1);
+  write_output("dl_ue_spec01.m","dl_cs01",output01,1024,1,1);
+  write_output("dl_ue_spec10.m","dl_cs10",output10,1024,1,1);
+  write_output("dl_ue_spec11.m","dl_cs11",output11,1024,1,1);
 }
 
 
diff --git a/openair1/PHY/LTE_REFSIG/lte_gold.c b/openair1/PHY/LTE_REFSIG/lte_gold.c
index 3f0a09a27e42f4419c57c56c33e50aae32dec67f..b15bc06cbdd1abf309f6c96862ae5dab1eae0d96 100644
--- a/openair1/PHY/LTE_REFSIG/lte_gold.c
+++ b/openair1/PHY/LTE_REFSIG/lte_gold.c
@@ -131,6 +131,44 @@ void lte_gold_ue_spec(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_uespec_t
   }
 }
 
+void lte_gold_ue_spec_port5(uint32_t lte_gold_uespec_port5_table[20][38],uint16_t Nid_cell, uint16_t n_rnti)
+{
+
+  unsigned char ns;
+  unsigned int n,x1,x2;
+
+
+  for (ns=0; ns<20; ns++) {
+
+    x2 = ((((ns>>1)+1)*((Nid_cell<<1)+1))<<16) + n_rnti;
+    //x2 = frame_parms->Ncp + (Nid_cell<<1) + (1+(Nid_cell<<1))*(1 + (3*l) + (7*(1+ns))); //cinit
+    //n = 0
+    //printf("cinit (ns %d, l %d) => %d\n",ns,l,x2);
+    x1 = 1+ (1<<31);
+    x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
+
+    //skip first 50 double words (1600 bits)
+    //printf("n=0 : x1 %x, x2 %x\n",x1,x2);
+    for (n=1; n<50; n++) {
+      x1 = (x1>>1) ^ (x1>>4);
+      x1 = x1 ^ (x1<<31) ^ (x1<<28);
+      x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+      x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+      //printf("x1 : %x, x2 : %x\n",x1,x2);
+    }
+
+    for (n=0; n<38; n++) {
+      x1 = (x1>>1) ^ (x1>>4);
+      x1 = x1 ^ (x1<<31) ^ (x1<<28);
+      x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+      x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+      lte_gold_uespec_port5_table[ns][n] = x1^x2;
+      //printf("n=%d : c %x\n",n,x1^x2);
+    }
+
+  }
+}
+
 /*! \brief gold sequenquence generator
 \param x1
 \param x2 this should be set to c_init if reset=1
diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c
index 24d533506ce244ca83469686963a588380164091..75583678176047ce1cb1f32484e9c5a6718675d5 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci.c
@@ -66,7 +66,7 @@ uint32_t check_phich_reg(LTE_DL_FRAME_PARMS *frame_parms,uint32_t kprime,uint8_t
 
   // compute REG based on symbol
   if ((lprime == 0)||
-      ((lprime==1)&&(frame_parms->nb_antennas_tx_eNB == 4)))
+      ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)))
     mprime = kprime/6;
   else
     mprime = kprime>>2;
@@ -293,7 +293,7 @@ void pdcch_interleaving(LTE_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **w
     for (row=0; row<RCC; row++) {
       //printf("col %d, index %d, row %d\n",col,index,row);
       if (index>=ND) {
-        for (a=0; a<frame_parms->nb_antennas_tx_eNB; a++) {
+        for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) {
           //printf("a %d k %d\n",a,k);
 
           wptr = &wtemp[a][k<<2];
@@ -317,7 +317,7 @@ void pdcch_interleaving(LTE_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **w
   // permutation
   for (i=0; i<Mquad; i++) {
 
-    for (a=0; a<frame_parms->nb_antennas_tx_eNB; a++) {
+    for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) {
 
       //wptr  = &wtemp[a][i<<2];
       //wptr2 = &wbar[a][((i+frame_parms->Nid_cell)%Mquad)<<2];
@@ -409,7 +409,7 @@ void pdcch_demapping(uint16_t *llr,uint16_t *wbar,LTE_DL_FRAME_PARMS *frame_parm
               re_offset0++;
             }
           }
-        } else if ((lprime==1)&&(frame_parms->nb_antennas_tx_eNB == 4)) {
+        } else if ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)) {
           // LATER!!!!
         } else { // no pilots in this symbol
           kprime_mod12 = kprime%12;
@@ -647,7 +647,7 @@ void pdcch_channel_level(int32_t **dl_ch_estimates_ext,
   int16x8_t *dl_ch128;
   int32x4_t *avg128P;
 #endif
-  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++)
+  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
       //clear average level
 #if defined(__x86_64__) || defined(__i386__)
@@ -825,7 +825,7 @@ void pdcch_detection_mrc_i(LTE_DL_FRAME_PARMS *frame_parms,
   int32_t i;
 
   if (frame_parms->nb_antennas_rx>1) {
-    for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
+    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
       //if (frame_parms->mode1_flag && (aatx>0)) break;
 
 #if defined(__x86_64__) || defined(__i386__)
@@ -1126,6 +1126,9 @@ void pdcch_extract_rbs_dual(int32_t **rxdataF,
   int nushiftmod3 = frame_parms->nushift%3;
 
   symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
+#ifdef DEBUG_DCI_DECODING
+  LOG_I(PHY, "extract_rbs_dual: symbol_mod %d\n",symbol_mod);
+#endif
 
   for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
 
@@ -1388,8 +1391,8 @@ void pdcch_channel_compensation(int32_t **rxdataF_ext,
   if (symbol==0)
     pilots=1;
 
-  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
-    //if (frame_parms->mode1_flag && aatx>0) break; //if mode1_flag is set then there is only one stream to extract, independent of nb_antennas_tx_eNB
+  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
+    //if (frame_parms->mode1_flag && aatx>0) break; //if mode1_flag is set then there is only one stream to extract, independent of nb_antenna_ports_eNB
 
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
 
@@ -1595,7 +1598,7 @@ void pdcch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
   int32_t i;
 
   if (frame_parms->nb_antennas_rx>1) {
-    for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
+    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
 #if defined(__x86_64__) || defined(__i386__)
       rxdataF_comp128_0   = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12];
       rxdataF_comp128_1   = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12];
@@ -1716,7 +1719,7 @@ int32_t rx_pdcch(LTE_UE_COMMON *common_vars,
                                high_speed_flag,
                                frame_parms);
 #endif //MU_RECEIVER
-    } else if (frame_parms->nb_antennas_tx_eNB>1) {
+    } else if (frame_parms->nb_antenna_ports_eNB>1) {
       pdcch_extract_rbs_dual(common_vars->rxdataF,
                              common_vars->dl_ch_estimates[eNB_id],
                              pdcch_vars[eNB_id]->rxdataF_ext,
@@ -1742,7 +1745,7 @@ int32_t rx_pdcch(LTE_UE_COMMON *common_vars,
 
   avgs = 0;
 
-  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++)
+  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
       avgs = cmax(avgs,avgP[(aarx<<1)+aatx]);
 
@@ -1983,10 +1986,10 @@ uint8_t get_num_pdcch_symbols(uint8_t num_dci,
   //if ((9*numCCE) <= (frame_parms->N_RB_DL*2))
   if (numCCE <= get_nCCE(1, frame_parms, get_mi(frame_parms, subframe)))
     return(cmax(1,nCCEmin));
-  //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 4 : 5)))
+  //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 4 : 5)))
   else if (numCCE <= get_nCCE(2, frame_parms, get_mi(frame_parms, subframe)))
     return(cmax(2,nCCEmin));
-  //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 7 : 8)))
+  //else if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 7 : 8)))
   else if (numCCE <= get_nCCE(3, frame_parms, get_mi(frame_parms, subframe)))
     return(cmax(3,nCCEmin));
   else if (frame_parms->N_RB_DL<=10) {
@@ -1996,10 +1999,10 @@ uint8_t get_num_pdcch_symbols(uint8_t num_dci,
              get_nCCE(2, frame_parms, get_mi(frame_parms, subframe)),
              get_nCCE(3, frame_parms, get_mi(frame_parms, subframe)));
 
-      if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 10 : 11)))
+      if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 10 : 11)))
         return(4);
     } else { // extended CP
-      if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antennas_tx_eNB==4) ? 9 : 10)))
+      if ((9*numCCE) <= (frame_parms->N_RB_DL*((frame_parms->nb_antenna_ports_eNB==4) ? 9 : 10)))
         return(4);
     }
   }
@@ -2244,7 +2247,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
         // Copy REG to TX buffer
 
         if ((lprime == 0)||
-            ((lprime==1)&&(frame_parms->nb_antennas_tx_eNB == 4))) {
+            ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4))) {
           // first symbol, or second symbol+4 TX antennas skip pilots
 
           kprime_mod12 = kprime%12;
@@ -2256,7 +2259,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
               if ((i!=(nushiftmod3))&&(i!=(nushiftmod3+3))) {
                 txdataF[0][tti_offset+i] = wbar[0][mprime];
 
-                if (frame_parms->nb_antennas_tx_eNB > 1)
+                if (frame_parms->nb_antenna_ports_eNB > 1)
                   txdataF[1][tti_offset+i] = wbar[1][mprime];
 
 #ifdef DEBUG_DCI_ENCODING
@@ -2276,7 +2279,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
               for (i=0; i<4; i++) {
                 txdataF[0][tti_offset+i] = wbar[0][mprime];
 
-                if (frame_parms->nb_antennas_tx_eNB > 1)
+                if (frame_parms->nb_antenna_ports_eNB > 1)
                   txdataF[1][tti_offset+i] = wbar[1][mprime];
 
 #ifdef DEBUG_DCI_ENCODING
@@ -2287,7 +2290,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
             } else {
               txdataF[0][tti_offset+0] = wbar[0][mprime];
 
-              if (frame_parms->nb_antennas_tx_eNB > 1)
+              if (frame_parms->nb_antenna_ports_eNB > 1)
                 txdataF[1][tti_offset+0] = wbar[1][mprime];
 
 #ifdef DEBUG_DCI_ENCODING
@@ -2296,7 +2299,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
               mprime++;
               txdataF[0][tti_offset+1] = wbar[0][mprime];
 
-              if (frame_parms->nb_antennas_tx_eNB > 1)
+              if (frame_parms->nb_antenna_ports_eNB > 1)
                 txdataF[1][tti_offset+1] = wbar[1][mprime];
 
 #ifdef DEBUG_DCI_ENCODING
@@ -2305,7 +2308,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
               mprime++;
               txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[0][mprime];
 
-              if (frame_parms->nb_antennas_tx_eNB > 1)
+              if (frame_parms->nb_antenna_ports_eNB > 1)
                 txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[1][mprime];
 
 #ifdef DEBUG_DCI_ENCODING
@@ -2315,7 +2318,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
               mprime++;
               txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[0][mprime];
 
-              if (frame_parms->nb_antennas_tx_eNB > 1)
+              if (frame_parms->nb_antenna_ports_eNB > 1)
                 txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[1][mprime];
 
 #ifdef DEBUG_DCI_ENCODING
@@ -2679,11 +2682,15 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars,
 
   nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols,frame_parms,mi);
 
-  if (nCCE > get_nCCE(3,frame_parms,1))
+  if (nCCE > get_nCCE(3,frame_parms,1)) {
+    LOG_D(PHY,"skip DCI decoding: nCCE=%d > get_nCCE(3,frame_parms,1)=%d\n", nCCE, get_nCCE(3,frame_parms,1));
     return;
+  }
 
-  if (nCCE<L2)
+  if (nCCE<L2) {
+    LOG_D(PHY,"skip DCI decoding: nCCE=%d < L2=%d\n", nCCE, L2);
     return;
+  }
 
   if (do_common == 1) {
     nb_candidates = (L2==4) ? 4 : 2;
@@ -2857,7 +2864,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars,
           }
         }
 
-        LOG_D(PHY,"DCI decoding CRNTI  [format_c: %d, nCCE[subframe: %d]: %d ]\n",format_c, subframe, pdcch_vars[eNB_id]->nCCE[subframe]);
+        LOG_D(PHY,"DCI decoding CRNTI  [format: %d, nCCE[subframe: %d]: %d ], AggregationLevel %d \n",format_c, subframe, pdcch_vars[eNB_id]->nCCE[subframe],L2);
         //  memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes);
 
 
@@ -2929,12 +2936,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
       format1_size_bits  = sizeof_DCI1_1_5MHz_TDD_t;
       format1_size_bytes = sizeof(DCI1_1_5MHz_TDD_t);
 
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         format2_size_bits  = sizeof_DCI2_1_5MHz_2A_TDD_t;
         format2_size_bytes = sizeof(DCI2_1_5MHz_2A_TDD_t);
         format2A_size_bits  = sizeof_DCI2A_1_5MHz_2A_TDD_t;
         format2A_size_bytes = sizeof(DCI2A_1_5MHz_2A_TDD_t);
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         format2_size_bits  = sizeof_DCI2_1_5MHz_4A_TDD_t;
         format2_size_bytes = sizeof(DCI2_1_5MHz_4A_TDD_t);
         format2A_size_bits  = sizeof_DCI2A_1_5MHz_4A_TDD_t;
@@ -2950,12 +2957,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
       format1_size_bits  = sizeof_DCI1_1_5MHz_FDD_t;
       format1_size_bytes = sizeof(DCI1_1_5MHz_FDD_t);
 
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         format2_size_bits  = sizeof_DCI2_1_5MHz_2A_FDD_t;
         format2_size_bytes = sizeof(DCI2_1_5MHz_2A_FDD_t);
         format2A_size_bits  = sizeof_DCI2A_1_5MHz_2A_FDD_t;
         format2A_size_bytes = sizeof(DCI2A_1_5MHz_2A_FDD_t);
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         format2_size_bits  = sizeof_DCI2_1_5MHz_4A_FDD_t;
         format2_size_bytes = sizeof(DCI2_1_5MHz_4A_FDD_t);
         format2A_size_bits  = sizeof_DCI2A_1_5MHz_4A_FDD_t;
@@ -2977,12 +2984,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
       format1_size_bits  = sizeof_DCI1_5MHz_TDD_t;
       format1_size_bytes = sizeof(DCI1_5MHz_TDD_t);
 
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         format2_size_bits  = sizeof_DCI2_5MHz_2A_TDD_t;
         format2_size_bytes = sizeof(DCI2_5MHz_2A_TDD_t);
         format2A_size_bits  = sizeof_DCI2A_5MHz_2A_TDD_t;
         format2A_size_bytes = sizeof(DCI2A_5MHz_2A_TDD_t);
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         format2_size_bits  = sizeof_DCI2_5MHz_4A_TDD_t;
         format2_size_bytes = sizeof(DCI2_5MHz_4A_TDD_t);
         format2A_size_bits  = sizeof_DCI2A_5MHz_4A_TDD_t;
@@ -2998,12 +3005,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
       format1_size_bits  = sizeof_DCI1_5MHz_FDD_t;
       format1_size_bytes = sizeof(DCI1_5MHz_FDD_t);
 
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         format2_size_bits  = sizeof_DCI2_5MHz_2A_FDD_t;
         format2_size_bytes = sizeof(DCI2_5MHz_2A_FDD_t);
         format2A_size_bits  = sizeof_DCI2A_5MHz_2A_FDD_t;
         format2A_size_bytes = sizeof(DCI2A_5MHz_2A_FDD_t);
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         format2_size_bits  = sizeof_DCI2_5MHz_4A_FDD_t;
         format2_size_bytes = sizeof(DCI2_5MHz_4A_FDD_t);
         format2A_size_bits  = sizeof_DCI2A_5MHz_4A_FDD_t;
@@ -3024,12 +3031,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
       format1_size_bits  = sizeof_DCI1_10MHz_TDD_t;
       format1_size_bytes = sizeof(DCI1_10MHz_TDD_t);
 
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         format2_size_bits  = sizeof_DCI2_10MHz_2A_TDD_t;
         format2_size_bytes = sizeof(DCI2_10MHz_2A_TDD_t);
         format2A_size_bits  = sizeof_DCI2A_10MHz_2A_TDD_t;
         format2A_size_bytes = sizeof(DCI2A_10MHz_2A_TDD_t);
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         format2_size_bits  = sizeof_DCI2_10MHz_4A_TDD_t;
         format2_size_bytes = sizeof(DCI2_10MHz_4A_TDD_t);
         format2A_size_bits  = sizeof_DCI2A_10MHz_4A_TDD_t;
@@ -3045,12 +3052,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
       format1_size_bits  = sizeof_DCI1_10MHz_FDD_t;
       format1_size_bytes = sizeof(DCI1_10MHz_FDD_t);
 
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         format2_size_bits  = sizeof_DCI2_10MHz_2A_FDD_t;
         format2_size_bytes = sizeof(DCI2_10MHz_2A_FDD_t);
         format2A_size_bits  = sizeof_DCI2A_10MHz_2A_FDD_t;
         format2A_size_bytes = sizeof(DCI2A_10MHz_2A_FDD_t);
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         format2_size_bits  = sizeof_DCI2_10MHz_4A_FDD_t;
         format2_size_bytes = sizeof(DCI2_10MHz_4A_FDD_t);
         format2A_size_bits  = sizeof_DCI2A_10MHz_4A_FDD_t;
@@ -3071,12 +3078,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
       format1_size_bits  = sizeof_DCI1_20MHz_TDD_t;
       format1_size_bytes = sizeof(DCI1_20MHz_TDD_t);
 
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         format2_size_bits  = sizeof_DCI2_20MHz_2A_TDD_t;
         format2_size_bytes = sizeof(DCI2_20MHz_2A_TDD_t);
         format2A_size_bits  = sizeof_DCI2A_20MHz_2A_TDD_t;
         format2A_size_bytes = sizeof(DCI2A_20MHz_2A_TDD_t);
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         format2_size_bits  = sizeof_DCI2_20MHz_4A_TDD_t;
         format2_size_bytes = sizeof(DCI2_20MHz_4A_TDD_t);
         format2A_size_bits  = sizeof_DCI2A_20MHz_4A_TDD_t;
@@ -3092,12 +3099,12 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
       format1_size_bits  = sizeof_DCI1_20MHz_FDD_t;
       format1_size_bytes = sizeof(DCI1_20MHz_FDD_t);
 
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         format2_size_bits  = sizeof_DCI2_20MHz_2A_FDD_t;
         format2_size_bytes = sizeof(DCI2_20MHz_2A_FDD_t);
         format2A_size_bits  = sizeof_DCI2A_20MHz_2A_FDD_t;
         format2A_size_bytes = sizeof(DCI2A_20MHz_2A_FDD_t);
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         format2_size_bits  = sizeof_DCI2_20MHz_4A_FDD_t;
         format2_size_bytes = sizeof(DCI2_20MHz_4A_FDD_t);
         format2A_size_bits  = sizeof_DCI2A_20MHz_4A_FDD_t;
@@ -3248,7 +3255,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
                           SI_RNTI,
                           ra_rnti,
 			  P_RNTI,
-			  3,
+			  0,
                           format1A,
                           format1A,
                           format1A,
@@ -3277,7 +3284,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
                           SI_RNTI,
                           ra_rnti,
 			  P_RNTI,
-			  2,
+			  1,
                           format1A,
                           format1A,
                           format1A,
@@ -3310,7 +3317,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
                           SI_RNTI,
                           ra_rnti,
 			  P_RNTI,
-                          1,
+                          2,
                           format1A,
                           format1A,
                           format1A,
@@ -3339,7 +3346,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
                           SI_RNTI,
                           ra_rnti,
 			  P_RNTI,
-                          0,
+                          3,
                           format1A,
                           format1A,
                           format1A,
@@ -3361,7 +3368,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
 
 
   // These are for CRNTI based on transmission mode
-  if (tmode < 3) {
+  if ((tmode < 3) || (tmode == 7)) {
     // Now check UE_SPEC format 1 search spaces at aggregation 1
     old_dci_cnt=dci_cnt;
     dci_decoding_procedure0(pdcch_vars,0,subframe,
@@ -3730,7 +3737,7 @@ uint16_t dci_decoding_procedure(PHY_VARS_UE *ue,
                             &CCEmap1,
                             &CCEmap2);
     //#endif
-  } else if (tmode >=5) { // This is MU-MIMO
+  } else if ((tmode==5) || (tmode==6)) { // This is MU-MIMO
 
     // Now check UE_SPEC format 1E_2A_M10PRB search spaces aggregation 1
 #ifdef DEBUG_DCI_DECODING
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
index f66ec5fe4bbaaf3697a010b5c4d9f525fd8a5310..1dfbc9d7df4f5b322c7f460f679817c3522cdcbc 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
@@ -36,7 +36,10 @@
 #include "PHY/vars.h"
 #endif
 #include "assertions.h"
- 
+
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/MAC/defs.h"
+
 //#define DEBUG_DCI
 
 uint32_t localRIV2alloc_LUT6[32];
@@ -862,7 +865,8 @@ int generate_eNB_dlsch_params_from_dci(int frame,
                                        uint16_t si_rnti,
                                        uint16_t ra_rnti,
                                        uint16_t p_rnti,
-                                       uint16_t DL_pmi_single)
+                                       uint16_t DL_pmi_single,
+				       uint8_t beamforming_mode)
 {
 
   uint8_t harq_pid = UINT8_MAX;
@@ -1230,7 +1234,13 @@ int generate_eNB_dlsch_params_from_dci(int frame,
 
     dlsch0_harq->Nl          = 1;
     //    dlsch[0]->layer_index = 0;
-    dlsch0_harq->mimo_mode   = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI;
+    if (beamforming_mode == 0)
+      dlsch0_harq->mimo_mode = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI;
+    else if (beamforming_mode == 7)
+      dlsch0_harq->mimo_mode = TM7;
+    else
+      LOG_E(PHY,"Invalid beamforming mode %dL\n", beamforming_mode);
+      
     dlsch0_harq->dl_power_off = 1;
     /*
       if (dlsch[0]->harq_processes[harq_pid]->first_tx == 1) {
@@ -1260,6 +1270,11 @@ int generate_eNB_dlsch_params_from_dci(int frame,
       dlsch0_harq->TBS         = TBStable[get_I_TBS(dlsch0_harq->mcs)][NPRB-1];
 
     }
+    else
+    {
+    	LOG_E(PHY,"DL Received HarqReTx round=%d mcs=%d rballoc=%d rv=%d \n",
+    			dlsch0_harq->round,mcs,rballoc,rv);
+    }
 
 
     dlsch[0]->current_harq_pid = harq_pid;
@@ -2674,7 +2689,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
   // compute DL power control parameters
   computeRhoA_eNB(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off);
 
-  computeRhoB_eNB(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antennas_tx_eNB,dlsch[0],dlsch0_harq->dl_power_off);
+  computeRhoB_eNB(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antenna_ports_eNB,dlsch[0],dlsch0_harq->dl_power_off);
 
   return(0);
 }
@@ -3440,7 +3455,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci)
 
     if ((frame_parms->frame_type == TDD) &&
         (frame_parms->tdd_config>0)) {
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         switch(frame_parms->N_RB_DL) {
         case 6:
           LOG_D(PHY,"DCI format2A 2 antennas (FDD 1.5 MHz), rnti %x (%x): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d\n",
@@ -3519,7 +3534,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci)
           DevParam (frame_parms->N_RB_DL, 0, 0);
           break;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         switch(frame_parms->N_RB_DL) {
         case 6:
           LOG_D(PHY,"DCI format2A 4 antennas (TDD 1.5 MHz), rnti %x (%llx): rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, TPC %d, dai %d, tbswap %d, tpmi %d\n",
@@ -3604,7 +3619,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci)
         }
       }
     } else if (frame_parms->frame_type == FDD) {
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         switch(frame_parms->N_RB_DL) {
         case 6:
           LOG_D(PHY,"DCI format2A 2 antennas (FDD, 1.5 MHz), rnti %x (%x):  rb_alloc %x, mcs1 %d, mcs2 %d, harq_pid %d, ndi1 %d, ndi2 %d, RV1 %d, RV2 %d, tb_swap %d, TPC %d\n",
@@ -3678,7 +3693,7 @@ int dump_dci(LTE_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci)
           DevParam (frame_parms->N_RB_DL, 0, 0);
           break;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         switch(frame_parms->N_RB_DL) {
 
         case 6:
@@ -3802,7 +3817,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
                                       PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated,
                                       uint16_t si_rnti,
                                       uint16_t ra_rnti,
-                                      uint16_t p_rnti)
+                                      uint16_t p_rnti,
+                                      uint8_t beamforming_mode)
 {
 
   uint8_t harq_pid=0;
@@ -3917,10 +3933,10 @@ int generate_ue_dlsch_params_from_dci(int frame,
         dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
       } else {
 
-        if (harq_pid>1) {
-          LOG_E(PHY,"Format 1A: harq_pid > 1\n");
-          return(-1);
-        }
+        //if (harq_pid>1) {
+        //  LOG_E(PHY,"Format 1A: harq_pid > 1\n");
+         // return(-1);
+        //}
 
         dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
         NPRB = RIV2nb_rb_LUT25[rballoc];
@@ -4119,6 +4135,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
     dlsch0_harq->rvidx = rv;
     dlsch0_harq->Nl = 1;
     //    dlsch[0]->layer_index = 0;
+
     dlsch0_harq->mimo_mode = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI;
     dlsch0_harq->dl_power_off = 1; //no power offset
 
@@ -4143,6 +4160,20 @@ int generate_ue_dlsch_params_from_dci(int frame,
 
     dlsch0_harq->DCINdi = ndi;
 
+    // this a retransmission
+    if(dlsch0_harq->round)
+    {
+	// compare old TBS to new TBS
+    	if(dlsch0_harq->TBS != TBStable[get_I_TBS(mcs)][NPRB-1])
+    	{
+    		// this is an eNB issue
+    		// retransmisison but old and new TBS are different !!!
+    		// work around, consider it as a new transmission
+    		LOG_E(PHY,"Format1A Retransmission but TBS are different: consider it as new transmission !!! \n");
+    		dlsch0_harq->round = 0;
+    	}
+    }
+
     dlsch0_harq->mcs = mcs;
     if ((rnti==si_rnti) || (rnti==p_rnti) || (rnti==ra_rnti)) {
       dlsch0_harq->TBS = TBStable[mcs][NPRB-1];
@@ -4434,6 +4465,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
       dlsch0_harq->status = ACTIVE;
       dlsch0_harq->DCINdi = ndi;
 
+      dlsch[0]->harq_ack[subframe].send_harq_status = 1;
       if (dlsch0_harq->first_tx==1) {
         LOG_D(PHY,"[PDSCH %x/%d] Format 1 DCI First TX: Clearing flag\n");
         dlsch0_harq->first_tx = 0;
@@ -4452,6 +4484,20 @@ int generate_ue_dlsch_params_from_dci(int frame,
 
     dlsch0_harq->mcs         = mcs;
 
+    // this a retransmission
+    if(dlsch0_harq->round)
+    {
+    	// compare old TBS to new TBS
+    	if(dlsch0_harq->TBS != TBStable[get_I_TBS(mcs)][NPRB-1])
+    	{
+    		// this is an eNB issue
+    		// retransmisison but old and new TBS are different !!!
+    		// work around, consider it as a new transmission
+    		LOG_E(PHY,"Format1 Retransmission but TBS are different: consider it as new transmission !!! \n");
+    		dlsch0_harq->round = 0;
+    	}
+    }
+
     dlsch0_harq->TBS         = TBStable[get_I_TBS(mcs)][NPRB-1];
     if (mcs <= 28)
       dlsch0_harq->Qm          = get_Qm(mcs);
@@ -4466,7 +4512,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
 
     dlsch[0]->rnti = rnti;
 
-    dlsch0_harq->mimo_mode   = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI;
+    if (beamforming_mode == 0)
+      dlsch0_harq->mimo_mode   = (frame_parms->mode1_flag == 1) ? SISO : ALAMOUTI;
+    else if (beamforming_mode == 7)
+      dlsch0_harq->mimo_mode   = TM7;
+    else
+      LOG_E(PHY,"Not supported beamforming mode %d\n",beamforming_mode);
+       
 
     dlsch0 = dlsch[0];
 
@@ -4476,7 +4528,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
     switch (frame_parms->N_RB_DL) {
 
     case 6:
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4496,7 +4548,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tbswap    = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap;
           tpmi      = ((DCI2_1_5MHz_2A_FDD_t *)dci_pdu)->tpmi;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2_1_5MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4517,13 +4569,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tpmi      = ((DCI2_1_5MHz_4A_FDD_t *)dci_pdu)->tpmi;
         }
       } else {
-        LOG_E(PHY,"UE: subframe %d Format2 DCI: unsupported number of TX antennas %d\n",subframe,frame_parms->nb_antennas_tx_eNB);
+        LOG_E(PHY,"UE: subframe %d Format2 DCI: unsupported number of TX antennas %d\n",subframe,frame_parms->nb_antenna_ports_eNB);
       }
 
       break;
 
     case 25:
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2_5MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4545,7 +4597,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tbswap    = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tb_swap;
           tpmi      = ((DCI2_5MHz_2A_FDD_t *)dci_pdu)->tpmi;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2_5MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4568,13 +4620,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tpmi      = ((DCI2_5MHz_4A_FDD_t *)dci_pdu)->tpmi;
         }
       } else {
-        LOG_E(PHY,"UE: Format2 DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antennas_tx_eNB);
+        LOG_E(PHY,"UE: Format2 DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antenna_ports_eNB);
       }
 
       break;
 
     case 50:
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2_10MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4596,7 +4648,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tbswap    = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tb_swap;
           tpmi      = ((DCI2_10MHz_2A_FDD_t *)dci_pdu)->tpmi;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2_10MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4619,13 +4671,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tpmi      = ((DCI2_10MHz_4A_FDD_t *)dci_pdu)->tpmi;
         }
       } else {
-        LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antennas_tx_eNB);
+        LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antenna_ports_eNB);
       }
 
       break;
 
     case 100:
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2_20MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4647,7 +4699,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tbswap    = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tb_swap;
           tpmi      = ((DCI2_20MHz_2A_FDD_t *)dci_pdu)->tpmi;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2_20MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4670,7 +4722,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tpmi      = ((DCI2_20MHz_4A_FDD_t *)dci_pdu)->tpmi;
         }
       } else {
-        LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antennas_tx_eNB);
+        LOG_E(PHY,"UE: Format2A DCI: unsupported number of TX antennas %d\n",frame_parms->nb_antenna_ports_eNB);
       }
 
       break;
@@ -4865,7 +4917,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
     switch (frame_parms->N_RB_DL) {
 
     case 6:
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2A_1_5MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4887,7 +4939,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           harq_pid  = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->harq_pid;
           tbswap    = ((DCI2A_1_5MHz_2A_FDD_t *)dci_pdu)->tb_swap;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2A_1_5MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4912,13 +4964,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tpmi      = ((DCI2A_1_5MHz_4A_FDD_t *)dci_pdu)->tpmi;
         }
       } else {
-        LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antennas_tx_eNB);
+        LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB);
       }
 
       break;
 
     case 25:
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2A_5MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4942,7 +4994,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           harq_pid  = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->harq_pid;
           tbswap    = ((DCI2A_5MHz_2A_FDD_t *)dci_pdu)->tb_swap;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2A_5MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -4969,13 +5021,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tpmi      = ((DCI2A_5MHz_4A_FDD_t *)dci_pdu)->tpmi;
         }
       } else {
-        LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antennas_tx_eNB);
+        LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB);
       }
 
       break;
 
     case 50:
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2A_10MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -4999,7 +5051,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           harq_pid  = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->harq_pid;
           tbswap    = ((DCI2A_10MHz_2A_FDD_t *)dci_pdu)->tb_swap;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2A_10MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -5026,13 +5078,13 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tpmi      = ((DCI2A_10MHz_4A_FDD_t *)dci_pdu)->tpmi;
         }
       } else {
-        LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antennas_tx_eNB);
+        LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB);
       }
 
       break;
 
     case 100:
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2A_20MHz_2A_TDD_t *)dci_pdu)->mcs2;
@@ -5056,7 +5108,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           harq_pid  = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->harq_pid;
           tbswap    = ((DCI2A_20MHz_2A_FDD_t *)dci_pdu)->tb_swap;
         }
-      } else if (frame_parms->nb_antennas_tx_eNB == 4) {
+      } else if (frame_parms->nb_antenna_ports_eNB == 4) {
         if (frame_type == TDD) {
           mcs1      = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->mcs1;
           mcs2      = ((DCI2A_20MHz_4A_TDD_t *)dci_pdu)->mcs2;
@@ -5083,7 +5135,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
           tpmi    = ((DCI2A_20MHz_4A_FDD_t *)dci_pdu)->tpmi;
         }
       } else {
-        LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antennas_tx_eNB);
+        LOG_E(PHY,"eNB: subframe %d UE %x, Format2A DCI: unsupported number of TX antennas %d\n",subframe,rnti,frame_parms->nb_antenna_ports_eNB);
       }
 
       break;
@@ -5226,7 +5278,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
       }
     }
 
-    if (frame_parms->nb_antennas_tx_eNB == 2) {
+    if (frame_parms->nb_antenna_ports_eNB == 2) {
       dlsch0_harq->TBS         = TBStable[get_I_TBS(dlsch0_harq->mcs)][dlsch0_harq->nb_rb-1];
       dlsch1_harq->TBS         = TBStable[get_I_TBS(dlsch1_harq->mcs)][dlsch0_harq->nb_rb-1];
 
@@ -5241,7 +5293,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
         dlsch0_harq->mimo_mode   = ALAMOUTI;
         dlsch1_harq->mimo_mode   = ALAMOUTI;
       }
-    } else if (frame_parms->nb_antennas_tx_eNB == 4) { // 4 antenna case
+    } else if (frame_parms->nb_antenna_ports_eNB == 4) { // 4 antenna case
       if ((dlsch0->active==1) && (dlsch1->active==1)) {
         switch (tpmi) {
         case 0: // one layer per transport block
@@ -5325,7 +5377,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
         }
       }
     } else {
-      LOG_E(PHY,"Illegal number of antennas for eNB %d\n",frame_parms->nb_antennas_tx_eNB);
+      LOG_E(PHY,"Illegal number of antennas for eNB %d\n",frame_parms->nb_antenna_ports_eNB);
     }
 
     if (mcs1 <= 28)
@@ -5519,7 +5571,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
 
 #ifdef DEBUG_DCI
 
-  if (dlsch[0]) {
+  if (dlsch[0] && (dlsch[0]->rnti != 0xffff)) {
+    printf("dci_format:%d Abssubframe: %d.%d \n",dci_format,frame,subframe);
     printf("PDSCH dlsch0 UE: rnti     %x\n",dlsch[0]->rnti);
     printf("PDSCH dlsch0 UE: NBRB     %d\n",dlsch0_harq->nb_rb);
     printf("PDSCH dlsch0 UE: rballoc  %x\n",dlsch0_harq->rb_alloc_even[0]);
@@ -5537,7 +5590,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
   // compute DL power control parameters
   computeRhoA_UE(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off);
 
-  computeRhoB_UE(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antennas_tx_eNB,dlsch[0],dlsch0_harq->dl_power_off);
+  computeRhoB_UE(pdsch_config_dedicated,&(frame_parms->pdsch_config_common),frame_parms->nb_antenna_ports_eNB,dlsch[0],dlsch0_harq->dl_power_off);
 
   return(0);
 }
@@ -6194,13 +6247,22 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
 
   uint8_t harq_pid;
   uint8_t transmission_mode = ue->transmission_mode[eNB_id];
-  ANFBmode_t AckNackFBMode = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode;
+  ANFBmode_t AckNackFBMode;
   LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id];
   //  LTE_UE_DLSCH_t **dlsch = ue->dlsch[0];
   PHY_MEASUREMENTS *meas = &ue->measurements;
   LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
   //  uint32_t current_dlsch_cqi = ue->current_dlsch_cqi[eNB_id];
 
+  if(frame_parms->frame_type == TDD)
+  {
+      AckNackFBMode = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode;
+  }
+  else
+  {
+      AckNackFBMode = 1; // 1: multiplexing for FDD
+  }
+
   uint32_t cqi_req;
   uint32_t dai=0;
   uint32_t cshift;
@@ -6351,8 +6413,10 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
 
 
     if (rballoc > RIV_max) {
-      LOG_E(PHY,"frame %d, subframe %d, rnti %x, format %d: FATAL ERROR: generate_ue_ulsch_params_from_dci, rb_alloc > RIV_max\n",
-            proc->frame_rx, subframe, rnti, dci_format);
+      LOG_E(PHY,"frame %d, subframe %d, rnti %x, format %d: FATAL ERROR: generate_ue_ulsch_params_from_dci, rb_alloc[%d] > RIV_max[%d]\n",
+            proc->frame_rx, subframe, rnti, dci_format,rballoc,RIV_max);
+      LOG_E(PHY,"Wrong DCI0 detection, do not transmit PUSCH for HARQID: %d\n",harq_pid);
+      ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
       return(-1);
     }
 
@@ -6361,7 +6425,11 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
     if ((rnti >= cba_rnti) && (rnti < p_rnti))
       ulsch->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1; //+=1 this indicates the number of dci / cba group: not supported in the data struct
     else
-      ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+    {
+        ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+        //LOG_I(PHY,"[HARQ-UL harqId: %d] DCI0 ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round);
+
+    }
 
     ulsch->harq_processes[harq_pid]->TPC                                   = TPC;
 
@@ -6391,7 +6459,42 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
         ulsch->harq_processes[harq_pid]->round = 0;
       } else {
         //  ulsch->harq_processes[harq_pid]->Ndi = 0;
-        // ulsch->harq_processes[harq_pid]->round++;  // This is done in phich RX
+        //ulsch->harq_processes[harq_pid]->round++;  // This is done in phich RX
+
+        //#ifdef DEBUG_PHICH
+        //LOG_I(PHY,"[UE  %d][PUSCH %d] Frame %d subframe %d Adaptative Retrans, NDI not toggled => Nack. maxHARQ_Tx %d \n",
+        //      ue->Mod_id,harq_pid,
+        //      proc->frame_rx,
+        //      subframe,
+        //      ulsch->Mlimit);
+        //#endif
+/*
+        if (ulsch->harq_processes[harq_pid]->round > 0) // NACK detected on phich
+        {
+            // ulsch->harq_processes[harq_pid]->round++; already done on phich_rx
+            // ulsch->harq_processes[harq_pid] = ulsch->harq_processes[8];
+            // LOG_I(PHY,"          Adaptative retransmission - copy temporary harq Process to current harq process. [harqId %d round %d] \n",harq_pid, ulsch->harq_processes[8]->round);
+
+            if (ulsch->harq_processes[harq_pid]->round >= ulsch->Mlimit) //UE_mac_inst[eNB_id].scheduling_info.maxHARQ_Tx)
+            {
+                ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+                ulsch->harq_processes[harq_pid]->round  = 0;
+                ulsch->harq_processes[harq_pid]->status = IDLE;
+                //LOG_I(PHY,"          PUSCH MAX Retransmission acheived ==> flush harq buff (%d) \n",harq_pid);
+                //LOG_I(PHY,"          [HARQ-UL harqId: %d] Adaptative retransmission NACK MAX RETRANS(%d) ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, UE_mac_inst[eNB_id].scheduling_info.maxHARQ_Tx, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round);
+            }
+            else
+            {
+                // ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+                uint8_t rv_table[4] = {0, 2, 3, 1};
+                ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3];
+                ulsch->O_RI = 0;
+                ulsch->O    = 0;
+                ulsch->uci_format = HLC_subband_cqi_nopmi;
+                //LOG_I(PHY,"          [HARQ-UL harqId: %d] Adaptative retransmission NACK ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag,ulsch->harq_processes[harq_pid]->round);
+            }
+        }
+*/
       }
     }
 
@@ -6441,7 +6544,16 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
 
 
     if (cqi_req == 1) {
-      ulsch->O_RI = 1; //we only support 2 antenna ports, so this is always 1 according to 3GPP 36.213 Table
+
+      if( (AntennaInfoDedicated__transmissionMode_tm3 == transmission_mode) || (AntennaInfoDedicated__transmissionMode_tm4 == transmission_mode) )
+      {
+          ulsch->O_RI = 1;
+      }
+      else
+      {
+          ulsch->O_RI = 0;
+      }
+      //ulsch->O_RI = 0; //we only support 2 antenna ports, so this is always 1 according to 3GPP 36.213 Table
 
       switch(transmission_mode) {
         // The aperiodic CQI reporting mode is fixed for every transmission mode instead of being configured by higher layer signaling
@@ -7001,15 +7113,19 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
 
     // ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift;
 
-#ifdef DEBUG_DCI
+ #ifdef DEBUG_DCI 
+    printf("Format 0 DCI : ulsch (ue): AbsSubframe %d.%d\n",proc->frame_rx,subframe);
     printf("Format 0 DCI : ulsch (ue): NBRB        %d\n",ulsch->harq_processes[harq_pid]->nb_rb);
     printf("Format 0 DCI :ulsch (ue): first_rb    %d\n",ulsch->harq_processes[harq_pid]->first_rb);
+    printf("Format 0 DCI :ulsch (ue): rballoc     %d\n",rballoc);
     printf("Format 0 DCI :ulsch (ue): harq_pid    %d\n",harq_pid);
+    printf("Format 0 DCI :ulsch (ue): first_tx       %d\n",ulsch->harq_processes[harq_pid]->first_tx);
+    printf("Format 0 DCI :ulsch (ue): DCINdi       %d\n",ulsch->harq_processes[harq_pid]->DCINdi);
     printf("Format 0 DCI :ulsch (ue): round       %d\n",ulsch->harq_processes[harq_pid]->round);
     printf("Format 0 DCI :ulsch (ue): TBS         %d\n",ulsch->harq_processes[harq_pid]->TBS);
     printf("Format 0 DCI :ulsch (ue): mcs         %d\n",ulsch->harq_processes[harq_pid]->mcs);
     printf("Format 0 DCI :ulsch (ue): O           %d\n",ulsch->O);
-
+    printf("Format 0 DCI :ulsch (ue): cqiReq      %d\n",cqi_req);
     if (frame_parms->frame_type == TDD)
       printf("Format 0 DCI :ulsch (ue): O_ACK/DAI   %d/%d\n",ulsch->harq_processes[harq_pid]->O_ACK,dai);
     else
@@ -7017,6 +7133,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
 
     printf("Format 0 DCI :ulsch (ue): Nsymb_pusch   %d\n",ulsch->Nsymb_pusch);
     printf("Format 0 DCI :ulsch (ue): cshift        %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2);
+    printf("Format 0 DCI :ulsch (ue): phich status  %d\n",ulsch->harq_processes[harq_pid]->status);
 #else
     UNUSED_VARIABLE(dai);
 #endif
@@ -7689,7 +7806,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
   switch(transmission_mode) {
   case 1:
     for (count=0; count<frame_parms->N_RB_DL*12; count++) {
-      for(a_tx=0; a_tx<frame_parms->nb_antennas_tx_eNB; a_tx++) {
+      for(a_tx=0; a_tx<frame_parms->nb_antenna_ports_eNB; a_tx++) {
         for (a_rx=0; a_rx<frame_parms->nb_antennas_rx; a_rx++) {
           s_dB[count] = 10*log10(pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2],2) + pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2],
                                  2)) - meas->n0_power_avg_dB;
@@ -7703,7 +7820,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
     for (count=0; count<frame_parms->N_RB_DL*12; count++) {
       abs_channel=0;
 
-      for(a_tx=0; a_tx<frame_parms->nb_antennas_tx_eNB; a_tx++) {
+      for(a_tx=0; a_tx<frame_parms->nb_antenna_ports_eNB; a_tx++) {
         for (a_rx=0; a_rx<frame_parms->nb_antennas_rx; a_rx++) {
           abs_channel += (pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+(LTE_CE_FILTER_LENGTH)*2],2) + pow(((int16_t *) dl_channel_est[(a_tx<<1)+a_rx])[2*count+1+(LTE_CE_FILTER_LENGTH)*2],2));
         }
@@ -7723,7 +7840,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
       qq = (q>>(((count/12)>>2)<<1))&3;
 
       //printf("pmi_alloc %d: rb %d, pmi %d\n",q,count/12,qq);
-      for(a_tx=0; a_tx<frame_parms->nb_antennas_tx_eNB; a_tx++) {
+      for(a_tx=0; a_tx<frame_parms->nb_antenna_ports_eNB; a_tx++) {
         for (a_rx=0; a_rx<frame_parms->nb_antennas_rx; a_rx++) {
           switch(qq) {
           case 0:
@@ -7805,7 +7922,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
       qq = (q>>(((count/12)>>2)<<1))&3;
 
       //printf("pmi_alloc %d: rb %d, pmi %d\n",q,count/12,qq);
-      for(a_tx=0; a_tx<frame_parms->nb_antennas_tx_eNB; a_tx++) {
+      for(a_tx=0; a_tx<frame_parms->nb_antenna_ports_eNB; a_tx++) {
         for (a_rx=0; a_rx<frame_parms->nb_antennas_rx; a_rx++) {
           switch(qq) {
           case 0:
diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h
index 01d6cdc449a01feaa793df2039a6786580648956..b6bbe09b31dcead2d2197ef17d9b34ffa2fee886 100644
--- a/openair1/PHY/LTE_TRANSPORT/defs.h
+++ b/openair1/PHY/LTE_TRANSPORT/defs.h
@@ -227,11 +227,20 @@ typedef struct {
   uint8_t control_only;
   /// Flag to indicate that this is a calibration ULSCH (i.e. no MAC SDU and filled with TDD calibration information)
   //  int calibration_flag;
+  /// Number of soft channel bits
+  uint32_t G;
+
+  // decode phich
+  uint8_t decode_phich;
 } LTE_UL_UE_HARQ_t;
 
 typedef struct {
   /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding)
-  uint32_t *txdataF[8];
+  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]; 
+  /// dl channel estimates (estimated from ul channel estimates)
+  int32_t **calib_dl_ch_estimates;
   /// Allocated RNTI (0 means DLSCH_t is not currently used)
   uint16_t rnti;
   /// Active flag for baseband transmitter processing
@@ -333,12 +342,16 @@ typedef struct {
   int16_t Po_PUSCH;
   /// PHR - current power headroom (based on last PUSCH transmission)
   int16_t PHR;
+  /// Po_SRS - target output power for SRS
+  int16_t Po_SRS;
   /// num active cba group
   uint8_t num_active_cba_groups;
   /// num dci found for cba
   uint8_t num_cba_dci[10];
   /// allocated CBA RNTI
   uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP];
+  /// UL max-harq-retransmission
+  uint8_t Mlimit;
 } LTE_UE_ULSCH_t;
 
 typedef struct {
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
index 0284ca27adfd0ff34fed88b304b2732fd125080a..08279188639a026527a514c2327188aa266d8bc9 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
@@ -111,12 +111,14 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch)
   
 }
 
-LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag)
+LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms)
 {
 
   LTE_eNB_DLSCH_t *dlsch;
-  unsigned char exit_flag = 0,i,j,r;
+  unsigned char exit_flag = 0,i,j,r,aa,layer;
+  int re;
   unsigned char bw_scaling =1;
+  uint8_t nb_antennas_tx = frame_parms->nb_antennas_tx;
 
   switch (N_RB_DL) {
   case 6:
@@ -145,6 +147,23 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_
     dlsch->Mlimit = 4;
     dlsch->Nsoft = Nsoft;
 
+    for (layer=0; layer<4; layer++) {
+      dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
+  
+       for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+         dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
+         for (re=0;re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
+           dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
+         }
+       }
+     }
+
+     dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
+     for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+       dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
+       
+     }
+
     for (i=0; i<10; i++)
       dlsch->harq_ids[i] = Mdlharq;
 
@@ -189,7 +208,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_
         exit_flag=3;
       }
     }
-
+    
     if (exit_flag==0) {
       for (i=0; i<Mdlharq; i++) {
         dlsch->harq_processes[i]->round=0;
@@ -379,7 +398,7 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
 
   A = dlsch->harq_processes[harq_pid]->TBS; //6228
   mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs);
-  G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe);
+  G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,dlsch->harq_processes[harq_pid]->mimo_mode==TM7?7:0);
 
 
   if (dlsch->harq_processes[harq_pid]->round == 0) {  // this is a new packet
@@ -557,6 +576,7 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
   unsigned char mod_order;
   unsigned int Kr=0,Kr_bytes,r,r_offset=0;
   unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
+  uint8_t beamforming_mode=0;
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
 
@@ -564,7 +584,13 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
   // printf("Encoder: A: %d\n",A);
   mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs);
 
-  G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe);
+  if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7)
+    beamforming_mode = 7;
+  else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8)
+    beamforming_mode = 8;
+  else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10)
+    beamforming_mode = 9;
+  G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode);
 
 
   //  if (dlsch->harq_processes[harq_pid]->Ndi == 1) {  // this is a new packet
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
index f4ab4c092442e30983641d397f5d7b520912b166..4a80110b22fbd86bbdbeb23d49fab26c3747347a 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
@@ -249,7 +249,12 @@ uint32_t  dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
     tc = phy_threegpplte_turbo_decoder16;
   }
   else
-    tc = phy_threegpplte_turbo_decoder8;
+  {
+	  AssertFatal (harq_process->TBS >= 256 , "Mismatch flag nbRB=%d TBS=%d mcs=%d Qm=%d RIV=%d round=%d \n",
+			  harq_process->nb_rb, harq_process->TBS,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
+	    tc = phy_threegpplte_turbo_decoder8;
+  }
+
 
   //  nb_rb = dlsch->nb_rb;
 
@@ -448,6 +453,11 @@ uint32_t  dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
 #if 1
     if (err_flag == 0) {
 
+    	if (llr8_flag) {
+    		AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n",
+    				Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round);
+    	}
+
       start_meas(dlsch_turbo_decoding_stats);
       ret = tc
             (&harq_process->d[r][96],
@@ -609,7 +619,11 @@ uint32_t  dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
     harq_process->errors[harq_process->round]++;
     harq_process->round++;
 
-    //    LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round);
+
+    if(is_crnti)
+    {
+    LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round,harq_process->TBS);
+    }
     //    printf("Rate: [UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round);
     if (harq_process->round >= dlsch->Mdlharq) {
       harq_process->status = SCH_IDLE;
@@ -622,7 +636,10 @@ uint32_t  dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
     dlsch->harq_ack[subframe].ack = 1;
     dlsch->harq_ack[subframe].harq_id = harq_pid;
     dlsch->harq_ack[subframe].send_harq_status = 1;
-    LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round);
+    if(is_crnti)
+    {
+    LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for subframe %d (pid %d, round %d, TBS %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round,harq_process->TBS);
+    }
 
   }
 
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
index 036eb86b24c4a3bbcba645896ccd611b998ec021..33d798576871a02d75ee81e59e8c4cbe09f7e7b9 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_demodulation.c
@@ -21,7 +21,7 @@
 
 /*! \file PHY/LTE_TRANSPORT/dlsch_demodulation.c
  * \brief Top-level routines for demodulating the PDSCH physical channel from 36-211, V8.6 2009-03
- * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert
+ * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, X. Xiang
  * \date 2011
  * \version 0.1
  * \company Eurecom
@@ -89,9 +89,11 @@ int rx_pdsch(PHY_VARS_UE *ue,
   LTE_UE_DLSCH_t   **dlsch;
 
   unsigned char aatx,aarx;
-  unsigned short nb_rb;
+  unsigned short nb_rb=0;
   int avgs, rb;
   LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_harq = 0;
+  
+  uint8_t beamforming_mode;
   uint32_t *rballoc;
 
   switch (type) {
@@ -99,12 +101,14 @@ int rx_pdsch(PHY_VARS_UE *ue,
     pdsch_vars = &ue->pdsch_vars_SI[eNB_id];
     dlsch          = &ue->dlsch_SI[eNB_id];
     dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
+    beamforming_mode  = 0;
     break;
 
   case RA_PDSCH:
     pdsch_vars = &ue->pdsch_vars_ra[eNB_id];
     dlsch          = &ue->dlsch_ra[eNB_id];
     dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
+    beamforming_mode  = 0;
     break;
 
   case PDSCH:
@@ -112,6 +116,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
     dlsch          = ue->dlsch[eNB_id];
     dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
     dlsch1_harq       = dlsch[1]->harq_processes[harq_pid];
+    beamforming_mode  = ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id];
     break;
 
   default:
@@ -153,7 +158,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
   else
     rballoc = dlsch0_harq->rb_alloc_even;
 
-  if (frame_parms->nb_antennas_tx_eNB>1) {
+  if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) {
 #ifdef DEBUG_DLSCH_MOD
     LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch[0],dlsch0_harq->rb_alloc_even[0]);
 #endif
@@ -195,8 +200,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
                                        ue->high_speed_flag,
                                        frame_parms);
     }
-  } // if n_tx>1
-  else {
+  } else if (beamforming_mode==0) { //else if nb_antennas_ports_eNB==1 && beamforming_mode == 0
     nb_rb = dlsch_extract_rbs_single(common_vars->rxdataF,
                                      common_vars->dl_ch_estimates[eNB_id],
                                      pdsch_vars[eNB_id]->rxdataF_ext,
@@ -235,7 +239,20 @@ int rx_pdsch(PHY_VARS_UE *ue,
 					 ue->high_speed_flag,
                                          frame_parms);
     }
-  } //else n_tx>1
+  } else if (beamforming_mode==7) { //else if beamforming_mode == 7
+    nb_rb = dlsch_extract_rbs_TM7(common_vars->rxdataF,
+                                  pdsch_vars[eNB_id]->dl_bf_ch_estimates,
+                                  pdsch_vars[eNB_id]->rxdataF_ext,
+                                  pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
+				  rballoc,
+                                  symbol,
+                                  subframe,
+                                  ue->high_speed_flag,
+                                  frame_parms);
+    
+  } else if(beamforming_mode>7) {
+    LOG_W(PHY,"dlsch_demodulation:beamforming mode not supported yet.\n");
+  }
 
   //  printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id);
   if (nb_rb==0) {
@@ -252,11 +269,19 @@ int rx_pdsch(PHY_VARS_UE *ue,
   nb_rb);
   */
   if (first_symbol_flag==1) {
-    dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
-                        frame_parms,
-                        avg,
-                        symbol,
-                        nb_rb);
+    if (beamforming_mode==0)
+       dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
+                           frame_parms,
+                           avg,
+                           symbol,
+                           nb_rb);
+    else if (beamforming_mode==7)
+       dlsch_channel_level_TM7(pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
+                           frame_parms,
+                           avg,
+                           symbol,
+                           nb_rb);
+       
 #ifdef DEBUG_PHY
     LOG_D(PHY,"[DLSCH] avg[0] %d\n",avg[0]);
 #endif
@@ -266,7 +291,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
     // in case of precoding we add an additional factor of two for the precoding gain
     avgs = 0;
 
-    for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++)
+    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
       for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
         avgs = cmax(avgs,avg[(aatx<<1)+aarx]);
 
@@ -274,7 +299,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
 
 
     pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1;
-    // + log2_approx(frame_parms->nb_antennas_tx_eNB-1) //-1 because log2_approx counts the number of bits
+    // + log2_approx(frame_parms->nb_antenna_ports_eNB-1) //-1 because log2_approx counts the number of bits
     //      + log2_approx(frame_parms->nb_antennas_rx-1);
 
     if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
@@ -287,11 +312,11 @@ int rx_pdsch(PHY_VARS_UE *ue,
        Nb_tx*Nb_rx   in TM2,4,5
        Nb_tx^2*Nb_rx in TM6 */
     /*
-      K = frame_parms->nb_antennas_rx*frame_parms->nb_antennas_tx_eNB; //that also covers TM1 since Nb_tx=1
+      K = frame_parms->nb_antennas_rx*frame_parms->nb_antenna_ports_eNB; //that also covers TM1 since Nb_tx=1
       if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
       (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) &&
       (dlsch0_harq->dl_power_off==1)) // we are in TM 6
-      K *= frame_parms->nb_antennas_tx_eNB;
+      K *= frame_parms->nb_antenna_ports_eNB;
 
       pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2);
     */
@@ -302,7 +327,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
 #endif
   }
 
-  aatx = frame_parms->nb_antennas_tx_eNB;
+  aatx = frame_parms->nb_antenna_ports_eNB;
   aarx = frame_parms->nb_antennas_rx;
 
   if (dlsch0_harq->mimo_mode<LARGE_CDD) {// SISO or ALAMOUTI
@@ -363,7 +388,7 @@ int rx_pdsch(PHY_VARS_UE *ue,
     }
   } else if (dlsch0_harq->mimo_mode == LARGE_CDD) { // TM3
     //   LOG_I(PHY,"Running PDSCH RX for TM3\n");
-    if (frame_parms->nb_antennas_tx_eNB == 2) {
+    if (frame_parms->nb_antenna_ports_eNB == 2) {
       if (first_symbol_flag==1) {
         // effective channel of desired user is always stronger than interfering eff. channel
         dlsch_channel_level_TM3(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
@@ -522,12 +547,28 @@ int rx_pdsch(PHY_VARS_UE *ue,
                                       pdsch_vars[eNB_id]->log2_maxh,
                                       1);
     }
+  } else if (dlsch0_harq->mimo_mode==TM7) { //TM7
+
+    dlsch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext,
+                               pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
+                               pdsch_vars[eNB_id]->dl_ch_mag0,
+                               pdsch_vars[eNB_id]->dl_ch_magb0,
+                               pdsch_vars[eNB_id]->rxdataF_comp0,
+                               (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL,
+                               frame_parms,
+                               symbol,
+                               first_symbol_flag,
+                               get_Qm(dlsch0_harq->mcs),
+                               nb_rb,
+                               //9,
+                               pdsch_vars[eNB_id]->log2_maxh,
+                               phy_measurements); // log2_maxh+I0_shift
   }
 
   //  printf("MRC\n");
   if (frame_parms->nb_antennas_rx > 1) {
     if (dlsch0_harq->mimo_mode == LARGE_CDD) {
-      if (frame_parms->nb_antennas_tx_eNB == 2) {
+      if (frame_parms->nb_antenna_ports_eNB == 2) {
         dlsch_detection_mrc(frame_parms,
                             pdsch_vars[eNB_id]->rxdataF_comp0,
                             pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round],
@@ -561,8 +602,8 @@ int rx_pdsch(PHY_VARS_UE *ue,
   //  printf("Combining");
   if ((dlsch0_harq->mimo_mode == SISO) ||
       ((dlsch0_harq->mimo_mode >= UNIFORM_PRECODING11) &&
-       (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0))) {
-
+       (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0)) ||
+       (dlsch0_harq->mimo_mode == TM7)) {
     /*
       dlsch_siso(frame_parms,
       pdsch_vars[eNB_id]->rxdataF_comp,
@@ -599,7 +640,8 @@ int rx_pdsch(PHY_VARS_UE *ue,
                        pdsch_vars[eNB_id]->llr[0],
                        symbol,first_symbol_flag,nb_rb,
                        adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
-                       pdsch_vars[eNB_id]->llr128);
+                       pdsch_vars[eNB_id]->llr128,
+                       beamforming_mode);
       else if (i_mod == 2) {
         dlsch_qpsk_qpsk_llr(frame_parms,
                             pdsch_vars[eNB_id]->rxdataF_comp0,
@@ -692,7 +734,8 @@ int rx_pdsch(PHY_VARS_UE *ue,
                       pdsch_vars[eNB_id]->dl_ch_mag0,
                       symbol,first_symbol_flag,nb_rb,
                       adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol),
-                      pdsch_vars[eNB_id]->llr128);
+                      pdsch_vars[eNB_id]->llr128,
+                      beamforming_mode);
     } else if (i_mod == 2) {
       dlsch_16qam_qpsk_llr(frame_parms,
                            pdsch_vars[eNB_id]->rxdataF_comp0,
@@ -738,7 +781,8 @@ int rx_pdsch(PHY_VARS_UE *ue,
                       pdsch_vars[eNB_id]->dl_ch_magb0,
                       symbol,first_symbol_flag,nb_rb,
                       adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol),
-                      pdsch_vars[eNB_id]->llr128);
+                      pdsch_vars[eNB_id]->llr128,
+                      beamforming_mode);
     } else if (i_mod == 2) {
       dlsch_64qam_qpsk_llr(frame_parms,
                            pdsch_vars[eNB_id]->rxdataF_comp0,
@@ -781,7 +825,6 @@ int rx_pdsch(PHY_VARS_UE *ue,
     return(-1);
     break;
   }
-
   return(0);
 }
 
@@ -821,7 +864,7 @@ void dlsch_channel_compensation(int **rxdataF_ext,
       pilots=1;
   }
 
-  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
+  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
     if (mod_order == 4) {
       QAM_amp128 = _mm_set1_epi16(QAM16_n1);  // 2/sqrt(10)
       QAM_amp128b = _mm_setzero_si128();
@@ -1081,7 +1124,7 @@ void dlsch_channel_compensation(int **rxdataF_ext,
     }
   }
 
-  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
+  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
     if (mod_order == 4) {
       QAM_amp128  = vmovq_n_s16(QAM16_n1);  // 2/sqrt(10)
       QAM_amp128b = vmovq_n_s16(0);
@@ -2594,7 +2637,7 @@ void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
 
   if (frame_parms->nb_antennas_rx>1) {
 
-    for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
+    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
 
       rxdataF_comp128_0   = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12];
       rxdataF_comp128_1   = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12];
@@ -2654,7 +2697,7 @@ void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
 
   if (frame_parms->nb_antennas_rx>1) {
 
-    for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
+    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
 
       rxdataF_comp128_0   = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12];
       rxdataF_comp128_1   = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12];
@@ -2736,7 +2779,7 @@ void dlsch_scale_channel(int **dl_ch_estimates_ext,
 
   ch_amp128 = _mm_set1_epi16(ch_amp); // Q3.13
 
-  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
+  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
 
       dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12];
@@ -2780,7 +2823,7 @@ void dlsch_channel_level(int **dl_ch_estimates_ext,
 
   symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
 
-  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++)
+  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
       //clear average level
       avg128D = _mm_setzero_si128();
@@ -2837,7 +2880,7 @@ void dlsch_channel_level(int **dl_ch_estimates_ext,
 
   symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
 
-  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++)
+  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
       //clear average level
       avg128D = vdupq_n_s32(0);
@@ -3054,6 +3097,76 @@ void dlsch_channel_level_TM56(int **dl_ch_estimates_ext,
 #endif
 }
 
+//compute average channel_level for TM7
+void dlsch_channel_level_TM7(int **dl_bf_ch_estimates_ext,
+                         LTE_DL_FRAME_PARMS *frame_parms,
+                         int *avg,
+                         uint8_t symbol,
+                         unsigned short nb_rb)
+{
+
+#if defined(__x86_64__)||defined(__i386__)
+
+  short rb;
+  unsigned char aatx,aarx,nre=12,symbol_mod;
+  __m128i *dl_ch128,avg128D;
+
+  symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
+
+  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
+    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+      //clear average level
+      avg128D = _mm_setzero_si128();
+      // 5 is always a symbol with no pilots for both normal and extended prefix
+
+      dl_ch128=(__m128i *)&dl_bf_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12];
+
+      for (rb=0; rb<nb_rb; rb++) {
+        //  printf("rb %d : ",rb);
+        //  print_shorts("ch",&dl_ch128[0]);
+        avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
+        avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[1],dl_ch128[1]));
+
+        if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) {
+          dl_ch128+=2;
+        } else {
+          avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
+          dl_ch128+=3;
+        }
+
+        /*
+          if (rb==0) {
+          print_shorts("dl_ch128",&dl_ch128[0]);
+          print_shorts("dl_ch128",&dl_ch128[1]);
+          print_shorts("dl_ch128",&dl_ch128[2]);
+          }
+        */
+      }
+
+      if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1))))
+        nre=10;
+      else if ((frame_parms->Ncp==0) && (symbol==3 || symbol==6 || symbol==9 || symbol==12))
+        nre=9;
+      else if ((frame_parms->Ncp==1) && (symbol==4 || symbol==7 || symbol==9))
+        nre=8;
+      else
+        nre=12;
+
+      avg[(aatx<<1)+aarx] = (((int*)&avg128D)[0] +
+                             ((int*)&avg128D)[1] +
+                             ((int*)&avg128D)[2] +
+                             ((int*)&avg128D)[3])/(nb_rb*nre);
+
+      //            printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
+    }
+
+  _mm_empty();
+  _m_empty();
+
+#elif defined(__arm__)
+
+#endif
+}
 
 void dlsch_alamouti(LTE_DL_FRAME_PARMS *frame_parms,
                     int **rxdataF_comp,
@@ -4183,50 +4296,907 @@ unsigned short dlsch_extract_rbs_dual(int **rxdataF,
   return(nb_rb/frame_parms->nb_antennas_rx);
 }
 
-//==============================================================================================
-// Auxiliary functions
-//==============================================================================================
+unsigned short dlsch_extract_rbs_TM7(int **rxdataF,
+                                     int **dl_bf_ch_estimates,
+                                     int **rxdataF_ext,
+                                     int **dl_bf_ch_estimates_ext,
+                                     unsigned int *rb_alloc,
+                                     unsigned char symbol,
+                                     unsigned char subframe,
+                                     uint32_t high_speed_flag,
+                                     LTE_DL_FRAME_PARMS *frame_parms)
+{
 
-#ifdef USER_MODE
+  unsigned short rb,nb_rb=0;
+  unsigned char rb_alloc_ind;
+  unsigned char i,aarx,l,nsymb,skip_half=0,sss_symb,pss_symb=0;
+  int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
 
-void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int round)
-{
+  unsigned char symbol_mod,pilots=0,uespec_pilots=0,j=0,poffset=0,uespec_poffset=0;
+  int8_t uespec_nushift = frame_parms->Nid_cell%3;
 
-  unsigned int nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12;
-  char fname[32],vname[32];
-  int N_RB_DL=ue->frame_parms.N_RB_DL;
+  symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
+  pilots = ((symbol_mod==0)||(symbol_mod==(4-frame_parms->Ncp))) ? 1 : 0;
+  l=symbol;
+  nsymb = (frame_parms->Ncp==NORMAL) ? 14:12;
 
-  sprintf(fname,"dlsch%d_rxF_r%d_ext0.m",eNB_id,round);
-  sprintf(vname,"dl%d_rxF_r%d_ext0",eNB_id,round);
-  write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb,1,1);
+  if (frame_parms->Ncp==0){
+    if (symbol==3 || symbol==6 || symbol==9 || symbol==12)
+      uespec_pilots = 1;
+  } else{
+    if (symbol==4 || symbol==7 || symbol==10)
+      uespec_pilots = 1;
+  }
 
-  if (ue->frame_parms.nb_antennas_rx >1) {
-    sprintf(fname,"dlsch%d_rxF_r%d_ext1.m",eNB_id,round);
-    sprintf(vname,"dl%d_rxF_r%d_ext1",eNB_id,round);
-    write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_ext[1],12*N_RB_DL*nsymb,1,1);
+  if (frame_parms->frame_type == TDD) {// TDD
+    sss_symb = nsymb-1;
+    pss_symb = 2;
+  } else {
+    sss_symb = (nsymb>>1)-2;
+    pss_symb = (nsymb>>1)-1;
   }
 
-  sprintf(fname,"dlsch%d_ch_r%d_ext00.m",eNB_id,round);
-  sprintf(vname,"dl%d_ch_r%d_ext00",eNB_id,round);
-  write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1);
+  if (symbol_mod==(4-frame_parms->Ncp))
+    poffset=3;
 
-  if (ue->frame_parms.nb_antennas_rx == 2) {
-    sprintf(fname,"dlsch%d_ch_r%d_ext01.m",eNB_id,round);
-    sprintf(vname,"dl%d_ch_r%d_ext01",eNB_id,round);
-    write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1);
-  }
+  if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7))
+    uespec_poffset=2;
 
-  if (ue->frame_parms.nb_antennas_tx_eNB == 2) {
-    sprintf(fname,"dlsch%d_ch_r%d_ext10.m",eNB_id,round);
-    sprintf(vname,"dl%d_ch_r%d_ext10",eNB_id,round);
-    write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1);
+  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
 
-    if (ue->frame_parms.nb_antennas_rx == 2) {
-      sprintf(fname,"dlsch%d_ch_r%d_ext11.m",eNB_id,round);
-      sprintf(vname,"dl%d_ch_r%d_ext11",eNB_id,round);
-      write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1);
-    }
-  }
+    if (high_speed_flag == 1)
+      dl_ch0     = &dl_bf_ch_estimates[aarx][symbol*(frame_parms->ofdm_symbol_size)];
+    else
+      dl_ch0     = &dl_bf_ch_estimates[aarx][0];
+
+    dl_ch0_ext = &dl_bf_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)];
+
+    rxF_ext    = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)];
+    rxF        = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))];
+
+    if ((frame_parms->N_RB_DL&1) == 0)  // even number of RBs
+      for (rb=0; rb<frame_parms->N_RB_DL; rb++) {
+
+        if (rb < 32)
+          rb_alloc_ind = (rb_alloc[0]>>rb) & 1;
+        else if (rb < 64)
+          rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1;
+        else if (rb < 96)
+          rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1;
+        else if (rb < 100)
+          rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1;
+        else
+          rb_alloc_ind = 0;
+
+	if (rb_alloc_ind == 1)
+          nb_rb++;
+
+        // For second half of RBs skip DC carrier
+        if (rb==(frame_parms->N_RB_DL>>1)) {
+          rxF       = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))];
+          //dl_ch0++;
+        }
+        
+        // PBCH
+        if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) {
+          rb_alloc_ind = 0;
+        }
+
+        //SSS
+        if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+          rb_alloc_ind = 0;
+        }
+
+
+        if (frame_parms->frame_type == FDD) {
+          //PSS
+          if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+        }
+
+        if ((frame_parms->frame_type == TDD) &&
+            (subframe==6)) { //TDD Subframe 6
+          if ((rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+        }
+
+        if (rb_alloc_ind==1) {
+
+          /*
+              printf("rb %d\n",rb);
+              for (i=0;i<12;i++)
+              printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]);
+              printf("\n");
+          */
+          if (pilots==0 && uespec_pilots==0) {
+            memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int));
+
+            for (i=0; i<12; i++) {
+              rxF_ext[i]=rxF[i];
+            }
+
+            dl_ch0_ext+=12;
+            rxF_ext+=12;
+          } else if(pilots==1 && uespec_pilots==0) {
+            j=0;
+
+            for (i=0; i<12; i++) {
+              if ((i!=(frame_parms->nushift+poffset)) &&
+                  (i!=((frame_parms->nushift+poffset+6)%12))) {
+                rxF_ext[j]=rxF[i];
+                dl_ch0_ext[j++]=dl_ch0[i];
+              }
+            }
+
+            dl_ch0_ext+=10;
+            rxF_ext+=10;
+
+          } else if (pilots==0 && uespec_pilots==1) {
+            j=0;
+
+
+	    for (i=0; i<12; i++){
+              if (frame_parms->Ncp==0){
+                if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){                
+		  rxF_ext[j] = rxF[i];
+                  dl_ch0_ext[j++]=dl_ch0[i];  
+                }
+              } else{
+                if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){                
+		  rxF_ext[j] = rxF[i];
+                  dl_ch0_ext[j++]=dl_ch0[i];
+                }  
+              }
+  
+	    }
+             
+            dl_ch0_ext+=9-frame_parms->Ncp;
+            rxF_ext+=9-frame_parms->Ncp; 
+
+          } else {
+            msg("dlsch_extract_rbs_TM7(dl_demodulation.c):pilot or ue spec pilot detection error\n");
+            exit(-1);
+          }
+
+        }
+
+        dl_ch0+=12;
+        rxF+=12;
+
+      }
+    else {  // Odd number of RBs
+      for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) {
+        skip_half=0;
+
+        if (rb < 32)
+          rb_alloc_ind = (rb_alloc[0]>>rb) & 1;
+        else if (rb < 64)
+          rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1;
+        else if (rb < 96)
+          rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1;
+        else if (rb < 100)
+          rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1;
+        else
+          rb_alloc_ind = 0;
+
+        if (rb_alloc_ind == 1)
+          nb_rb++;
+
+        // PBCH
+        if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) {
+          rb_alloc_ind = 0;
+        }
+
+        //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3
+        if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+          skip_half=1;
+        else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+          skip_half=2;
+
+        //SSS
+
+        if (((subframe==0)||(subframe==5)) &&
+            (rb>((frame_parms->N_RB_DL>>1)-3)) &&
+            (rb<((frame_parms->N_RB_DL>>1)+3)) &&
+            (l==sss_symb) ) {
+          rb_alloc_ind = 0;
+        }
+
+        //SSS
+        if (((subframe==0)||(subframe==5)) &&
+            (rb==((frame_parms->N_RB_DL>>1)-3)) &&
+            (l==sss_symb))
+          skip_half=1;
+        else if (((subframe==0)||(subframe==5)) &&
+                 (rb==((frame_parms->N_RB_DL>>1)+3)) &&
+                 (l==sss_symb))
+          skip_half=2;
+
+        //PSS in subframe 0/5 if FDD
+        if (frame_parms->frame_type == FDD) {  //FDD
+          if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+
+          if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+            skip_half=1;
+          else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+            skip_half=2;
+        }
+
+        if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6
+          if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+
+          if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+            skip_half=1;
+          else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+            skip_half=2;
+        }
+
+
+        if (rb_alloc_ind==1) {
+#ifdef DEBUG_DLSCH_DEMOD
+          printf("rb %d/symbol %d pilots %d, uespec_pilots %d, (skip_half %d)\n",rb,l,pilots,uespec_pilots,skip_half);
+#endif
+
+          if (pilots==0 && uespec_pilots==0) {
+            //printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+
+            if (skip_half==1) {
+              memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int));
+
+              for (i=0; i<6; i++) {
+                rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+		printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+              }
+
+              dl_ch0_ext+=6;
+              rxF_ext+=6;
+            } else if (skip_half==2) {
+              memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int));
+
+              for (i=0; i<6; i++) {
+                rxF_ext[i]=rxF[(i+6)];
+#ifdef DEBUG_DLSCH_DEMOD
+		printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+              }
+
+              dl_ch0_ext+=6;
+              rxF_ext+=6;
+            } else {
+              memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int));
+
+              for (i=0; i<12; i++){
+                rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+                printf("extract rb %d, re %d => (%d,%d)\n",symbol,rb,i,*(short *)&rxF[i],*(1+(short*)&rxF[i]));
+#endif
+              }
+              dl_ch0_ext+=12;
+              rxF_ext+=12;
+            }
+          } else if (pilots==1 && uespec_pilots==0) {
+            // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+            j=0;
+
+            if (skip_half==1) {
+              for (i=0; i<6; i++) {
+                if (i!=((frame_parms->nushift+poffset)%6)) {
+                  rxF_ext[j]=rxF[i];
+                  dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+		printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                }
+              }
+
+              dl_ch0_ext+=5;
+              rxF_ext+=5;
+            } else if (skip_half==2) {
+              for (i=0; i<6; i++) {
+                if (i!=((frame_parms->nushift+poffset)%6)) {
+                  rxF_ext[j]=rxF[(i+6)];
+                  dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+		printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                }
+              }
+
+              dl_ch0_ext+=5;
+              rxF_ext+=5;
+            } else {
+              for (i=0; i<12; i++) {
+                if ((i!=(frame_parms->nushift+poffset)) &&
+                    (i!=((frame_parms->nushift+poffset+6)%12))) {
+                  rxF_ext[j]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+                  printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j]));
+#endif
+                  dl_ch0_ext[j++]=dl_ch0[i];
+
+                }
+              }
+
+              dl_ch0_ext+=10;
+              rxF_ext+=10;
+            }
+          } else if(pilots==0 && uespec_pilots==1){
+            //printf("Extracting with uespec pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+            j=0;
+
+            if (skip_half==1) {
+              if (frame_parms->Ncp==0){
+                for (i=0; i<6; i++) {
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+                    rxF_ext[j]=rxF[i];
+                    dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+       		    printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                }
+                dl_ch0_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6);
+                rxF_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6);
+
+              } else{
+                for (i=0; i<6; i++) {
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){                
+                    rxF_ext[j]=rxF[i];
+                    dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+		    printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                }
+                dl_ch0_ext+=4;
+                rxF_ext+=4;
+              }
+
+            } else if (skip_half==2) {
+              if(frame_parms->Ncp==0){
+                for (i=0; i<6; i++) {
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+                    rxF_ext[j]=rxF[(i+6)];
+                    dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+        	    printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                }
+                dl_ch0_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6);
+                rxF_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6);
+
+              } else {
+                for (i=0; i<6; i++) {
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){                
+                    rxF_ext[j]=rxF[(i+6)];
+                    dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+		    printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                }
+                dl_ch0_ext+=4;
+                rxF_ext+=4;
+              }
+
+            } else {
+
+	      for (i=0; i<12; i++){
+                if (frame_parms->Ncp==0){
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+	            rxF_ext[j] = rxF[i];
+                    dl_ch0_ext[j++] = dl_ch0[i];  
+#ifdef DEBUG_DLSCH_DEMOD
+                    printf("extract rb %d, re %d, j %d => (%d,%d)\n",symbol,rb,i,j-1,*(short *)&dl_ch0[j],*(1+(short*)&dl_ch0[i]));
+#endif
+                  }
+                } else{
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){                
+	            rxF_ext[j] = rxF[i];
+                    dl_ch0_ext[j++]=dl_ch0[i]; 
+#ifdef DEBUG_DLSCH_DEMOD
+		    printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  } 
+                }
+  
+	      }
+               
+              dl_ch0_ext+=9-frame_parms->Ncp;
+              rxF_ext+=9-frame_parms->Ncp; 
+	    }
+ 
+          } else {
+            msg("dlsch_extract_rbs_TM7(dl_demodulation.c):pilot or ue spec pilot detection error\n");
+            exit(-1);
+            
+          }
+        }
+
+        dl_ch0+=12;
+        rxF+=12;
+      } // first half loop
+
+
+      // Do middle RB (around DC)
+      if (rb < 32)
+        rb_alloc_ind = (rb_alloc[0]>>rb) & 1;
+      else if (rb < 64)
+        rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1;
+      else if (rb < 96)
+        rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1;
+      else if (rb < 100)
+        rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1;
+      else
+        rb_alloc_ind = 0;
+
+      if (rb_alloc_ind == 1)
+        nb_rb++;
+
+      // PBCH
+      if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) {
+        rb_alloc_ind = 0;
+      }
+
+      //SSS
+      if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+        rb_alloc_ind = 0;
+      }
+
+      if (frame_parms->frame_type == FDD) {
+        //PSS
+        if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+          rb_alloc_ind = 0;
+        }
+      }
+
+      if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) {
+        //PSS
+        if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+          rb_alloc_ind = 0;
+        }
+      }
+
+      //printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]);
+      //printf("DC rb %d (%p)\n",rb,rxF);
+      if (rb_alloc_ind==1) {
+        //printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half);
+        if (pilots==0 && uespec_pilots==0) {
+          for (i=0; i<6; i++) {
+            dl_ch0_ext[i]=dl_ch0[i];
+            rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+	    printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+          }
+
+          rxF       = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];
+
+          for (; i<12; i++) {
+            dl_ch0_ext[i]=dl_ch0[i];
+            rxF_ext[i]=rxF[(1+i-6)];
+#ifdef DEBUG_DLSCH_DEMOD
+	    printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+          }
+
+          dl_ch0_ext+=12;
+          rxF_ext+=12;
+        } else if(pilots==1 && uespec_pilots==0){ // pilots==1
+          j=0;
+
+          for (i=0; i<6; i++) {
+            if (i!=((frame_parms->nushift+poffset)%6)) {
+              dl_ch0_ext[j]=dl_ch0[i];
+              rxF_ext[j++]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+	      printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+            }
+          }
+
+          rxF       = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];
+
+          for (; i<12; i++) {
+            if (i!=((frame_parms->nushift+6+poffset)%12)) {
+              dl_ch0_ext[j]=dl_ch0[i];
+              rxF_ext[j++]=rxF[(1+i-6)];
+#ifdef DEBUG_DLSCH_DEMOD
+	      printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+            }
+          }
+
+          dl_ch0_ext+=10;
+          rxF_ext+=10;
+        } else if(pilots==0 && uespec_pilots==1) {
+          j=0;
+
+	  for (i=0; i<6; i++) {
+            if (frame_parms->Ncp==0){
+              if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){                
+                dl_ch0_ext[j]=dl_ch0[i];  
+	        rxF_ext[j++] = rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+	        printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+              }
+            } else {
+              if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+                dl_ch0_ext[j]=dl_ch0[i];  
+	        rxF_ext[j++] = rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+    	        printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+              }
+            }
+	  }
+          
+          rxF       = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];
+
+          for (; i<12; i++) {
+            if (frame_parms->Ncp==0){
+              if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){                
+                dl_ch0_ext[j]=dl_ch0[i];
+                rxF_ext[j++]=rxF[(1+i-6)];
+#ifdef DEBUG_DLSCH_DEMOD
+	        printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+              }
+            } else {
+              if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){
+                dl_ch0_ext[j]=dl_ch0[i];  
+	        rxF_ext[j++] = rxF[(1+i-6)];
+#ifdef DEBUG_DLSCH_DEMOD
+	        printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+              }
+            }
+          }
+           
+          dl_ch0_ext+=9-frame_parms->Ncp;
+          rxF_ext+=9-frame_parms->Ncp; 
+          	  
+	}// symbol_mod==0
+
+      } // rballoc==1
+      else {
+        rxF       = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];
+      }
+
+      dl_ch0+=12;
+      rxF+=7;
+      rb++;
+
+      for (; rb<frame_parms->N_RB_DL; rb++) {
+        //  printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]);
+        //  printf("rb %d (%p)\n",rb,rxF);
+        skip_half=0;
+
+        if (rb < 32)
+          rb_alloc_ind = (rb_alloc[0]>>rb) & 1;
+        else if (rb < 64)
+          rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1;
+        else if (rb < 96)
+          rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1;
+        else if (rb < 100)
+          rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1;
+        else
+          rb_alloc_ind = 0;
+
+        if (rb_alloc_ind==1)
+          nb_rb++;
+
+        // PBCH
+        if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) {
+          rb_alloc_ind = 0;
+        }
+
+        //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3
+        if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+          skip_half=1;
+        else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
+          skip_half=2;
+
+        //SSS
+        if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) {
+          rb_alloc_ind = 0;
+        }
+
+        //SSS
+        if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb))
+          skip_half=1;
+        else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb))
+          skip_half=2;
+
+        //PSS
+        if (frame_parms->frame_type == FDD) {
+          if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+
+          if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+            skip_half=1;
+          else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+            skip_half=2;
+        }
+
+        if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6
+          if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) {
+            rb_alloc_ind = 0;
+          }
+
+          if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb))
+            skip_half=1;
+          else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb))
+            skip_half=2;
+        }
+
+        if (rb_alloc_ind==1) {
+#ifdef DEBUG_DLSCH_DEMOD
+           printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half);
+#endif
+          /*
+              printf("rb %d\n",rb);
+            for (i=0;i<12;i++)
+            printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]);
+            printf("\n");
+          */
+          if (pilots==0 && uespec_pilots==0) {
+            //printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+            if (skip_half==1) {
+              memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int));
+
+              for (i=0; i<6; i++) {
+                rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+	        printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+              }
+
+              dl_ch0_ext+=6;
+              rxF_ext+=6;
+
+            } else if (skip_half==2) {
+              memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int));
+
+              for (i=0; i<6; i++) {
+                rxF_ext[i]=rxF[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+	        printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+              }
+
+              dl_ch0_ext+=6;
+              rxF_ext+=6;
+
+            } else {
+              memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int));
+              //printf("symbol %d, extract rb %d, => (%d,%d)\n",symbol,rb,*(short *)&dl_ch0[j],*(1+(short*)&dl_ch0[i]));
+
+              for (i=0; i<12; i++) {
+                rxF_ext[i]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+	        printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+              }
+
+              dl_ch0_ext+=12;
+              rxF_ext+=12;
+            }
+          } else if (pilots==1 && uespec_pilots==0){
+            //printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half);
+            j=0;
+
+            if (skip_half==1) {
+              for (i=0; i<6; i++) {
+                if (i!=((frame_parms->nushift+poffset)%6)) {
+                  rxF_ext[j]=rxF[i];
+                  dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+	          printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                }
+              }
+
+              dl_ch0_ext+=5;
+              rxF_ext+=5;
+            } else if (skip_half==2) {
+              for (i=0; i<6; i++) {
+                if (i!=((frame_parms->nushift+poffset)%6)) {
+                  rxF_ext[j]=rxF[(i+6)];
+                  dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+	          printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                }
+              }
+
+              dl_ch0_ext+=5;
+              rxF_ext+=5;
+            } else {
+              for (i=0; i<12; i++) {
+                if ((i!=(frame_parms->nushift+poffset)) &&
+                    (i!=((frame_parms->nushift+poffset+6)%12))) {
+                  rxF_ext[j]=rxF[i];
+#ifdef DEBUG_DLSCH_DEMOD
+                  printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j]));
+#endif
+                  dl_ch0_ext[j++]=dl_ch0[i];
+                }
+              }
+
+              dl_ch0_ext+=10;
+              rxF_ext+=10;
+            }
+          } else if(pilots==0 && uespec_pilots==1) {
+            j=0;
+
+            if (skip_half==1) {
+              if (frame_parms->Ncp==0){
+                for (i=0; i<6; i++) {
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+                    rxF_ext[j]=rxF[i];
+                    dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+	            printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                }
+                dl_ch0_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6);
+                rxF_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6);
+
+              } else{
+                for (i=0; i<6; i++) {
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){                
+                    rxF_ext[j]=rxF[i];
+                    dl_ch0_ext[j++]=dl_ch0[i];
+#ifdef DEBUG_DLSCH_DEMOD
+	            printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                }
+                dl_ch0_ext+=4;
+                rxF_ext+=4;
+              }
+
+            } else if (skip_half==2) {
+              if(frame_parms->Ncp==0){
+                for (i=0; i<6; i++) {
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+                    rxF_ext[j]=rxF[i+6];
+                    dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+	            printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                }
+                dl_ch0_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6);
+                rxF_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6);
+
+              } else {
+                for (i=0; i<6; i++) {
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){                
+                    rxF_ext[j]=rxF[(i+6)];
+                    dl_ch0_ext[j++]=dl_ch0[i+6];
+#ifdef DEBUG_DLSCH_DEMOD
+	            printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                }
+                dl_ch0_ext+=4;
+                rxF_ext+=4;
+              }
+
+            } else {
+	      for (i=0; i<12; i++){
+                if (frame_parms->Ncp==0){
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){
+	            rxF_ext[j] = rxF[i];
+                    dl_ch0_ext[j++]=dl_ch0[i];  
+#ifdef DEBUG_DLSCH_DEMOD
+	            printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                } else{
+                  if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){                
+	            rxF_ext[j] = rxF[i];
+                    dl_ch0_ext[j++]=dl_ch0[i]; 
+#ifdef DEBUG_DLSCH_DEMOD
+	            printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i]));
+#endif
+                  }
+                }
+	      }
+               
+              dl_ch0_ext+=9-frame_parms->Ncp;
+              rxF_ext+=9-frame_parms->Ncp; 
+
+            }
+	      
+          }// pilots=0
+        }
+
+        dl_ch0+=12;
+        rxF+=12;
+      }
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+  return(nb_rb/frame_parms->nb_antennas_rx);
+}
+              
+
+              
+//==============================================================================================
+
+#ifdef USER_MODE
+
+void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int round)
+{
+
+  unsigned int nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12;
+  char fname[32],vname[32];
+  int N_RB_DL=ue->frame_parms.N_RB_DL;
+
+  sprintf(fname,"dlsch%d_rxF_r%d_ext0.m",eNB_id,round);
+  sprintf(vname,"dl%d_rxF_r%d_ext0",eNB_id,round);
+  write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb,1,1);
+
+  if (ue->frame_parms.nb_antennas_rx >1) {
+    sprintf(fname,"dlsch%d_rxF_r%d_ext1.m",eNB_id,round);
+    sprintf(vname,"dl%d_rxF_r%d_ext1",eNB_id,round);
+    write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_ext[1],12*N_RB_DL*nsymb,1,1);
+  }
+
+  sprintf(fname,"dlsch%d_ch_r%d_ext00.m",eNB_id,round);
+  sprintf(vname,"dl%d_ch_r%d_ext00",eNB_id,round);
+  write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1);
+
+  if (ue->transmission_mode[eNB_id]==7){
+    sprintf(fname,"dlsch%d_bf_ch_r%d.m",eNB_id,round);
+    sprintf(vname,"dl%d_bf_ch_r%d",eNB_id,round);
+    write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_bf_ch_estimates[0],512*nsymb,1,1);
+    //write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates[0],512,1,1);
+
+    sprintf(fname,"dlsch%d_bf_ch_r%d_ext00.m",eNB_id,round);
+    sprintf(vname,"dl%d_bf_ch_r%d_ext00",eNB_id,round);
+    write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1);
+  }
+
+  if (ue->frame_parms.nb_antennas_rx == 2) {
+    sprintf(fname,"dlsch%d_ch_r%d_ext01.m",eNB_id,round);
+    sprintf(vname,"dl%d_ch_r%d_ext01",eNB_id,round);
+    write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1);
+  }
+
+  if (ue->frame_parms.nb_antenna_ports_eNB == 2) {
+    sprintf(fname,"dlsch%d_ch_r%d_ext10.m",eNB_id,round);
+    sprintf(vname,"dl%d_ch_r%d_ext10",eNB_id,round);
+    write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1);
+
+    if (ue->frame_parms.nb_antennas_rx == 2) {
+      sprintf(fname,"dlsch%d_ch_r%d_ext11.m",eNB_id,round);
+      sprintf(vname,"dl%d_ch_r%d_ext11",eNB_id,round);
+      write_output(fname,vname,ue->pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1);
+    }
+  }
+
+  sprintf(fname,"dlsch%d_rxF_r%d_uespec0.m",eNB_id,round);
+  sprintf(vname,"dl%d_rxF_r%d_uespec0",eNB_id,round);
+  write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_uespec_pilots[0],12*N_RB_DL,1,1);
 
   /*
     write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1);
@@ -4240,7 +5210,7 @@ void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword
   sprintf(fname,"dlsch%d_rxF_r%d_comp0.m",eNB_id,round);
   sprintf(vname,"dl%d_rxF_r%d_comp0",eNB_id,round);
   write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb,1,1);
-  if (ue->frame_parms.nb_antennas_tx_eNB == 2) {
+  if (ue->frame_parms.nb_antenna_ports_eNB == 2) {
     sprintf(fname,"dlsch%d_rxF_r%d_comp1.m",eNB_id,round);
     sprintf(vname,"dl%d_rxF_r%d_comp1",eNB_id,round);
     write_output(fname,vname,ue->pdsch_vars[eNB_id]->rxdataF_comp1[0][round],12*N_RB_DL*nsymb,1,1);
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c
index 92169858157a7dde25259b8ce6b2eaac9b708d2f..8165bc1f23f085e0df9a7b647cca08eaa3afbbf7 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c
@@ -21,7 +21,7 @@
 
 /*! \file PHY/LTE_TRANSPORT/dlsch_llr_computation.c
  * \brief Top-level routines for LLR computation of the PDSCH physical channel from 36-211, V8.6 2009-03
- * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, S. Wagner
+ * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, S. Wagner, X Jiang
  * \date 2011
  * \version 0.1
  * \company Eurecom
@@ -632,7 +632,8 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
                    uint8_t first_symbol_flag,
                    uint16_t nb_rb,
                    uint16_t pbch_pss_sss_adjust,
-                   int16_t **llr32p)
+                   int16_t **llr32p,
+		   uint8_t beamforming_mode)
 {
 
   uint32_t *rxF = (uint32_t*)&rxdataF_comp[0][((int32_t)symbol*frame_parms->N_RB_DL*12)];
@@ -657,6 +658,10 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
       len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
     else
       len = (nb_rb*10) - (5*pbch_pss_sss_adjust/6);
+  } else if((beamforming_mode==7) && (frame_parms->Ncp==0) && (symbol==3 || symbol==6 || symbol==9 || symbol==12)){
+      len = (nb_rb*9) - (3*pbch_pss_sss_adjust/4);
+  } else if((beamforming_mode==7) && (frame_parms->Ncp==1) && (symbol==4 || symbol==7 || symbol==10)){
+      len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
   } else {
     len = (nb_rb*12) - pbch_pss_sss_adjust;
   }
@@ -688,7 +693,8 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
                      uint8_t first_symbol_flag,
                      uint16_t nb_rb,
                      uint16_t pbch_pss_sss_adjust,
-                     int16_t **llr32p)
+                     int16_t **llr32p,
+                     uint8_t beamforming_mode)
 {
 
 #if defined(__x86_64__) || defined(__i386__)
@@ -731,11 +737,15 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
 #endif
   if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) {
     if (frame_parms->mode1_flag==0)
-      len = nb_rb*8 - (2*pbch_pss_sss_adjust/3);
+      len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
     else
-      len = nb_rb*10 - (5*pbch_pss_sss_adjust/6);
+      len = (nb_rb*10) - (5*pbch_pss_sss_adjust/6);
+  } else if((beamforming_mode==7) && (frame_parms->Ncp==0) && (symbol==3 || symbol==6 || symbol==9 || symbol==12)){
+      len = (nb_rb*9) - (3*pbch_pss_sss_adjust/4);
+  } else if((beamforming_mode==7) && (frame_parms->Ncp==1) && (symbol==4 || symbol==7 || symbol==10)){
+      len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
   } else {
-    len = nb_rb*12 - pbch_pss_sss_adjust;
+    len = (nb_rb*12) - pbch_pss_sss_adjust;
   }
 
   // update output pointer according to number of REs in this symbol (<<2 because 4 bits per RE)
@@ -811,7 +821,8 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
                      uint8_t first_symbol_flag,
                      uint16_t nb_rb,
                      uint16_t pbch_pss_sss_adjust,
-                     int16_t **llr_save)
+                     int16_t **llr_save,
+                     uint8_t beamforming_mode)
 {
 #if defined(__x86_64__) || defined(__i386__)
   __m128i *rxF = (__m128i*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
@@ -841,11 +852,15 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
 #endif
   if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) {
     if (frame_parms->mode1_flag==0)
-      len = nb_rb*8 - (2*pbch_pss_sss_adjust/3);
+      len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
     else
-      len = nb_rb*10 - (5*pbch_pss_sss_adjust/6);
+      len = (nb_rb*10) - (5*pbch_pss_sss_adjust/6);
+  } else if((beamforming_mode==7) && (frame_parms->Ncp==0) && (symbol==3 || symbol==6 || symbol==9 || symbol==12)){
+      len = (nb_rb*9) - (3*pbch_pss_sss_adjust/4);
+  } else if((beamforming_mode==7) && (frame_parms->Ncp==1) && (symbol==4 || symbol==7 || symbol==10)){
+      len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3);
   } else {
-    len = nb_rb*12 - pbch_pss_sss_adjust;
+    len = (nb_rb*12) - pbch_pss_sss_adjust;
   }
 
   llr2 = llr;
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
index bafa37b96f90922bbab35ae8d0114520c74d3b3e..d6e680344be663c9d330249ae627eb3006f51920 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
@@ -20,15 +20,15 @@
  */
 
 /*! \file PHY/LTE_TRANSPORT/dlsch_modulation.c
-* \brief Top-level routines for generating the PDSCH physical channel from 36-211, V8.6 2009-03
-* \author R. Knopp, F. Kaltenberger
-* \date 2011
-* \version 0.1
-* \company Eurecom
-* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
-* \note
-* \warning
-*/
+ * \brief Top-level routines for generating the PDSCH physical channel from 36-211, V8.6 2009-03
+ * \author R. Knopp, F. Kaltenberger
+ * \date 2011
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
+ * \note
+ * \warning
+ */
 #include "PHY/defs.h"
 #include "PHY/extern.h"
 #include "PHY/CODING/defs.h"
@@ -62,10 +62,36 @@ uint8_t is_not_pilot(uint8_t pilots, uint8_t re, uint8_t nushift, uint8_t use2nd
   return(0);
 }
 
-uint8_t is_not_UEspecRS(int first_layer,int re)
+/*uint8_t is_not_UEspecRS(int first_layer,int re)
 {
-
   return(1);
+}*/
+uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode)
+{
+  uint8_t offset = (lprime==1||lprime==3)?2:0;
+  if (lprime==-1)
+    return(1);
+
+  switch (beamforming_mode) {
+    case 7:
+      if (Ncp == NORMAL){
+        if ((re!=nushift+offset) && (re!=((nushift+4+offset)%12)) &&  (re!=((nushift+8+offset)%12))) 
+          return(1);
+        /*else{
+          printf("(is_no_UEspec_RS):lprime=%d, re=%d, nushift=%d, offset=%d\n",lprime, re,nushift,offset);
+        }*/
+      } else { 
+        if ((re!=nushift+offset) && (re!=((nushift+3+offset)%12)) && (re!=((nushift+6+offset)%12)) && (re!=((nushift+9+offset)%12)))
+          return(1);
+      }
+      break;
+
+    default:
+      msg("is_not_UEspecRS() [dlsch_modulation.c] : ERROR, unknown beamforming_mode %d\n",beamforming_mode);
+      return(-1);
+  }
+
+  return(0);
 }
 
 void generate_64qam_table(void)
@@ -102,36 +128,36 @@ void layer1prec2A(int32_t *antenna0_sample, int32_t *antenna1_sample, uint8_t pr
 
   switch (precoding_index) {
 
-  case 0: // 1 1
-    *antenna1_sample=*antenna0_sample;
-    break;
+    case 0: // 1 1
+      *antenna1_sample=*antenna0_sample;
+      break;
 
-  case 1: // 1 -1
-    ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[0];
-    ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[1];
-    break;
+    case 1: // 1 -1
+      ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[0];
+      ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[1];
+      break;
 
-  case 2: // 1 j
-    ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[1];
-    ((int16_t *)antenna1_sample)[1] = ((int16_t *)antenna0_sample)[0];
-    break;
+    case 2: // 1 j
+      ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[1];
+      ((int16_t *)antenna1_sample)[1] = ((int16_t *)antenna0_sample)[0];
+      break;
 
-  case 3: // 1 -j
-    ((int16_t *)antenna1_sample)[0] = ((int16_t *)antenna0_sample)[1];
-    ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[0];
-    break;
+    case 3: // 1 -j
+      ((int16_t *)antenna1_sample)[0] = ((int16_t *)antenna0_sample)[1];
+      ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[0];
+      break;
   }
 
   // normalize
   /*  ((int16_t *)antenna0_sample)[0] = (int16_t)((((int16_t *)antenna0_sample)[0]*ONE_OVER_SQRT2_Q15)>>15);
-  ((int16_t *)antenna0_sample)[1] = (int16_t)((((int16_t *)antenna0_sample)[1]*ONE_OVER_SQRT2_Q15)>>15);  ((int16_t *)antenna1_sample)[0] = (int16_t)((((int16_t *)antenna1_sample)[0]*ONE_OVER_SQRT2_Q15)>>15);
-  ((int16_t *)antenna1_sample)[1] = (int16_t)((((int16_t *)antenna1_sample)[1]*ONE_OVER_SQRT2_Q15)>>15);  */
+      ((int16_t *)antenna0_sample)[1] = (int16_t)((((int16_t *)antenna0_sample)[1]*ONE_OVER_SQRT2_Q15)>>15);  ((int16_t *)antenna1_sample)[0] = (int16_t)((((int16_t *)antenna1_sample)[0]*ONE_OVER_SQRT2_Q15)>>15);
+      ((int16_t *)antenna1_sample)[1] = (int16_t)((((int16_t *)antenna1_sample)[1]*ONE_OVER_SQRT2_Q15)>>15);  */
 }
 
 uint32_t FOUR[2]={0,4};
 uint32_t TWO[2]={0,2};
 
-int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB,
 					    int **txdataF,
 					    uint32_t *jj,
 					    uint32_t *jj2,
@@ -147,11 +173,14 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
 					    uint32_t *re_allocated,
 					    uint8_t skip_dc,
 					    uint8_t skip_half,
+					    uint8_t lprime,
+					    uint8_t mprime,
+					    uint8_t Ns,
 					    int *P1_SHIFT,
 					    int *P2_SHIFT)
 {
 
-
+  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms;
   uint8_t *x0             = dlsch0_harq->e;
   uint32_t qam16_table_offset_re = 0;
   uint32_t qam16_table_offset_im = 0;
@@ -205,7 +234,7 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
     return(0);
 }
 
-int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB,
 					 int **txdataF,
 					 uint32_t *jj,
 					 uint32_t *jj2,
@@ -221,10 +250,14 @@ int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
 					 uint32_t *re_allocated,
 					 uint8_t skip_dc,
 					 uint8_t skip_half,
+					 uint8_t lprime,
+					 uint8_t mprime,
+					 uint8_t Ns,
 					 int *P1_SHIFT,
 					 int *P2_SHIFT)
 {
   
+  LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms;
 
   uint8_t *x0             = dlsch0_harq->e;
   uint32_t qam16_table_offset_re = 0;
@@ -287,7 +320,7 @@ int allocate_REs_in_RB_pilots_16QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
   return(0);
 }
 
-int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB,
 					    int **txdataF,
 					    uint32_t *jj,
 					    uint32_t *jj2,
@@ -303,10 +336,14 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
 					    uint32_t *re_allocated,
 					    uint8_t skip_dc,
 					    uint8_t skip_half,
+					    uint8_t lprime,
+					    uint8_t mprime,
+					    uint8_t Ns,
 					    int *P1_SHIFT,
 					    int *P2_SHIFT)
 {
 
+  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms;
 
   uint8_t *x0             = dlsch0_harq->e;
   uint32_t qam64_table_offset_re = 0;
@@ -423,7 +460,7 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
   return(0);
 }
 
-int allocate_REs_in_RB_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB,
 					 int **txdataF,
 					 uint32_t *jj,
 					 uint32_t *jj2,
@@ -439,10 +476,14 @@ int allocate_REs_in_RB_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
 					 uint32_t *re_allocated,
 					 uint8_t skip_dc,
 					 uint8_t skip_half,
+					 uint8_t lprime,
+					 uint8_t mprime,
+					 uint8_t Ns,
 					 int *P1_SHIFT,
 					 int *P2_SHIFT)
 {
   
+  LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms;
 
   uint8_t *x0             = dlsch0_harq->e;
   uint32_t qam64_table_offset_re = 0;
@@ -511,7 +552,7 @@ int allocate_REs_in_RB_pilots_64QAM_siso(LTE_DL_FRAME_PARMS *frame_parms,
   return(0);
 }
 
-int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
+int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB,
                        int32_t **txdataF,
                        uint32_t *jj,
                        uint32_t *jj2,
@@ -527,11 +568,16 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
                        uint32_t *re_allocated,
                        uint8_t skip_dc,
                        uint8_t skip_half,
+		       uint8_t lprime,
+		       uint8_t mprime,
+		       uint8_t Ns,
 		       int *P1_SHIFT,
 		       int *P2_SHIFT)
 {
 
 
+  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms;
+
   uint8_t *x0             = dlsch0_harq->e;
   MIMO_mode_t mimo_mode   = dlsch0_harq->mimo_mode;
 
@@ -573,10 +619,21 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
   int32_t tmp_sample1,tmp_sample2;
   int16_t tmp_amp=amp;
   int s=1;
+  int mprime2 = mprime,ind,ind_dword,ind_qpsk_symb;
 
   gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
   //  if (mimo_mode == LARGE_CDD) gain_lin_QPSK>>=1;
 
+  int32_t qpsk[4];
+  ((int16_t *)&qpsk[0])[0] = gain_lin_QPSK;
+  ((int16_t *)&qpsk[0])[1] = gain_lin_QPSK;
+  ((int16_t *)&qpsk[1])[0] = -gain_lin_QPSK;
+  ((int16_t *)&qpsk[1])[1] = gain_lin_QPSK;;
+  ((int16_t *)&qpsk[2])[0] = gain_lin_QPSK;;
+  ((int16_t *)&qpsk[2])[1] = -gain_lin_QPSK;;
+  ((int16_t *)&qpsk[3])[0] = -gain_lin_QPSK;;
+  ((int16_t *)&qpsk[3])[1] = -gain_lin_QPSK;
+
   if (dlsch1_harq) {
     x1             = dlsch1_harq->e;
     // Fill these in later for TM8-10
@@ -587,7 +644,8 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
   }
 
 #ifdef DEBUG_DLSCH_MODULATION
-  printf("allocate_re (mod %d): symbol_offset %d re_offset %d (%d,%d), jj %d -> %d,%d\n",mod_order0,symbol_offset,re_offset,skip_dc,skip_half,*jj, x0[*jj], x0[1+*jj]);
+  printf("allocate_re (mod %d): symbol_offset %d re_offset %d (%d,%d), jj %d -> %d,%d\n",mod_order0,symbol_offset,re_offset,skip_dc,skip_half,*jj, x0[*jj],
+x0[1+*jj]);
 #endif
 
   first_re=0;
@@ -620,15 +678,11 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
         case 2:  //QPSK
 
 	  //          printf("re %d %d(%d) : %d,%d => ",re,tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
-          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-            ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
-          }
+	  ((int16_t*)&txdataF[0][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
 
           *jj = *jj + 1;
 
-          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-            ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
-          }
+	  ((int16_t*)&txdataF[0][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
 
           *jj = *jj + 1;
 
@@ -661,12 +715,10 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
 
           *jj=*jj+1;
 
-          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-            ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s0[qam16_table_offset_re];
-            ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s0[qam16_table_offset_im];
-            //      ((int16_t *)&txdataF[aa][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
-            //      ((int16_t *)&txdataF[aa][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
-          }
+	  ((int16_t *)&txdataF[0][tti_offset])[0]+=qam_table_s0[qam16_table_offset_re];
+	  ((int16_t *)&txdataF[0][tti_offset])[1]+=qam_table_s0[qam16_table_offset_im];
+	  //      ((int16_t *)&txdataF[aa][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
+	  //      ((int16_t *)&txdataF[aa][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
 
           break;
 
@@ -706,10 +758,8 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
 
           *jj=*jj+1;
 
-          for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-            ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s0[qam64_table_offset_re];
-            ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s0[qam64_table_offset_im];
-          }
+	  ((int16_t *)&txdataF[0][tti_offset])[0]+=qam_table_s0[qam64_table_offset_re];
+	  ((int16_t *)&txdataF[0][tti_offset])[1]+=qam_table_s0[qam64_table_offset_im];
 
           break;
 
@@ -912,7 +962,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
 
         *re_allocated = *re_allocated + 1;
 
-        if (frame_parms->nb_antennas_tx == 2) {
+        if (frame_parms->nb_antenna_ports_eNB == 2) {
           switch (mod_order0) {
           default:
             LOG_E(PHY,"Unknown mod_order0 %d\n",mod_order0);
@@ -1128,7 +1178,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
           ((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
           ((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
 
-          if (frame_parms->nb_antennas_tx == 2) {
+          if (frame_parms->nb_antenna_ports_eNB == 2) {
             layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index);
             ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
             ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
@@ -1168,7 +1218,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
           ((int16_t *)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0];
           ((int16_t *)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1];
 
-          if (frame_parms->nb_antennas_tx == 2) {
+          if (frame_parms->nb_antenna_ports_eNB == 2) {
             layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index);
             ((int16_t*)&txdataF[1][tti_offset])[0] += ((int16_t*)&tmp_sample2)[0];
             ((int16_t*)&txdataF[1][tti_offset])[1] += ((int16_t*)&tmp_sample2)[1];
@@ -1218,7 +1268,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
           ((int16_t *)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0];
           ((int16_t *)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1];
 
-          if (frame_parms->nb_antennas_tx == 2) {
+          if (frame_parms->nb_antenna_ports_eNB == 2) {
             layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index);
             ((int16_t*)&txdataF[1][tti_offset])[0] += ((int16_t*)&tmp_sample2)[0];
             ((int16_t*)&txdataF[1][tti_offset])[1] += ((int16_t*)&tmp_sample2)[1];
@@ -1226,7 +1276,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
 
           break;
 
-        }
+	}
       }
 
       if (mimo_mode == ALAMOUTI) {
@@ -1238,10 +1288,114 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
           *re_allocated = *re_allocated + 1;
         }
       }
+     
+      if (mimo_mode == TM7) {
+        *re_allocated = *re_allocated + 1;
+
+        if (is_not_UEspecRS(lprime,re,frame_parms->Nid_cell%3,frame_parms->Ncp,7)) {
+
+          switch (mod_order0){
+            case 2:  //QPSK
+
+              ((int16_t*)&txdataF[5][tti_offset])[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+              *jj = *jj + 1;
+              ((int16_t*)&txdataF[5][tti_offset])[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+              *jj = *jj + 1;
+
+              //printf("%d(%d) : %d,%d =>
+              //",tti_offset,*jj,((int16_t*)&tmp_sample1)[0],((int16_t*)&tmp_sample1)[1]);
+              break;
+
+            case 4:  //16QAM
+
+              qam16_table_offset_re = 0;
+              qam16_table_offset_im = 0;
+
+              if (x0[*jj] == 1)
+                qam16_table_offset_re+=2;
+
+              *jj=*jj+1;
+
+              if (x0[*jj] == 1)
+                qam16_table_offset_im+=2;
+
+              *jj=*jj+1;
+
+
+              if (x0[*jj] == 1)
+                qam16_table_offset_re+=1;
+
+              *jj=*jj+1;
+
+              if (x0[*jj] == 1)
+                qam16_table_offset_im+=1;
+
+              *jj=*jj+1;
+
+              ((int16_t*)&txdataF[5][tti_offset])[0] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
+              ((int16_t*)&txdataF[5][tti_offset])[1] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
+
+              break;
+
+            case 6:  //64QAM
+
+
+              qam64_table_offset_re = 0;
+              qam64_table_offset_im = 0;
 
-      if (mimo_mode >= TM8) { //TM8,TM9,TM10
+              if (x0[*jj] == 1)
+                qam64_table_offset_re+=4;
+
+              *jj=*jj+1;
+
+              if (x0[*jj] == 1)
+                qam64_table_offset_im+=4;
+
+              *jj=*jj+1;
+
+              if (x0[*jj] == 1)
+                qam64_table_offset_re+=2;
+
+              *jj=*jj+1;
+
+              if (x0[*jj] == 1)
+                qam64_table_offset_im+=2;
+
+              *jj=*jj+1;
+
+              if (x0[*jj] == 1)
+                qam64_table_offset_re+=1;
+
+              *jj=*jj+1;
+
+              if (x0[*jj] == 1)
+                qam64_table_offset_im+=1;
 
-        if (is_not_UEspecRS(first_layer0,re)) {
+              *jj=*jj+1;
+
+              ((int16_t*)&txdataF[5][tti_offset])[0] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
+              ((int16_t*)&txdataF[5][tti_offset])[1] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
+
+              break;
+
+          }
+        } else {
+          //precoding UE spec RS
+          //printf("precoding UE spec RS\n");
+
+          ind = 3*lprime*dlsch0_harq->nb_rb+mprime2;
+          ind_dword = ind>>4;
+          ind_qpsk_symb = ind&0xf;
+
+          txdataF[5][tti_offset] = qpsk[(phy_vars_eNB->lte_gold_uespec_port5_table[0][Ns][ind_dword]>>(2*ind_qpsk_symb))&3];
+          mprime2++;
+
+        }
+
+      } else if (mimo_mode >= TM8) { //TM8,TM9,TM10
+	//uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode)
+
+        if (is_not_UEspecRS(lprime,re,frame_parms->nushift,frame_parms->Ncp,8)) {
           switch (mod_order0) {
           case 2:  //QPSK
 
@@ -1256,7 +1410,7 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
             break;
 
           case 4:  //16QAM
-            if (is_not_UEspecRS(0/*layer (FIXME uninitialized!)*/,re)) {
+            if (is_not_UEspecRS(lprime,re,frame_parms->nushift,frame_parms->Ncp,8)) {
               qam16_table_offset_re = 0;
               qam16_table_offset_im = 0;
 
@@ -1345,21 +1499,22 @@ int allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
   return(0);
 }
 
+
 int allocate_REs_in_RB_MCH(int32_t **txdataF,
                            uint32_t *jj,
-                           uint16_t re_offset,
-                           uint32_t symbol_offset,
-                           uint8_t *x0,
-                           uint8_t l,
-                           uint8_t mod_order,
-                           int16_t amp,
-                           int16_t *qam_table_s,
-                           uint32_t *re_allocated,
-                           uint8_t skip_dc,
-                           LTE_DL_FRAME_PARMS *frame_parms)
+                            uint16_t re_offset,
+                            uint32_t symbol_offset,
+                            uint8_t *x0,
+                            uint8_t l,
+                            uint8_t mod_order,
+                            int16_t amp,
+                            int16_t *qam_table_s,
+                            uint32_t *re_allocated,
+                            uint8_t skip_dc,
+                            LTE_DL_FRAME_PARMS *frame_parms)
 {
 
-  uint32_t tti_offset,aa;
+  uint32_t tti_offset;
   uint8_t re;
   uint8_t qam64_table_offset_re = 0;
   uint8_t qam64_table_offset_im = 0;
@@ -1397,99 +1552,91 @@ int allocate_REs_in_RB_MCH(int32_t **txdataF,
 
 
     switch (mod_order) {
-    case 2:  //QPSK
+      case 2:  //QPSK
 
       //            printf("%d : %d,%d => ",tti_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
-      for (aa=0; aa<frame_parms->nb_antennas_tx; aa++)
-        ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
+      ((int16_t*)&txdataF[4][tti_offset])[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
 
       *jj = *jj + 1;
 
-      for (aa=0; aa<frame_parms->nb_antennas_tx; aa++)
-        ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
+      ((int16_t*)&txdataF[4][tti_offset])[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
 
       *jj = *jj + 1;
 
       //      printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
       break;
 
-    case 4:  //16QAM
+      case 4:  //16QAM
 
-      qam16_table_offset_re = 0;
-      qam16_table_offset_im = 0;
+    qam16_table_offset_re = 0;
+    qam16_table_offset_im = 0;
 
-      if (x0[*jj] == 1)
-        qam16_table_offset_re+=2;
+    if (x0[*jj] == 1)
+      qam16_table_offset_re+=2;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
-      if (x0[*jj] == 1)
-        qam16_table_offset_im+=2;
+    if (x0[*jj] == 1)
+      qam16_table_offset_im+=2;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
 
-      if (x0[*jj] == 1)
-        qam16_table_offset_re+=1;
+    if (x0[*jj] == 1)
+      qam16_table_offset_re+=1;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
-      if (x0[*jj] == 1)
-        qam16_table_offset_im+=1;
+    if (x0[*jj] == 1)
+      qam16_table_offset_im+=1;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
-      for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-        ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s[qam16_table_offset_re];
-        ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s[qam16_table_offset_im];
-        //      ((int16_t *)&txdataF[aa][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
-        //      ((int16_t *)&txdataF[aa][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
-      }
+    ((int16_t *)&txdataF[4][tti_offset])[0]=qam_table_s[qam16_table_offset_re];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
+    ((int16_t *)&txdataF[4][tti_offset])[1]=qam_table_s[qam16_table_offset_im];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
 
-      break;
+    break;
 
-    case 6:  //64QAM
+      case 6:  //64QAM
 
 
-      qam64_table_offset_re = 0;
-      qam64_table_offset_im = 0;
+    qam64_table_offset_re = 0;
+    qam64_table_offset_im = 0;
 
-      if (x0[*jj] == 1)
-        qam64_table_offset_re+=4;
+    if (x0[*jj] == 1)
+      qam64_table_offset_re+=4;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
-      if (x0[*jj] == 1)
-        qam64_table_offset_im+=4;
+    if (x0[*jj] == 1)
+      qam64_table_offset_im+=4;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
-      if (x0[*jj] == 1)
-        qam64_table_offset_re+=2;
+    if (x0[*jj] == 1)
+      qam64_table_offset_re+=2;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
-      if (x0[*jj] == 1)
-        qam64_table_offset_im+=2;
+    if (x0[*jj] == 1)
+      qam64_table_offset_im+=2;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
-      if (x0[*jj] == 1)
-        qam64_table_offset_re+=1;
+    if (x0[*jj] == 1)
+      qam64_table_offset_re+=1;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
-      if (x0[*jj] == 1)
-        qam64_table_offset_im+=1;
+    if (x0[*jj] == 1)
+      qam64_table_offset_im+=1;
 
-      *jj=*jj+1;
+    *jj=*jj+1;
 
-      for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-        ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
-        ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
-      }
+    ((int16_t *)&txdataF[4][tti_offset])[0]=qam_table_s[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
+    ((int16_t *)&txdataF[4][tti_offset])[1]=qam_table_s[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
 
-      break;
+    break;
 
     }
   }
@@ -1506,38 +1653,38 @@ uint8_t get_pmi(uint8_t N_RB_DL,LTE_DL_eNB_HARQ_t *dlsch_harq,uint16_t rb)
 
   //  printf("Getting pmi for RB %d => %d\n",rb,(pmi_alloc>>((rb>>2)<<1))&3);
   switch (N_RB_DL) {
-  case 6:   // 1 PRB per subband
-    if (mode <= PUSCH_PRECODING1)
-      return((pmi_alloc>>(rb<<1))&3);
-    else
-      return((pmi_alloc>>rb)&1);
+    case 6:   // 1 PRB per subband
+      if (mode <= PUSCH_PRECODING1)
+        return((pmi_alloc>>(rb<<1))&3);
+      else
+        return((pmi_alloc>>rb)&1);
 
-    break;
+      break;
 
-  default:
-  case 25:  // 4 PRBs per subband
-    if (mode <= PUSCH_PRECODING1)
-      return((pmi_alloc>>((rb>>2)<<1))&3);
-    else
-      return((pmi_alloc>>(rb>>2))&1);
+    default:
+    case 25:  // 4 PRBs per subband
+      if (mode <= PUSCH_PRECODING1)
+        return((pmi_alloc>>((rb>>2)<<1))&3);
+      else
+        return((pmi_alloc>>(rb>>2))&1);
 
-    break;
+      break;
 
-  case 50: // 6 PRBs per subband
-    if (mode <= PUSCH_PRECODING1)
-      return((pmi_alloc>>((rb/6)<<1))&3);
-    else
-      return((pmi_alloc>>(rb/6))&1);
+    case 50: // 6 PRBs per subband
+      if (mode <= PUSCH_PRECODING1)
+        return((pmi_alloc>>((rb/6)<<1))&3);
+      else
+        return((pmi_alloc>>(rb/6))&1);
 
-    break;
+      break;
 
-  case 100: // 8 PRBs per subband
-    if (mode <= PUSCH_PRECODING1)
-      return((pmi_alloc>>((rb>>3)<<1))&3);
-    else
-      return((pmi_alloc>>(rb>>3))&1);
+    case 100: // 8 PRBs per subband
+      if (mode <= PUSCH_PRECODING1)
+        return((pmi_alloc>>((rb>>3)<<1))&3);
+      else
+        return((pmi_alloc>>(rb>>3))&1);
 
-    break;
+      break;
   }
 }
 
@@ -1679,14 +1826,15 @@ inline int check_skip_dc(int rb,LTE_DL_FRAME_PARMS *frame_parms) {
 }
 
 
-int dlsch_modulation(int32_t **txdataF,
+int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
+                     int32_t **txdataF,
                      int16_t amp,
                      uint32_t subframe_offset,
-                     LTE_DL_FRAME_PARMS *frame_parms,
                      uint8_t num_pdcch_symbols,
                      LTE_eNB_DLSCH_t *dlsch0,
                      LTE_eNB_DLSCH_t *dlsch1)
 {
+  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms;
 
   uint8_t nsymb;
   uint8_t harq_pid = dlsch0->current_harq_pid;
@@ -1704,7 +1852,7 @@ int dlsch_modulation(int32_t **txdataF,
   int16_t qam16_table_a0[4],qam64_table_a0[8],qam16_table_b0[4],qam64_table_b0[8];
   int16_t qam16_table_a1[4],qam64_table_a1[8],qam16_table_b1[4],qam64_table_b1[8];
   int16_t *qam_table_s0=NULL,*qam_table_s1=NULL;
-  int (*allocate_REs)(LTE_DL_FRAME_PARMS *,
+  int (*allocate_REs)(PHY_VARS_eNB*,
 		      int **,
 		      uint32_t*,
 		      uint32_t*,
@@ -1720,10 +1868,17 @@ int dlsch_modulation(int32_t **txdataF,
 		      uint32_t *,
 		      uint8_t,
 		      uint8_t,
+		      uint8_t,
+		      uint8_t,
+		      uint8_t,
 		      int *,
 		      int *);
   int P1_SHIFT[13],P2_SHIFT[13];
   int offset,nushiftmod3;
+  MIMO_mode_t mimo_mode = dlsch0_harq->mimo_mode;
+  uint8_t mprime=0,Ns;
+  int8_t  lprime=-1;
+  int aa=0;
 
 #ifdef DEBUG_DLSCH_MODULATION
   uint8_t Nl0 = dlsch0_harq->Nl;
@@ -1746,7 +1901,7 @@ int dlsch_modulation(int32_t **txdataF,
   amp_rho_b = (int16_t)(((int32_t)amp*dlsch0->sqrt_rho_b)>>13);
 
   if (mod_order0 == 4)
-    for (i=0; i<4; i++) {
+    for (i=0;i<4; i++) {
       qam16_table_a0[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_a)>>15);
       qam16_table_b0[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_b)>>15);
     }
@@ -1804,6 +1959,39 @@ int dlsch_modulation(int32_t **txdataF,
         pilots=0;
     }
 
+    if(mimo_mode==TM7){ //36.211 V8.6.0 2009-03
+      mprime = 0;
+      if (frame_parms->Ncp==0) { // normal prefix
+        if (l==12)
+          lprime=3;   // pilots in nushift+3, nushift+9
+        else if (l==9)
+          lprime=2;   // pilots in nushift, nushift+6
+        else if (l==6)
+          lprime=1;   // pilots in nushift+3, nushift+9
+        else if (l==3)
+          lprime=0;   // pilots in nushift, nushift+6
+        else
+          lprime=-1;
+      } else {
+        if (l==10)
+          lprime=2;
+        else if (l==7)
+          lprime=1;
+        else if (l==4)
+          lprime=0;
+        else
+          lprime=-1;
+      }
+
+      // mapping ue specific beamforming weights from UE specified DLSCH structure to common space
+      for (aa=0;aa<frame_parms->nb_antennas_tx;aa++){
+        memcpy(phy_vars_eNB->common_vars.beam_weights[0][5][aa],dlsch0->ue_spec_bf_weights[0][aa],frame_parms->ofdm_symbol_size*sizeof(int32_t));
+      }
+ 
+    }
+  
+    Ns = 2*subframe_offset+(l>=(nsymb>>1));
+
     offset = (pilots==2)?3:0;
     nushiftmod3 = frame_parms->nushift%3;
 
@@ -1934,25 +2122,32 @@ int dlsch_modulation(int32_t **txdataF,
 
 
       if (rb_alloc_ind > 0) {
-	//	printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj);
-	allocate_REs(frame_parms,
-		     txdataF,
-		     &jj,
-		     &jj2,
-		     re_offset,
-		     symbol_offset,
-		     dlsch0->harq_processes[harq_pid],
-		     (dlsch1==NULL) ? NULL : dlsch1->harq_processes[harq_pid],
-		     pilots,
-		     ((pilots) ? amp_rho_b : amp_rho_a),
-		     get_pmi(frame_parms->N_RB_DL,dlsch0->harq_processes[harq_pid],rb),
-		     qam_table_s0,
-		     qam_table_s1,
-		     &re_allocated,
-		     skip_dc,
-		     skip_half,
-		     P1_SHIFT,
-		     P2_SHIFT);
+        //      printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj);
+          allocate_REs(phy_vars_eNB,
+       		       txdataF,
+      		       &jj,
+      		       &jj2,
+      		       re_offset,
+      		       symbol_offset,
+      		       dlsch0->harq_processes[harq_pid],
+      		       (dlsch1==NULL) ? NULL : dlsch1->harq_processes[harq_pid],
+      		       pilots,
+      		       ((pilots) ? amp_rho_b : amp_rho_a),
+      		       get_pmi(frame_parms->N_RB_DL,dlsch0->harq_processes[harq_pid],rb),
+      		       qam_table_s0,
+      		       qam_table_s1,
+      		       &re_allocated,
+      		       skip_dc,
+      		       skip_half,
+		       lprime,
+		       mprime,
+		       Ns,
+      		       P1_SHIFT,
+      		       P2_SHIFT);
+
+          if ((mimo_mode == TM7) && (lprime>=0))
+            mprime +=3+frame_parms->Ncp;
+
       }
       else {
 	//	printf("Unallocated rb %d/symbol %d, re_offset %d, jj %d\n",rb,l,re_offset,jj);
@@ -1974,7 +2169,7 @@ int dlsch_modulation(int32_t **txdataF,
 
 
 #ifdef DEBUG_DLSCH_MODULATION
-  printf("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch0_harq->nb_rb,dlsch0_harq->rb_alloc,mod_order0,Nl0,2,0,subframe_offset));
+  printf("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch0_harq->nb_rb,dlsch0_harq->rb_alloc,mod_order0,Nl0,2,0,subframe_offset,1/*transmission mode*/));
 #endif
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT);
@@ -2073,7 +2268,7 @@ int mch_modulation(int32_t **txdataF,
 
 
 #ifdef DEBUG_DLSCH_MODULATION
-  printf("generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset));
+  printf("generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset,1/*transmission mode*/));
 #endif
 
   return (re_allocated);
diff --git a/openair1/PHY/LTE_TRANSPORT/group_hopping.c b/openair1/PHY/LTE_TRANSPORT/group_hopping.c
index be3acce5bdfec717bcc455c902cde056cf742bb0..bbd908b34abba06b02b3ec996109cb7f2e461c54 100644
--- a/openair1/PHY/LTE_TRANSPORT/group_hopping.c
+++ b/openair1/PHY/LTE_TRANSPORT/group_hopping.c
@@ -42,6 +42,8 @@ void generate_grouphop(LTE_DL_FRAME_PARMS *frame_parms)
   // This is from Section 5.5.1.3
   uint32_t fss_pusch = frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH;
 
+  uint32_t fss_pucch = frame_parms->Nid_cell;
+
   x2 = frame_parms->Nid_cell/30;
 #ifdef DEBUG_GROUPHOP
   printf("[PHY] GroupHop:");
@@ -49,7 +51,10 @@ void generate_grouphop(LTE_DL_FRAME_PARMS *frame_parms)
 
   for (ns=0; ns<20; ns++) {
     if (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled == 0)
+    {
       frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[ns] = fss_pusch%30;
+      frame_parms->pucch_config_common.grouphop[ns]                          = fss_pucch%30;
+    }
     else {
       if ((ns&3) == 0) {
         s = lte_gold_generic(&x1,&x2,reset);
@@ -57,6 +62,7 @@ void generate_grouphop(LTE_DL_FRAME_PARMS *frame_parms)
       }
 
       frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[ns] = (((uint8_t*)&s)[ns&3]+fss_pusch)%30;
+      frame_parms->pucch_config_common.grouphop[ns]                          = (((uint8_t*)&s)[ns&3]+fss_pucch)%30;
     }
 
 #ifdef DEBUG_GROUPHOP
diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c
index 93f6e121cb33e44089f339ce7c2e50476d451b13..ed1a8607e95753667ad6d53f05de6814053ea7c8 100755
--- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c
@@ -132,7 +132,7 @@ void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type
                                         symbol_id,
                                         &tx_buffer,
                                         db_fulllength,
-      			                            1,
+					1,
                                         IF4p5_PULFFT)) < 0) {
         perror("ETHERNET write for IF4p5_PULFFT\n");
       }
@@ -234,7 +234,7 @@ void recv_IF4p5(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_t
 
     LOG_D(PHY,"DL_IF4p5: CC_id %d : frame %d, subframe %d, symbol %d\n",eNB->CC_id,*frame,*subframe,*symbol_number);
 
-    slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + ((*subframe)&1)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1;
+    slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1;
     blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; 
         
     for (element_id=0; element_id<db_halflength; element_id++) {
diff --git a/openair1/PHY/LTE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_TRANSPORT/initial_sync.c
index 661fe96be86a0add8a1488736f40d351d88bb704..75c558f52cba6042ce5249c83aae7924cc5fe513 100644
--- a/openair1/PHY/LTE_TRANSPORT/initial_sync.c
+++ b/openair1/PHY/LTE_TRANSPORT/initial_sync.c
@@ -152,7 +152,7 @@ int pbch_detection(PHY_VARS_UE *ue, runmode_t mode)
 
   if (pbch_decoded) {
 
-    frame_parms->nb_antennas_tx_eNB = pbch_tx_ant;
+    frame_parms->nb_antenna_ports_eNB = pbch_tx_ant;
 
     // set initial transmission mode to 1 or 2 depending on number of detected TX antennas
     frame_parms->mode1_flag = (pbch_tx_ant==1);
@@ -462,6 +462,13 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
     }
   }
 
+  /* Consider this is a false detection if the offset is > 1000 Hz */
+  if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) )
+  {
+	  ret=-1;
+	  LOG_E(HW,"Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset);
+  }
+
   if (ret==0) {  // PBCH found so indicate sync to higher layers and configure frame parameters
 
     //#ifdef DEBUG_INITIAL_SYNCH
@@ -469,6 +476,15 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
     //#endif
 
     if (ue->UE_scan_carrier == 0) {
+
+    #if UE_AUTOTEST_TRACE
+      LOG_I(PHY,"[UE  %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n",
+              ue->Mod_id,
+              ue->proc.proc_rxtx[0].frame_rx,
+              ue->rx_offset,
+              ue->common_vars.freq_offset );
+    #endif
+
       if (ue->mac_enabled==1) {
 	LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id);
 	//mac_resynch();
@@ -506,7 +522,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
 	  ue->frame_parms.N_RB_DL,
 	  ue->frame_parms.phich_config_common.phich_duration,
 	  phich_string[ue->frame_parms.phich_config_common.phich_resource],
-	  ue->frame_parms.nb_antennas_tx_eNB);
+	  ue->frame_parms.nb_antenna_ports_eNB);
 
 #if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
     LOG_I(PHY,"[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n",
diff --git a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c
index b4f158f8738e5b8b9fd27d4599f08be4f518836c..0abc1511ea78ad5877b9183163b3e018a803bd6c 100644
--- a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c
+++ b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c
@@ -325,11 +325,8 @@ int adjust_G(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_orde
   return(0);
 }
 
-int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe)
+int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe,uint8_t beamforming_mode)
 {
-
-
-
   int G_adj;
 
   if (is_pmch_subframe(frame,subframe,frame_parms) == 0) {
@@ -340,9 +337,11 @@ int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint
       // PDDDPDD PDDDPDD - 13 PDSCH symbols, 10 full, 3 w/ pilots = 10*12 + 3*8
       // PCDDPDD PDDDPDD - 12 PDSCH symbols, 9 full, 3 w/ pilots = 9*12 + 3*8
       // PCCDPDD PDDDPDD - 11 PDSCH symbols, 8 full, 3 w/pilots = 8*12 + 3*8
-      if (frame_parms->mode1_flag==0) // SISO
+      if (beamforming_mode==0 && frame_parms->mode1_flag==0) 
         return((((int)nb_rb * mod_order * ((11-num_pdcch_symbols)*12 + 3*8)) - G_adj)*Nl);
-      else
+      else if(beamforming_mode==7)
+        return(((int)nb_rb * mod_order * ((7-num_pdcch_symbols)*12 + 3*10 + 4*9)) - G_adj);
+      else //SISO
         return(((int)nb_rb * mod_order * ((11-num_pdcch_symbols)*12 + 3*10)) - G_adj);
     } else {
       // PDDPDD PDDPDD - 11 PDSCH symbols, 8 full, 3 w/ pilots = 8*12 + 3*8
@@ -350,7 +349,9 @@ int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint
       // PCCPDD PDDPDD - 9 PDSCH symbols, 6 full, 3 w/pilots = 6*12 + 3*8
       if (frame_parms->mode1_flag==0)
         return((((int)nb_rb * mod_order * ((9-num_pdcch_symbols)*12 + 3*8)) - G_adj)*Nl);
-      else
+      else if(beamforming_mode==7)
+        return(((int)nb_rb * mod_order * ((5-num_pdcch_symbols)*12 + 3*8 + 4*9)) - G_adj);
+      else //SISO
         return(((int)nb_rb * mod_order * ((9-num_pdcch_symbols)*12 + 3*10)) - G_adj);
     }
   } else { // This is an MBSFN subframe
diff --git a/openair1/PHY/LTE_TRANSPORT/pbch.c b/openair1/PHY/LTE_TRANSPORT/pbch.c
index 03190de43ba00f50682133a31695efd63be8fd3a..8f6489861bcbba82daa2599e3927b86076be4fd9 100644
--- a/openair1/PHY/LTE_TRANSPORT/pbch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pbch.c
@@ -66,7 +66,7 @@ int allocate_pbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
   MIMO_mode_t mimo_mode   = (frame_parms->mode1_flag==1)?SISO:ALAMOUTI;
 
 
-  uint32_t tti_offset,aa;
+  uint32_t tti_offset;
   uint8_t re;
   int16_t gain_lin_QPSK;
   int16_t re_off=re_offset;
@@ -91,15 +91,11 @@ int allocate_pbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
         *re_allocated = *re_allocated + 1;
 
         //    printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
-        for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-          ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
-        }
+        ((int16_t*)&txdataF[0][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
 
         *jj = *jj + 1;
 
-        for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-          ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
-        }
+        ((int16_t*)&txdataF[0][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
 
         *jj = *jj + 1;
       } else if (mimo_mode == ALAMOUTI) {
@@ -192,7 +188,7 @@ int generate_pbch(LTE_eNB_PBCH *eNB_pbch,
 
     /*
     // scramble crc with PBCH CRC mask (Table 5.3.1.1-1 of 3GPP 36.212-860)
-    switch (frame_parms->nb_antennas_tx_eNB) {
+    switch (frame_parms->nb_antenna_ports_eNB) {
     case 1:
     crc = crc ^ (uint16_t) 0;
     break;
@@ -224,7 +220,7 @@ int generate_pbch(LTE_eNB_PBCH *eNB_pbch,
     if (frame_parms->mode1_flag == 1)
       amask = 0x0000;
     else {
-      switch (frame_parms->nb_antennas_tx_eNB) {
+      switch (frame_parms->nb_antenna_ports_eNB) {
       case 1:
         amask = 0x0000;
         break;
@@ -484,7 +480,7 @@ uint16_t pbch_extract(int **rxdataF,
       }
     }
 
-    for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antennas_tx_eNB;aatx++) {
+    for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antenna_ports_eNB;aatx++) {
       if (high_speed_flag == 1)
         dl_ch0     = &dl_ch_estimates[(aatx<<1)+aarx][LTE_CE_OFFSET+ch_offset+(symbol*(frame_parms->ofdm_symbol_size))];
       else
@@ -546,7 +542,7 @@ int pbch_channel_level(int **dl_ch_estimates_ext,
   uint32_t nsymb = (frame_parms->Ncp==0) ? 7:6;
   uint32_t symbol_mod = symbol % nsymb;
 
-  for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antennas_tx_eNB;aatx++)
+  for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antenna_ports_eNB;aatx++)
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
       //clear average level
 
@@ -616,7 +612,7 @@ void pbch_channel_compensation(int **rxdataF_ext,
 #endif
   symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
 
-  for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antennas_tx_eNB;aatx++)
+  for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antenna_ports_eNB;aatx++)
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
 
 #if defined(__x86_64__) || defined(__i386__)
@@ -723,7 +719,7 @@ void pbch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
   symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
 
   if (frame_parms->nb_antennas_rx>1) {
-    for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antennas_tx_eNB;aatx++) {
+    for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antenna_ports_eNB;aatx++) {
 #if defined(__x86_64__) || defined(__i386__)
       rxdataF_comp128_0   = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol_mod*6*12];
       rxdataF_comp128_1   = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol_mod*6*12];
@@ -1070,7 +1066,7 @@ uint16_t rx_pbch_emul(PHY_VARS_UE *phy_vars_ue,
   if (pbch_phase == (frame_rx % 4)) {
     if (uniformrandom() >= bler) {
       memcpy(phy_vars_ue->pbch_vars[eNB_id]->decoded_output,PHY_vars_eNB_g[eNB_id][CC_id]->pbch_pdu,PBCH_PDU_SIZE);
-      return(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antennas_tx_eNB);
+      return(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antenna_ports_eNB);
     } else
       return(-1);
   } else
diff --git a/openair1/PHY/LTE_TRANSPORT/pcfich.c b/openair1/PHY/LTE_TRANSPORT/pcfich.c
index f7e4fe58b55066ab2accace2167d6b00818f0730..3b141372f03dd0e12e7077c69903c0033862b9e2 100644
--- a/openair1/PHY/LTE_TRANSPORT/pcfich.c
+++ b/openair1/PHY/LTE_TRANSPORT/pcfich.c
@@ -208,7 +208,7 @@ void generate_pcfich(uint8_t num_pdcch_symbols,
       if ((i!=nushiftmod3)&&(i!=(nushiftmod3+3))) {
         txdataF[0][symbol_offset+reg_offset+i] = pcfich_d[0][m];
 
-        if (frame_parms->nb_antennas_tx_eNB>1)
+        if (frame_parms->nb_antenna_ports_eNB>1)
           txdataF[1][symbol_offset+reg_offset+i] = pcfich_d[1][m];
 
         m++;
diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c
index 6b66ee0282084e68a27858e9e2c7dcef39eb9b4b..989567ca3498d075237a8b50982460748ab7cf69 100644
--- a/openair1/PHY/LTE_TRANSPORT/phich.c
+++ b/openair1/PHY/LTE_TRANSPORT/phich.c
@@ -34,6 +34,10 @@
 #include "PHY/extern.h"
 #include "SCHED/defs.h"
 #include "defs.h"
+
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/MAC/defs.h"
+
 #ifndef USER_MODE
 #include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
 #endif
@@ -1046,7 +1050,6 @@ void generate_phich(LTE_DL_FRAME_PARMS *frame_parms,
 
 // This routine demodulates the PHICH and updates PUSCH/ULSCH parameters
 
-
 void rx_phich(PHY_VARS_UE *ue,
 	      UE_rxtx_proc_t *proc,
               uint8_t subframe,
@@ -1081,8 +1084,10 @@ void rx_phich(PHY_VARS_UE *ue,
   if (!ulsch)
     return;
 
+  LOG_D(PHY,"[UE  %d][PUSCH %d] Frame %d subframe %d PHICH RX Status: %d \n",ue->Mod_id,harq_pid,proc->frame_rx,subframe, ulsch->harq_processes[harq_pid]->status);
+
   if (ulsch->harq_processes[harq_pid]->status == ACTIVE) {
-    LOG_D(PHY,"[UE  %d][PUSCH %d] Frame %d subframe %d PHICH RX ACTIVE\n",ue->Mod_id,harq_pid,proc->frame_rx,subframe);
+     LOG_D(PHY,"[UE  %d][PUSCH %d] Frame %d subframe %d PHICH RX ACTIVE\n",ue->Mod_id,harq_pid,proc->frame_rx,subframe);
     Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48;
 
     if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0)
@@ -1375,15 +1380,39 @@ void rx_phich(PHY_VARS_UE *ue,
             subframe,
             HI16,
             nseq_PHICH,
-            ngroup_PHICH);
+            ngroup_PHICH,
+            ulsch->Mlimit);
       //#endif
-      ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+
       //      ulsch->harq_processes[harq_pid]->Ndi = 0;
       ulsch->harq_processes[harq_pid]->round++;
-      ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3];
-      ulsch->O_RI = 0;
-      ulsch->O    = 0;
-      ulsch->uci_format = HLC_subband_cqi_nopmi;
+      
+      if ( ulsch->harq_processes[harq_pid]->round >= (ulsch->Mlimit - 1) )
+      {
+          // this is last push re transmission
+          ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3];
+          ulsch->O_RI = 0;
+          ulsch->O    = 0;
+          ulsch->uci_format = HLC_subband_cqi_nopmi;
+
+          // disable phich decoding since it is the last retransmission
+          ulsch->harq_processes[harq_pid]->status = IDLE;
+
+          //ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+          //ulsch->harq_processes[harq_pid]->round  = 0;
+
+          //LOG_I(PHY,"PUSCH MAX Retransmission acheived ==> flush harq buff (%d) \n",harq_pid);
+          //LOG_I(PHY,"[HARQ-UL harqId: %d] PHICH NACK MAX RETRANS(%d) ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->Mlimit, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round);
+      }
+      else
+      {
+          // ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
+          ulsch->harq_processes[harq_pid]->rvidx = rv_table[ulsch->harq_processes[harq_pid]->round&3];
+          ulsch->O_RI = 0;
+          ulsch->O    = 0;
+          ulsch->uci_format = HLC_subband_cqi_nopmi;
+          //LOG_I(PHY,"[HARQ-UL harqId: %d] PHICH NACK ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag,ulsch->harq_processes[harq_pid]->round);
+      }
     }
 
 
@@ -1405,11 +1434,22 @@ void rx_phich(PHY_VARS_UE *ue,
       //#endif
     }
 
+   // LOG_I(PHY,"[HARQ-UL harqId: %d] subframe_scheduling_flag = %d \n",harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag);
+
+    // Incase of adaptive retransmission, PHICH is always decoded as ACK (at least with OAI-eNB)
+    // Workaround:
+    // rely only on DCI0 decoding and check if NDI has toggled
+    //   save current harq_processes content in temporary struct
+    //   harqId-8 corresponds to the temporary struct. In total we have 8 harq process(0 ..7) + 1 temporary harq process()
+    //ulsch->harq_processes[8] = ulsch->harq_processes[harq_pid];
+
     ulsch->harq_processes[harq_pid]->subframe_scheduling_flag =0;
     ulsch->harq_processes[harq_pid]->status = IDLE;
     ulsch->harq_processes[harq_pid]->round  = 0;
     // inform MAC?
     ue->ulsch_Msg3_active[eNB_id] = 0;
+
+   //LOG_I(PHY,"[HARQ-UL harqId: %d] PHICH ACK ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round);
   }
 
 }
diff --git a/openair1/PHY/LTE_TRANSPORT/pilots.c b/openair1/PHY/LTE_TRANSPORT/pilots.c
index a1f7d5bac6dfe29f7f4f837a89eb194338219517..a4d0fae2599d18c6a09ed229efd6b95e11d281a0 100644
--- a/openair1/PHY/LTE_TRANSPORT/pilots.c
+++ b/openair1/PHY/LTE_TRANSPORT/pilots.c
@@ -62,7 +62,7 @@ void generate_pilots(PHY_VARS_eNB *eNB,
     //    printf("tti %d : offset %d (slot %d)\n",tti,tti_offset,slot_offset);
     //Generate Pilots
 
-    //antenna 0 symbol 0 slot 0
+    //antenna port 0 symbol 0 slot 0
     lte_dl_cell_spec(eNB,&txdataF[0][tti_offset],
                      amp,
                      slot_offset,
@@ -71,7 +71,7 @@ void generate_pilots(PHY_VARS_eNB *eNB,
 
 
     //    printf("tti %d : second_pilot offset %d \n",tti,tti_offset+(second_pilot*samples_per_symbol));
-    //antenna 0 symbol 3/4 slot 0
+    //antenna port 0 symbol 3/4 slot 0
     lte_dl_cell_spec(eNB,&txdataF[0][tti_offset+(second_pilot*samples_per_symbol)],
                      amp,
                      slot_offset,
@@ -79,7 +79,7 @@ void generate_pilots(PHY_VARS_eNB *eNB,
                      0);
 
     //    printf("tti %d : third_pilot offset %d \n",tti,tti_offset+((Nsymb>>1)*samples_per_symbol));
-    //antenna 0 symbol 0 slot 1
+    //antenna port 0 symbol 0 slot 1
     lte_dl_cell_spec(eNB,&txdataF[0][tti_offset+((Nsymb>>1)*samples_per_symbol)],
                      amp,
                      1+slot_offset,
@@ -87,7 +87,7 @@ void generate_pilots(PHY_VARS_eNB *eNB,
                      0);
 
     //    printf("tti %d : third_pilot offset %d \n",tti,tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol));
-    //antenna 0 symbol 3/4 slot 1
+    //antenna port 0 symbol 3/4 slot 1
     lte_dl_cell_spec(eNB,&txdataF[0][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)],
                      amp,
                      1+slot_offset,
@@ -95,66 +95,35 @@ void generate_pilots(PHY_VARS_eNB *eNB,
                      0);
 
 
-    if (frame_parms->nb_antennas_tx > 1) {
-      if (frame_parms->mode1_flag) {
-        // antenna 1 symbol 0 slot 0
-        lte_dl_cell_spec(eNB,&txdataF[1][tti_offset],
-                         amp,
-                         slot_offset,
-                         0,
-                         0);
-
-        // antenna 1 symbol 3 slot 0
-        lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(second_pilot*samples_per_symbol)],
-                         amp,
-                         slot_offset,
-                         1,
-                         0);
+    if (frame_parms->nb_antenna_ports_eNB > 1) {
 
-        //antenna 1 symbol 0 slot 1
-        lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(Nsymb>>1)*samples_per_symbol],
-                         amp,
-                         1+slot_offset,
-                         0,
-                         0);
-
-        // antenna 1 symbol 3 slot 1
-        lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)],
-                         amp,
-                         1+slot_offset,
-                         1,
-                         0);
-
-      } else {
-
-        // antenna 1 symbol 0 slot 0
+        // antenna port 1 symbol 0 slot 0
         lte_dl_cell_spec(eNB,&txdataF[1][tti_offset],
                          amp,
                          slot_offset,
                          0,
                          1);
 
-        // antenna 1 symbol 3 slot 0
+        // antenna port 1 symbol 3 slot 0
         lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(second_pilot*samples_per_symbol)],
                          amp,
                          slot_offset,
                          1,
                          1);
 
-        //antenna 1 symbol 0 slot 1
+        //antenna port 1 symbol 0 slot 1
         lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(Nsymb>>1)*samples_per_symbol],
                          amp,
                          1+slot_offset,
                          0,
                          1);
 
-        // antenna 1 symbol 3 slot 1
+        // antenna port 1 symbol 3 slot 1
         lte_dl_cell_spec(eNB,&txdataF[1][tti_offset+(((Nsymb>>1)+second_pilot)*samples_per_symbol)],
                          amp,
                          1+slot_offset,
                          1,
                          1);
-      }
     }
   }
 }
@@ -185,7 +154,7 @@ int generate_pilots_slot(PHY_VARS_eNB *eNB,
   //    printf("tti %d : offset %d (slot %d)\n",tti,tti_offset,slot_offset);
   //Generate Pilots
 
-  //antenna 0 symbol 0 slot 0
+  //antenna port 0 symbol 0 slot 0
   lte_dl_cell_spec(eNB,
                    &txdataF[0][slot_offset],
                    amp,
@@ -204,44 +173,24 @@ int generate_pilots_slot(PHY_VARS_eNB *eNB,
                      0);
   }
 
-  if (frame_parms->nb_antennas_tx > 1) {
-    if (frame_parms->mode1_flag) {
-      // antenna 1 symbol 0 slot 0
-      lte_dl_cell_spec(eNB,
-                       &txdataF[1][slot_offset],
-                       amp,
-                       slot,
-                       0,
-                       0);
+  if (frame_parms->nb_antenna_ports_eNB > 1) {
 
-      if (first_pilot_only==0) {
-        // antenna 1 symbol 3 slot 0
-        lte_dl_cell_spec(eNB,
-                         &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
-                         amp,
-                         slot,
-                         1,
-                         0);
-      }
-    } else {
+    // antenna port 1 symbol 0 slot 0
+    lte_dl_cell_spec(eNB,
+                     &txdataF[1][slot_offset],
+                     amp,
+                     slot,
+                     0,
+                     1);
 
-      // antenna 1 symbol 0 slot 0
+    if (first_pilot_only == 0) {
+      // antenna port 1 symbol 3 slot 0
       lte_dl_cell_spec(eNB,
-                       &txdataF[1][slot_offset],
+                       &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
                        amp,
                        slot,
-                       0,
+                       1,
                        1);
-
-      if (first_pilot_only == 0) {
-        // antenna 1 symbol 3 slot 0
-        lte_dl_cell_spec(eNB,
-                         &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
-                         amp,
-                         slot,
-                         1,
-                         1);
-      }
     }
   }
 
diff --git a/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c b/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a9010fca0daa712a9db006f0bbf87594283668f
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/pilots_ue_spec.c
@@ -0,0 +1,217 @@
+/*******************************************************************************
+    OpenAirInterface
+    Copyright(c) 1999 - 2014 Eurecom
+
+    OpenAirInterface is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+
+    OpenAirInterface is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenAirInterface.The full GNU General Public License is
+   included in this distribution in the file called "COPYING". If not,
+   see <http://www.gnu.org/licenses/>.
+
+  Contact Information
+  OpenAirInterface Admin: openair_admin@eurecom.fr
+  OpenAirInterface Tech : openair_tech@eurecom.fr
+  OpenAirInterface Dev  : openair4g-devel@eurecom.fr
+
+  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+
+/*! \file PHY/LTE_TRANSPORT/uespec_pilots.c
+* \brief Top-level routines for generating DL ue-specific reference signals V12.5 2015-03
+* \author X.JIANG
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: xiwen.jiangeurecom.fr
+* \note
+* \warning
+*/
+//#include "defs.h"
+#include "PHY/defs.h"
+
+void generate_ue_spec_pilots(PHY_VARS_eNB *phy_vars_eNB,
+                     uint8_t UE_id,
+                     int32_t **txdataF,
+                     int16_t amp,
+                     uint16_t Ntti,
+		     uint8_t beamforming_mode)
+{
+
+  /*LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms;
+
+  uint32_t tti,tti_offset,slot_offset,Nsymb,samples_per_symbol;
+  uint8_t second_pilot,aa;
+
+  //  printf("Doing TX pilots Nsymb %d, second_pilot %d\n",Nsymb,second_pilot);
+  
+  switch(beamforming_mode){
+  case 7:
+    for (tti=0; tti<Ntti; tti++) {
+
+      tti_offset = tti*frame_parms->ofdm_symbol_size*Nsymb;
+      samples_per_symbol = frame_parms->ofdm_symbol_size;
+      slot_offset = (tti*2)%20;
+
+      //    printf("tti %d : offset %d (slot %d)\n",tti,tti_offset,slot_offset);
+      //Generate UE specific Pilots
+      printf("generate_dl_ue_spec:tti_offset=%d\n",tti_offset);
+
+      if(frame_parms->Ncp==0) {
+        for(aa=0;aa<frame_parms->nb_antennas_tx;aa++){ 
+          //antenna port 5 symbol 0 slot 0
+          lte_dl_ue_spec(phy_vars_eNB,
+                         UE_id,
+                         &txdataF[aa][tti_offset+3*samples_per_symbol],
+                         amp,
+                         slot_offset,
+              	         1,
+                         5,
+                         0);
+
+          //antenna port 5 symbol 1 slot 0
+          lte_dl_ue_spec(phy_vars_eNB,
+                         UE_id,
+                         &txdataF[aa][tti_offset+6*samples_per_symbol],
+                         amp,
+                         slot_offset,
+            	         1,
+                         5,
+                         0);
+
+          //antenna port 5 symbol 0 slot 1
+          lte_dl_ue_spec(phy_vars_eNB,
+                         UE_id,
+                         &txdataF[aa][tti_offset+9*samples_per_symbol],
+                         amp,
+                         slot_offset+1,
+            	         0,
+                         5,
+                         0);
+
+          //antenna port 5 symbol 1 slot 1
+          lte_dl_ue_spec(phy_vars_eNB,
+                         UE_id,
+                         &txdataF[aa][tti_offset+12*samples_per_symbol],
+                         amp,
+                         slot_offset+1,
+            	         1,
+                         5,
+                         0);
+	}
+      } else{
+      	msg("generate_ue_soec_pilots:Extented Cyclic Prefix for TM7 is not supported yet.\n");
+      }
+
+
+    }
+    break;
+
+  case 8:
+  case 9:
+  case 10:
+  default:
+    msg("[generate_ue_spec_pilots(in uespec_pilots.c)]ERROR:beamforming mode %d is not supported\n",beamforming_mode);
+    
+ }*/
+}
+
+/*int generate_ue_spec_pilots_slot(PHY_VARS_eNB *phy_vars_eNB,
+                         int32_t **txdataF,
+                         int16_t amp,
+                         uint16_t slot,
+                         int first_pilot_only)
+{
+
+  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms;
+  uint32_t slot_offset,Nsymb,samples_per_symbol;
+  uint8_t second_pilot;
+
+  if (slot<0 || slot>= 20) {
+    msg("generate_pilots_slot: slot not in range (%d)\n",slot);
+    return(-1);
+  }
+
+  Nsymb = (frame_parms->Ncp==0)?7:6;
+  second_pilot = (frame_parms->Ncp==0)?4:3;
+
+
+  slot_offset = slot*frame_parms->ofdm_symbol_size*Nsymb;
+  samples_per_symbol = frame_parms->ofdm_symbol_size;
+
+  //    printf("tti %d : offset %d (slot %d)\n",tti,tti_offset,slot_offset);
+  //Generate Pilots
+
+  //antenna 0 symbol 0 slot 0
+  lte_dl_cell_spec(phy_vars_eNB,
+                   &txdataF[0][slot_offset],
+                   amp,
+                   slot,
+                   0,
+                   0);
+
+
+  if (first_pilot_only==0) {
+    //antenna 0 symbol 3 slot 0
+    lte_dl_cell_spec(phy_vars_eNB,
+                     &txdataF[0][slot_offset+(second_pilot*samples_per_symbol)],
+                     amp,
+                     slot,
+                     1,
+                     0);
+  }
+
+  if (frame_parms->nb_antennas_tx > 1) {
+    if (frame_parms->mode1_flag) {
+      // antenna 1 symbol 0 slot 0
+      lte_dl_cell_spec(phy_vars_eNB,
+                       &txdataF[1][slot_offset],
+                       amp,
+                       slot,
+                       0,
+                       0);
+
+      if (first_pilot_only==0) {
+        // antenna 1 symbol 3 slot 0
+        lte_dl_cell_spec(phy_vars_eNB,
+                         &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
+                         amp,
+                         slot,
+                         1,
+                         0);
+      }
+    } else {
+
+      // antenna 1 symbol 0 slot 0
+      lte_dl_cell_spec(phy_vars_eNB,
+                       &txdataF[1][slot_offset],
+                       amp,
+                       slot,
+                       0,
+                       1);
+
+      if (first_pilot_only == 0) {
+        // antenna 1 symbol 3 slot 0
+        lte_dl_cell_spec(phy_vars_eNB,
+                         &txdataF[1][slot_offset+(second_pilot*samples_per_symbol)],
+                         amp,
+                         slot,
+                         1,
+                         1);
+      }
+    }
+  }
+
+  return(0);
+}*/
+
diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c
index c4088a8a5b26de64e0fe2594a533418d4467836c..1a2838e5cfa3aa86839c9a56e4f4ed95dc60e8c9 100644
--- a/openair1/PHY/LTE_TRANSPORT/pmch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pmch.c
@@ -305,7 +305,7 @@ void generate_mch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t *a)
               eNB->frame_parms.N_RB_DL,
               eNB->dlsch_MCH->harq_processes[0]->rb_alloc,
               get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs),1,
-              2,proc->frame_tx,subframe);
+              2,proc->frame_tx,subframe,0);
 
     generate_mbsfn_pilot(eNB,proc,
                          eNB->common_vars.txdataF[0],
diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c
index d9f5434cf55b2657e50d225d252d67da04732fa3..33780a7defc05282a7f465088aa8c188a206b26f 100644
--- a/openair1/PHY/LTE_TRANSPORT/prach.c
+++ b/openair1/PHY/LTE_TRANSPORT/prach.c
@@ -629,6 +629,13 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
 
 #if defined(EXMIMO) || defined(OAI_USRP)
   prach_start =  (ue->rx_offset+subframe*ue->frame_parms.samples_per_tti-ue->hw_timing_advance-ue->N_TA_offset);
+#ifdef PRACH_DEBUG
+    LOG_I(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id,
+        prach_start,
+        ue->rx_offset,
+        ue->hw_timing_advance,
+        ue->N_TA_offset);
+#endif
 
   if (prach_start<0)
     prach_start+=(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h
index 86bc3723af220571326b57fc8c0b0fb179e82bc3..94aa21c7178362ace62b4161521e3f44472796e5 100644
--- a/openair1/PHY/LTE_TRANSPORT/proto.h
+++ b/openair1/PHY/LTE_TRANSPORT/proto.h
@@ -48,7 +48,7 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch);
 
 void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
 
-/** \fn new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag)
+/** \fn new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms)
     \brief This function allocates structures for a particular DLSCH at eNB
     @returns Pointer to DLSCH to be removed
     @param Kmimo Kmimo factor from 36-212/36-213
@@ -56,8 +56,9 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
     @param Nsoft Soft-LLR buffer size from UE-Category
     @params N_RB_DL total number of resource blocks (determine the operating BW)
     @param abstraction_flag Flag to indicate abstracted interface
+    @param frame_parms Pointer to frame descriptor structure
 */
-LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t N_RB_DL, uint8_t abstraction_flag);
+LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms);
 
 /** \fn free_ue_dlsch(LTE_UE_DLSCH_t *dlsch)
     \brief This function frees memory allocated for a particular DLSCH at UE
@@ -158,6 +159,45 @@ void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB,
                          LTE_eNB_DLSCH_t *dlsch);
 
 
+// Functions below implement 36-211
+
+/** \fn allocate_REs_in_RB(int32_t **txdataF,
+    uint32_t *jj,
+    uint32_t *jj2,
+    uint16_t re_offset,
+    uint32_t symbol_offset,
+    LTE_DL_eNB_HARQ_t *dlsch0_harq,
+    LTE_DL_eNB_HARQ_t *dlsch1_harq,
+    uint8_t pilots,
+    int16_t amp,
+    int16_t *qam_table_s,
+    uint32_t *re_allocated,
+    uint8_t skip_dc,
+    uint8_t skip_half,
+    uint8_t use2ndpilots,
+    LTE_DL_FRAME_PARMS *frame_parms);
+
+    \brief Fills RB with data
+    \param txdataF pointer to output data (frequency domain signal)
+    \param jj index to output (from CW 1)
+    \param jj index to output (from CW 2)
+    \param re_offset index of the first RE of the RB
+    \param symbol_offset index to the OFDM symbol
+    \param dlsch0_harq Pointer to Transport block 0 HARQ structure
+    \param dlsch0_harq Pointer to Transport block 1 HARQ structure
+    \param pilots =1 if symbol_offset is an OFDM symbol that contains pilots, 0 otherwise
+    \param amp Amplitude for symbols
+    \param qam_table_s0 pointer to scaled QAM table for Transport Block 0 (by rho_a or rho_b)
+    \param qam_table_s1 pointer to scaled QAM table for Transport Block 1 (by rho_a or rho_b)
+    \param re_allocated pointer to allocation counter
+    \param skip_dc offset for positive RBs
+    \param skip_half indicate that first or second half of RB must be skipped for PBCH/PSS/SSS
+    \param ue_spec_rs UE specific RS indicator 
+    \param nb_antennas_tx_phy Physical antenna elements which can be different with antenna port number, especially in beamforming case
+    \param use2ndpilots Set to use the pilots from antenna port 1 for PDSCH
+    \param frame_parms Frame parameter descriptor
+*/
+
 // Functions below implement 36-211
 
 /** \fn allocate_REs_in_RB(int32_t **txdataF,
@@ -195,7 +235,7 @@ void dlsch_encoding_emul(PHY_VARS_eNB *phy_vars_eNB,
     \param frame_parms Frame parameter descriptor
 */
 
-int32_t allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
+int32_t allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB,
                            int32_t **txdataF,
                            uint32_t *jj,
                            uint32_t *jj2,
@@ -211,6 +251,9 @@ int32_t allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
                            uint32_t *re_allocated,
                            uint8_t skip_dc,
                            uint8_t skip_half,
+			   uint8_t lprime,
+			   uint8_t mprime,
+			   uint8_t Ns,
 			   int *P1_SHIFT,
 			   int *P2_SHIFT);
 
@@ -230,12 +273,11 @@ int32_t allocate_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
     @param num_pdcch_symbols Number of PDCCH symbols in this subframe
     @param dlsch0 Pointer to Transport Block 0 DLSCH descriptor for this allocation
     @param dlsch1 Pointer to Transport Block 0 DLSCH descriptor for this allocation
-
 */
-int32_t dlsch_modulation(int32_t **txdataF,
+int32_t dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
+                         int32_t **txdataF,
                          int16_t amp,
                          uint32_t sub_frame_offset,
-                         LTE_DL_FRAME_PARMS *frame_parms,
                          uint8_t num_pdcch_symbols,
                          LTE_eNB_DLSCH_t *dlsch0,
                          LTE_eNB_DLSCH_t *dlsch1);
@@ -329,6 +371,13 @@ int32_t generate_mbsfn_pilot(PHY_VARS_eNB *phy_vars_eNB,
 			     int32_t **txdataF,
                              int16_t amp);
 
+void generate_ue_spec_pilots(PHY_VARS_eNB *phy_vars_eNB,
+                             uint8_t UE_id,
+                             int32_t **txdataF,
+                             int16_t amp,
+                             uint16_t Ntti,
+		             uint8_t beamforming_mode);
+
 int32_t generate_pss(int32_t **txdataF,
                      int16_t amp,
                      LTE_DL_FRAME_PARMS *frame_parms,
@@ -714,6 +763,7 @@ int dlsch_64qam_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
     @param nb_rb number of RBs for this allocation
     @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
     @param llr128p pointer to pointer to symbol in dlsch_llr
+    @param beamforming_mode beamforming mode
 */
 int32_t dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
                        int32_t **rxdataF_comp,
@@ -722,7 +772,8 @@ int32_t dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
                        uint8_t first_symbol_flag,
                        uint16_t nb_rb,
                        uint16_t pbch_pss_sss_adj,
-                       int16_t **llr128p);
+                       int16_t **llr128p,
+                       uint8_t beamforming_mode);
 
 /**
    \brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
@@ -735,6 +786,7 @@ int32_t dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
    @param nb_rb number of RBs for this allocation
    @param pbch_pss_sss_adjust  Adjustment factor in RE for PBCH/PSS/SSS allocations
    @param llr128p pointer to pointer to symbol in dlsch_llr
+   @param beamforming_mode beamforming mode
 */
 
 void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
@@ -745,7 +797,8 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
                      uint8_t first_symbol_flag,
                      uint16_t nb_rb,
                      uint16_t pbch_pss_sss_adjust,
-                     int16_t **llr128p);
+                     int16_t **llr128p,
+                     uint8_t beamforming_mode);
 
 /**
    \brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
@@ -758,6 +811,7 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
    @param first_symbol_flag
    @param nb_rb number of RBs for this allocation
    @param pbch_pss_sss_adjust PBCH/PSS/SSS RE adjustment (in REs)
+   @param beamforming_mode beamforming mode
 */
 void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
                      int32_t **rxdataF_comp,
@@ -768,7 +822,8 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
                      uint8_t first_symbol_flag,
                      uint16_t nb_rb,
                      uint16_t pbch_pss_sss_adjust,
-                     short **llr_save);
+                     int16_t **llr_save,
+                     uint8_t beamforming_mode);
 
 /** \fn dlsch_siso(LTE_DL_FRAME_PARMS *frame_parms,
     int32_t **rxdataF_comp,
@@ -939,6 +994,37 @@ uint16_t dlsch_extract_rbs_dual(int32_t **rxdataF,
                                 uint32_t high_speed_flag,
                                 LTE_DL_FRAME_PARMS *frame_parms);
 
+/** \fn dlsch_extract_rbs_TM7(int32_t **rxdataF,
+    int32_t **dl_bf_ch_estimates,
+    int32_t **rxdataF_ext,
+    int32_t **dl_bf_ch_estimates_ext,
+    uint32_t *rb_alloc,
+    uint8_t symbol,
+    uint8_t subframe,
+    uint32_t high_speed_flag,
+    LTE_DL_FRAME_PARMS *frame_parms)
+    \brief This function extracts the received resource blocks, both channel estimates and data symbols,
+    for the current allocation and for single antenna eNB transmission.
+    @param rxdataF Raw FFT output of received signal
+    @param dl_bf_ch_estimates Beamforming channel estimates of current slot
+    @param rxdataF_ext FFT output for RBs in this allocation
+    @param dl_bf_ch_estimates_ext Beamforming channel estimates for RBs in this allocation
+    @param rb_alloc RB allocation vector
+    @param symbol Symbol to extract
+    @param subframe Subframe number
+    @param high_speed_flag
+    @param frame_parms Pointer to frame descriptor
+*/
+uint16_t dlsch_extract_rbs_TM7(int32_t **rxdataF,
+                               int32_t **dl_bf_ch_estimates,
+                               int32_t **rxdataF_ext,
+                               int32_t **dl_bf_ch_estimates_ext,
+                               uint32_t *rb_alloc,
+                               uint8_t symbol,
+                               uint8_t subframe,
+                               uint32_t high_speed_flag,
+                               LTE_DL_FRAME_PARMS *frame_parms);
+
 /** \brief This function performs channel compensation (matched filtering) on the received RBs for this allocation.  In addition, it computes the squared-magnitude of the channel with weightings for 16QAM/64QAM detection as well as dual-stream detection (cross-correlation)
     @param rxdataF_ext Frequency-domain received signal in RBs to be demodulated
     @param dl_ch_estimates_ext Frequency-domain channel estimates in RBs to be demodulated
@@ -1029,6 +1115,12 @@ void dlsch_channel_level_TM56(int32_t **dl_ch_estimates_ext,
                               uint8_t symbol_mod,
                               uint16_t nb_rb);
 
+void dlsch_channel_level_TM7(int32_t **dl_bf_ch_estimates_ext,
+                         LTE_DL_FRAME_PARMS *frame_parms,
+                         int32_t *avg,
+                         uint8_t pilots_flag,
+                         uint16_t nb_rb);
+
 void dlsch_scale_channel(int32_t **dl_ch_estimates_ext,
                          LTE_DL_FRAME_PARMS *frame_parms,
                          LTE_UE_DLSCH_t **dlsch_ue,
@@ -1293,7 +1385,7 @@ uint8_t get_transmission_mode(module_id_t Mod_id, uint8_t CC_id, rnti_t rnti);
 */
 uint32_t conv_nprb(uint8_t ra_header,uint32_t rb_alloc,int N_RB_DL);
 
-int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe);
+int get_G(LTE_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe, uint8_t beamforming_mode);
 
 int adjust_G(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe);
 int adjust_G2(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe,uint8_t symbol);
@@ -1406,7 +1498,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
                                       PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated,
                                       uint16_t si_rnti,
                                       uint16_t ra_rnti,
-                                      uint16_t p_rnti);
+                                      uint16_t p_rnti,
+                                      uint8_t beamforming_mode);
 
 int32_t generate_eNB_dlsch_params_from_dci(int frame,
     uint8_t subframe,
@@ -1419,7 +1512,8 @@ int32_t generate_eNB_dlsch_params_from_dci(int frame,
     uint16_t si_rnti,
     uint16_t ra_rnti,
     uint16_t p_rnti,
-    uint16_t DL_pmi_single);
+    uint16_t DL_pmi_single,
+    uint8_t beamforming_mode);
 
 int32_t generate_eNB_ulsch_params_from_rar(uint8_t *rar_pdu,
     frame_t frame,
@@ -1445,6 +1539,9 @@ int32_t generate_ue_ulsch_params_from_rar(PHY_VARS_UE *phy_vars_ue,
 					  uint8_t eNB_id);
 double sinr_eff_cqi_calc(PHY_VARS_UE *phy_vars_ue,
                          uint8_t eNB_id);
+
+uint8_t sinr2cqi(double sinr,uint8_t trans_mode);
+
 int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *PHY_vars_eNB,
 				       eNB_rxtx_proc_t *proc,
 				       void *dci_pdu,
@@ -1633,7 +1730,7 @@ uint8_t phich_subframe2_pusch_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t s
     @param subframe Subframe of received/transmitted PHICH
     @returns frame of PUSCH transmission
 */
-uint8_t phich_frame2_pusch_frame(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame,uint8_t subframe);;
+uint8_t phich_frame2_pusch_frame(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame,uint8_t subframe);
 
 void print_CQI(void *o,UCI_format_t uci_format,uint8_t eNB_id,int N_RB_DL);
 
@@ -1712,6 +1809,20 @@ void generate_pucch1x(int32_t **txdataF,
 		      int16_t amp,
 		      uint8_t subframe);
 
+void generate_pucch2x(int32_t **txdataF,
+		      LTE_DL_FRAME_PARMS *fp,
+		      uint8_t ncs_cell[20][7],
+		      PUCCH_FMT_t fmt,
+		      PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
+		      uint16_t n2_pucch,
+		      uint16_t *payload,
+		      int A,
+		      int B2,
+		      int16_t amp,
+		      uint8_t subframe,
+		      uint16_t rnti);
+
+
 void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue,
 			 UE_rxtx_proc_t *proc,
                          PUCCH_FMT_t format,
@@ -1821,6 +1932,8 @@ int is_pmch_subframe(frame_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parm
 
 uint8_t is_not_pilot(uint8_t pilots, uint8_t re, uint8_t nushift, uint8_t use2ndpilots);
 
+uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode);
+
 uint32_t dlsch_decoding_abstraction(double *dlsch_MIPB,
                                     LTE_DL_FRAME_PARMS *lte_frame_parms,
                                     LTE_UE_DLSCH_t *dlsch,
diff --git a/openair1/PHY/LTE_TRANSPORT/pss.c b/openair1/PHY/LTE_TRANSPORT/pss.c
index f74675157bb5d89a94bde9dcf71c14507c51af8f..44c7bffd9a5e051fede7f5080ab2bf8a569538b3 100644
--- a/openair1/PHY/LTE_TRANSPORT/pss.c
+++ b/openair1/PHY/LTE_TRANSPORT/pss.c
@@ -72,12 +72,12 @@ int generate_pss(int32_t **txdataF,
     return(-1);
   }
 
-  a = (frame_parms->nb_antennas_tx == 1) ? amp: (amp*ONE_OVER_SQRT2_Q15)>>15;
+  a = (frame_parms->nb_antenna_ports_eNB == 1) ? amp: (amp*ONE_OVER_SQRT2_Q15)>>15;
   //printf("[PSS] amp=%d, a=%d\n",amp,a);
 
   Nsymb = (frame_parms->Ncp==NORMAL)?14:12;
 
-  for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+  for (aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) {
     //  aa = 0;
 
     // The PSS occupies the inner 6 RBs, which start at
diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c
index c0c54b9782b909abb1cb9d0c908cbdad0e4805ca..34e64dfd5f74b325cbc68747c3e63b1962508cc0 100644
--- a/openair1/PHY/LTE_TRANSPORT/pucch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pucch.c
@@ -442,7 +442,7 @@ inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti
   int i;
   uint8_t c;
 
-  x2 = (rnti<<14) + ((1+subframe)<<16)*(1+(fp->Nid_cell<<1)); //this is c_init in 36.211 Sec 6.3.1
+  x2 = (rnti) + ((uint32_t)(1+subframe)<<16)*(1+(fp->Nid_cell<<1)); //this is c_init in 36.211 Sec 6.3.1
   s = lte_gold_generic(&x1, &x2, 1);
   for (i=0;i<19;i++) {
     c = (uint8_t)((s>>i)&1);
@@ -456,22 +456,24 @@ inline void pucch2x_modulation(uint8_t *btilde,int16_t *d,int16_t amp) {
   int i;
 
   for (i=0;i<20;i++) 
-    d[i] = btilde[i] == 1 ? amp : -amp;
+    d[i] = btilde[i] == 1 ? -amp : amp;
 
 }
 
+
+
 uint32_t pucch_code[13] = {0xFFFFF,0x5A933,0x10E5A,0x6339C,0x73CE0,
 			   0xFFC00,0xD8E64,0x4F6B0,0x218EC,0x1B746,
 			   0x0FFFF,0x33FFF,0x3FFFC};
 
+
 void generate_pucch2x(int32_t **txdataF,
 		      LTE_DL_FRAME_PARMS *fp,
 		      uint8_t ncs_cell[20][7],
 		      PUCCH_FMT_t fmt,
 		      PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
 		      uint16_t n2_pucch,
-		      uint8_t shortened_format,
-		      uint32_t *payload,
+		      uint16_t *payload,
 		      int A,
 		      int B2,
 		      int16_t amp,
@@ -486,13 +488,14 @@ void generate_pucch2x(int32_t **txdataF,
   uint8_t NRB2                      = fp->pucch_config_common.nRB_CQI;
   uint8_t Ncs1                      = fp->pucch_config_common.nCS_AN;
 
-  uint32_t u0 = (fp->Nid_cell + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30;
-  uint32_t u1 = (fp->Nid_cell + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30;
-  uint32_t v0=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
-  uint32_t v1=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
+  uint32_t u0 = fp->pucch_config_common.grouphop[subframe<<1];
+  uint32_t u1 = fp->pucch_config_common.grouphop[1+(subframe<<1)];
+  uint32_t v0 = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
+  uint32_t v1 = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
+
   uint32_t z[12*14],*zptr;
   uint32_t u,v,n;
-  uint8_t ns,N_UL_symb,nsymb;
+  uint8_t ns,N_UL_symb,nsymb_slot0,nsymb_pertti;
   uint32_t nprime,l,n_cs;
   int alpha_ind,data_ind;
   int16_t ref_re,ref_im;
@@ -509,7 +512,6 @@ void generate_pucch2x(int32_t **txdataF,
     return;
   }
 
-
   // pucch2x_encoding
   for (i=0;i<A;i++)
     if ((*payload & (1<<i)) > 0)
@@ -545,66 +547,72 @@ void generate_pucch2x(int32_t **txdataF,
     }
   }
 
-  zptr = z;
 
 #ifdef DEBUG_PUCCH_TX
   printf("[PHY] PUCCH2x: n2_pucch %d\n",n2_pucch);
 #endif
 
   N_UL_symb = (fp->Ncp==0) ? 7 : 6;
-
+  data_ind  = 0;
+  zptr      = z;
   for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) {
 
     if ((ns&1) == 0)
-      nprime = (n2_pucch < 12*NRB2) ? 
-	n2_pucch % 12 :
-	(n2_pucch+Ncs1 + 1)%12;
-    else
-      nprime = (n2_pucch < 12*NRB2) ? 
-        ((12*(nprime+1)) % 13)-1 :
-	(10-n2_pucch)%12;
-
+        nprime = (n2_pucch < 12*NRB2) ?
+                n2_pucch % 12 :
+                (n2_pucch+Ncs1 + 1)%12;
+    else {
+        nprime = (n2_pucch < 12*NRB2) ?
+                ((12*(nprime+1)) % 13)-1 :
+                (10-n2_pucch)%12;
+    }
     //loop over symbols in slot
     for (l=0; l<N_UL_symb; l++) {
       // Compute n_cs (36.211 p. 18)
       n_cs = (ncs_cell[ns][l]+nprime)%12;
 
-      alpha_ind = n_cs;
-      data_ind = 0;
-
+      alpha_ind = 0;
       for (n=0; n<12; n++) {
-
-        // this is r_uv^alpha(n)
-        ref_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15);
-        ref_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);
-
-        if ((l<2)||(l>=(N_UL_symb-2))) { //these are PUCCH data symbols
-	  ((int16_t *)&zptr[n])[0] = ((int32_t)d[data_ind]*ref_re - (int32_t)d[data_ind+1]*ref_im)>>15;
-	  ((int16_t *)&zptr[n])[1] = ((int32_t)d[data_ind]*ref_im + (int32_t)d[data_ind+1]*ref_re)>>15;
-	}
-	else {
-	  ((int16_t *)&zptr[n])[0] = ref_re;
-	  ((int16_t *)&zptr[n])[1] = ref_im;
-	}
-
+          // this is r_uv^alpha(n)
+          ref_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15);
+          ref_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);
+
+          if ((l!=1)&&(l!=5)) { //these are PUCCH data symbols
+              ((int16_t *)&zptr[n])[0] = ((int32_t)d[data_ind]*ref_re - (int32_t)d[data_ind+1]*ref_im)>>15;
+              ((int16_t *)&zptr[n])[1] = ((int32_t)d[data_ind]*ref_im + (int32_t)d[data_ind+1]*ref_re)>>15;
+              //LOG_I(PHY,"slot %d ofdm# %d ==> d[%d,%d] \n",ns,l,data_ind,n);
+          }
+          else {
+              ((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re>>15);
+              ((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im>>15);
+              //LOG_I(PHY,"slot %d ofdm# %d ==> dmrs[%d] \n",ns,l,n);
+          }
+          alpha_ind = (alpha_ind + n_cs)%12;
       } // n
-      if ((l<2)||(l>=(N_UL_symb-2)))  //these are PUCCH data symbols so increment data index
-	data_ind+=2;
+      zptr+=12;
+
+      if ((l!=1)&&(l!=5))  //these are PUCCH data symbols so increment data index
+	     data_ind+=2;
     } // l
   } //ns
 
   m = n2_pucch/12;
 
 #ifdef DEBUG_PUCCH_TX
-  printf("[PHY] PUCCH: m %d\n",m);
+  LOG_D(PHY,"[PHY] PUCCH: n2_pucch %d m %d\n",n2_pucch,m);
 #endif
-  nsymb = N_UL_symb<<1;
+
+  nsymb_slot0  = ((fp->Ncp==0) ? 7 : 6);
+  nsymb_pertti = nsymb_slot0 << 1;
+
+  //nsymb = nsymb_slot0<<1;
 
   //for (j=0,l=0;l<(nsymb-1);l++) {
-  for (j=0,l=0; l<(nsymb); l++) {
-    if ((l<(nsymb>>1)) && ((m&1) == 0))
+  for (j=0,l=0; l<(nsymb_pertti); l++) {
+
+    if ((l<nsymb_slot0) && ((m&1) == 0))
       re_offset = (m*6) + fp->first_carrier_offset;
-    else if ((l<(nsymb>>1)) && ((m&1) == 1))
+    else if ((l<nsymb_slot0) && ((m&1) == 1))
       re_offset = fp->first_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12;
     else if ((m&1) == 0)
       re_offset = fp->first_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12;
@@ -614,23 +622,33 @@ void generate_pucch2x(int32_t **txdataF,
     if (re_offset > fp->ofdm_symbol_size)
       re_offset -= (fp->ofdm_symbol_size);
 
-    symbol_offset = (unsigned int)fp->ofdm_symbol_size*(l+(subframe*nsymb));
+
+
+    symbol_offset = (unsigned int)fp->ofdm_symbol_size*(l+(subframe*nsymb_pertti));
     txptr = &txdataF[0][symbol_offset];
 
+    //LOG_I(PHY,"ofdmSymb %d/%d, firstCarrierOffset %d, symbolOffset[sfn %d] %d, reOffset %d, &txptr: %x \n", l, nsymb, fp->first_carrier_offset, subframe, symbol_offset, re_offset, &txptr[0]);
+
     for (i=0; i<12; i++,j++) {
-      txptr[re_offset++] = z[j];
+      txptr[re_offset] = z[j];
+
+      re_offset++;
 
       if (re_offset==fp->ofdm_symbol_size)
-        re_offset = 0;
+          re_offset -= (fp->ofdm_symbol_size);
 
 #ifdef DEBUG_PUCCH_TX
-      printf("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]);
+      LOG_D(PHY,"[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]);
 #endif
     }
   }
 }
 
 
+//#define Amax 13
+//void init_pucch2x_rx() {};
+
+
 uint32_t rx_pucch(PHY_VARS_eNB *eNB,
 		  PUCCH_FMT_t fmt,
 		  uint8_t UE_id,
diff --git a/openair1/PHY/LTE_TRANSPORT/rar_tools.c b/openair1/PHY/LTE_TRANSPORT/rar_tools.c
index f86c009543fb68a79fb49fefcff51b07ff3a195d..60fa52df16d06087a0a2513ac4cdd64999426090 100644
--- a/openair1/PHY/LTE_TRANSPORT/rar_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/rar_tools.c
@@ -34,6 +34,7 @@
 #include "SCHED/extern.h"
 #include "LAYER2/MAC/defs.h"
 #include "SCHED/defs.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
 
 #include "assertions.h"
 
@@ -171,6 +172,8 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue,
                                       unsigned char eNB_id )
 {
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_RAR,VCD_FUNCTION_IN);
+
   //  RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)rar_pdu;
   uint8_t transmission_mode = ue->transmission_mode[eNB_id];
   unsigned char *rar_pdu = ue->dlsch_ra[eNB_id]->harq_processes[0]->b;
@@ -315,6 +318,9 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue,
   msg("ulsch ra (UE): TPC      %d\n",ulsch->harq_processes[harq_pid]->TPC);
   msg("ulsch ra (UE): O        %d\n",ulsch->O);
   msg("ulsch ra (UE): ORI      %d\n",ulsch->O_RI);
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_RAR,VCD_FUNCTION_OUT);
+
   //#endif
   return(0);
 }
diff --git a/openair1/PHY/LTE_TRANSPORT/srs_modulation.c b/openair1/PHY/LTE_TRANSPORT/srs_modulation.c
index a78536246f75ca5cf6c89e68aad80c4204915016..7e29d998a10e30c49d96ba934d2822d86127fe75 100644
--- a/openair1/PHY/LTE_TRANSPORT/srs_modulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/srs_modulation.c
@@ -129,18 +129,27 @@ int32_t generate_srs_tx(PHY_VARS_UE *ue,
 
   LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
   SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id];
-  int32_t *txdataF = ue->common_vars.txdataF[0];
+  int32_t **txdataF = ue->common_vars.txdataF;
   uint16_t msrsb=0,Nb=0,nb,b,msrs0=0,k,Msc_RS,Msc_RS_idx,carrier_pos,symbol_offset;
   uint16_t *Msc_idx_ptr;
   int32_t k0;
-  uint32_t T_SFC;
-  uint32_t subframe_offset;
+  //uint32_t subframe_offset;
   uint8_t Bsrs  = soundingrs_ul_config_dedicated->srs_Bandwidth;
   uint8_t Csrs  = frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig;
   uint8_t Ssrs  = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
   uint8_t n_RRC = soundingrs_ul_config_dedicated->freqDomainPosition;
   uint8_t kTC   = soundingrs_ul_config_dedicated->transmissionComb;
 
+  // u is the PUCCH sequence-group number defined in Section 5.5.1.3
+  // ν is the base sequence number defined in Section 5.5.1.4
+  uint32_t u=frame_parms->pucch_config_common.grouphop[1+(subframe<<1)];;
+  uint32_t v=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
+
+  LOG_D(PHY,"SRS root sequence: u %d, v %d\n",u,v);
+  LOG_D(PHY,"CommonSrsConfig:    Csrs %d, Ssrs %d, AnSrsSimultan %d \n",Csrs,Ssrs,frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission);
+  LOG_D(PHY,"DedicatedSrsConfig: Bsrs %d, bhop %d, nRRC %d, Isrs %d, kTC %d, n_SRS %d\n",Bsrs,soundingrs_ul_config_dedicated->srs_HoppingBandwidth,n_RRC
+                                                                                       ,soundingrs_ul_config_dedicated->srs_ConfigIndex,kTC
+                                                                                       ,soundingrs_ul_config_dedicated->cyclicShift);
 
   if (frame_parms->N_RB_UL < 41) {
     msrs0 = msrsb_6_40[Csrs][0];
@@ -161,7 +170,7 @@ int32_t generate_srs_tx(PHY_VARS_UE *ue,
   }
 
   Msc_RS = msrsb * 6;
-  k0 = (((frame_parms->N_RB_UL>>1)-(msrs0>>1))*12) + kTC;
+  k0 = ( ( (int16_t)(frame_parms->N_RB_UL>>1) - (int16_t)(msrs0>>1) ) * 12 ) + kTC;
   nb  = (4*n_RRC/msrsb)%Nb;
 
   for (b=0; b<=Bsrs; b++) {
@@ -200,53 +209,32 @@ int32_t generate_srs_tx(PHY_VARS_UE *ue,
   msg("generate_srs_tx: Msc_RS = %d, Msc_RS_idx = %d\n",Msc_RS, Msc_RS_idx);
 #endif
 
-  T_SFC = (Ssrs<=7 ? 5 : 10);
-
-  if ((1<<(subframe%T_SFC))&transmission_offset_tdd[Ssrs]) {
+    carrier_pos = (frame_parms->first_carrier_offset + k0);
+    if (carrier_pos>frame_parms->ofdm_symbol_size) {
+        carrier_pos -= frame_parms->ofdm_symbol_size;
+    }
+    uint16_t nsymb = (frame_parms->Ncp==0) ? 14:12;
+    symbol_offset = (int)frame_parms->ofdm_symbol_size*((subframe*nsymb)+(nsymb-1));
 
-#ifndef IFFT_FPGA_UE
-    carrier_pos = (frame_parms->first_carrier_offset + k0) % frame_parms->ofdm_symbol_size;
     //msg("carrier_pos = %d\n",carrier_pos);
+    //subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->ofdm_symbol_size;
+    //symbol_offset = subframe_offset+(frame_parms->symbols_per_tti-1)*frame_parms->ofdm_symbol_size;
 
-    subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->ofdm_symbol_size;
-    symbol_offset = subframe_offset+(frame_parms->symbols_per_tti-1)*frame_parms->ofdm_symbol_size;
+    int32_t *txptr;
+    txptr = &txdataF[0][symbol_offset];
 
     for (k=0; k<Msc_RS; k++) {
-      ((short*) txdataF)[2*(symbol_offset + carrier_pos)]   = (short) (((int32_t) amp * (int32_t) ul_ref_sigs[0][0][Msc_RS_idx][k<<1])>>15);
-      ((short*) txdataF)[2*(symbol_offset + carrier_pos)+1] = (short) (((int32_t) amp * (int32_t) ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1])>>15);
-      carrier_pos+=2;
+      int32_t real = ((int32_t) amp * (int32_t) ul_ref_sigs[u][v][Msc_RS_idx][k<<1])     >> 15;
+      int32_t imag = ((int32_t) amp * (int32_t) ul_ref_sigs[u][v][Msc_RS_idx][(k<<1)+1]) >> 15;
+      txptr[carrier_pos] = (real&0xFFFF) + ((imag<<16)&0xFFFF0000);
 
-      if (carrier_pos >= frame_parms->ofdm_symbol_size)
-        carrier_pos=1;
-    }
 
-#else
-    carrier_pos = (frame_parms->N_RB_UL*12/2 + k0) % (frame_parms->N_RB_UL*12);
-    //msg("carrier_pos = %d\n",carrier_pos);
+      carrier_pos = carrier_pos+2;
 
-    subframe_offset = subframe*frame_parms->symbols_per_tti*frame_parms->N_RB_UL*12;
-    symbol_offset = subframe_offset+(frame_parms->symbols_per_tti-1)*frame_parms->N_RB_UL*12;
-
-    for (k=0; k<Msc_RS; k++) {
-      if ((ul_ref_sigs[0][0][Msc_RS_idx][k<<1] >= 0) && (ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1] >= 0))
-        txdataF[symbol_offset+carrier_pos] = (int32_t) 4;
-      else if ((ul_ref_sigs[0][0][Msc_RS_idx][k<<1] >= 0) && (ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1] < 0))
-        txdataF[symbol_offset+carrier_pos] = (int32_t) 2;
-      else if ((ul_ref_sigs[0][0][Msc_RS_idx][k<<1] < 0) && (ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1] >= 0))
-        txdataF[symbol_offset+carrier_pos] = (int32_t) 3;
-      else if ((ul_ref_sigs[0][0][Msc_RS_idx][k<<1] < 0) && (ul_ref_sigs[0][0][Msc_RS_idx][(k<<1)+1] < 0))
-        txdataF[symbol_offset+carrier_pos] = (int32_t) 1;
-
-      carrier_pos+=2;
-
-      if (carrier_pos >= frame_parms->N_RB_UL*12)
-        carrier_pos=0;
+      if (carrier_pos >= frame_parms->ofdm_symbol_size)
+        carrier_pos=carrier_pos-frame_parms->ofdm_symbol_size;
     }
 
-#endif
-    //  write_output("srs_txF.m","srstxF",&txdataF[symbol_offset],512,1,1);
-  }
-
   return(0);
 }
 
diff --git a/openair1/PHY/LTE_TRANSPORT/sss.c b/openair1/PHY/LTE_TRANSPORT/sss.c
index 39112725b12369d185e1e87126a1021d81223aa5..320d7ac75ad7604b964a075a58ae10b4ebda761b 100644
--- a/openair1/PHY/LTE_TRANSPORT/sss.c
+++ b/openair1/PHY/LTE_TRANSPORT/sss.c
@@ -59,10 +59,10 @@ int generate_sss(int32_t **txdataF,
 
   Nsymb = (frame_parms->Ncp==NORMAL)?14:12;
   k = frame_parms->ofdm_symbol_size-3*12+5;
-  a = (frame_parms->nb_antennas_tx == 1) ? amp : (amp*ONE_OVER_SQRT2_Q15)>>15;
+  a = (frame_parms->nb_antenna_ports_eNB == 1) ? amp : (amp*ONE_OVER_SQRT2_Q15)>>15;
 
   for (i=0; i<62; i++) {
-    for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+    for (aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) {
 
       ((int16_t*)txdataF[aa])[2*(slot_offset*Nsymb/2*frame_parms->ofdm_symbol_size +
                                  symbol*frame_parms->ofdm_symbol_size + k)] =
diff --git a/openair1/PHY/LTE_TRANSPORT/uci_tools.c b/openair1/PHY/LTE_TRANSPORT/uci_tools.c
index a8f9f6ba574978ff72f164cdf93e11f1ad7f4dd8..37c5dc1432ef818de613c74f757880b5754409d8 100644
--- a/openair1/PHY/LTE_TRANSPORT/uci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/uci_tools.c
@@ -836,3 +836,5 @@ void print_CQI(void *o,UCI_format_t uci_format,unsigned char eNB_id,int N_RB_DL)
 
 }
 
+
+
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c
index 53eaa849fd9eaac63cafc8f8d734ff494d56534f..4559aaa326bd620137d0e6184db2b0cd222c6757 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c
@@ -140,6 +140,8 @@ LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag)
   if (ulsch) {
     memset(ulsch,0,sizeof(LTE_UE_ULSCH_t));
 
+    ulsch->Mlimit = 4;
+
     for (i=0; i<8; i++) {
 
       ulsch->harq_processes[i] = (LTE_UL_UE_HARQ_t *)malloc16(sizeof(LTE_UL_UE_HARQ_t));
@@ -498,6 +500,21 @@ uint32_t ulsch_encoding(uint8_t *a,
 
 
     G = G - Q_RI - Q_CQI;
+    ulsch->harq_processes[harq_pid]->G = G;
+
+/*
+    LOG_I(PHY,"ULSCH Encoding G %d, Q_RI %d (O_RI%d, Msc_initial %d, Nsymb_initial%d, beta_offset_ri_times8 %d), Q_CQI %d, Q_ACK %d \n",G,Q_RI,ulsch->O_RI,ulsch->harq_processes[harq_pid]->Msc_initial,ulsch->harq_processes[harq_pid]->Nsymb_initial,ulsch->beta_offset_ri_times8,Q_CQI,Q_ACK);
+
+    LOG_I(PHY,"ULSCH Encoding (Nid_cell %d, rnti %x): harq_pid %d round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d\n",
+          frame_parms->Nid_cell,ulsch->rnti,
+          harq_pid,
+          ulsch->harq_processes[harq_pid]->round,
+          ulsch->harq_processes[harq_pid]->rvidx,
+          ulsch->harq_processes[harq_pid]->mcs,
+          ulsch->O_RI,
+          ulsch->harq_processes[harq_pid]->O_ACK,
+          G);
+*/
 
     if ((int)G < 0) {
       LOG_E(PHY,"FATAL: ulsch_coding.c G < 0 (%d) : Q_RI %d, Q_CQI %d, O %d, betaCQI_times8 %d)\n",G,Q_RI,Q_CQI,ulsch->O,ulsch->beta_offset_cqi_times8);
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
index 0ce810a52cfabd7d856bcee07d0f7cfe095abef8..8edb1eaf9460443a4ebe58ceba7776c42a696ad2 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
@@ -872,7 +872,7 @@ unsigned int  ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
   int16_t ys,c;
   uint32_t wACK_idx;
   uint8_t dummy_w_cc[3*(MAX_CQI_BITS+8+32)];
-  int16_t y[6*14*1200];
+  int16_t y[6*14*1200] __attribute__((aligned(32)));
   uint8_t ytag[14*1200];
   //  uint8_t ytag2[6*14*1200],*ytag2_ptr;
   int16_t cseq[6*14*1200];
@@ -1440,9 +1440,9 @@ unsigned int  ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
       
       j2+=Q_m;
     }
-
+    /* To be improved according to alignment of j2
 #if defined(__x86_64__)||defined(__i386__)
-#ifndef __AVX2
+#ifndef __AVX2__
     for (iprime=0; iprime<G;iprime+=8,j2+=8)
       *((__m128i *)&ulsch_harq->e[iprime]) = *((__m128i *)&y[j2]);
 #else
@@ -1452,9 +1452,24 @@ unsigned int  ulsch_decoding(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,
 #elif defined(__arm__)
     for (iprime=0; iprime<G;iprime+=8,j2+=8)
       *((int16x8_t *)&ulsch_harq->e[iprime]) = *((int16x8_t *)&y[j2]);
-#endif 
+#endif
+    */
+    int16_t *yp,*ep;
+    for (iprime=0,yp=&y[j2],ep=&ulsch_harq->e[0]; 
+	 iprime<G;
+	 iprime+=8,j2+=8,ep+=8,yp+=8) {
+      ep[0] = yp[0];
+      ep[1] = yp[1];
+      ep[2] = yp[2];
+      ep[3] = yp[3];
+      ep[4] = yp[4];
+      ep[5] = yp[5];
+      ep[6] = yp[6];
+      ep[7] = yp[7];
+    }
   }
-
+    
+   
   stop_meas(&eNB->ulsch_demultiplexing_stats);
 
   //  printf("after ACKNAK2 c[%d] = %p (iprime %d, G %d)\n",0,ulsch_harq->c[0],iprime,G);
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c
index 80168dd3c5519dee1d67d688d0419b30b7721526..ee9bfc53cdd431c2fb7770914f6dcfe3091be058 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_modulation.c
@@ -426,13 +426,14 @@ void ulsch_modulation(int32_t **txdataF,
 
   G = (int)ulsch->harq_processes[harq_pid]->nb_rb * (12 * Q_m) * (ulsch->Nsymb_pusch);
 
+
   // Mapping
   nsymb = (frame_parms->Ncp==0) ? 14:12;
   Msc_PUSCH = ulsch->harq_processes[harq_pid]->nb_rb*12;
 
 #ifdef DEBUG_ULSCH_MODULATION
-  printf("ulsch_modulation.c: Doing modulation (rnti %x,x2 %x) for G=%d bits, harq_pid %d , nb_rb %d, Q_m %d, Nsymb_pusch %d (nsymb %d), subframe %d\n",
-      ulsch->rnti,x2,G,harq_pid,ulsch->harq_processes[harq_pid]->nb_rb,Q_m, ulsch->Nsymb_pusch,nsymb,subframe);
+  LOG_D(PHY,"ulsch_modulation.c: Doing modulation (rnti %x,x2 %x) for G=%d bits, harq_pid %d , nb_rb %d, Q_m %d, Nsymb_pusch %d (nsymb %d), subframe %d\n",
+        ulsch->rnti,x2,G,harq_pid,ulsch->harq_processes[harq_pid]->nb_rb,Q_m, ulsch->Nsymb_pusch,nsymb,subframe);
 #endif
 
   // scrambling (Note the placeholding bits are handled in ulsch_coding.c directly!)
diff --git a/openair1/PHY/MODULATION/beamforming.c b/openair1/PHY/MODULATION/beamforming.c
new file mode 100644
index 0000000000000000000000000000000000000000..6557a47ee7a35c6d31ea267cdb7762c0ffede9d5
--- /dev/null
+++ b/openair1/PHY/MODULATION/beamforming.c
@@ -0,0 +1,91 @@
+/*******************************************************************************
+  OpenAirInterface
+  Copyright(c) 1999 - 2014 Eurecom
+
+  OpenAirInterface is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+
+  OpenAirInterface is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with OpenAirInterface.The full GNU General Public License is
+  included in this distribution in the file called "COPYING". If not,
+  see <http://www.gnu.org/licenses/>.
+
+  Contact Information
+  OpenAirInterface Admin: openair_admin@eurecom.fr
+  OpenAirInterface Tech : openair_tech@eurecom.fr
+  OpenAirInterface Dev  : openair4g-devel@eurecom.fr
+
+Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+
+/*! \file PHY/MODULATION/beamforming.c
+ * \brief 
+ * \author X. JIANG, F. Kaltenberger, R. KNOPP
+ * \date 2016
+ * \version 0.1
+ * \company Eurecom
+ * \email: xiwen.jiang@eurecom.fr,florian.kaltenberger@eurecom.fr,raymond.knopp@eurecom.fr
+ * \note
+ * \warning
+ */
+#include "PHY/defs.h"
+#include "PHY/extern.h"
+#include "PHY/CODING/defs.h"
+#include "PHY/CODING/extern.h"
+#include "PHY/CODING/lte_interleaver_inline.h"
+#include "PHY/LTE_TRANSPORT/defs.h"
+#include "defs.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+
+int beam_precoding(int32_t **txdataF,
+	           int32_t **txdataF_BF,
+                   LTE_DL_FRAME_PARMS *frame_parms,
+	           int32_t ***beam_weights,
+                   int slot,
+                   int symbol,
+                   int aa)
+{
+  uint8_t p;
+  uint16_t re=0;
+  int slot_offset_F;
+  
+  slot_offset_F = slot*(frame_parms->ofdm_symbol_size)*((frame_parms->Ncp==1) ? 6 : 7);
+
+  // clear txdata_BF[aa][re] for each call of ue_spec_beamforming
+  memset(txdataF_BF[aa],0,sizeof(int32_t)*(frame_parms->ofdm_symbol_size));
+
+  for (p=0; p<14; p++) {
+    //if (p==0 || p==1 || p==5 || p>7)
+    //  mult_cpx_conj_vector((int16_t*)txdataF[p], (int16_t*)beam_weights[p][aa], (int16_t*)txdataF_BF[aa], frame_parms->ofdm_symbol_size, 15);
+    for (re=0;re<frame_parms->ofdm_symbol_size;re++) {
+      if ((p==0 || p==1 || p==5 || p>=7) && txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re]!=0) {
+        ((int16_t*)&txdataF_BF[aa][re])[0] += (int16_t)((((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[0]*((int16_t*)&beam_weights[p][aa][re])[0])>>15);
+        ((int16_t*)&txdataF_BF[aa][re])[0] -= (int16_t)((((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[1]*((int16_t*)&beam_weights[p][aa][re])[1])>>15);
+        ((int16_t*)&txdataF_BF[aa][re])[1] += (int16_t)((((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[0]*((int16_t*)&beam_weights[p][aa][re])[1])>>15);
+        ((int16_t*)&txdataF_BF[aa][re])[1] += (int16_t)((((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[1]*((int16_t*)&beam_weights[p][aa][re])[0])>>15);
+
+	  /*
+          printf("beamforming.c:txdataF[%d][%d]=%d+j%d, beam_weights[%d][%d][%d]=%d+j%d,txdata_BF[%d][%d]=%d+j%d\n",
+                 p,slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re,
+                 ((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[0],
+                 ((int16_t*)&txdataF[p][slot_offset_F+symbol*frame_parms->ofdm_symbol_size+re])[1],
+                 p,aa,re,
+                 ((int16_t*)&beam_weights[p][aa][re])[0],((int16_t*)&beam_weights[p][aa][re])[1],
+                 aa,re,
+                 ((int16_t*)&txdataF_BF[aa][re])[0],
+                 ((int16_t*)&txdataF_BF[aa][re])[1]); 
+	  */
+      } 
+    }
+  }
+  return 0;
+}
diff --git a/openair1/PHY/MODULATION/compute_bf_weights.c b/openair1/PHY/MODULATION/compute_bf_weights.c
new file mode 100644
index 0000000000000000000000000000000000000000..32a91c11f50706718e3c75823ec48a67c6d9806c
--- /dev/null
+++ b/openair1/PHY/MODULATION/compute_bf_weights.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <stdint.h>
+#include "PHY/impl_defs_lte.h"
+
+int f_read(char *calibF_fname, int nb_ant, int nb_freq, int32_t **tdd_calib_coeffs){
+
+  FILE *calibF_fd;
+  int i,j,l,calibF_e;
+  
+  calibF_fd = fopen(calibF_fname,"r");
+ 
+  if (calibF_fd) {
+    printf("Loading Calibration matrix from %s\n", calibF_fname);
+  
+    for(i=0;i<nb_ant;i++){
+      for(j=0;j<nb_freq*2;j++){
+  fscanf(calibF_fd, "%d", &calibF_e);
+        tdd_calib_coeffs[i][j] = (int16_t)calibF_e;
+      }
+    }
+    printf("%d\n",(int)tdd_calib_coeffs[0][0]);
+    printf("%d\n",(int)tdd_calib_coeffs[1][599]);
+  } else
+   printf("%s not found, running with defaults\n",calibF_fname);
+}
+
+
+int estimate_DLCSI_from_ULCSI(int32_t **calib_dl_ch_estimates, int32_t **ul_ch_estimates, int32_t **tdd_calib_coeffs, int nb_ant, int nb_freq) {
+
+
+}
+
+int compute_BF_weights(int32_t **beam_weights, int32_t **calib_dl_ch_estimates, PRECODE_TYPE_t precode_type, int nb_ant, int nb_freq) {
+  switch (precode_type) {
+  //case MRT
+  case 0 :
+  //case ZF
+  break;
+  case 1 :
+  //case MMSE
+  break;
+  case 2 :
+  break;
+  default :
+  break;  
+}
+} 
+
+// temporal test function
+/*
+void main(){
+  // initialization
+  // compare
+  printf("Hello world!\n");
+}
+*/
diff --git a/openair1/PHY/MODULATION/defs.h b/openair1/PHY/MODULATION/defs.h
index fdf76e61aa41f7e3f351be65f820fa2dcc85d02f..da599114a91919c05cb66631bc751c2dc1ce3ab4 100644
--- a/openair1/PHY/MODULATION/defs.h
+++ b/openair1/PHY/MODULATION/defs.h
@@ -82,6 +82,8 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA
 
 void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms);
 
+void do_OFDM_mod_symbol(LTE_eNB_COMMON *eNB_common_vars, int eNB_id, uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms,int do_precoding);
+
 void remove_7_5_kHz(PHY_VARS_eNB *phy_vars_eNB,uint8_t subframe);
 
 void apply_7_5_kHz(PHY_VARS_UE *phy_vars_ue,int32_t*txdata,uint8_t subframe);
@@ -92,6 +94,32 @@ void remove_625_Hz(PHY_VARS_eNB *phy_vars_eNB,int16_t *prach);
 
 void apply_625_Hz(PHY_VARS_UE *phy_vars_ue,int16_t *prach);
 
+/** \brief This function performs beamforming precoding for common
+ * data
+    @param txdataF Table of pointers for frequency-domain TX signals
+    @param txdataF_BF Table of pointers for frequency-domain TX signals
+    @param frame_parms Frame descriptor structure
+after beamforming
+    @param beam_weights Beamforming weights applied on each
+antenna element and each carrier
+    @param slot Slot number
+    @param symbol Symbol index on which to act
+    @param aa physical antenna index*/
+int beam_precoding(int32_t **txdataF,
+	           int32_t **txdataF_BF,
+                   LTE_DL_FRAME_PARMS *frame_parms,
+	           int32_t ***beam_weights,
+                   int slot,
+                   int symbol,
+                   int aa);
+
+int f_read(char *calibF_fname, int nb_ant, int nb_freq, int32_t **tdd_calib_coeffs);
+
+int estimate_DLCSI_from_ULCSI(int32_t **calib_dl_ch_estimates, int32_t **ul_ch_estimates, int32_t **tdd_calib_coeffs, int nb_ant, int nb_freq);
+
+int compute_BF_weights(int32_t **beam_weights, int32_t **calib_dl_ch_estimates, PRECODE_TYPE_t precode_type, int nb_ant, int nb_freq);
+
+
 #endif
 /** @}*/
 #endif
diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c
index ab8d376ac58bbe3e080dfeda2ad59a11c7fc4496..953e130115dfd67f948cc23e6f5d696283002223 100644
--- a/openair1/PHY/MODULATION/ofdm_mod.c
+++ b/openair1/PHY/MODULATION/ofdm_mod.c
@@ -31,6 +31,7 @@ This section deals with basic functions for OFDM Modulation.
 
 #include "PHY/defs.h"
 #include "UTIL/LOG/log.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
 
 //static short temp2[2048*4] __attribute__((aligned(16)));
 
@@ -283,4 +284,58 @@ void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t ne
 
 }
 
-/** @} */
+// OFDM modulation for each symbol
+void do_OFDM_mod_symbol(LTE_eNB_COMMON *eNB_common_vars, int eNB_id, uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms,int do_precoding)
+{
+
+  int aa, l, slot_offset;
+  int32_t **txdataF = eNB_common_vars->txdataF[eNB_id];
+  int32_t **txdataF_BF = (do_precoding==1)?eNB_common_vars->txdataF_BF[eNB_id]:txdataF;
+  int32_t **txdata = eNB_common_vars->txdata[eNB_id];
+
+  slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1);
+
+  //printf("Thread %d starting ... aa %d (%llu)\n",omp_get_thread_num(),aa,rdtsc());
+  for (l=0; l<frame_parms->symbols_per_tti>>1; l++) {
+  
+    for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+
+      //printf("do_OFDM_mod_l, slot=%d, l=%d, NUMBER_OF_OFDM_CARRIERS=%d,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES=%d\n",next_slot, l,NUMBER_OF_OFDM_CARRIERS,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES);
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,1);
+      if (do_precoding==1) beam_precoding(txdataF,txdataF_BF,frame_parms,eNB_common_vars->beam_weights[eNB_id],next_slot,l,aa);
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,0);
+
+      //PMCH case not implemented... 
+
+      if (frame_parms->Ncp == 1)
+        PHY_ofdm_mod(txdataF_BF[aa],         // input
+                     &txdata[aa][slot_offset+l*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],            // output
+                     frame_parms->ofdm_symbol_size,       
+                     1,                                   // number of symbols
+                     frame_parms->nb_prefix_samples,      // number of prefix samples
+                     CYCLIC_PREFIX);
+      else {
+        if (l==0) {
+          PHY_ofdm_mod(txdataF_BF[aa],        // input
+                       &txdata[aa][slot_offset],           // output
+                       frame_parms->ofdm_symbol_size,      
+                       1,                                  // number of symbols
+                       frame_parms->nb_prefix_samples0,    // number of prefix samples
+                       CYCLIC_PREFIX);
+           
+        } else {
+          PHY_ofdm_mod(txdataF_BF[aa],        // input
+                       &txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],           // output
+                       frame_parms->ofdm_symbol_size,      
+                       1,                                  // number of symbols
+                       frame_parms->nb_prefix_samples,     // number of prefix samples
+                       CYCLIC_PREFIX);
+
+          /* printf("txdata[%d][%d]=%d\n",aa,slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES,txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES]);
+ * */
+        }
+      }
+    }
+  }
+
+}
diff --git a/openair1/PHY/MODULATION/slot_fep.c b/openair1/PHY/MODULATION/slot_fep.c
index 0a592a1a19502f9f126f3cc7d48ce86819e990ec..94de0d3cbcae958fc5fd50d99186736a2f209973 100644
--- a/openair1/PHY/MODULATION/slot_fep.c
+++ b/openair1/PHY/MODULATION/slot_fep.c
@@ -47,6 +47,11 @@ int slot_fep(PHY_VARS_UE *ue,
   unsigned int frame_length_samples = frame_parms->samples_per_tti * 10;
   unsigned int rx_offset;
 
+  /*LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id];
+  unsigned char harq_pid = dlsch_ue[0]->current_harq_pid; 
+  LTE_DL_UE_HARQ_t *dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid];
+  int uespec_pilot[9][1200];*/
+
   void (*dft)(int16_t *,int16_t *, int);
   int tmp_dft_in[2048] __attribute__ ((aligned (32)));  // This is for misalignment issues for 6 and 15 PRBs
 
@@ -175,7 +180,7 @@ int slot_fep(PHY_VARS_UE *ue,
 
   if (ue->perfect_ce == 0) {
     if ((l==0) || (l==(4-frame_parms->Ncp))) {
-      for (aa=0; aa<frame_parms->nb_antennas_tx_eNB; aa++) {
+      for (aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) {
 
 #ifdef DEBUG_FEP
         printf("Channel estimation eNB %d, aatx %d, slot %d, symbol %d\n",eNB_id,aa,Ns,l);
@@ -215,6 +220,7 @@ int slot_fep(PHY_VARS_UE *ue,
 
       }
     }
+
   }
 
 #ifdef DEBUG_FEP
diff --git a/openair1/PHY/Makefile.inc b/openair1/PHY/Makefile.inc
index 06f944748831600d34b9728c60028e087df6fa99..1586f353c0f623853f6149ca91f313630847b92a 100644
--- a/openair1/PHY/Makefile.inc
+++ b/openair1/PHY/Makefile.inc
@@ -1,6 +1,7 @@
 PHY_OBJS =  $(TOP_DIR)/PHY/LTE_TRANSPORT/pss.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/sss.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/pilots.o
+PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/pilots_ue_spec.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/pilots_mbsfn.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_coding.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_TRANSPORT/dlsch_modulation.o
@@ -40,6 +41,7 @@ PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_sync_time.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_sync_timefreq.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_adjust_sync.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.o
+PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_est_freq_offset.o
@@ -47,7 +49,7 @@ PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_ue_measurements.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/lte_eNB_measurements.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_ESTIMATION/adjust_gain.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_dl_cell_spec.o
-PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_dl_uespec.o
+PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_dl_ue_spec.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_gold.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_gold_mbsfn.o
 PHY_OBJS += $(TOP_DIR)/PHY/LTE_REFSIG/lte_dl_mbsfn.o
diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c
index 1465da6544533bfadcd25c9ee262f2fb4c044de2..768dedddf548c9275605742c12b80acc61dcd324 100644
--- a/openair1/PHY/TOOLS/lte_phy_scope.c
+++ b/openair1/PHY/TOOLS/lte_phy_scope.c
@@ -484,7 +484,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
   LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms;
   int nsymb_ce = frame_parms->ofdm_symbol_size;//*frame_parms->symbols_per_tti;
   uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
-  uint8_t nb_antennas_tx = frame_parms->nb_antennas_tx_eNB;
+  uint8_t nb_antennas_tx = frame_parms->nb_antenna_ports_eNB;
   int16_t **rxsig_t;
   int16_t **chest_t;
   int16_t **chest_f;
@@ -507,6 +507,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
   int coded_bits_per_codeword = 0;
   int mcs = 0;
   unsigned char harq_pid = 0;
+  int beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0;
 
 
   if (phy_vars_ue->dlsch[eNB_id][0]!=NULL) {
@@ -537,7 +538,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
                                     phy_vars_ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl,
                                     num_pdcch_symbols,
                                     frame,
-                                    subframe);
+                                    subframe,
+                                    beamforming_mode);
   } else {
     coded_bits_per_codeword = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti);
   }
diff --git a/openair1/PHY/TOOLS/read_F.c b/openair1/PHY/TOOLS/read_F.c
new file mode 100644
index 0000000000000000000000000000000000000000..32ade0dfdb698c69c1ccc0cf757c10e739787822
--- /dev/null
+++ b/openair1/PHY/TOOLS/read_F.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<stdint.h>
+
+int f_read(char *calibF_fname, int nb_antM, int nb_freq, int16_t (*calibF_mtx)[nb_freq*2]){
+
+  FILE *calibF_fd;
+  int i,j,l,calibF_e;
+  
+  calibF_fd = fopen(calibF_fname,"r");
+ 
+  if (calibF_fd) {
+    printf("Loading Calibration matrix from %s\n", calibF_fname);
+  
+    for(i=0;i<nb_antM;i++){
+      for(j=0;j<nb_freq*2;j++){
+	fscanf(calibF_fd, "%d", &calibF_e);
+        calibF_mtx[i][j] = (int16_t)calibF_e;
+      }
+    }
+    printf("%d\n",(int)calibF_mtx[0][0]);
+    printf("%d\n",(int)calibF_mtx[1][599]);
+  } else
+   printf("%s not found, running with defaults\n",calibF_fname);
+}
diff --git a/openair1/PHY/TOOLS/smbv.c b/openair1/PHY/TOOLS/smbv.c
index f00bc017a01381df019999f4cb5bb009d510d140..adc512d7e5a2aeac61db41b8ae0e87d9cfd3841f 100644
--- a/openair1/PHY/TOOLS/smbv.c
+++ b/openair1/PHY/TOOLS/smbv.c
@@ -119,7 +119,7 @@ int smbv_write_config_from_frame_parms(const char* fname, LTE_DL_FRAME_PARMS *fr
   fprintf(f_ptr, "BB:EUTR:TDD:SPSC %d\n",frame_parms->tdd_config_S);
 
   // MIMO
-  fprintf(f_ptr, "BB:EUTR:DL:MIMO:CONF TX%d\n",frame_parms->nb_antennas_tx_eNB);
+  fprintf(f_ptr, "BB:EUTR:DL:MIMO:CONF TX%d\n",frame_parms->nb_antenna_ports_eNB);
   fprintf(f_ptr, "BB:EUTR:DL:MIMO:ANTA ANT1\n");
   fprintf(f_ptr, "BB:EUTR:DL:MIMO:ANTB NONE\n");
 
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 7922fb131ed12a33f9b1214de851583e40999e5b..51e50e0a976d840036546b3474fb215721023125 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -436,6 +436,8 @@ typedef struct PHY_VARS_eNB_s {
   int                  in_synch;
   // indicator for master/slave (RRU)
   int                  is_slave;
+  // indicator for precoding function (eNB,3GPP_eNB_BBU)
+  int                  do_precoding;
   void                 (*do_prach)(struct PHY_VARS_eNB_s *eNB,int frame,int subframe);
   void                 (*fep)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc);
   int                  (*td)(struct PHY_VARS_eNB_s *eNB,int UE_id,int harq_pid,int llr8_flag);
@@ -454,9 +456,6 @@ typedef struct PHY_VARS_eNB_s {
   LTE_eNB_COMMON       common_vars;
   LTE_eNB_SRS          srs_vars[NUMBER_OF_UE_MAX];
   LTE_eNB_PBCH         pbch;
-  /// \brief ?.
-  /// - first index: UE [0..NUMBER_OF_UE_MAX[ (hard coded)
-  /// - second index: UE [0..NUMBER_OF_UE_MAX[
   LTE_eNB_PUSCH       *pusch_vars[NUMBER_OF_UE_MAX];
   LTE_eNB_PRACH        prach_vars;
   LTE_eNB_DLSCH_t     *dlsch[NUMBER_OF_UE_MAX][2];   // Nusers times two spatial streams
@@ -469,6 +468,9 @@ typedef struct PHY_VARS_eNB_s {
   /// cell-specific reference symbols
   uint32_t         lte_gold_table[20][2][14];
 
+  /// UE-specific reference symbols (p=5), TM 7
+  uint32_t         lte_gold_uespec_port5_table[NUMBER_OF_UE_MAX][20][38];
+
   /// UE-specific reference symbols (p=7...14), TM 8/9/10
   uint32_t         lte_gold_uespec_table[2][20][2][21];
 
@@ -679,7 +681,7 @@ typedef struct {
   /// \brief Total gains with bypassed RF gain stage (ExpressMIMO2/Lime)
   uint32_t rx_gain_byp[4];
   /// \brief Current transmit power
-  int8_t tx_power_dBm[10];
+  int16_t tx_power_dBm[10];
   /// \brief Total number of REs in current transmission
   int tx_total_RE[10];
   /// \brief Maximum transmit power
@@ -729,8 +731,11 @@ typedef struct {
   /// cell-specific reference symbols
   uint32_t lte_gold_table[7][20][2][14];
 
+  /// UE-specific reference symbols (p=5), TM 7
+  uint32_t lte_gold_uespec_port5_table[20][38];
+
   /// ue-specific reference symbols
-  uint32_t         lte_gold_uespec_table[2][20][2][21];
+  uint32_t lte_gold_uespec_table[2][20][2][21];
 
   /// mbsfn reference symbols
   uint32_t lte_gold_mbsfn_table[10][3][42];
diff --git a/openair1/PHY/extern.h b/openair1/PHY/extern.h
index 09d4c74f5234d34ccf8260aa72aff0ac0eab5044..0eb5dc6c97de931dd421bacf0c09b5af394a47e8 100644
--- a/openair1/PHY/extern.h
+++ b/openair1/PHY/extern.h
@@ -117,5 +117,17 @@ extern char eNB_timing[2][20];
 extern int16_t unscrambling_lut[65536*16];
 extern uint8_t scrambling_lut[65536*16];
 
+extern unsigned short msrsb_6_40[8][4];
+extern unsigned short msrsb_41_60[8][4];
+extern unsigned short msrsb_61_80[8][4];
+extern unsigned short msrsb_81_110[8][4];
+extern unsigned short Nb_6_40[8][4];
+extern unsigned short Nb_41_60[8][4];
+extern unsigned short Nb_61_80[8][4];
+extern unsigned short Nb_81_110[8][4];
+
+extern uint16_t hundred_times_log10_NPRB[100];
+extern uint8_t alpha_lut[8];
+
 #endif /*__PHY_EXTERN_H__ */
 
diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h
index f80effbebd4ff67f104c155a083f103e79e0c70e..7a30bff6abefa8ae8b0f4599cce5da4c9919994d 100644
--- a/openair1/PHY/impl_defs_lte.h
+++ b/openair1/PHY/impl_defs_lte.h
@@ -142,6 +142,11 @@ typedef struct {
   uint8_t nCS_AN;
   /// Parameter: \f$N^{(1)}_\text{PUCCH}\f$ see TS 36.213 (10.1). \vr{[0..2047]}
   uint16_t n1PUCCH_AN;
+
+  /// group hopping sequence for DRS \note not part of offical UL-PUCCH_CONFIG_COMMON ASN1 specification.
+  uint8_t grouphop[20];
+  /// sequence hopping sequence for DRS \note not part of offical UL-PUCCH_CONFIG_COMMON ASN1 specification.
+  uint8_t seqhop[20];
 } PUCCH_CONFIG_COMMON;
 
 /// UL-ReferenceSignalsPUSCH from 36.331 RRC spec
@@ -315,6 +320,12 @@ typedef struct {
   uint16_t srs_ConfigIndex;
   /// Parameter: \f$n^\text{CS}_\text{SRS}\f$. See TS 36.211 (5.5.3.1). \vr{[0..7]} \note the specification sais it is an enumerated value.
   uint8_t cyclicShift;
+  // Parameter: ue srs subframe for internal implementation
+  uint8_t srsConfigDedicatedSetup;
+  // Parameter: cell srs subframe for internal implementation
+  uint8_t srsCellSubframe;
+  // Parameter: ue srs subframe for internal implementation
+  uint8_t srsUeSubframe;
 } SOUNDINGRS_UL_CONFIG_DEDICATED;
 
 /// UplinkPowerControlDedicated Information Element from 36.331 RRC spec
@@ -418,16 +429,20 @@ typedef struct {
 
 /// CQI-ReportPeriodic
 typedef struct {
-  /// Parameter: \f$n^{(2)}_\text{PUCCH}\f$, see TS 36.213 (7.2). \vr{[0..1185]}
-  uint16_t cqi_PUCCH_ResourceIndex;
+  /// Parameter: \f$n^{(2)}_\text{PUCCH}\f$, see TS 36.213 (7.2). \vr{[0..1185]}, -1 indicates inactivity
+  int16_t cqi_PUCCH_ResourceIndex;
   /// Parameter: CQI/PMI Periodicity and Offset Configuration Index \f$I_\text{CQI/PMI}\f$, see TS 36.213 (tables 7.2.2-1A and 7.2.2-1C). \vr{[0..1023]}
-  uint16_t cqi_PMI_ConfigIndex;
+  int16_t cqi_PMI_ConfigIndex;
   /// Parameter: K, see 36.213 (4.2.2). \vr{[1..4]}
   uint8_t K;
-  /// Parameter: RI Config Index \f$I_\text{RI}\f$, see TS 36.213 (7.2.2-1B). \vr{[0..1023]}
-  uint16_t ri_ConfigIndex;
+  /// Parameter: RI Config Index \f$I_\text{RI}\f$, see TS 36.213 (7.2.2-1B). \vr{[0..1023]}, -1 indicates inactivity
+  int16_t ri_ConfigIndex;
   /// Parameter: Simultaneous-AN-and-CQI, see TS 36.213 (10.1). \vr{[0..1]} 1 indicates that simultaneous transmission of ACK/NACK and CQI is allowed.
   uint8_t simultaneousAckNackAndCQI;
+  /// parameter computed from Tables 7.2.2-1A and 7.2.2-1C
+  uint16_t Npd;
+  /// parameter computed from Tables 7.2.2-1A and 7.2.2-1C
+  uint16_t N_OFFSET_CQI;
 } CQI_REPORTPERIODIC;
 
 /// Enumeration for parameter reporting mode \ref CQI_REPORT_CONFIG::cqi_ReportModeAperiodic.
@@ -527,12 +542,12 @@ typedef struct {
   uint32_t samples_per_tti;
   /// Number of OFDM/SC-FDMA symbols in one subframe (to be modified to account for potential different in UL/DL)
   uint16_t symbols_per_tti;
-  /// Number of Transmit antennas in node
+  /// Number of Physical transmit antennas in node
   uint8_t nb_antennas_tx;
   /// Number of Receive antennas in node
   uint8_t nb_antennas_rx;
-  /// Number of Transmit antennas in eNodeB
-  uint8_t nb_antennas_tx_eNB;
+  /// Number of Logical transmit antenna ports in eNodeB
+  uint8_t nb_antenna_ports_eNB;
   /// PRACH_CONFIG
   PRACH_CONFIG_COMMON prach_config_common;
   /// PUCCH Config Common (from 36-331 RRC spec)
@@ -586,10 +601,20 @@ typedef enum {
   DUALSTREAM_UNIFORM_PRECODING1=9,
   DUALSTREAM_UNIFORM_PRECODINGj=10,
   DUALSTREAM_PUSCH_PRECODING=11,
-  TM8=12,
-  TM9_10=13
+  TM7=12,
+  TM8=13,
+  TM9_10=14
 } MIMO_mode_t;
 
+typedef enum {
+  /// MRT
+  MRT=0,
+  /// ZF
+  ZF=1,
+  /// MMSE
+  MMSE=2
+} PRECODE_TYPE_t;
+
 typedef struct {
   /// \brief Holds the transmit data in time domain.
   /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
@@ -598,11 +623,17 @@ typedef struct {
   /// - third index:
   int32_t **txdata[3];
   /// \brief holds the transmit data in the frequency domain.
-  /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
+  /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. //?
   /// - first index: eNB id [0..2] (hard coded)
-  /// - second index: tx antenna [0..nb_antennas_tx[
+  /// - second index: tx antenna [0..14[ where 14 is the total supported antenna ports.
   /// - third index: sample [0..]
   int32_t **txdataF[3];
+  /// \brief holds the transmit data after beamforming in the frequency domain.
+  /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. //?
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: tx antenna [0..nb_antennas_tx[
+  /// - third index: sample [0..]
+  int32_t **txdataF_BF[3];
   /// \brief Holds the received data in time domain.
   /// Should point to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
   /// - first index: sector id [0..2] (hard coded)
@@ -623,6 +654,17 @@ typedef struct {
   /// - first index: sector id [0..2] (hard coded)
   /// - second index: sample [0..samples_per_tti*10[
   uint32_t *sync_corr[3];
+  /// \brief Holds the beamforming weights
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: eNB antenna port index (hard coded)
+  /// - third index: tx antenna [0..nb_antennas_tx[
+  /// - fourth index: sample [0..]
+  int32_t **beam_weights[3][15];
+  /// \brief Holds the tdd reciprocity calibration coefficients 
+  /// - first index: eNB id [0..2] (hard coded) 
+  /// - second index: tx antenna [0..nb_antennas_tx[
+  /// - third index: frequency [0..]
+  int32_t **tdd_calib_coeffs[3];
 } LTE_eNB_COMMON;
 
 typedef struct {
@@ -783,6 +825,10 @@ typedef struct {
   /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
   /// - second index: ? [0..168*N_RB_DL[
   int32_t **rxdataF_ext;
+  /// \brief Received frequency-domain ue specific pilots.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..12*N_RB_DL[
+  int32_t **rxdataF_uespec_pilots;
   /// \brief Received frequency-domain signal after extraction and channel compensation.
   /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
   /// - second index: ? [0..168*N_RB_DL[
@@ -796,6 +842,14 @@ typedef struct {
   /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
   /// - second index: ? [0..168*N_RB_DL[
   int32_t **dl_ch_estimates_ext;
+  /// \brief Downlink beamforming channel estimates in frequency domain.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[
+  int32_t **dl_bf_ch_estimates;
+  /// \brief Downlink beamforming channel estimates.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_bf_ch_estimates_ext;
   /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS.
   /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
   /// - second index: ? [0..168*N_RB_DL[
@@ -999,13 +1053,13 @@ typedef struct {
   /// first index: ? [0..1023] (hard coded)
   int16_t *prachF;
   /// \brief ?.
-  /// first index: rx antenna [0..3] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
+  /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
   /// second index: ? [0..ofdm_symbol_size*12[
-  int16_t *rxsigF[4];
+  int16_t *rxsigF[64];
   /// \brief local buffer to compute prach_ifft (necessary in case of multiple CCs)
-  /// first index: rx antenna [0..3] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
+  /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
   /// second index: ? [0..2047] (hard coded)
-  int16_t *prach_ifft[4];
+  int16_t *prach_ifft[64];
 } LTE_eNB_PRACH;
 
 typedef struct {
diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h
index c9e468948ef685cb74f387734912ffc711e13eee..79e684215c7f815d1542670a44680b7cbec1f68f 100644
--- a/openair1/PHY/impl_defs_top.h
+++ b/openair1/PHY/impl_defs_top.h
@@ -177,6 +177,7 @@
 #define DMA_BLKS_PER_SLOT    (SLOT_LENGTH_BYTES/2048)                    // Number of DMA blocks per slot
 #define SLOT_TIME_NS         (SLOT_LENGTH_SAMPLES*(1e3)/7.68)            // slot time in ns
 
+#define NB_ANTENNA_PORTS_ENB  14                                         // total number of eNB antenna ports
 
 #ifdef EXMIMO
 #define TARGET_RX_POWER 55    // Target digital power for the AGC
diff --git a/openair1/SCHED/Makefile.inc b/openair1/SCHED/Makefile.inc
index e3fd877e5d7bc6f7052c5f5413fc61c3264425db..559d3dca32b2db60e50caa0f8fc349edf9499e1e 100644
--- a/openair1/SCHED/Makefile.inc
+++ b/openair1/SCHED/Makefile.inc
@@ -3,3 +3,4 @@ SCHED_OBJS += $(TOP_DIR)/SCHED/phy_procedures_lte_ue.o
 SCHED_OBJS += $(TOP_DIR)/SCHED/phy_procedures_lte_eNb.o
 SCHED_OBJS += $(TOP_DIR)/SCHED/pusch_pc.o
 SCHED_OBJS += $(TOP_DIR)/SCHED/pucch_pc.o
+SCHED_OBJS += $(TOP_DIR)/SCHED/srs_pc.o
diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h
index 2a502f923a70fb8370ca5c5d4f69f8339b40c88f..b2d823d774a494f034b98fb111ce83d8f5c05102 100644
--- a/openair1/SCHED/defs.h
+++ b/openair1/SCHED/defs.h
@@ -69,6 +69,11 @@ enum openair_SYNCH_STATUS {
   openair_SCHED_EXIT
 };
 
+enum openair_HARQ_TYPE {
+  openair_harq_DL = 0,
+  openair_harq_UL,
+  openair_harq_RA
+};
 
 #define DAQ_AGC_ON 1
 #define DAQ_AGC_OFF 0
@@ -437,6 +442,17 @@ int8_t pucch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t subframe,ui
  */
 void pusch_power_cntl(PHY_VARS_UE *phy_vars_ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag);
 
+/*! \brief This function implements the power control mechanism for SRS from 36.213.
+    @param phy_vars_ue PHY variables
+    @param proc Pointer to proc descriptor
+    @param eNB_id Index of eNB
+    @param j index of type of PUSCH (SPS, Normal, Msg3)
+    @returns Transmit power
+ */
+void srs_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t *pnb_rb_srs, uint8_t abstraction_flag);
+
+void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id);
+
 int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id, uint8_t eNB_index);
 
 #ifdef LOCALIZATION
@@ -452,6 +468,8 @@ double aggregate_eNB_UE_localization_stats(PHY_VARS_eNB *phy_vars_eNB, int8_t UE
 #endif
 LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti);
 
+
+
 LTE_DL_FRAME_PARMS *get_lte_frame_parms(module_id_t Mod_id, uint8_t CC_id);
 
 MU_MIMO_mode* get_mu_mimo_mode (module_id_t Mod_id, uint8_t CC_id, rnti_t rnti);
diff --git a/openair1/SCHED/phy_mac_stub.c b/openair1/SCHED/phy_mac_stub.c
index 0ac194d051ec596bfec9dd747aa26d6bf6b3a842..cb22461656851884d7b3a0157974d5e4580edc67 100644
--- a/openair1/SCHED/phy_mac_stub.c
+++ b/openair1/SCHED/phy_mac_stub.c
@@ -40,14 +40,21 @@
 #include "SCHED/phy_procedures_emos.h"
 #endif
 
+/* SYRTEM */
+uint8_t dci_ndi_toggle_even[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+uint8_t dci_ndi_toggle_odd[8]  = {0, 0, 0, 0, 0, 0, 0, 0};
+
 void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
 {
-
+/* SYRTEM */
+  uint8_t *dci_ndi_toggle_tmp = NULL;
+  uint8_t harq_pid_value      = 0;
+/* End of SYRTEM */
 
   //uint8_t cooperation_flag = eNB->cooperation_flag;
   uint8_t transmission_mode = eNB->transmission_mode[0];
 
-  uint32_t rballoc = 0x7FFF;
+  uint32_t rballoc = 0x1FFFF;
   //uint32_t rballoc2 = 0x000F;
 
   int subframe = proc->subframe_tx;
@@ -63,17 +70,21 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
   uint32_t bcch_pdu;
   uint64_t dlsch_pdu;
 
+  LOG_I(PHY,"frame %d, subframe %d, transmission_mode %d\n",proc->frame_tx,proc->subframe_tx,transmission_mode);
+
   DCI_pdu->Num_common_dci = 0;
   DCI_pdu->Num_ue_spec_dci=0;
 
   switch (subframe) {
   case 5:
-    DCI_pdu->Num_common_dci = 1;
-    DCI_pdu->dci_alloc[0].L          = 2;
-    DCI_pdu->dci_alloc[0].firstCCE   = 0;
-    DCI_pdu->dci_alloc[0].rnti       = SI_RNTI;
-    DCI_pdu->dci_alloc[0].format     = format1A;
-    DCI_pdu->dci_alloc[0].ra_flag    = 0;
+   if ( !(proc->frame_tx&1) ) // SI message on even frame only (SFN mod 2 == 0)
+   {
+	DCI_pdu->Num_common_dci = 1;
+	DCI_pdu->dci_alloc[0].L          = 2;
+	DCI_pdu->dci_alloc[0].firstCCE   = 0;
+	DCI_pdu->dci_alloc[0].rnti       = SI_RNTI;
+	DCI_pdu->dci_alloc[0].format     = format1A;
+	DCI_pdu->dci_alloc[0].ra_flag    = 0;
 
     switch (eNB->frame_parms.N_RB_DL) {
     case 6:
@@ -187,6 +198,12 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
     }
     break; //subframe switch
 
+    }  // if ( !(proc->frame_tx&1) )
+    else // No SI message on odd frame (SFN mod 2 == 1)
+    {
+      /* warning: work around to send dlsch on subframe 5 odd frame !!! */
+      /* todo: clean up, espacially if subframe cases are added next !!! */
+    }
     /*
   case 6:
       DCI_pdu->Num_ue_spec_dci = 1;
@@ -218,22 +235,30 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
     DCI_pdu->dci_alloc[0].format     = format1;
     DCI_pdu->dci_alloc[0].ra_flag    = 0;
 
-    if (transmission_mode<3) {
+    if (transmission_mode<3 || transmission_mode == 7) {
       //user 1
       switch (eNB->frame_parms.N_RB_DL) {
       case 25:
         if (eNB->frame_parms.frame_type == FDD) {
           DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_5MHz_FDD_t;
 
+          harq_pid_value = (  ((proc->frame_tx * 10) + subframe) % 8 );
+
+          if (!(subframe&1)) // even subframe
+            dci_ndi_toggle_tmp = &(dci_ndi_toggle_even[harq_pid_value]);
+          else // odd subframe
+            dci_ndi_toggle_tmp = &(dci_ndi_toggle_odd[harq_pid_value]);
+
           ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc          = rballoc; //computeRIV(25,10,3);
           ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC              = 0;
-          ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid         = subframe % 5;
+          ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid         = harq_pid_value;
           ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs              = eNB->target_ue_dl_mcs;
-          //((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs            = (unsigned char) ((eNB->frame%1024)%28);
-          ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi              = subframe / 5;
+          ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi              = (*dci_ndi_toggle_tmp);
           ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv               = 0;
           ((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rah              = 0;
 
+          (*dci_ndi_toggle_tmp) = ((*dci_ndi_toggle_tmp) + 1) & 1;
+
           memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_FDD_t));
 
           /*
@@ -296,36 +321,24 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
         if (eNB->frame_parms.frame_type == FDD) {
           DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_10MHz_FDD_t;
 
+          harq_pid_value = (  ((proc->frame_tx * 10) + subframe) % 8 );
+
+          if (!(subframe&1)) // even subframe
+            dci_ndi_toggle_tmp = &(dci_ndi_toggle_even[harq_pid_value]);
+          else // odd subframe
+            dci_ndi_toggle_tmp = &(dci_ndi_toggle_odd[harq_pid_value]);
+
           ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rballoc          = rballoc; //computeRIV(50,10,3);
           ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->TPC              = 0;
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid         = subframe % 5;
+          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid         = harq_pid_value;
           ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs              = eNB->target_ue_dl_mcs;
-          //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs            = (unsigned char) ((eNB->frame%1024)%28);
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi              = subframe / 5;
+          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi              = (*dci_ndi_toggle_tmp);
           ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv               = 0;
           ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rah              = 0;
 
-          memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_FDD_t));
+          (*dci_ndi_toggle_tmp) = ((*dci_ndi_toggle_tmp) + 1) & 1;
 
-          /*
-          //user2
-          DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI1_10MHz_TDD_t;
-          DCI_pdu->dci_alloc[1].L          = 2;
-          DCI_pdu->dci_alloc[1].rnti       = 0x1236;
-          DCI_pdu->dci_alloc[1].format     = format1;
-          DCI_pdu->dci_alloc[1].ra_flag    = 0;
-
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rballoc          = rballoc2;
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->TPC              = 0;
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->dai              = 0;
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid         = 1;
-          //((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs              = (unsigned char) ((eNB->proc[subframe].frame%1024)%28);
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs              = eNB->target_ue_dl_mcs;
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi              = 1;
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv               = 0;
-          ((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rah              = 0;
-          memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_10MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_10MHz_TDD_t));
-          */
+          memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_FDD_t));
         } else {
           DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_10MHz_TDD_t;
 
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 89ae2304e37cd880dd63fbfa304af417e48a0465..85c822e273239beb4c94770380311817ab866119 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -21,11 +21,11 @@
 
 /*! \file phy_procedures_lte_eNB.c
  * \brief Implementation of eNB procedures from 36.213 LTE specifications
- * \author R. Knopp, F. Kaltenberger, N. Nikaein
+ * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
  * \date 2011
  * \version 0.1
  * \company Eurecom
- * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
  * \note
  * \warning
  */
@@ -61,6 +61,14 @@
 #   include "intertask_interface.h"
 #endif
 
+
+#if defined(FLEXRAN_AGENT_SB_IF)
+//Agent-related headers
+#include "ENB_APP/flexran_agent_extern.h"
+#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#endif
+
 //#define DIAG_PHY
 
 #define NS_PER_SLOT 500000
@@ -221,7 +229,7 @@ int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
   return(-1);
 }
 
-int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t ul_flag)
+int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t harq_flag)
 {
   LTE_eNB_DLSCH_t *DLSCH_ptr;
   LTE_eNB_ULSCH_t *ULSCH_ptr;
@@ -235,9 +243,20 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16
     return(-1);
   }
 
-  if (ul_flag == 0)  {// this is a DL request
+  if ((harq_flag == openair_harq_DL) || (harq_flag == openair_harq_RA))  {// this is a DL request
+
     DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch[(uint32_t)UE_id][0];
 
+    if (harq_flag == openair_harq_RA) {
+      if (DLSCH_ptr->harq_processes[0] != NULL) {
+	*harq_pid = 0;
+	*round = DLSCH_ptr->harq_processes[0]->round;
+	return 0;
+      } else {
+	return -1;
+      }
+    }
+
     /* let's go synchronous for the moment - maybe we can change at some point */
     i = (frame * 10 + subframe) % 8;
 
@@ -671,7 +690,8 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
 				       SI_RNTI,
 				       0,
 				       P_RNTI,
-				       eNB->UE_stats[0].DL_pmi_single);
+				       eNB->UE_stats[0].DL_pmi_single,
+				       0);
     
     
     eNB->dlsch_SI->nCCE[subframe] = dci_alloc->firstCCE;
@@ -704,7 +724,8 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
 				       SI_RNTI,
 				       dci_alloc->rnti,
 				       P_RNTI,
-				       eNB->UE_stats[0].DL_pmi_single);
+				       eNB->UE_stats[0].DL_pmi_single,
+				       0);
     
     
     eNB->dlsch_ra->nCCE[subframe] = dci_alloc->firstCCE;
@@ -753,7 +774,8 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
 					 SI_RNTI,
 					 0,
 					 P_RNTI,
-					 eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single);
+					 eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single,
+					 eNB->transmission_mode[(uint8_t)UE_id]<7?0:eNB->transmission_mode[(uint8_t)UE_id]);
       LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n",
 	    eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe);
       
@@ -886,7 +908,10 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
 	      dlsch_harq->rb_alloc,
 	      get_Qm(dlsch_harq->mcs),
 	      dlsch_harq->Nl,
-	      num_pdcch_symbols,frame,subframe),
+	      num_pdcch_symbols,
+	      frame,
+	      subframe,
+	      dlsch_harq->mimo_mode==TM7?7:0),
 	dlsch_harq->nb_rb,
 	dlsch_harq->mcs,
 	pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
@@ -905,7 +930,10 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
 			   dlsch_harq->rb_alloc,
 			   get_Qm(dlsch_harq->mcs),
 			   dlsch_harq->Nl,
-			   num_pdcch_symbols,frame,subframe),
+			   num_pdcch_symbols,
+			   frame,
+			   subframe,
+			   dlsch_harq->mimo_mode==TM7?7:0),
 		     dlsch_harq->nb_rb,
 		     dlsch_harq->mcs,
 		     pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
@@ -1062,7 +1090,9 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
 			   dlsch_harq->rb_alloc,
 			   get_Qm(dlsch_harq->mcs),
 			   dlsch_harq->Nl,
-			   num_pdcch_symbols,frame,subframe),
+			   num_pdcch_symbols,
+			   frame,subframe,
+			   0),
 		     0,
 		     subframe<<1);
     stop_meas(&eNB->dlsch_scrambling_stats);
@@ -1070,10 +1100,10 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
     start_meas(&eNB->dlsch_modulation_stats);
 
 
-    dlsch_modulation(eNB->common_vars.txdataF[0],
+    dlsch_modulation(eNB,
+		     eNB->common_vars.txdataF[0],
 		     AMP,
 		     subframe,
-		     fp,
 		     num_pdcch_symbols,
 		     dlsch,
 		     dlsch1);
@@ -1105,7 +1135,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
   int frame=proc->frame_tx;
   int subframe=proc->subframe_tx;
   //  uint16_t input_buffer_length;
-  uint32_t i,aa;
+  uint32_t i,j,aa;
   uint8_t harq_pid;
   DCI_PDU *DCI_pdu;
   DCI_PDU DCI_pdu_tmp;
@@ -1165,7 +1195,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
 
   // clear the transmit data array for the current subframe
   if (eNB->abstraction_flag==0) {
-    for (aa=0; aa<fp->nb_antennas_tx_eNB; aa++) {      
+    for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) {      
       memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
              0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
     }
@@ -1203,6 +1233,14 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
     fill_dci_emos(DCI_pdu,eNB);
 #else
     fill_dci(DCI_pdu,eNB,proc);
+    // clear previous allocation information for all UEs
+    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
+      if (eNB->dlsch[i][0]){
+        for (j=0; j<8; j++)
+          eNB->dlsch[i][0]->harq_processes[j]->round = 0;
+      }
+    }
+
 #endif
   }
 
@@ -1405,7 +1443,16 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
     
     eNB->dlsch_ra->active = 0;
   }
-  
+
+#if defined(FLEXRAN_AGENT_SB_IF)
+#ifndef DISABLE_SF_TRIGGER
+  //Send subframe trigger to the controller
+  if (mac_agent_registered[eNB->Mod_id]) {
+    agent_mac_xface[eNB->Mod_id]->flexran_agent_send_sf_trigger(eNB->Mod_id);
+  }
+#endif
+#endif
+
   // Now scan UE specific DLSCH
   for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
     {
diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c
index 3ed4c79ea3e1a7e62696592aff705662da369b67..1c6aa6b20cdc3c7f03653dc83c8c719c07ec50cf 100644
--- a/openair1/SCHED/phy_procedures_lte_ue.c
+++ b/openair1/SCHED/phy_procedures_lte_ue.c
@@ -56,11 +56,15 @@ fifo_dump_emos_UE emos_dump_UE;
 #endif
 
 #include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
 
 #if defined(ENABLE_ITTI)
 # include "intertask_interface.h"
 #endif
 
+#include "PHY/defs.h"
+
+#include "PHY/CODING/extern.h"
 
 #define DLSCH_RB_ALLOC 0x1fbf  // skip DC RB (total 23/25 RBs)
 #define DLSCH_RB_ALLOC_12 0x0aaa  // skip DC RB (total 23/25 RBs)
@@ -89,7 +93,9 @@ void dump_dlsch(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subf
                                   ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Qm,
                                   ue->dlsch[eNB_id][0]->harq_processes[harq_pid]->Nl,
                                   ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
-                                  proc->frame_rx,subframe);
+                                  proc->frame_rx,
+				  subframe,
+				  ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]);
 
   write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,2,1);
   write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
@@ -118,7 +124,9 @@ void dump_dlsch_SI(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s
                                   2,
                                   1,
                                   ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
-                                  proc->frame_rx,subframe);
+                                  proc->frame_rx,
+				  subframe,
+				  0);
   LOG_D(PHY,"[UE %d] Dumping dlsch_SI : ofdm_symbol_size %d, nsymb %d, nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n",
         ue->Mod_id,
 	ue->frame_parms.ofdm_symbol_size,
@@ -224,7 +232,9 @@ void dump_dlsch_ra(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s
                                   2,
                                   1,
                                   ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
-                                  proc->frame_rx,subframe);
+                                  proc->frame_rx,
+				  subframe,
+				  0);
   LOG_D(PHY,"[UE %d] Dumping dlsch_ra : nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n",
         ue->Mod_id,
         ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb,
@@ -377,6 +387,345 @@ uint8_t is_SR_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
   return(0);
 }
 
+uint8_t is_cqi_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
+{
+  int subframe = proc->subframe_tx;
+  int frame    = proc->frame_tx;
+  CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic;
+
+  //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for CQI TXOp (cqi_ConfigIndex %d) isCQIOp %d\n",
+  //      ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,subframe,
+  //      cqirep->cqi_PMI_ConfigIndex,
+  //      (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI));
+
+  if (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI)
+    return(1);
+  else
+    return(0);
+}
+uint8_t is_ri_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
+{
+
+
+  int subframe = proc->subframe_tx;
+  int frame    = proc->frame_tx;
+  CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic;
+  int log2Mri = cqirep->ri_ConfigIndex/161;
+  int N_OFFSET_RI = cqirep->ri_ConfigIndex % 161;
+
+  //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for RI TXOp (ri_ConfigIndex %d) isRIOp %d\n",
+  //      ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,subframe,
+  //      cqirep->ri_ConfigIndex,
+  //      (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0));
+
+  if (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0)
+    return(1);
+  else
+    return(0);
+}
+
+void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset)
+{
+    if(TDD == frameType)
+    {
+        if(isrs<10)
+        {
+            mac_xface->macphy_exit("2 ms SRS periodicity not supported");
+        }
+
+        if((isrs>9)&&(isrs<15))
+        {
+            *psrsPeriodicity=5;
+            *psrsOffset=isrs-10;
+        }
+        if((isrs>14)&&(isrs<25))
+        {
+            *psrsPeriodicity=10;
+            *psrsOffset=isrs-15;
+        }
+        if((isrs>24)&&(isrs<45))
+        {
+            *psrsPeriodicity=20;
+            *psrsOffset=isrs-25;
+        }
+        if((isrs>44)&&(isrs<85))
+        {
+            *psrsPeriodicity=40;
+            *psrsOffset=isrs-45;
+        }
+        if((isrs>84)&&(isrs<165))
+        {
+            *psrsPeriodicity=80;
+            *psrsOffset=isrs-85;
+        }
+        if((isrs>164)&&(isrs<325))
+        {
+            *psrsPeriodicity=160;
+            *psrsOffset=isrs-165;
+        }
+        if((isrs>324)&&(isrs<645))
+        {
+            *psrsPeriodicity=320;
+            *psrsOffset=isrs-325;
+        }
+
+        if(isrs>644)
+        {
+            mac_xface->macphy_exit("Isrs out of range");
+        }
+
+    }
+    else
+    {
+        if(isrs<2)
+        {
+            *psrsPeriodicity=2;
+            *psrsOffset=isrs;
+        }
+        if((isrs>1)&&(isrs<7))
+        {
+            *psrsPeriodicity=5;
+            *psrsOffset=isrs-2;
+        }
+        if((isrs>6)&&(isrs<17))
+        {
+            *psrsPeriodicity=10;
+            *psrsOffset=isrs-7;
+        }
+        if((isrs>16)&&(isrs<37))
+        {
+            *psrsPeriodicity=20;
+            *psrsOffset=isrs-17;
+        }
+        if((isrs>36)&&(isrs<77))
+        {
+            *psrsPeriodicity=40;
+            *psrsOffset=isrs-37;
+        }
+        if((isrs>76)&&(isrs<157))
+        {
+            *psrsPeriodicity=80;
+            *psrsOffset=isrs-77;
+        }
+        if((isrs>156)&&(isrs<317))
+        {
+            *psrsPeriodicity=160;
+            *psrsOffset=isrs-157;
+        }
+        if((isrs>316)&&(isrs<637))
+        {
+            *psrsPeriodicity=320;
+            *psrsOffset=isrs-317;
+        }
+        if(isrs>636)
+        {
+            mac_xface->macphy_exit("Isrs out of range");
+        }
+    }
+}
+
+void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
+{
+    LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
+    int frame_tx    = proc->frame_tx;
+    int subframe_tx = proc->subframe_tx;
+    uint8_t isSubframeSRS   = 0; // SRS Cell Occasion
+
+    uint8_t is_pucch2_subframe = 0;
+    uint8_t is_sr_an_subframe  = 0;
+
+    SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id];
+
+  // check for SRS opportunity
+  pSoundingrs_ul_config_dedicated->srsUeSubframe   = 0;
+  pSoundingrs_ul_config_dedicated->srsCellSubframe = 0;
+
+  ue->ulsch[eNB_id]->srs_active   = 0;
+  ue->ulsch[eNB_id]->Nsymb_pusch  = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active;
+  if(frame_parms->soundingrs_ul_config_common.enabled_flag)
+  {
+
+      LOG_D(PHY," SRS SUBFRAMECONFIG: %d, Isrs: %d \n", frame_parms->soundingrs_ul_config_common.srs_SubframeConfig, pSoundingrs_ul_config_dedicated->srs_ConfigIndex);
+
+      uint8_t  TSFC;
+      uint16_t deltaTSFC; // bitmap
+      uint8_t  srs_SubframeConfig;
+      uint16_t srsPeriodicity;
+      uint16_t srsOffset;
+
+      // table resuming TSFC (Period) and deltaSFC (offset)
+      const uint16_t deltaTSFCTabType1[15][2] = { {1,1},{1,2},{2,2},{1,5},{2,5},{4,5},{8,5},{3,5},{12,5},{1,10},{2,10},{4,10},{8,10},{351,10},{383,10} };      // Table 5.5.3.3-2 3GPP 36.211 FDD
+      const uint16_t deltaTSFCTabType2[14][2] = { {2,5},{6,5},{10,5},{18,5},{14,5},{22,5},{26,5},{30,5},{70,10},{74,10},{194,10},{326,10},{586,10},{210,10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD
+
+      srs_SubframeConfig = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
+      if (FDD == frame_parms->frame_type)
+      {
+          // srs_SubframeConfig =< 14
+          deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
+          TSFC      = deltaTSFCTabType1[srs_SubframeConfig][1];
+      }
+      else
+      {
+          // srs_SubframeConfig =< 13
+          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 = (subframe_tx %  TSFC);
+      if((1<<tmp) & deltaTSFC)
+      {
+          // This is a Sounding reference signal subframes
+          isSubframeSRS = 1;
+          pSoundingrs_ul_config_dedicated->srsCellSubframe  = 1;
+      }
+      LOG_D(PHY," ISTDD: %d, TSFC: %d, deltaTSFC: %d, AbsSubframeTX: %d.%d, srsCellSubframe: %d \n", frame_parms->frame_type, TSFC, deltaTSFC, frame_tx, subframe_tx, pSoundingrs_ul_config_dedicated->srsCellSubframe);
+      LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup);
+      if(pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup)
+      {
+          compute_srs_pos(frame_parms->frame_type, pSoundingrs_ul_config_dedicated->srs_ConfigIndex, &srsPeriodicity, &srsOffset);
+
+          LOG_D(PHY," srsPeriodicity: %d srsOffset: %d isSubframeSRS %d \n",srsPeriodicity,srsOffset,isSubframeSRS);
+
+          // transmit SRS if the four following constraints are respected:
+          // - UE is configured to transmit SRS
+          // - SRS are configured in current subframe
+          // - UE is configured to send SRS in this subframe
+
+          // 36.213 8.2
+          // 1- A UE shall not transmit SRS whenever SRS and PUCCH format 2/2a/2b transmissions happen to coincide in the same subframe
+          // 2- A UE shall not transmit SRS whenever SRS transmit
+          //    on and PUCCH transmission carrying ACK/NACK and/or
+          //    positive SR happen to coincide in the same subframe if the parameter
+          //    Simultaneous-AN-and-SRS is FALSE
+
+          // check PUCCH format 2/2a/2b transmissions
+          is_pucch2_subframe = is_cqi_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0);
+          is_pucch2_subframe = (is_ri_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0)) || is_pucch2_subframe;
+
+          // check ACK/SR transmission
+          if(frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission == FALSE)
+          {
+              if(is_SR_TXOp(ue,proc,eNB_id))
+              {
+                  uint32_t SR_payload = 0;
+                  if (ue->mac_enabled==1)
+                  {
+                      int Mod_id = ue->Mod_id;
+                      int CC_id = ue->CC_id;
+                      SR_payload = mac_xface->ue_get_SR(Mod_id,
+                              CC_id,
+                              frame_tx,
+                              eNB_id,
+                              ue->pdcch_vars[eNB_id]->crnti,
+                              subframe_tx); // subframe used for meas gap
+
+                      if (SR_payload > 0)
+                          is_sr_an_subframe = 1;
+                  }
+              }
+
+              uint8_t pucch_ack_payload[2];
+              if (get_ack(&ue->frame_parms,
+                      ue->dlsch[eNB_id][0]->harq_ack,
+                      subframe_tx,pucch_ack_payload) > 0)
+              {
+                  is_sr_an_subframe = 1;
+              }
+          }
+
+          // check SRS UE opportunity
+          if( isSubframeSRS  &&
+                  (((10*frame_tx+subframe_tx) % srsPeriodicity) == srsOffset)
+          )
+          {
+              if ((is_pucch2_subframe == 0) && (is_sr_an_subframe == 0))
+              {
+                  pSoundingrs_ul_config_dedicated->srsUeSubframe = 1;
+                  ue->ulsch[eNB_id]->srs_active   = 1;
+                  ue->ulsch[eNB_id]->Nsymb_pusch  = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active;
+              }
+              else
+              {
+                  LOG_I(PHY,"DROP UE-SRS-TX for this subframe %d.%d: collision with PUCCH2 or SR/AN: PUCCH2-occasion: %d, SR-AN-occasion[simSRS-SR-AN %d]: %d  \n", frame_tx, subframe_tx, is_pucch2_subframe, frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, is_sr_an_subframe);
+              }
+          }
+      }
+      LOG_D(PHY," srsCellSubframe: %d, srsUeSubframe: %d, Nsymb-pusch: %d \n", pSoundingrs_ul_config_dedicated->srsCellSubframe, pSoundingrs_ul_config_dedicated->srsUeSubframe, ue->ulsch[eNB_id]->Nsymb_pusch);
+  }
+}
+
+void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id)
+{
+
+  CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic;
+  int cqi_PMI_ConfigIndex = cqirep->cqi_PMI_ConfigIndex;
+
+  if (ue->frame_parms.frame_type == FDD) {
+    if (cqi_PMI_ConfigIndex <= 1) {        // 2 ms CQI_PMI period
+      cqirep->Npd = 2;
+      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex;
+    } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period
+      cqirep->Npd = 5;
+      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-2;
+    } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
+      cqirep->Npd = 10;
+      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-7;
+    } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
+      cqirep->Npd = 20;
+      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-17;
+    } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
+      cqirep->Npd = 40;
+      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-37;
+    } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
+      cqirep->Npd = 80;
+      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-77;
+    } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
+      cqirep->Npd = 160;
+      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-157;
+    }
+    else if (cqi_PMI_ConfigIndex > 317) {
+      
+      if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period
+	cqirep->Npd = 32;
+      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-318;
+      }
+      else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period
+	cqirep->Npd = 64;
+	cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-350;
+      }
+      else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period
+	cqirep->Npd = 128;
+	cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-414;
+      }  
+    }
+  }
+  else { // TDD
+   if (cqi_PMI_ConfigIndex == 0) {        // all UL subframes
+     cqirep->Npd = 1;
+     cqirep->N_OFFSET_CQI = 0;
+   } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period
+     cqirep->Npd = 5;
+     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-1;
+   } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
+     cqirep->Npd = 10;
+     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-6;
+   } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
+     cqirep->Npd = 20;
+     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-16;
+   } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
+     cqirep->Npd = 40;
+     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-36;
+   } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
+     cqirep->Npd = 80;
+     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-76;
+   } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
+     cqirep->Npd = 160;
+     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-156;
+   }
+  }
+}
+
 uint16_t get_n1_pucch(PHY_VARS_UE *ue,
 		      UE_rxtx_proc_t *proc,
                       uint8_t eNB_id,
@@ -600,14 +949,25 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc) {
   int dummy_tx_buffer[3840*4] __attribute__((aligned(16)));
 #endif
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_IN);
+
   start_meas(&ue->ofdm_mod_stats);
   nsymb = (frame_parms->Ncp == 0) ? 14 : 12;
   
 #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)//this is the EXPRESS MIMO case
   ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_tti-
-		 ue->hw_timing_advance-
-		 ue->timing_advance-
-		 ue->N_TA_offset+5)%(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
+         ue->hw_timing_advance-
+         ue->timing_advance-
+         ue->N_TA_offset+5);
+  //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);
+
+  if(ulsch_start < 0)
+      ulsch_start = ulsch_start + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
+
+  if (ulsch_start > (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti))
+      ulsch_start = ulsch_start % (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
+
+  //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);
 #else //this is the normal case
   ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance;
 #endif //else EXMIMO
@@ -678,12 +1038,21 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc) {
     }
 #endif
 #endif
+    /*
+    only for debug
+    LOG_I(PHY,"ul-signal [subframe: %d, ulsch_start %d, TA: %d, rxOffset: %d, timing_advance: %d, hw_timing_advance: %d]\n",subframe_tx, ulsch_start, ue->N_TA_offset, ue->rx_offset, ue->timing_advance, ue->hw_timing_advance);
+    if( (crash == 1) && (subframe_tx == 0) )
+    {
+      LOG_E(PHY,"***** DUMP TX Signal [ulsch_start %d] *****\n",ulsch_start);
+      write_output("txBuff.m","txSignal",&ue->common_vars.txdata[aa][ulsch_start],frame_parms->samples_per_tti,1,1);
+    }
+    */
     
   } //nb_antennas_tx
   
   stop_meas(&ue->ofdm_mod_stats);
 
-
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_OUT);
 
 }
 
@@ -694,6 +1063,8 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
   int prach_power;
   PRACH_RESOURCES_t prach_resources_local;
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN);
+
   ue->generate_prach=0;
 
   if (ue->mac_enabled==0){
@@ -782,14 +1153,15 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
     } else {
       UE_transport_info[ue->Mod_id][ue->CC_id].cntl.prach_flag=1;
       UE_transport_info[ue->Mod_id][ue->CC_id].cntl.prach_id=ue->prach_resources[eNB_id]->ra_PreambleIndex;
-      if (ue->mac_enabled==1){
-	mac_xface->Msg1_transmitted(ue->Mod_id,
-				    ue->CC_id,
-				    frame_tx,
-				    eNB_id);
-      }
     }
     
+    if (ue->mac_enabled==1){
+      mac_xface->Msg1_transmitted(ue->Mod_id,
+          ue->CC_id,
+          frame_tx,
+          eNB_id);
+    }
+
     LOG_D(PHY,"[UE  %d][RAPROC] Frame %d, subframe %d: Generating PRACH (eNB %d) preamble index %d for UL, TX power %d dBm (PL %d dB), l3msg \n",
 	  ue->Mod_id,frame_tx,subframe_tx,eNB_id,
 	  ue->prach_resources[eNB_id]->ra_PreambleIndex,
@@ -810,6 +1182,8 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
   
   if (ue->prach_cnt==3)
     ue->generate_prach=0;
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_OUT);
 }
 
 void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) {
@@ -829,6 +1203,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
   uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32)));
   uint8_t access_mode;
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_IN);
+
   // get harq_pid from subframe relationship
   harq_pid = subframe2harq_pid(&ue->frame_parms,
 			       frame_tx,
@@ -857,8 +1233,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
     } else {
       
       if (harq_pid==255) {
-	LOG_E(PHY,"[UE%d] Frame %d ulsch_decoding.c: FATAL ERROR: illegal harq_pid, returning\n",
-	      Mod_id,frame_tx);
+	LOG_E(PHY,"[UE%d] Frame %d subframe %d ulsch_decoding.c: FATAL ERROR: illegal harq_pid, returning\n",
+	      Mod_id,frame_tx, subframe_tx);
 	mac_xface->macphy_exit("Error in ulsch_decoding");
 	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT);
 	stop_meas(&ue->phy_proc_tx);
@@ -874,7 +1250,14 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
     ue->generate_ul_signal[eNB_id] = 1;
     
     // deactivate service request
-    ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+    // ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+    LOG_D(PHY,"Generating PUSCH (Abssubframe: %d.%d): harq-Id: %d, round: %d, MaxReTrans: %d \n",frame_tx,subframe_tx,harq_pid,ue->ulsch[eNB_id]->harq_processes[harq_pid]->round,ue->ulsch[eNB_id]->Mlimit);
+    if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->round >= (ue->ulsch[eNB_id]->Mlimit - 1))
+    {
+        LOG_D(PHY,"PUSCH MAX Retransmission acheived ==> send last pusch (%d) \n");
+        ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+        ue->ulsch[eNB_id]->harq_processes[harq_pid]->round  = 0;
+    }
     
     ack_status = get_ack(&ue->frame_parms,
 			 ue->dlsch[eNB_id][0]->harq_ack,
@@ -887,6 +1270,27 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
     
     
     
+
+    if (ack_status > 0) {
+
+      // check if we received a PDSCH at subframe_tx - 4
+      // ==> send ACK/NACK on PUSCH
+      if( (ue->dlsch[eNB_id][0]->harq_ack[proc->subframe_rx].send_harq_status) == 1)
+      {
+          ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK = 1;
+      }
+      else
+      {
+          ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK = 0;
+      }
+      LOG_D(PHY,"[UE  %d][PDSCH %x] Frame %d subframe %d Generating ACK (%d,%d) for %d bits on PUSCH\n",
+        Mod_id,
+        ue->ulsch[eNB_id]->rnti,
+        frame_tx,subframe_tx,
+        ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1],
+        ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK);
+    }
+
 #ifdef DEBUG_PHY_PROC
     LOG_D(PHY,
 	  "[UE  %d][PUSCH %d] Frame %d subframe %d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, rv %d, cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d\n",
@@ -905,15 +1309,6 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
 	  ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK);
 #endif
     
-    if (ack_status > 0) {
-      LOG_D(PHY,"[UE  %d][PDSCH %x] Frame %d subframe %d Generating ACK (%d,%d) for %d bits on PUSCH\n",
-	    Mod_id,
-	    ue->ulsch[eNB_id]->rnti,
-	    frame_tx,subframe_tx,
-	    ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1],
-	    ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK);
-    }
-    
     
     
     
@@ -1076,17 +1471,98 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
       ue->sr[subframe_tx]=0;
     }
   } // subframe_scheduling_flag==1
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_OUT);
+
+}
+
+void ue_srs_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag)
+{
+
+  //LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
+  //int8_t  frame_tx    = proc->frame_tx;
+  int8_t  subframe_tx = proc->subframe_tx;
+  int16_t tx_amp;
+  int16_t Po_SRS;
+  uint8_t nb_rb_srs;
+
+  SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id];
+  uint8_t isSrsTxOccasion = pSoundingrs_ul_config_dedicated->srsUeSubframe;
+
+  if(isSrsTxOccasion)
+  {
+    ue->generate_ul_signal[eNB_id] = 1;
+    if (ue->mac_enabled==1)
+    {
+      srs_power_cntl(ue,proc,eNB_id, (uint8_t*)(&nb_rb_srs), abstraction_flag);
+      Po_SRS = ue->ulsch[eNB_id]->Po_SRS;
+    }
+    else
+    {
+      Po_SRS = ue->tx_power_max_dBm;
+    }
+
+#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
+    if (ue->mac_enabled==1)
+    {
+    tx_amp = get_tx_amp(Po_SRS,
+                        ue->tx_power_max_dBm,
+                        ue->frame_parms.N_RB_UL,
+                        nb_rb_srs);
+    }
+    else
+    {
+        tx_amp = AMP;
+    }
+#else
+      tx_amp = AMP;
+#endif
+    LOG_D(PHY,"SRS PROC; TX_MAX_POWER %d, Po_SRS %d, NB_RB_UL %d, NB_RB_SRS %d TX_AMPL %d\n",ue->tx_power_max_dBm,
+            Po_SRS,
+            ue->frame_parms.N_RB_UL,
+            nb_rb_srs,
+            tx_amp);
+
+    generate_srs_tx(ue, eNB_id, tx_amp, subframe_tx);
+  }
 }
 
+int16_t get_pucch2_cqi(PHY_VARS_UE *ue,int eNB_id,int *len) {
+
+  if ((ue->transmission_mode[eNB_id]<4)||
+      (ue->transmission_mode[eNB_id]==7)) { // Mode 1-0 feedback
+    // 4-bit CQI message
+    *len=4;
+    return(sinr2cqi((double)ue->measurements.wideband_cqi_avg[eNB_id],
+		    ue->transmission_mode[eNB_id]));
+  }
+  else { // Mode 1-1 feedback, later
+    *len=0;
+    // 2-antenna ports RI=1, 6 bits (2 PMI, 4 CQI)
+
+    // 2-antenna ports RI=2, 8 bits (1 PMI, 7 CQI/DIFF CQI)
+    return(0);
+  }
+}
+
+
+int16_t get_pucch2_ri(PHY_VARS_UE *ue,int eNB_id) {
+
+  return(1);
+}
 
 void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag) {
 
 
   uint8_t pucch_ack_payload[2];
-  uint8_t n1_pucch;
+  uint8_t n1_pucch,n2_pucch;
   ANFBmode_t bundling_flag;
   PUCCH_FMT_t format;
+
   uint8_t SR_payload;
+  uint16_t CQI_payload;
+  uint16_t RI_payload;
+
   LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
   int frame_tx=proc->frame_tx;
   int subframe_tx=proc->subframe_tx;
@@ -1095,6 +1571,28 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
   int tx_amp;
   int8_t Po_PUCCH;
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_IN);
+  
+  SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id];
+
+  // 36.213 8.2
+  /*if ackNackSRS_SimultaneousTransmission ==  TRUE and in the cell specific SRS subframes UE shall transmit
+    ACK/NACK and SR using the shortened PUCCH format. This shortened PUCCH format shall be used in a cell
+    specific SRS subframe even if the UE does not transmit SRS in that subframe
+  */
+
+  int harq_pid = subframe2harq_pid(&ue->frame_parms,
+                                   frame_tx,
+                                   subframe_tx);
+
+  if(ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag)
+  {
+      LOG_D(PHY,"PUSCH is programmed on this subframe [pid %d] AbsSuframe %d.%d ==> Skip PUCCH transmission \n",harq_pid,frame_tx,subframe_tx);
+      return;
+  }
+
+  uint8_t isShortenPucch = (pSoundingrs_ul_config_dedicated->srsCellSubframe && frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission);
+
   bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode;
   
   if ((frame_parms->frame_type==FDD) ||
@@ -1167,19 +1665,23 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 #endif
 	    
     if (SR_payload>0) {
-      LOG_D(PHY,"[UE  %d][SR %x] Frame %d subframe %d Generating PUCCH 1a/1b payload %d,%d (with SR for PUSCH), n1_pucch %d, Po_PUCCH, amp %d\n",
+      LOG_D(PHY,"[UE  %d][SR %x] Frame %d subframe %d Generating PUCCH 1a/1b payload %d,%d (with SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH, amp %d\n",
 	    Mod_id,
 	    ue->dlsch[eNB_id][0]->rnti,
+		frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission,
+	    isShortenPucch,
 	    frame_tx, subframe_tx,
 	    pucch_ack_payload[0],pucch_ack_payload[1],
 	    ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex,
 	    Po_PUCCH,
 	    tx_amp);
     } else {
-      LOG_D(PHY,"[UE  %d][PDSCH %x] Frame %d subframe %d Generating PUCCH 1a/1b, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n",
+      LOG_D(PHY,"[UE  %d][PDSCH %x] Frame %d subframe %d Generating PUCCH 1a/1b, an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n",
 	    Mod_id,
 	    ue->dlsch[eNB_id][0]->rnti,
 	    frame_tx, subframe_tx,
+		frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission,
+	    isShortenPucch,
 	    n1_pucch,pucch_ack_payload[0],pucch_ack_payload[1],SR_payload,
 	    Po_PUCCH,
 	    tx_amp);
@@ -1193,7 +1695,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 		       format,
 		       &ue->pucch_config_dedicated[eNB_id],
 		       n1_pucch,
-		       1,  // shortened format
+		       isShortenPucch,  // shortened format
 		       pucch_ack_payload,
 		       tx_amp,
 		       subframe_tx);
@@ -1210,7 +1712,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 #endif
     }
   } else if (SR_payload==1) { // no ACK/NAK but SR is triggered by MAC
-	    
+
     if (ue->mac_enabled == 1) {
       Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,pucch_format1);
     }
@@ -1228,10 +1730,12 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 #else
     tx_amp = AMP;
 #endif
-    LOG_D(PHY,"[UE  %d][SR %x] Frame %d subframe %d Generating PUCCH 1 (SR for PUSCH), n1_pucch %d, Po_PUCCH %d\n",
+    LOG_D(PHY,"[UE  %d][SR %x] Frame %d subframe %d Generating PUCCH 1 (SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH %d\n",
 	  Mod_id,
 	  ue->dlsch[eNB_id][0]->rnti,
 	  frame_tx, subframe_tx,
+	  frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission,
+	  isShortenPucch,
 	  ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex,
 	  Po_PUCCH);
 	    
@@ -1243,7 +1747,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 		       pucch_format1,
 		       &ue->pucch_config_dedicated[eNB_id],
 		       ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex,
-		       1,  // shortened format
+		       isShortenPucch,  // shortened format
 		       pucch_ack_payload,  // this is ignored anyway, we just need a pointer
 		       tx_amp,
 		       subframe_tx);
@@ -1258,6 +1762,113 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 
     }
   } // SR_Payload==1
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_OUT);
+  
+  // PUCCH 2x
+
+  if (ue->generate_ul_signal[eNB_id] == 0) { // we have not generated ACK/NAK/SR in this subframe
+
+    n2_pucch = ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PUCCH_ResourceIndex;
+    // only use format2 for now, i.e. now ACK/NAK - CQI multiplexing
+    format = pucch_format2;
+
+    // Periodic CQI report
+    if ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0)&&
+	(is_cqi_TXOp(ue,proc,eNB_id)==1)){
+
+      if (ue->mac_enabled == 1) {
+	Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format);
+      }
+      else {
+	Po_PUCCH = ue->tx_power_max_dBm;
+      }
+      ue->tx_power_dBm[subframe_tx] = Po_PUCCH;
+      ue->tx_total_RE[subframe_tx] = 12;
+      
+#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
+      tx_amp =  get_tx_amp(Po_PUCCH,
+			   ue->tx_power_max_dBm,
+			   ue->frame_parms.N_RB_UL,
+			   1);
+#else
+      tx_amp = AMP;
+#endif
+      LOG_D(PHY,"[UE  %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2 (CQI), n2_pucch %d, Po_PUCCH %d, isShortenPucch %d, amp %d\n",
+	    Mod_id,
+	    ue->dlsch[eNB_id][0]->rnti,
+	    frame_tx, subframe_tx,
+	    n2_pucch,
+	    Po_PUCCH,
+	    isShortenPucch,
+	    tx_amp);
+      
+      int len;
+      // get the payload : < 12 bits, returned in len
+      CQI_payload = get_pucch2_cqi(ue,eNB_id,&len);
+      generate_pucch2x(ue->common_vars.txdataF,
+		       &ue->frame_parms,
+		       ue->ncs_cell,
+		       format,
+		       &ue->pucch_config_dedicated[eNB_id],
+		       n2_pucch,
+		       &CQI_payload,
+		       len,          // A
+		       0,            // B2 not needed
+		       tx_amp,
+		       subframe_tx,
+		       ue->pdcch_vars[eNB_id]->crnti);
+
+      ue->generate_ul_signal[eNB_id] = 1;
+    }
+    // Periodic RI report
+    else if ((ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0) &&
+	     (is_ri_TXOp(ue,proc,eNB_id)==1)){
+
+      if (ue->mac_enabled == 1) {
+	Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format);
+      }
+      else {
+	Po_PUCCH = ue->tx_power_max_dBm;
+      }
+      ue->tx_power_dBm[subframe_tx] = Po_PUCCH;
+      ue->tx_total_RE[subframe_tx] = 12;
+      
+#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
+      tx_amp =  get_tx_amp(Po_PUCCH,
+			   ue->tx_power_max_dBm,
+			   ue->frame_parms.N_RB_UL,
+			   1);
+#else
+      tx_amp = AMP;
+#endif
+      LOG_D(PHY,"[UE  %d][RNTI %x] AbsSubFrame %d.%d Generating PUCCH 2 (RI), n2_pucch %d, Po_PUCCH %d, isShortenPucch %d, amp %d\n",
+	    Mod_id,
+	    ue->dlsch[eNB_id][0]->rnti,
+	    frame_tx, subframe_tx,
+	    n2_pucch,
+	    Po_PUCCH,
+	    isShortenPucch,
+	    tx_amp);
+
+      RI_payload = get_pucch2_ri(ue,eNB_id);
+
+      generate_pucch2x(ue->common_vars.txdataF,
+		       &ue->frame_parms,
+		       ue->ncs_cell,
+		       format,
+		       &ue->pucch_config_dedicated[eNB_id],
+		       n2_pucch,
+		       &RI_payload,
+		       1,            // A
+		       0,            // B2 not needed
+		       tx_amp,
+		       subframe_tx,
+		       ue->pdcch_vars[eNB_id]->crnti);
+      
+      ue->generate_ul_signal[eNB_id] = 1;
+    }
+  }
 }
 
 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) {
@@ -1293,13 +1904,18 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui
   }
       
   if (ue->UE_mode[eNB_id] != PRACH) {
+    // check cell srs subframe and ue srs subframe. This has an impact on pusch encoding
+    ue_compute_srs_occasion(ue,proc,eNB_id);
 
     ue_ulsch_uespec_procedures(ue,proc,eNB_id,abstraction_flag);
 
   }
   	  
-  if (ue->UE_mode[eNB_id] == PUSCH) { // check if we need to use PUCCH 1a/1b
-	  ue_pucch_procedures(ue,proc,eNB_id,abstraction_flag);
+  if (ue->UE_mode[eNB_id] == PUSCH) {
+      // check if we need to use PUCCH 1a/1b
+      ue_pucch_procedures(ue,proc,eNB_id,abstraction_flag);
+      // check if we need to use SRS
+      ue_srs_procedures(ue,proc,eNB_id,abstraction_flag);
   } // UE_mode==PUSCH
 	
   	
@@ -1709,6 +2325,17 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uin
 
   if ((pbch_tx_ant>0) && (pbch_tx_ant<=4)) {
 
+    if (opt_enabled) {
+      static uint8_t dummy[3];
+      dummy[0] = ue->pbch_vars[eNB_id]->decoded_output[2];
+      dummy[1] = ue->pbch_vars[eNB_id]->decoded_output[1];
+      dummy[2] = ue->pbch_vars[eNB_id]->decoded_output[0];
+      trace_pdu(1, dummy, 3, ue->Mod_id, 0, 0,
+          frame_rx, subframe_rx, 0, 0);
+      LOG_D(OPT,"[UE %d][PBCH] Frame %d trace pdu for PBCH\n",
+          ue->Mod_id, subframe_rx);
+    }
+
     if (pbch_tx_ant>2) {
       LOG_W(PHY,"[openair][SCHED][SYNCH] PBCH decoding: pbch_tx_ant>2 not supported\n");
       VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT);
@@ -1972,7 +2599,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
 					     ue->pdsch_config_dedicated,
 					     SI_RNTI,
 					     0,
-					     P_RNTI)==0)) {
+					     P_RNTI,
+					     ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0)) {
 
 	ue->dlsch_received[eNB_id]++;
 	
@@ -2015,7 +2643,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
 					    ue->pdsch_config_dedicated,
 					    SI_RNTI,
 					    0,
-					    P_RNTI)==0) {
+					    P_RNTI,
+					    ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0) {
 
 	ue->dlsch_SI_received[eNB_id]++;
  
@@ -2037,14 +2666,15 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
       if (generate_ue_dlsch_params_from_dci(frame_rx,
 					    subframe_rx,
 					    (void *)&dci_alloc_rx[i].dci_pdu,
-					    SI_RNTI,
+						P_RNTI,
 					    dci_alloc_rx[i].format,
 					    &ue->dlsch_SI[eNB_id],
 					    &ue->frame_parms,
 					    ue->pdsch_config_dedicated,
 					    SI_RNTI,
 					    0,
-					    P_RNTI)==0) {
+					    P_RNTI,
+					    ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0) {
 
 	ue->dlsch_p_received[eNB_id]++;
  
@@ -2078,7 +2708,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
 					    ue->pdsch_config_dedicated,
 					    SI_RNTI,
 					    ue->prach_resources[eNB_id]->ra_RNTI,
-					    P_RNTI)==0) {
+					    P_RNTI,
+					    ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0) {
 
 	ue->dlsch_ra_received[eNB_id]++;
 
@@ -2227,7 +2858,9 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,int eNB_id,int abs
 						       ue->dlsch_MCH[0]->harq_processes[0]->Qm,
 						       1,
 						       2,
-						       frame_rx,subframe_rx);
+						       frame_rx,
+						       subframe_rx,
+						       0);
 	
 	dlsch_unscrambling(&ue->frame_parms,1,ue->dlsch_MCH[0],
 			   ue->dlsch_MCH[0]->harq_processes[0]->G,
@@ -2338,7 +2971,18 @@ void ue_pdsch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, PDSC
 	eNB_id_i = eNB_id+1;
 	i_mod = 0;
       }
-      
+
+      //TM7 UE specific channel estimation here!!!
+      if (ue->transmission_mode[eNB_id]==7) {
+        if (ue->frame_parms.Ncp==0) {
+          if ((m==3) || (m==6) || (m==9) || (m==12))
+            //LOG_D(PHY,"[UE %d] dlsch->active in subframe %d => %d, l=%d\n",phy_vars_ue->Mod_id,subframe_rx,phy_vars_ue->dlsch_ue[eNB_id][0]->active, l);
+            lte_dl_bf_channel_estimation(ue,eNB_id,0,subframe_rx*2+(m>6?1:0),5,m);
+        } else {
+          LOG_E(PHY,"[UE %d]Beamforming channel estimation not supported yet for TM7 extented CP.\n",ue->Mod_id);
+        }
+      }
+     
       if ((m==s0) && (m<4))
 	first_symbol_flag = 1;
       else
@@ -2387,6 +3031,7 @@ void process_rar(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, runmode_t mo
       timing_advance = mac_xface->ue_process_rar(ue->Mod_id,
 						 ue->CC_id,
 						 frame_rx,
+						 ue->prach_resources[eNB_id]->ra_RNTI,
 						 dlsch0->harq_processes[0]->b,
 						 &ue->pdcch_vars[eNB_id]->crnti,
 						 ue->prach_resources[eNB_id]->ra_PreambleIndex);
@@ -2510,7 +3155,9 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
 						  dlsch0->harq_processes[harq_pid]->Qm,
 						  dlsch0->harq_processes[harq_pid]->Nl,
 						  ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
-						  frame_rx,subframe_rx);
+						  frame_rx,
+						  subframe_rx,
+						  ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]);
       start_meas(&ue->dlsch_unscrambling_stats);
       dlsch_unscrambling(&ue->frame_parms,
 			 0,
@@ -2530,7 +3177,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
 			   subframe_rx,
 			   harq_pid,
 			   pdsch==PDSCH?1:0,
-			   dlsch0->harq_processes[harq_pid]->nb_rb>10?1:0);
+			   dlsch0->harq_processes[harq_pid]->TBS>256?1:0);
       stop_meas(&ue->dlsch_decoding_stats);
     }
 	
@@ -2547,22 +3194,27 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
     if (ret == (1+dlsch0->max_turbo_iterations)) {
       *dlsch_errors=*dlsch_errors+1;
       
-
+      if(dlsch0->rnti != 0xffff)
+      {
       LOG_D(PHY,"[UE  %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d,TBS %d)\n",
 	    ue->Mod_id,dlsch0->rnti,
 	    harq_pid,frame_rx,subframe_rx,
 	    dlsch0->harq_processes[harq_pid]->rvidx,
 	    dlsch0->harq_processes[harq_pid]->mcs,
 	    dlsch0->harq_processes[harq_pid]->TBS);
+      }
       
 
     } else {
+        if(dlsch0->rnti != 0xffff)
+        {
       LOG_D(PHY,"[UE  %d][PDSCH %x/%d] Frame %d subframe %d: Received DLSCH (rv %d,mcs %d,TBS %d)\n",
 	    ue->Mod_id,dlsch0->rnti,
 	    harq_pid,frame_rx,subframe_rx,
 	    dlsch0->harq_processes[harq_pid]->rvidx,
 	    dlsch0->harq_processes[harq_pid]->mcs,
 	    dlsch0->harq_processes[harq_pid]->TBS);
+        }
 
 #ifdef DEBUG_DLSCH
       int j;
@@ -2701,11 +3353,19 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
     l2 = (ue->frame_parms.symbols_per_tti/2)-1;
   }
   
-  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-  // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch)
-  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-  
-  for (l=1; l<=l2; l++) {
+  int prev_subframe_rx = (subframe_rx - 1)<0? 9: (subframe_rx - 1);
+  if (subframe_select(&ue->frame_parms,prev_subframe_rx) != SF_DL) {
+    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    // RX processing of symbols l=0...l2
+    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    l=0;
+  } else {
+    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch)
+    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    l=1;
+  }
+  for (; l<=l2; l++) {
     if (abstraction_flag == 0) {
       start_meas(&ue->ofdm_demod_stats);
       VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN);
@@ -2751,6 +3411,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
  
   // do procedures for C-RNTI
   if (ue->dlsch[eNB_id][0]->active == 1) {
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
     ue_pdsch_procedures(ue,
 			proc,
 			eNB_id,
@@ -2760,9 +3421,11 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 			ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
 			ue->frame_parms.symbols_per_tti>>1,
 			abstraction_flag);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
   }
   // do procedures for SI-RNTI
   if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) {
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN);
     ue_pdsch_procedures(ue,
 			proc,
 			eNB_id,
@@ -2772,10 +3435,12 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 			ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
 			ue->frame_parms.symbols_per_tti>>1,
 			abstraction_flag);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT);
   }
 
   // do procedures for SI-RNTI
   if ((ue->dlsch_p[eNB_id]) && (ue->dlsch_p[eNB_id]->active == 1)) {
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN);
     ue_pdsch_procedures(ue,
 			proc,
 			eNB_id,
@@ -2785,10 +3450,12 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 			ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
 			ue->frame_parms.symbols_per_tti>>1,
 			abstraction_flag);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT);
   }
 
   // do procedures for RA-RNTI
   if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) {
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN);
     ue_pdsch_procedures(ue,
 			proc,
 			eNB_id,
@@ -2798,6 +3465,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 			ue->pdcch_vars[eNB_id]->num_pdcch_symbols,
 			ue->frame_parms.symbols_per_tti>>1,
 			abstraction_flag);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT);
   }    
   
   if (subframe_select(&ue->frame_parms,subframe_rx) != SF_S) {  // do front-end processing for second slot, and first symbol of next subframe
@@ -2818,13 +3486,18 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
       ue_measurement_procedures(l-1,ue,proc,eNB_id,abstraction_flag,mode);
       
     } // for l=1..l2
-      // do first symbol of next subframe for channel estimation
-    slot_fep(ue,
-	     0,
-	     (2+(subframe_rx<<1))%20,
-	     ue->rx_offset,
-	     0,
-	     0);
+
+    // do first symbol of next downlink subframe for channel estimation
+    int next_subframe_rx = (1+subframe_rx)%10;
+    if (subframe_select(&ue->frame_parms,next_subframe_rx) != SF_UL)
+    {
+      slot_fep(ue,
+         0,
+         (next_subframe_rx<<1),
+         ue->rx_offset,
+         0,
+         0);
+    }
   } // not an S-subframe
 
   // run pbch procedures if subframe is 0
@@ -2833,6 +3506,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
    
   // do procedures for C-RNTI
   if (ue->dlsch[eNB_id][0]->active == 1) {
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN);
     ue_pdsch_procedures(ue,
 			proc,
 			eNB_id,
@@ -2851,7 +3525,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 			&ue->dlsch_errors[eNB_id],
 			mode,
 			abstraction_flag);
-      
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
 
   }
   else {
@@ -2944,6 +3618,13 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
     LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n",
 	  ue->Mod_id,frame_rx,ue->total_TBS[eNB_id],
 	  ue->total_TBS_last[eNB_id],(float) ue->bitrate[eNB_id]/1000.0);
+
+  #if UE_AUTOTEST_TRACE
+    if ((frame_rx % 100 == 0)) {
+      LOG_I(PHY,"[UE  %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[eNB_id]/1000.0, frame_rx);
+    }
+  #endif
+
   }
 
 
@@ -3077,12 +3758,14 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u
        
     if (ue->mac_enabled==1) {
       if (slot==0) {
-	ret = mac_xface->ue_scheduler(ue->Mod_id,
-				      frame_tx,
-				      subframe_rx,
-				      subframe_select(&ue->frame_parms,subframe_tx),
-				      eNB_id,
-				      0/*FIXME CC_id*/);
+        ret = mac_xface->ue_scheduler(ue->Mod_id,
+            frame_rx,
+            subframe_rx,
+            frame_tx,
+            subframe_tx,
+            subframe_select(&ue->frame_parms,subframe_tx),
+            eNB_id,
+            0/*FIXME CC_id*/);
 	   
 	if (ret == CONNECTION_LOST) {
 	  LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",ue->Mod_id,
diff --git a/openair1/SCHED/pucch_pc.c b/openair1/SCHED/pucch_pc.c
index 5afd57e6a0f9a54ad1be5e09e2d74acc1e04bb07..2795fe65a931d0c0f3c88764e59ac37b54876938 100644
--- a/openair1/SCHED/pucch_pc.c
+++ b/openair1/SCHED/pucch_pc.c
@@ -88,7 +88,7 @@ int8_t pucch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t subframe,ui
   }
 
   if (pucch_fmt!=pucch_format1) {
-    LOG_I(PHY,"[UE  %d][PDSCH %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB, g_pucch %d dB\n",
+    LOG_D(PHY,"[UE  %d][PDSCH %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB, g_pucch %d dB\n",
           ue->Mod_id,
           ue->dlsch[eNB_id][0]->rnti,proc->frame_tx,subframe,
           Po_PUCCH,
@@ -96,7 +96,7 @@ int8_t pucch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t subframe,ui
           get_PL(ue->Mod_id,ue->CC_id,eNB_id),
           ue->dlsch[eNB_id][0]->g_pucch);
   } else {
-    LOG_I(PHY,"[UE  %d][SR %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB g_pucch %d dB\n",
+    LOG_D(PHY,"[UE  %d][SR %x] frame %d, subframe %d: Po_PUCCH %d dBm : Po_NOMINAL_PUCCH %d dBm, PL %d dB g_pucch %d dB\n",
           ue->Mod_id,
           ue->dlsch[eNB_id][0]->rnti,proc->frame_tx,subframe,
           Po_PUCCH,
diff --git a/openair1/SCHED/srs_pc.c b/openair1/SCHED/srs_pc.c
new file mode 100644
index 0000000000000000000000000000000000000000..98049b2ed0cd09a9e1c32da5e8dfad4254970242
--- /dev/null
+++ b/openair1/SCHED/srs_pc.c
@@ -0,0 +1,100 @@
+/*
+ * 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.0  (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 srs_pc.c
+ * \brief Implementation of UE SRS Power Control procedures from 36.213 LTE specifications (Section
+ * \author H. Bilel
+ * \date 2016
+ * \version 0.1
+ * \company TCL
+ * \email: haithem.bilel@alcatelOneTouch.com
+ * \note
+ * \warning
+ */
+
+#include "PHY/defs.h"
+#include "PHY/LTE_TRANSPORT/proto.h"
+#include "PHY/extern.h"
+
+void srs_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t *pnb_rb_srs, uint8_t abstraction_flag)
+{
+
+  int16_t PL;
+  int8_t  p0_NominalPUSCH;
+  int8_t  p0_UE_PUSCH;
+  int8_t  Psrs_offset;
+  int16_t P_srs;
+  int16_t f_pusch;
+  uint8_t alpha;
+  uint8_t Msrs = 0;
+  
+
+  SOUNDINGRS_UL_CONFIG_DEDICATED *psoundingrs_ul_config_dedicated = &ue->soundingrs_ul_config_dedicated[eNB_id];
+  LTE_DL_FRAME_PARMS             *pframe_parms                    = &ue->frame_parms;
+  
+  uint8_t Bsrs  = psoundingrs_ul_config_dedicated->srs_Bandwidth;
+  uint8_t Csrs  = pframe_parms->soundingrs_ul_config_common.srs_BandwidthConfig;
+  LOG_D(PHY," SRS Power Control; AbsSubframe %d.%d, eNB_id %d, N_RB_UL %d, srs_Bandwidth %d, srs_BandwidthConfig %d \n",proc->frame_tx,proc->subframe_tx,eNB_id,pframe_parms->N_RB_UL,Bsrs,Csrs);
+  
+  if (pframe_parms->N_RB_UL < 41)
+  {
+    Msrs    = Nb_6_40[Csrs][Bsrs];
+  } 
+  else if (pframe_parms->N_RB_UL < 61)
+  {
+    Msrs    = Nb_41_60[Csrs][Bsrs];
+  } 
+  else if (pframe_parms->N_RB_UL < 81)
+  {
+    Msrs    = Nb_61_80[Csrs][Bsrs];
+  } 
+  else if (pframe_parms->N_RB_UL <111)
+  {
+    Msrs    = Nb_81_110[Csrs][Bsrs];
+  }
+
+  // SRS Power control 36.213 5.1.3.1
+  // P_srs   =  P_srs_offset+ 10log10(Msrs) + P_opusch(j) + alpha*PL + f(i))
+
+  p0_NominalPUSCH = ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
+  p0_UE_PUSCH     = ue->ul_power_control_dedicated[eNB_id].p0_UE_PUSCH;
+  Psrs_offset     = (ue->ul_power_control_dedicated[eNB_id].pSRS_Offset - 3);
+
+
+  f_pusch     = ue->ulsch[eNB_id]->f_pusch;
+  alpha       = alpha_lut[ue->frame_parms.ul_power_control_config_common.alpha];
+  PL          = get_PL(ue->Mod_id,ue->CC_id,eNB_id);
+
+  LOG_D(PHY," SRS Power Control; eNB_id %d, p0_NominalPUSCH %d, p0_UE_PUSCH %d, alpha %d \n",eNB_id,p0_NominalPUSCH,p0_UE_PUSCH,alpha);
+  LOG_D(PHY," SRS Power Control; eNB_id %d, pSRS_Offset[dB] %d, Msrs %d, PL %d, f_pusch %d \n",eNB_id,Psrs_offset,Msrs,PL,f_pusch);
+
+  P_srs  = (p0_NominalPUSCH + p0_UE_PUSCH) + Psrs_offset + f_pusch;
+  P_srs += (((int32_t)alpha * (int32_t)PL) + hundred_times_log10_NPRB[Msrs-1])/100 ;
+  
+  ue->ulsch[eNB_id]->Po_SRS = P_srs;
+  if(ue->ulsch[eNB_id]->Po_SRS > ue->tx_power_max_dBm)
+  {
+      ue->ulsch[eNB_id]->Po_SRS = ue->tx_power_max_dBm;
+  }
+
+  pnb_rb_srs[0]             = Msrs;
+  LOG_D(PHY," SRS Power Control; eNB_id %d, Psrs_pc[dBm] %d, Pcmax[dBm] %d, Psrs[dBm] %d\n",eNB_id,P_srs,ue->tx_power_max_dBm,ue->ulsch[eNB_id]->Po_SRS);
+}
diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c
index 96c533bde50dddba3876991f1c687153037cd3a3..f9a8acfa85cbcd5ffac2014489e83e62472c2e48 100644
--- a/openair1/SIMULATION/LTE_PHY/dlsim.c
+++ b/openair1/SIMULATION/LTE_PHY/dlsim.c
@@ -275,6 +275,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
     case 1:
 
     case 2:
+
+    case 7:
       if (common_flag == 0) {
 	
 	if (eNB->frame_parms.frame_type == TDD) {
@@ -403,7 +405,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
                                              SI_RNTI,
                                              0,
                                              P_RNTI,
-                                             eNB->UE_stats[0].DL_pmi_single);
+                                             eNB->UE_stats[0].DL_pmi_single,
+					     transmission_mode>=7?transmission_mode:0);
 
           *num_dci = *num_dci+1;
           *num_ue_spec_dci = *num_ue_spec_dci+1;
@@ -543,7 +546,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
                                              SI_RNTI,
                                              0,
                                              P_RNTI,
-                                             eNB->UE_stats[0].DL_pmi_single);
+                                             eNB->UE_stats[0].DL_pmi_single,
+					     transmission_mode>=7?transmission_mode:0);
 
           *num_common_dci=*num_common_dci+1;
           *num_dci = *num_dci + 1;
@@ -710,7 +714,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
                                              SI_RNTI,
                                              0,
                                              P_RNTI,
-                                             eNB->UE_stats[0].DL_pmi_single);
+                                             eNB->UE_stats[0].DL_pmi_single,
+					     transmission_mode>=7?transmission_mode:0);
 
           *num_dci = *num_dci + 1;
           *num_ue_spec_dci = *num_ue_spec_dci + 1;
@@ -850,7 +855,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
                                              SI_RNTI,
                                              0,
                                              P_RNTI,
-                                             eNB->UE_stats[0].DL_pmi_single);
+                                             eNB->UE_stats[0].DL_pmi_single,
+					     transmission_mode>=7?transmission_mode:0);
 
           *num_common_dci = *num_common_dci + 1;
           *num_dci = *num_dci + 1;
@@ -1018,7 +1024,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
                                              SI_RNTI,
                                              0,
                                              P_RNTI,
-                                             eNB->UE_stats[0].DL_pmi_single);
+                                             eNB->UE_stats[0].DL_pmi_single,
+					     transmission_mode>=7?transmission_mode:0);
 
           *num_dci = *num_dci + 1;
           *num_ue_spec_dci = *num_ue_spec_dci + 1;
@@ -1158,7 +1165,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
                                              SI_RNTI,
                                              0,
                                              P_RNTI,
-                                             eNB->UE_stats[0].DL_pmi_single);
+                                             eNB->UE_stats[0].DL_pmi_single,
+					     transmission_mode>=7?transmission_mode:0);
 
           *num_common_dci = *num_common_dci + 1;
           *num_dci = *num_dci + 1;
@@ -1187,7 +1195,8 @@ void fill_DCI(PHY_VARS_eNB *eNB,
                                            SI_RNTI,
                                            0,
                                            P_RNTI,
-                                           eNB->UE_stats[k].DL_pmi_single);
+                                           eNB->UE_stats[k].DL_pmi_single,
+					   transmission_mode>=7?transmission_mode:0);
 
         dump_dci(&eNB->frame_parms,&dci_alloc[*num_dci]);
         *num_ue_spec_dci = *num_ue_spec_dci + 1;
@@ -1252,6 +1261,7 @@ int main(int argc, char **argv)
 
   int c;
   int k,i,aa;
+  int re;
 
   int s,Kr,Kr_bytes;
 
@@ -1268,7 +1278,7 @@ int main(int argc, char **argv)
   double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel
 
 
-  uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx=1,n_rx=2;
+  uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=2;
   uint16_t Nid_cell=0;
 
   int eNB_id = 0;
@@ -1409,7 +1419,7 @@ int main(int argc, char **argv)
   //  num_layers = 1;
   perfect_ce = 0;
 
-  while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:Pl:WXY")) != -1) {
+  while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:q:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:Pl:WXY")) != -1) {
     switch (c) {
     case 'a':
       awgn_flag = 1;
@@ -1610,7 +1620,7 @@ int main(int argc, char **argv)
       dual_stream_UE=1;
       UE->use_ia_receiver = 1;
 
-      if ((n_tx!=2) || (transmission_mode!=5)) {
+      if ((n_tx_port!=2) || (transmission_mode!=5)) {
         msg("IA receiver only supported for TM5!");
         exit(-1);
       }
@@ -1631,6 +1641,17 @@ int main(int argc, char **argv)
       print_perf=1;
       break;
 
+    case 'q':
+      n_tx_port=atoi(optarg);
+
+      if ((n_tx_port==0) || ((n_tx_port>2))) {
+        msg("Unsupported number of cell specific antennas ports %d\n",n_tx_port);
+        exit(-1);
+      }
+
+      break;
+
+
     case 'x':
       transmission_mode=atoi(optarg);
 
@@ -1639,25 +1660,37 @@ int main(int argc, char **argv)
           (transmission_mode!=3) &&
           (transmission_mode!=4) &&
           (transmission_mode!=5) &&
-          (transmission_mode!=6)) {
+          (transmission_mode!=6) &&
+          (transmission_mode!=7)) {
         msg("Unsupported transmission mode %d\n",transmission_mode);
         exit(-1);
       }
 
-      if (transmission_mode>1) {
-        n_tx = 2;
+      if (transmission_mode>1 && transmission_mode<7) {
+        n_tx_port = 2;
       }
 
       break;
 
     case 'y':
-      n_tx=atoi(optarg);
+      n_tx_phy=atoi(optarg);
 
-      if ((n_tx==0) || (n_tx>2)) {
-        msg("Unsupported number of tx antennas %d\n",n_tx);
+      if (n_tx_phy < n_tx_port) {
+        msg("n_tx_phy mush not be smaller than n_tx_port");
         exit(-1);
       }
 
+      if ((transmission_mode>1 && transmission_mode<7) && n_tx_port<2) {
+        msg("n_tx_port must be >1 for transmission_mode %d\n",transmission_mode);
+        exit(-1);
+      }
+
+      if (transmission_mode==7 && (n_tx_phy!=1 && n_tx_phy!=2 && n_tx_phy!=4 && n_tx_phy!=8 && n_tx_phy!=16 && n_tx_phy!=64 && n_tx_phy!=128)) {
+        msg("Physical number of antennas not supported for TM7.\n");
+        exit(-1);
+      }
+
+      break;
       break;
 
     case 'X':
@@ -1686,7 +1719,7 @@ int main(int argc, char **argv)
 
     case 'h':
     default:
-      printf("%s -h(elp) -a(wgn on) -d(ci decoding on) -p(extended prefix on) -m mcs1 -M mcs2 -n n_frames -s snr0 -x transmission mode (1,2,5,6) -y TXant -z RXant -I trch_file\n",argv[0]);
+      printf("%s -h(elp) -a(wgn on) -d(ci decoding on) -p(extended prefix on) -m mcs1 -M mcs2 -n n_frames -s snr0 -x transmission mode (1,2,5,6,7) -y TXant -z RXant -I trch_file\n",argv[0]);
       printf("-h This message\n");
       printf("-a Use AWGN channel and not multipath\n");
       printf("-c Number of PDCCH symbols\n");
@@ -1701,7 +1734,8 @@ int main(int argc, char **argv)
       printf("-r ressource block allocation (see  section 7.1.6.3 in 36.213\n");
       printf("-g [A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M')\n");
       printf("-F forgetting factor (0 new channel every trial, 1 channel constant\n");
-      printf("-x Transmission mode (1,2,6 for the moment)\n");
+      printf("-x Transmission mode (1,2,6,7 for the moment)\n");
+      printf("-q Number of TX antennas ports used in eNB\n");
       printf("-y Number of TX antennas used in eNB\n");
       printf("-z Number of RX antennas used in UE\n");
       printf("-t MCS of interfering UE\n");
@@ -1740,9 +1774,6 @@ int main(int argc, char **argv)
   } else
     NB_RB = 4;
 
-  if ((transmission_mode > 1) && (n_tx != 2))
-    printf("n_tx must be >1 for transmission_mode %d\n",transmission_mode);
-
   if (xforms==1) {
     fl_initialize (&argc, argv, NULL, 0, 0);
     form_ue = create_lte_phy_scope_ue();
@@ -1762,7 +1793,8 @@ int main(int argc, char **argv)
     printf("dual_stream_UE=%d\n", dual_stream_UE);
   }
 
-  lte_param_init(n_tx,
+  lte_param_init(n_tx_port,
+		 n_tx_phy,
 		 n_rx,
 		 transmission_mode,
 		 extended_prefix_flag,
@@ -1774,6 +1806,12 @@ int main(int argc, char **argv)
 		 osf,
 		 perfect_ce);
 
+  if ((transmission_mode==1) || (transmission_mode==7)) {
+    for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) 
+     for (re=0; re<eNB->frame_parms.ofdm_symbol_size; re++) 
+       eNB->common_vars.beam_weights[0][0][aa][re] = 0x00007fff/eNB->frame_parms.nb_antennas_tx; 
+  }
+
   eNB->mac_enabled=1;
   if (two_thread_flag == 0) {
     eNB->te = dlsch_encoding;
@@ -1795,7 +1833,7 @@ int main(int argc, char **argv)
   printf("Setting mcs2 = %d\n",mcs2);
   printf("NPRB = %d\n",NB_RB);
   printf("n_frames = %d\n",n_frames);
-  printf("Transmission mode %d with %dx%d antenna configuration, Extended Prefix %d\n",transmission_mode,n_tx,n_rx,extended_prefix_flag);
+  printf("Transmission mode %d with %dx%d antenna configuration, Extended Prefix %d\n",transmission_mode,n_tx_phy,n_rx,extended_prefix_flag);
 
   snr1 = snr0+snr_int;
   printf("SNR0 %f, SNR1 %f\n",snr0,snr1);
@@ -1830,7 +1868,7 @@ int main(int argc, char **argv)
     //char dirname[FILENAME_MAX];
     //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname );
     sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv",
-            N_RB_DL,mcs1,n_tx,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode);
+            N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode);
     //mkdir(dirname,0777);
     time_meas_fd = fopen(time_meas_fname,"w");
     if (time_meas_fd==NULL) {
@@ -2042,7 +2080,7 @@ int main(int argc, char **argv)
   for (k=0; k<n_users; k++) {
     // Create transport channel structures for 2 transport blocks (MIMO)
     for (i=0; i<2; i++) {
-      eNB->dlsch[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0);
+      eNB->dlsch[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
 
       if (!eNB->dlsch[k][i]) {
         printf("Can't get eNB dlsch structures\n");
@@ -2065,7 +2103,7 @@ int main(int argc, char **argv)
   }
 
   // structure for SIC at UE
-  UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0);
+  UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
 
   if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) {
 
@@ -2159,7 +2197,9 @@ int main(int argc, char **argv)
                                   get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs),
                                   eNB->dlsch[0][0]->harq_processes[0]->Nl,
                                   num_pdcch_symbols,
-                                  0,subframe);
+                                  0,
+				  subframe,
+				  transmission_mode>=7?transmission_mode:0);
 
   uncoded_ber_bit = (short*) malloc(sizeof(short)*coded_bits_per_codeword);
   printf("uncoded_ber_bit=%p\n",uncoded_ber_bit);
@@ -2354,6 +2394,7 @@ int main(int argc, char **argv)
 	    
 	    start_meas(&eNB->ofdm_mod_stats);
 	    
+            /*
 	    do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id],
 			  eNB->common_vars.txdata[eNB_id],
 			  (subframe*2),
@@ -2363,7 +2404,19 @@ int main(int argc, char **argv)
 			  eNB->common_vars.txdata[eNB_id],
 			  (subframe*2)+1,
 			  &eNB->frame_parms);
-	    
+	    */
+
+            do_OFDM_mod_symbol(&eNB->common_vars,
+                               eNB_id,
+                               (subframe*2),
+                               &eNB->frame_parms);
+
+            do_OFDM_mod_symbol(&eNB->common_vars,
+                               eNB_id,
+                               (subframe*2)+1,
+                               &eNB->frame_parms);
+
+
 	    stop_meas(&eNB->ofdm_mod_stats);
 	    
 	    // generate next subframe for channel estimation
@@ -2393,11 +2446,15 @@ int main(int argc, char **argv)
 	      
             if (n_frames==1) {
               printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB);
-              write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe* eNB->frame_parms.samples_per_tti],
 
-                           eNB->frame_parms.samples_per_tti,1,1);
-	      write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],
-			   nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+              write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe* eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti,1,1);
+
+              if (transmission_mode<7) {
+	        write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+              } else if (transmission_mode == 7) {
+                write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][5][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+                write_output("txsigF0_BF.m","txsF0_BF", &eNB->common_vars.txdataF_BF[eNB_id][0][0],eNB->frame_parms.ofdm_symbol_size,1,1);
+              }
             }
 	  }
 
diff --git a/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c
new file mode 100644
index 0000000000000000000000000000000000000000..66dea185de1a039af9cdda09e6660961af5837f6
--- /dev/null
+++ b/openair1/SIMULATION/LTE_PHY/dlsim_tm7.c
@@ -0,0 +1,4326 @@
+ /******************************************************************************
+    OpenAirInterface
+    Copyright(c) 1999 - 2014 Eurecom
+
+    OpenAirInterface is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+
+    OpenAirInterface is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenAirInterface.The full GNU General Public License is
+   included in this distribution in the file called "COPYING". If not,
+   see <http://www.gnu.org/licenses/>.
+
+  Contact Information
+  OpenAirInterface Admin: openair_admin@eurecom.fr
+  OpenAirInterface Tech : openair_tech@eurecom.fr
+  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
+
+  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+
+/*! \file dlsim.c
+ \brief Top-level DL simulator
+ \author R. Knopp
+ \date 2011 - 2014
+ \version 0.1
+ \company Eurecom
+ \email: knopp@eurecom.fr
+ \note
+ \warning
+*/
+
+#include <string.h>
+#include <math.h>
+#include <unistd.h>
+#include <execinfo.h>
+#include <signal.h>
+
+#include "SIMULATION/TOOLS/defs.h"
+#include "PHY/types.h"
+#include "PHY/defs.h"
+#include "PHY/vars.h"
+
+#include "SCHED/defs.h"
+#include "SCHED/vars.h"
+#include "LAYER2/MAC/vars.h"
+
+#include "OCG_vars.h"
+#include "UTIL/LOG/log.h"
+#include "UTIL/LISTS/list.h"
+
+#include "unitary_defs.h"
+
+extern unsigned int dlsch_tbs25[27][25],TBStable[27][110];
+extern unsigned char offset_mumimo_llr_drange_fix;
+
+#include "PHY/TOOLS/lte_phy_scope.h"
+
+PHY_VARS_eNB *eNB;
+PHY_VARS_UE *UE;
+
+int otg_enabled=0;
+/*the following parameters are used to control the processing times calculations*/
+double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */
+double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */
+double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */
+double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */
+int n_tx_dropped = 0; /*!< \brief initial max process time for tx */
+int n_rx_dropped = 0; /*!< \brief initial max process time for rx */
+
+void handler(int sig)
+{
+  void *array[10];
+  size_t size;
+
+  // get void*'s for all entries on the stack
+  size = backtrace(array, 10);
+
+  // print out all the frames to stderr
+  fprintf(stderr, "Error: signal %d:\n", sig);
+  backtrace_symbols_fd(array, size, 2);
+  exit(1);
+}
+
+
+
+//DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_2A[2];
+
+DCI1E_5MHz_2A_M10PRB_TDD_t  DLSCH_alloc_pdu2_1E[2];
+uint64_t DLSCH_alloc_pdu_1[2];
+
+#define UL_RB_ALLOC 0x1ff;
+#define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2)
+//#define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13
+//#define DLSCH_RB_ALLOC 0x0001
+
+int main(int argc, char **argv)
+{
+
+  int c;
+  int k,i,j,aa,aarx,aatx;
+  int re;
+
+  int s,Kr,Kr_bytes;
+
+  double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1,rate;
+  double snr_step=1,input_snr_step=1, snr_int=30;
+
+  LTE_DL_FRAME_PARMS *frame_parms;
+  double **s_re,**s_im,**r_re,**r_im;
+  double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel
+  double iqim=0.0;
+
+  uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=1;
+  uint16_t Nid_cell=0;
+  int32_t **cell_spec_bf_weights;
+  int32_t *ue_spec_bf_weights;
+
+  int eNB_id = 0, eNB_id_i = 1;
+  unsigned char mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0,round,dci_flag=0;
+  unsigned char i_mod = 2;
+  unsigned short NB_RB;
+  unsigned char Ns,l,m;
+  uint16_t tdd_config=3;
+  uint16_t n_rnti=0x1234;
+  int n_users = 1;
+
+  SCM_t channel_model=Rayleigh1;
+  //  unsigned char *input_data,*decoded_output;
+
+  unsigned char *input_buffer0[2],*input_buffer1[2];
+  unsigned short input_buffer_length0,input_buffer_length1;
+  unsigned int ret;
+  unsigned int coded_bits_per_codeword=0,nsymb,dci_cnt,tbs=0;
+
+  unsigned int tx_lev=0,tx_lev_dB=0,trials,errs[4]= {0,0,0,0},errs2[4]= {0,0,0,0},round_trials[4]= {0,0,0,0},dci_errors=0,dlsch_active=0;//,num_layers;
+  int re_allocated;
+  char fname[32],vname[32];
+  FILE *bler_fd;
+  char bler_fname[256];
+  FILE *time_meas_fd;
+  char time_meas_fname[256];
+  //  FILE *tikz_fd;
+  //  char tikz_fname[256];
+
+  FILE *input_trch_fd=NULL;
+  unsigned char input_trch_file=0;
+  FILE *input_fd=NULL;
+  unsigned char input_file=0;
+  //  char input_val_str[50],input_val_str2[50];
+
+  char input_trch_val[16];
+  double channelx,channely;
+
+  unsigned char pbch_pdu[6];
+
+  DCI_ALLOC_t dci_alloc[8],dci_alloc_rx[8];
+  int num_common_dci=0,num_ue_spec_dci=0,num_dci=0;
+
+  //  FILE *rx_frame_file;
+
+  int n_frames;
+  int n_ch_rlz = 1;
+  channel_desc_t *eNB2UE[4];
+  uint8_t num_pdcch_symbols=1,num_pdcch_symbols_2=0;
+  uint8_t pilot1,pilot2,pilot3;
+  uint8_t rx_sample_offset = 0;
+  //char stats_buffer[4096];
+  //int len;
+  uint8_t num_rounds = 4;//,fix_rounds=0;
+  uint8_t subframe=7;
+  int u;
+  int n=0;
+  int abstx=0;
+  int iii;
+  FILE *csv_fd=NULL;
+  char csv_fname[512];
+  int ch_realization;
+  int pmi_feedback=0;
+  int hold_channel=0;
+
+  // void *data;
+  // int ii;
+  //  int bler;
+  double blerr[4],uncoded_ber,avg_ber;
+  short *uncoded_ber_bit=NULL;
+  uint8_t N_RB_DL=25,osf=1;
+  frame_t frame_type = FDD;
+  int xforms=0;
+  FD_lte_phy_scope_ue *form_ue = NULL;
+  char title[255];
+  uint32_t DLSCH_RB_ALLOC = 0x1fff;
+  int numCCE=0;
+  int dci_length_bytes=0,dci_length=0;
+  //double channel_bandwidth = 5.0, sampling_rate=7.68;
+  int common_flag=0,TPC=0;
+
+  double cpu_freq_GHz;
+  //  time_stats_t ts;//,sts,usts;
+  int avg_iter,iter_trials;
+  int rballocset=0;
+  int print_perf=0;
+  int test_perf=0;
+  int dump_table=0;
+  int llr8_flag=0;
+
+  double effective_rate=0.0;
+  char channel_model_input[10]="I";
+
+  int TB0_active = 1;
+  uint32_t perfect_ce = 0;
+
+  //  LTE_DL_UE_HARQ_t *dlsch0_ue_harq;
+  //  LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq;
+  uint8_t Kmimo;
+  uint8_t ue_category=4;
+  uint32_t Nsoft;
+
+
+
+  int CCE_table[800];
+
+  int threequarter_fs=0;
+
+  opp_enabled=1; // to enable the time meas
+
+#if defined(__arm__)
+  FILE    *proc_fd = NULL;
+  char buf[64];
+
+  proc_fd = fopen("/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq", "r");
+  if(!proc_fd)
+     printf("cannot open /sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq");
+  else {
+     while(fgets(buf, 63, proc_fd))
+        printf("%s", buf);
+  }
+  fclose(proc_fd);
+  cpu_freq_GHz = ((double)atof(buf))/1e6;
+#else
+  cpu_freq_GHz = get_cpu_freq_GHz();
+#endif
+  printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz);
+
+  //signal(SIGSEGV, handler);
+  //signal(SIGABRT, handler);
+
+  logInit();
+
+  // default parameters
+  n_frames = 1000;
+  snr0 = 0;
+  //  num_layers = 1;
+  perfect_ce = 0;
+
+  while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:p:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:PLl:XY")) != -1) {
+    switch (c) {
+    case 'a':
+      awgn_flag = 1;
+      channel_model = AWGN;
+      break;
+
+    case 'A':
+      abstx = 1;
+      break;
+
+    case 'b':
+      tdd_config=atoi(optarg);
+      break;
+
+    case 'B':
+      N_RB_DL=atoi(optarg);
+      break;
+
+    case 'c':
+      num_pdcch_symbols=atoi(optarg);
+      break;
+
+    case 'C':
+      Nid_cell = atoi(optarg);
+      break;
+
+    case 'd':
+      dci_flag = 1;
+      break;
+
+    case 'D':
+      frame_type=TDD;
+      break;
+
+    case 'e':
+      num_rounds=1;
+      common_flag = 1;
+      TPC = atoi(optarg);
+      break;
+      
+    case 'E':
+      threequarter_fs=1;
+      break;
+
+    case 'f':
+      input_snr_step= atof(optarg);
+      break;
+
+    case 'F':
+      forgetting_factor = atof(optarg);
+      break;
+
+    case 'i':
+      input_fd = fopen(optarg,"r");
+      input_file=1;
+      dci_flag = 1;
+      break;
+
+    case 'I':
+      input_trch_fd = fopen(optarg,"r");
+      input_trch_file=1;
+      break;
+
+    case 'L':
+      llr8_flag=1;
+      break;
+
+    case 'l':
+      offset_mumimo_llr_drange_fix=atoi(optarg);
+      break;
+
+    case 'm':
+      mcs1 = atoi(optarg);
+      break;
+
+    case 'M':
+      mcs2 = atoi(optarg);
+      break;
+
+    case 'O':
+      test_perf=atoi(optarg);
+      //print_perf =1;
+      break;
+
+    case 't':
+      mcs_i = atoi(optarg);
+      i_mod = get_Qm(mcs_i);
+      break;
+
+    case 'n':
+      n_frames = atoi(optarg);
+      break;
+
+    case 'o':
+      rx_sample_offset = atoi(optarg);
+      break;
+
+    case 'r':
+      DLSCH_RB_ALLOC = atoi(optarg);
+      rballocset = 1;
+      break;
+
+    case 's':
+      snr0 = atof(optarg);
+      break;
+
+    case 'w':
+      snr_int = atof(optarg);
+      break;
+
+    case 'N':
+      n_ch_rlz= atof(optarg);
+      break;
+
+    case 'p':
+      extended_prefix_flag=1;
+      break;
+
+    case 'g':
+      memcpy(channel_model_input,optarg,10);
+
+      switch((char)*optarg) {
+      case 'A':
+        channel_model=SCM_A;
+        break;
+
+      case 'B':
+        channel_model=SCM_B;
+        break;
+
+      case 'C':
+        channel_model=SCM_C;
+        break;
+
+      case 'D':
+        channel_model=SCM_D;
+        break;
+
+      case 'E':
+        channel_model=EPA;
+        break;
+
+      case 'F':
+        channel_model=EVA;
+        break;
+
+      case 'G':
+        channel_model=ETU;
+        break;
+
+      case 'H':
+        channel_model=Rayleigh8;
+        break;
+
+      case 'I':
+        channel_model=Rayleigh1;
+        break;
+
+      case 'J':
+        channel_model=Rayleigh1_corr;
+        break;
+
+      case 'K':
+        channel_model=Rayleigh1_anticorr;
+        break;
+
+      case 'L':
+        channel_model=Rice8;
+        break;
+
+      case 'M':
+        channel_model=Rice1;
+        break;
+
+      case 'N':
+        channel_model=AWGN;
+        break;
+      default:
+        msg("Unsupported channel model!\n");
+        exit(-1);
+      }
+
+      break;
+
+    case 'R':
+      num_rounds=atoi(optarg);
+      break;
+
+    case 'S':
+      subframe=atoi(optarg);
+      break;
+
+    case 'T':
+      n_rnti=atoi(optarg);
+      break;
+
+    case 'u':
+      dual_stream_UE=1;
+      UE->use_ia_receiver = 1;
+
+      if ((n_tx_port!=2) || (transmission_mode!=5)) {
+        msg("IA receiver only supported for TM5!");
+        exit(-1);
+      }
+
+      break;
+
+    case 'v':
+      i_mod = atoi(optarg);
+
+      if (i_mod!=2 && i_mod!=4 && i_mod!=6) {
+        msg("Wrong i_mod %d, should be 2,4 or 6\n",i_mod);
+        exit(-1);
+      }
+
+      break;
+
+    case 'P':
+      print_perf=1;
+      break;
+
+    case 'q':
+      n_tx_port=atoi(optarg);
+
+      if ((n_tx_port==0) || ((n_tx_port>2))) {
+        msg("Unsupported number of cell specific antennas ports %d\n",n_tx_port);
+        exit(-1);
+      }
+
+      break;
+
+
+    case 'x':
+      transmission_mode=atoi(optarg);
+
+      if ((transmission_mode!=1) &&
+          (transmission_mode!=2) &&
+          (transmission_mode!=3) &&
+          (transmission_mode!=4) &&
+          (transmission_mode!=5) &&
+          (transmission_mode!=6) &&
+          (transmission_mode!=7)) {
+        msg("Unsupported transmission mode %d\n",transmission_mode);
+        exit(-1);
+      }
+
+      if (transmission_mode>1 && transmission_mode<7) {
+        n_tx_port = 2;
+      }
+
+      break;
+
+    case 'y':
+      n_tx_phy=atoi(optarg);
+      
+      if (transmission_mode>1&&transmission_mode<7) {
+        if(n_tx_phy==1) {
+          msg("n_tx_phy must be >1 for transmission_mode %d\n",transmission_mode);
+          exit(-1);
+        } 
+      }
+
+      if (transmission_mode==7 && (n_tx_phy!=1 && n_tx_phy!=2 && n_tx_phy!=4 && n_tx_phy!=8 && n_tx_phy!=16 && n_tx_phy!=64 && n_tx_phy!=128)) {
+        msg("Physical number of antennas not supported for TM7.\n");
+        exit(-1);
+      }
+
+      break;
+
+    case 'X':
+      xforms=1;
+      break;
+
+    case 'Y':
+      perfect_ce=1;
+      break;
+
+    case 'z':
+      n_rx=atoi(optarg);
+
+      if ((n_rx==0) || (n_rx>2)) {
+        msg("Unsupported number of rx antennas %d\n",n_rx);
+        exit(-1);
+      }
+
+      break;
+
+    case 'Z':
+      dump_table=1;
+      break;
+
+
+
+    case 'h':
+    default:
+      printf("%s -h(elp) -a(wgn on) -d(ci decoding on) -p(extended prefix on) -m mcs1 -M mcs2 -n n_frames -s snr0 -x transmission mode (1,2,5,6,7) -y TXant -z RXant -I trch_file\n",argv[0]);
+      printf("-h This message\n");
+      printf("-a Use AWGN channel and not multipath\n");
+      printf("-c Number of PDCCH symbols\n");
+      printf("-m MCS1 for TB 1\n");
+      printf("-M MCS2 for TB 2\n");
+      printf("-d Transmit the DCI and compute its error statistics and the overall throughput\n");
+      printf("-p Use extended prefix mode\n");
+      printf("-n Number of frames to simulate\n");
+      printf("-o Sample offset for receiver\n");
+      printf("-s Starting SNR, runs from SNR to SNR+%.1fdB in steps of %.1fdB. If n_frames is 1 then just SNR is simulated and MATLAB/OCTAVE output is generated\n", snr_int, snr_step);
+      printf("-f step size of SNR, default value is 1.\n");
+      printf("-r ressource block allocation (see  section 7.1.6.3 in 36.213\n");
+      printf("-g [A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M')\n");
+      printf("-F forgetting factor (0 new channel every trial, 1 channel constant\n");
+      printf("-x Transmission mode (1,2,6,7 for the moment)\n");
+      printf("-q Number of TX antennas ports used in eNB\n");
+      printf("-y Number of physical TX antennas used in eNB\n");
+      printf("-z Number of RX antennas used in UE\n");
+      printf("-t MCS of interfering UE\n");
+      printf("-R Number of HARQ rounds (fixed)\n");
+      printf("-A Turns on calibration mode for abstraction.\n");
+      printf("-N Determines the number of Channel Realizations in Abstraction mode. Default value is 1. \n");
+      printf("-O Set the percenatge of effective rate to testbench the modem performance (typically 30 and 70, range 1-100) \n");
+      printf("-I Input filename for TrCH data (binary)\n");
+      printf("-u Enables the Interference Aware Receiver for TM5 (default is normal receiver)\n");
+      exit(1);
+      break;
+    }
+  }
+
+  if (common_flag == 0) {
+    switch (N_RB_DL) {
+    case 6:
+      if (rballocset==0) DLSCH_RB_ALLOC = 0x3f;
+      num_pdcch_symbols = 3;
+      break;
+
+    case 25:
+      if (rballocset==0) DLSCH_RB_ALLOC = 0x1fff;
+      break;
+
+    case 50:
+      if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffff;
+      break;
+
+    case 100:
+      if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffffff;
+      break;
+    }
+
+    NB_RB=conv_nprb(0,DLSCH_RB_ALLOC,N_RB_DL);
+  } else
+    NB_RB = 4;
+
+
+  if (xforms==1) {
+    fl_initialize (&argc, argv, NULL, 0, 0);
+    form_ue = create_lte_phy_scope_ue();
+    sprintf (title, "LTE PHY SCOPE eNB");
+    fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
+    
+    if (!dual_stream_UE==0) {
+      UE->use_ia_receiver = 1;
+      fl_set_button(form_ue->button_0,1);
+      fl_set_object_label(form_ue->button_0, "IA Receiver ON");
+      fl_set_object_color(form_ue->button_0, FL_GREEN, FL_GREEN);
+    }
+  }
+
+  if (transmission_mode==5) {
+    n_users = 2;
+    printf("dual_stream_UE=%d\n", dual_stream_UE);
+  }
+
+  lte_param_init(n_tx_port,n_tx_phy,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,tdd_config,N_RB_DL,threequarter_fs,osf,perfect_ce);
+
+  frame_parms = &eNB->frame_parms;
+
+  /*
+  cell_spec_bf_weights = eNB->common_vars.beam_weights[0][0];
+  for(aa=0;aa<n_tx_phy;aa++) {
+    for(re=0;re<frame_parms->ofdm_symbol_size;re++) {
+      if (n_tx_phy==1 || n_tx_phy==2)
+        cell_spec_bf_weights[aa][re] = 0x00007fff;
+      else if (n_tx_phy==4 || n_tx_phy==8)
+        cell_spec_bf_weights[aa][re] = 0x00007fff>>1;
+      else if (n_tx_phy==16)
+        cell_spec_bf_weights[aa][re] = 0x00007fff>>2;
+      else if (n_tx_phy==64)
+        cell_spec_bf_weights[aa][re] = 0x00007fff>>4;
+    }
+  } 
+
+  if (transmission_mode==7){
+    lte_gold_ue_spec_port5(eNB->lte_gold_uespec_port5_table[0],Nid_cell,n_rnti);
+    lte_gold_ue_spec_port5(UE->lte_gold_uespec_port5_table,Nid_cell,n_rnti);
+  }*/
+
+    
+  eNB_id_i = UE->n_connected_eNB;
+
+  printf("Setting mcs1 = %d\n",mcs1);
+  printf("Setting mcs2 = %d\n",mcs2);
+  printf("NPRB = %d\n",NB_RB);
+  printf("n_frames = %d\n",n_frames);
+  printf("Transmission mode %d with %dx%d antenna configuration, Extended Prefix %d\n",transmission_mode,n_tx_phy,n_rx,extended_prefix_flag);
+
+  snr1 = snr0+snr_int;
+  printf("SNR0 %f, SNR1 %f\n",snr0,snr1);
+
+
+  s_re = malloc(n_tx_phy*sizeof(double*));
+  s_im = malloc(n_tx_phy*sizeof(double*));
+  r_re = malloc(2*sizeof(double*));
+  r_im = malloc(2*sizeof(double*));
+  //  r_re0 = malloc(2*sizeof(double*));
+  //  r_im0 = malloc(2*sizeof(double*));
+
+  nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12;
+
+  printf("Channel Model= (%s,%d)\n",channel_model_input, channel_model);
+  printf("SCM-A=%d, SCM-B=%d, SCM-C=%d, SCM-D=%d, EPA=%d, EVA=%d, ETU=%d, Rayleigh8=%d, Rayleigh1=%d, Rayleigh1_corr=%d, Rayleigh1_anticorr=%d, Rice1=%d, Rice8=%d\n",
+         SCM_A, SCM_B, SCM_C, SCM_D, EPA, EVA, ETU, Rayleigh8, Rayleigh1, Rayleigh1_corr, Rayleigh1_anticorr, Rice1, Rice8);
+
+  if(transmission_mode==5)
+    sprintf(bler_fname,"bler_tm%d_chan%d_perfce%d_ntx%d_nrx%d_mcs%d_mcsi%d_u%d_imod%d.csv",transmission_mode,channel_model,perfect_ce,n_tx_phy,n_rx,mcs1,mcs_i,dual_stream_UE,i_mod);
+  else
+    sprintf(bler_fname,"bler_tm%d_chan%d_perfce%d_ntx%d_nrx%d_mcs%d.csv",transmission_mode,channel_model,perfect_ce,n_tx_phy,n_rx,mcs1);
+
+  bler_fd = fopen(bler_fname,"w");
+  if (bler_fd==NULL) {
+    fprintf(stderr,"Cannot create file %s!\n",bler_fname);
+    exit(-1);
+  }
+  fprintf(bler_fd,"SNR; MCS; TBS; rate; err0; trials0; err1; trials1; err2; trials2; err3; trials3; dci_err\n");
+
+  if (test_perf != 0) {
+    char hostname[1024];
+    hostname[1023] = '\0';
+    gethostname(hostname, 1023);
+    printf("Hostname: %s\n", hostname);
+    //char dirname[FILENAME_MAX];
+    //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname );
+    sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv",
+            N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode);
+    //mkdir(dirname,0777);
+    time_meas_fd = fopen(time_meas_fname,"w");
+    if (time_meas_fd==NULL) {
+      fprintf(stderr,"Cannot create file %s!\n",time_meas_fname);
+      exit(-1);
+    }
+  }
+
+  if(abstx) {
+    // CSV file
+    sprintf(csv_fname,"dataout_tx%d_u2%d_mcs%d_chan%d_nsimus%d_R%d.m",transmission_mode,dual_stream_UE,mcs1,channel_model,n_frames,num_rounds);
+    csv_fd = fopen(csv_fname,"w");
+    fprintf(csv_fd,"data_all%d=[",mcs1);
+    if (csv_fd==NULL) {
+      fprintf(stderr,"Cannot create file %s!\n",csv_fname);
+      exit(-1);
+    }
+  }
+
+  /*
+  //sprintf(tikz_fname, "second_bler_tx%d_u2=%d_mcs%d_chan%d_nsimus%d.tex",transmission_mode,dual_stream_UE,mcs,channel_model,n_frames);
+  sprintf(tikz_fname, "second_bler_tx%d_u2%d_mcs%d_chan%d_nsimus%d",transmission_mode,dual_stream_UE,mcs,channel_model,n_frames);
+  tikz_fd = fopen(tikz_fname,"w");
+  //fprintf(tikz_fd,"\\addplot[color=red, mark=o] plot coordinates {");
+  switch (mcs)
+    {
+    case 0:
+      fprintf(tikz_fd,"\\addplot[color=blue, mark=star] plot coordinates {");
+      break;
+    case 1:
+      fprintf(tikz_fd,"\\addplot[color=red, mark=star] plot coordinates {");
+      break;
+    case 2:
+      fprintf(tikz_fd,"\\addplot[color=green, mark=star] plot coordinates {");
+      break;
+    case 3:
+      fprintf(tikz_fd,"\\addplot[color=yellow, mark=star] plot coordinates {");
+      break;
+    case 4:
+      fprintf(tikz_fd,"\\addplot[color=black, mark=star] plot coordinates {");
+      break;
+    case 5:
+      fprintf(tikz_fd,"\\addplot[color=blue, mark=o] plot coordinates {");
+      break;
+    case 6:
+      fprintf(tikz_fd,"\\addplot[color=red, mark=o] plot coordinates {");
+      break;
+    case 7:
+      fprintf(tikz_fd,"\\addplot[color=green, mark=o] plot coordinates {");
+      break;
+    case 8:
+      fprintf(tikz_fd,"\\addplot[color=yellow, mark=o] plot coordinates {");
+      break;
+    case 9:
+      fprintf(tikz_fd,"\\addplot[color=black, mark=o] plot coordinates {");
+      break;
+    case 10:
+      fprintf(tikz_fd,"\\addplot[color=blue, mark=square] plot coordinates {");
+      break;
+    case 11:
+      fprintf(tikz_fd,"\\addplot[color=red, mark=square] plot coordinates {");
+      break;
+    case 12:
+      fprintf(tikz_fd,"\\addplot[color=green, mark=square] plot coordinates {");
+      break;
+    case 13:
+      fprintf(tikz_fd,"\\addplot[color=yellow, mark=square] plot coordinates {");
+      break;
+    case 14:
+      fprintf(tikz_fd,"\\addplot[color=black, mark=square] plot coordinates {");
+      break;
+    case 15:
+      fprintf(tikz_fd,"\\addplot[color=blue, mark=diamond] plot coordinates {");
+      break;
+    case 16:
+      fprintf(tikz_fd,"\\addplot[color=red, mark=diamond] plot coordinates {");
+      break;
+    case 17:
+      fprintf(tikz_fd,"\\addplot[color=green, mark=diamond] plot coordinates {");
+      break;
+    case 18:
+      fprintf(tikz_fd,"\\addplot[color=yellow, mark=diamond] plot coordinates {");
+      break;
+    case 19:
+      fprintf(tikz_fd,"\\addplot[color=black, mark=diamond] plot coordinates {");
+      break;
+    case 20:
+      fprintf(tikz_fd,"\\addplot[color=blue, mark=x] plot coordinates {");
+      break;
+    case 21:
+      fprintf(tikz_fd,"\\addplot[color=red, mark=x] plot coordinates {");
+      break;
+    case 22:
+      fprintf(tikz_fd,"\\addplot[color=green, mark=x] plot coordinates {");
+      break;
+    case 23:
+      fprintf(tikz_fd,"\\addplot[color=yellow, mark=x] plot coordinates {");
+      break;
+    case 24:
+      fprintf(tikz_fd,"\\addplot[color=black, mark=x] plot coordinates {");
+      break;
+    case 25:
+      fprintf(tikz_fd,"\\addplot[color=blue, mark=x] plot coordinates {");
+      break;
+    case 26:
+      fprintf(tikz_fd,"\\addplot[color=red, mark=+] plot coordinates {");
+      break;
+    case 27:
+      fprintf(tikz_fd,"\\addplot[color=green, mark=+] plot coordinates {");
+      break;
+    case 28:
+      fprintf(tikz_fd,"\\addplot[color=yellow, mark=+] plot coordinates {");
+      break;
+    }
+  */
+
+  for (i=0; i<n_tx_phy; i++){
+    s_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
+    s_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
+  }
+
+  for (i=0; i<2; i++) {
+    r_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
+    r_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
+    //    r_re0[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
+    //    bzero(r_re0[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
+    //    r_im0[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
+    //    bzero(r_im0[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
+  }
+
+
+  UE->pdcch_vars[0]->crnti = n_rnti;
+
+  // Fill in UL_alloc
+  UL_alloc_pdu.type    = 0;
+  UL_alloc_pdu.hopping = 0;
+  UL_alloc_pdu.rballoc = UL_RB_ALLOC;
+  UL_alloc_pdu.mcs     = 1;
+  UL_alloc_pdu.ndi     = 1;
+  UL_alloc_pdu.TPC     = 0;
+  UL_alloc_pdu.cqi_req = 1;
+
+  CCCH_alloc_pdu.type               = 0;
+  CCCH_alloc_pdu.vrb_type           = 0;
+  CCCH_alloc_pdu.rballoc            = CCCH_RB_ALLOC;
+  CCCH_alloc_pdu.ndi      = 1;
+  CCCH_alloc_pdu.mcs      = 1;
+  CCCH_alloc_pdu.harq_pid = 0;
+
+  DLSCH_alloc_pdu2_1E[0].rah              = 0;
+  DLSCH_alloc_pdu2_1E[0].rballoc          = DLSCH_RB_ALLOC;
+  DLSCH_alloc_pdu2_1E[0].TPC              = 0;
+  DLSCH_alloc_pdu2_1E[0].dai              = 0;
+  DLSCH_alloc_pdu2_1E[0].harq_pid         = 0;
+  //DLSCH_alloc_pdu2_1E[0].tb_swap          = 0;
+  DLSCH_alloc_pdu2_1E[0].mcs             = mcs1;
+  DLSCH_alloc_pdu2_1E[0].ndi             = 1;
+  DLSCH_alloc_pdu2_1E[0].rv              = 0;
+  // Forget second codeword
+  DLSCH_alloc_pdu2_1E[0].tpmi             = (transmission_mode>=5 ? 5 : 0);  // precoding
+  DLSCH_alloc_pdu2_1E[0].dl_power_off     = (transmission_mode==5 ? 0 : 1);
+
+  DLSCH_alloc_pdu2_1E[1].rah              = 0;
+  DLSCH_alloc_pdu2_1E[1].rballoc          = DLSCH_RB_ALLOC;
+  DLSCH_alloc_pdu2_1E[1].TPC              = 0;
+  DLSCH_alloc_pdu2_1E[1].dai              = 0;
+  DLSCH_alloc_pdu2_1E[1].harq_pid         = 0;
+  //DLSCH_alloc_pdu2_1E[1].tb_swap          = 0;
+  DLSCH_alloc_pdu2_1E[1].mcs             = mcs_i;
+  DLSCH_alloc_pdu2_1E[1].ndi             = 1;
+  DLSCH_alloc_pdu2_1E[1].rv              = 0;
+  // Forget second codeword
+  DLSCH_alloc_pdu2_1E[1].tpmi             = (transmission_mode>=5 ? 5 : 0) ;  // precoding
+  DLSCH_alloc_pdu2_1E[1].dl_power_off     = (transmission_mode==5 ? 0 : 1);
+
+  eNB2UE[0] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx,
+                                   UE->frame_parms.nb_antennas_rx,
+                                   channel_model,
+                                   N_RB2sampling_rate(eNB->frame_parms.N_RB_DL),
+				   N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
+                                   forgetting_factor,
+                                   rx_sample_offset,
+                                   0);
+
+  if(num_rounds>1) {
+    for(n=1; n<4; n++)
+      eNB2UE[n] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx,
+                                       UE->frame_parms.nb_antennas_rx,
+                                       channel_model,
+				       N_RB2sampling_rate(eNB->frame_parms.N_RB_DL),
+				       N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL),
+				       forgetting_factor,
+                                       rx_sample_offset,
+                                       0);
+  }
+
+  if (eNB2UE[0]==NULL) {
+    msg("Problem generating channel model. Exiting.\n");
+    exit(-1);
+  }
+
+  if ((transmission_mode == 3) || (transmission_mode==4))
+    Kmimo=2;
+  else
+    Kmimo=1;
+
+  switch (ue_category) {
+  case 1:
+    Nsoft = 250368;
+    break;
+  case 2:
+  case 3:
+    Nsoft = 1237248;
+    break;
+  case 4:
+    Nsoft = 1827072;
+    break;
+  default:
+    printf("Unsupported UE category %d\n",ue_category);
+    exit(-1);
+    break;
+  }
+
+  for (k=0; k<n_users; k++) {
+    // Create transport channel structures for 2 transport blocks (MIMO)
+    for (i=0; i<2; i++) {
+      eNB->dlsch[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
+
+      if (!eNB->dlsch[k][i]) {
+        printf("Can't get eNB dlsch structures\n");
+        exit(-1);
+      } else {
+         // this initilisation may should be moved to another place
+        for (j=0; j<4; j++) {                                                            
+          for (aa=0; aa<n_tx_phy; aa++) {                                          
+            ue_spec_bf_weights = eNB->dlsch[k][i]->ue_spec_bf_weights[j][aa];
+
+            for (re=0;re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES;re++) {
+              if (n_tx_phy==1 || n_tx_phy==2)
+                ue_spec_bf_weights[re] = 0x00007fff;
+              else if (n_tx_phy==4 || n_tx_phy==8)
+                ue_spec_bf_weights[re] = 0x00007fff>>1;
+              else if (n_tx_phy==16)
+                ue_spec_bf_weights[re] = 0x00007fff>>2;
+              else if (n_tx_phy==64)
+                ue_spec_bf_weights[re] = 0x00007fff>>4;
+            }
+
+          }
+        } 
+
+      }
+
+      eNB->dlsch[k][i]->rnti = n_rnti+k;
+    }
+  }
+
+  for (i=0; i<2; i++) {
+    UE->dlsch[0][i]  = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0);
+
+    if (!UE->dlsch[0][i]) {
+      printf("Can't get ue dlsch structures\n");
+      exit(-1);
+    }
+
+    UE->dlsch[0][i]->rnti   = n_rnti;
+  }
+
+  // structure for SIC at UE
+  UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
+
+  if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) {
+
+    eNB->UE_stats[0].DL_pmi_single = (unsigned short)(taus()&0xffff);
+
+    if (n_users>1)
+      eNB->UE_stats[1].DL_pmi_single = (eNB->UE_stats[0].DL_pmi_single ^ 0x1555); //opposite PMI
+  } else {
+    eNB->UE_stats[0].DL_pmi_single = 0;
+
+    if (n_users>1)
+      eNB->UE_stats[1].DL_pmi_single = 0;
+  }
+
+  //TODO: allocate memory for calibration matrix and calib_dl_ch_estimates in init_lte.c
+  //for first tests initialze calibration matrix with idendity
+  //read_calibration_matrix(calib_fname, nb_ant, nb_freq, eNB->common_vars.tdd_calib_coeffs[0]);
+
+  if (input_fd==NULL) {
+
+
+    /*
+    // common DCI
+    memcpy(&dci_alloc[num_dci].dci_pdu[0],&CCCH_alloc_pdu,sizeof(DCI1A_5MHz_TDD_1_6_t));
+    dci_alloc[num_dci].dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
+    dci_alloc[num_dci].L          = 2;
+    dci_alloc[num_dci].rnti       = SI_RNTI;
+    num_dci++;
+    num_common_dci++;
+    */
+
+    // UE specific DCI
+    for(k=0; k<n_users; k++) {
+      switch(transmission_mode) {
+      case 1:
+      case 2:
+      case 7:
+        if (common_flag == 0) {
+
+          if (eNB->frame_parms.frame_type == TDD) {
+
+            switch (eNB->frame_parms.N_RB_DL) {
+            case 6:
+              dci_length = sizeof_DCI1_1_5MHz_TDD_t;
+              dci_length_bytes = sizeof(DCI1_1_5MHz_TDD_t);
+              ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+              ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+              ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+              ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 1;
+              ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 25:
+              dci_length = sizeof_DCI1_5MHz_TDD_t;
+              dci_length_bytes = sizeof(DCI1_5MHz_TDD_t);
+              ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+              ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+              ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+              ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 1;
+              ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 50:
+              dci_length = sizeof_DCI1_10MHz_TDD_t;
+              dci_length_bytes = sizeof(DCI1_10MHz_TDD_t);
+              ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+              ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+              ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+              ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 1;
+              ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 100:
+              ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+              ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+              ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+              ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 1;
+              ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              dci_length = sizeof_DCI1_20MHz_TDD_t;
+              dci_length_bytes = sizeof(DCI1_20MHz_TDD_t);
+              break;
+            }
+          } else {
+            switch (eNB->frame_parms.N_RB_DL) {
+            case 6:
+              dci_length = sizeof_DCI1_1_5MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1_1_5MHz_FDD_t);
+              ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+              ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+              ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+              ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 1;
+              ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 25:
+              dci_length = sizeof_DCI1_5MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1_5MHz_FDD_t);
+              ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+              ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+              ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+              ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 1;
+              ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 50:
+              dci_length = sizeof_DCI1_10MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1_10MHz_FDD_t);
+              ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+              ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+              ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+              ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 1;
+              ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 100:
+              dci_length = sizeof_DCI1_20MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1_20MHz_FDD_t);
+              ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+              ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+              ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+              ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 1;
+              ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+            }
+          }
+
+          memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+          dci_alloc[num_dci].dci_length = dci_length;
+          dci_alloc[num_dci].L          = 1;
+          dci_alloc[num_dci].rnti       = n_rnti+k;
+          dci_alloc[num_dci].format     = format1;
+          dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+          printf("Generating dlsch params for user %d\n",k);
+          generate_eNB_dlsch_params_from_dci(0,
+					     subframe,
+                                             &DLSCH_alloc_pdu_1[0],
+                                             n_rnti+k,
+                                             format1,
+                                             eNB->dlsch[0],
+                                             &eNB->frame_parms,
+                                             eNB->pdsch_config_dedicated,
+                                             SI_RNTI,
+                                             0,
+                                             P_RNTI,
+                                             eNB->UE_stats[0].DL_pmi_single,
+                                             transmission_mode<7?0:transmission_mode);
+
+          /*if (transmission_mode == 7)
+	    eNB->dlsch[0][0]->harq_processes[0]->mimo_mode = TM7; //Xiwen: to check about harq_pid*/
+
+          num_dci++;
+          num_ue_spec_dci++;
+        } else {
+          if (eNB->frame_parms.frame_type == TDD) {
+
+            switch (eNB->frame_parms.N_RB_DL) {
+            case 6:
+              dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t);
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 25:
+              dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t);
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 1;
+              break;
+
+            case 50:
+              dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t);
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 100:
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t);
+              break;
+            }
+          } else {
+            switch (eNB->frame_parms.N_RB_DL) {
+            case 6:
+              dci_length = sizeof_DCI1A_1_5MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t);
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 25:
+              dci_length = sizeof_DCI1A_5MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t);
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 50:
+              dci_length = sizeof_DCI1A_10MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t);
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 100:
+              dci_length = sizeof_DCI1A_20MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t);
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+            }
+          }
+
+          memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+          dci_alloc[num_dci].dci_length = dci_length;
+          dci_alloc[num_dci].L          = 1;
+          dci_alloc[num_dci].rnti       = SI_RNTI;
+          dci_alloc[num_dci].format     = format1A;
+          dci_alloc[num_dci].firstCCE       = 0;
+          dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+          printf("Generating dlsch params for user %d\n",k);
+          generate_eNB_dlsch_params_from_dci(0,
+					     subframe,
+                                             &DLSCH_alloc_pdu_1[0],
+                                             SI_RNTI,
+                                             format1A,
+                                             eNB->dlsch[0],
+                                             &eNB->frame_parms,
+                                             eNB->pdsch_config_dedicated,
+                                             SI_RNTI,
+                                             0,
+                                             P_RNTI,
+                                             eNB->UE_stats[0].DL_pmi_single,
+                                             0);
+
+          num_common_dci++;
+          num_dci++;
+
+        }
+       
+        break;
+
+      case 3:
+        if (common_flag == 0) {
+
+          if (eNB->frame_parms.nb_antennas_tx == 2) {
+
+            if (eNB->frame_parms.frame_type == TDD) {
+
+              switch (eNB->frame_parms.N_RB_DL) {
+              case 6:
+                dci_length = sizeof_DCI2A_1_5MHz_2A_TDD_t;
+                dci_length_bytes = sizeof(DCI2A_1_5MHz_2A_TDD_t);
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 25:
+                dci_length = sizeof_DCI2A_5MHz_2A_TDD_t;
+                dci_length_bytes = sizeof(DCI2A_5MHz_2A_TDD_t);
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 50:
+                dci_length = sizeof_DCI2A_10MHz_2A_TDD_t;
+                dci_length_bytes = sizeof(DCI2A_10MHz_2A_TDD_t);
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 100:
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                dci_length = sizeof_DCI2A_20MHz_2A_TDD_t;
+                dci_length_bytes = sizeof(DCI2A_20MHz_2A_TDD_t);
+                break;
+              }
+            }
+
+            else {
+              switch (eNB->frame_parms.N_RB_DL) {
+              case 6:
+                dci_length = sizeof_DCI2A_1_5MHz_2A_FDD_t;
+                dci_length_bytes = sizeof(DCI2A_1_5MHz_2A_FDD_t);
+                ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 25:
+                dci_length = sizeof_DCI2A_5MHz_2A_FDD_t;
+                dci_length_bytes = sizeof(DCI2A_5MHz_2A_FDD_t);
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 50:
+                dci_length = sizeof_DCI2A_10MHz_2A_FDD_t;
+                dci_length_bytes = sizeof(DCI2A_10MHz_2A_FDD_t);
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 100:
+                dci_length = sizeof_DCI2A_20MHz_2A_FDD_t;
+                dci_length_bytes = sizeof(DCI2A_20MHz_2A_FDD_t);
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+              }
+            }
+          } else if (eNB->frame_parms.nb_antennas_tx == 4) {
+
+          }
+
+          memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+          dci_alloc[num_dci].dci_length = dci_length;
+          dci_alloc[num_dci].L          = 1;
+          dci_alloc[num_dci].rnti       = n_rnti+k;
+          dci_alloc[num_dci].format     = format2A;
+          dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+          printf("Generating dlsch params for user %d / format 2A (%d)\n",k,format2A);
+          generate_eNB_dlsch_params_from_dci(0,
+					     subframe,
+                                             &DLSCH_alloc_pdu_1[0],
+                                             n_rnti+k,
+                                             format2A,
+                                             eNB->dlsch[0],
+                                             &eNB->frame_parms,
+                                             eNB->pdsch_config_dedicated,
+                                             SI_RNTI,
+                                             0,
+                                             P_RNTI,
+                                             eNB->UE_stats[0].DL_pmi_single,
+                                             0);
+
+          num_dci++;
+          num_ue_spec_dci++;
+        } else {
+          if (eNB->frame_parms.frame_type == TDD) {
+
+            switch (eNB->frame_parms.N_RB_DL) {
+            case 6:
+              dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t);
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 25:
+              dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t);
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 1;
+              break;
+
+            case 50:
+              dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t);
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 100:
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t);
+              break;
+            }
+          } else {
+            switch (eNB->frame_parms.N_RB_DL) {
+            case 6:
+              dci_length = sizeof_DCI1A_1_5MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t);
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 25:
+              dci_length = sizeof_DCI1A_5MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t);
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 50:
+              dci_length = sizeof_DCI1A_10MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t);
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 100:
+              dci_length = sizeof_DCI1A_20MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t);
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+            }
+          }
+
+          memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+          dci_alloc[num_dci].dci_length = dci_length;
+          dci_alloc[num_dci].L          = 1;
+          dci_alloc[num_dci].rnti       = SI_RNTI;
+          dci_alloc[num_dci].format     = format1A;
+          dci_alloc[num_dci].firstCCE       = 0;
+          dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+          printf("Generating dlsch params for user %d\n",k);
+          generate_eNB_dlsch_params_from_dci(0,
+					     subframe,
+                                             &DLSCH_alloc_pdu_1[0],
+                                             SI_RNTI,
+                                             format1A,
+                                             eNB->dlsch[0],
+                                             &eNB->frame_parms,
+                                             eNB->pdsch_config_dedicated,
+                                             SI_RNTI,
+                                             0,
+                                             P_RNTI,
+                                             eNB->UE_stats[0].DL_pmi_single,
+                                             0);
+
+          num_common_dci++;
+          num_dci++;
+
+        }
+
+        printf("Generated DCI format 2A (Transmission Mode 3)\n");
+        break;
+
+      case 4:
+        if (common_flag == 0) {
+
+          if (eNB->frame_parms.nb_antennas_tx == 2) {
+
+            if (eNB->frame_parms.frame_type == TDD) {
+
+              switch (eNB->frame_parms.N_RB_DL) {
+              case 6:
+                dci_length = sizeof_DCI2_1_5MHz_2A_TDD_t;
+                dci_length_bytes = sizeof(DCI2_1_5MHz_2A_TDD_t);
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 25:
+                dci_length = sizeof_DCI2_5MHz_2A_TDD_t;
+                dci_length_bytes = sizeof(DCI2_5MHz_2A_TDD_t);
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 50:
+                dci_length = sizeof_DCI2_10MHz_2A_TDD_t;
+                dci_length_bytes = sizeof(DCI2_10MHz_2A_TDD_t);
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 100:
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                dci_length = sizeof_DCI2_20MHz_2A_TDD_t;
+                dci_length_bytes = sizeof(DCI2_20MHz_2A_TDD_t);
+                break;
+              }
+            }
+
+            else {
+              switch (eNB->frame_parms.N_RB_DL) {
+              case 6:
+                dci_length = sizeof_DCI2_1_5MHz_2A_FDD_t;
+                dci_length_bytes = sizeof(DCI2_1_5MHz_2A_FDD_t);
+                ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 25:
+                dci_length = sizeof_DCI2_5MHz_2A_FDD_t;
+                dci_length_bytes = sizeof(DCI2_5MHz_2A_FDD_t);
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 50:
+                dci_length = sizeof_DCI2_10MHz_2A_FDD_t;
+                dci_length_bytes = sizeof(DCI2_10MHz_2A_FDD_t);
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+
+              case 100:
+                dci_length = sizeof_DCI2_20MHz_2A_FDD_t;
+                dci_length_bytes = sizeof(DCI2_20MHz_2A_FDD_t);
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rah              = 0;
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = DLSCH_RB_ALLOC;
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = 0;
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs1             = mcs1;
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi1             = 1;
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv1              = 0;
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs2             = mcs2;
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi2             = 1;
+                ((DCI2_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv2              = 0;
+                break;
+              }
+            }
+          } else if (eNB->frame_parms.nb_antennas_tx == 4) {
+
+          }
+
+          memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+          dci_alloc[num_dci].dci_length = dci_length;
+          dci_alloc[num_dci].L          = 1;
+          dci_alloc[num_dci].rnti       = n_rnti+k;
+          dci_alloc[num_dci].format     = format2;
+          dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+          printf("Generating dlsch params for user %d\n",k);
+          generate_eNB_dlsch_params_from_dci(0,
+					     subframe,
+                                             &DLSCH_alloc_pdu_1[0],
+                                             n_rnti+k,
+                                             format2,
+                                             eNB->dlsch[0],
+                                             &eNB->frame_parms,
+                                             eNB->pdsch_config_dedicated,
+                                             SI_RNTI,
+                                             0,
+                                             P_RNTI,
+                                             eNB->UE_stats[0].DL_pmi_single,
+                                             0);
+
+          num_dci++;
+          num_ue_spec_dci++;
+        } else {
+          if (eNB->frame_parms.frame_type == TDD) {
+
+            switch (eNB->frame_parms.N_RB_DL) {
+            case 6:
+              dci_length = sizeof_DCI1A_1_5MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t);
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_1_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 25:
+              dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t);
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_5MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 1;
+              break;
+
+            case 50:
+              dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t);
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_10MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 100:
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->dai              = 0;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_20MHz_TDD_1_6_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t;
+              dci_length_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t);
+              break;
+            }
+          } else {
+            switch (eNB->frame_parms.N_RB_DL) {
+            case 6:
+              dci_length = sizeof_DCI1A_1_5MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_1_5MHz_FDD_t);
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 25:
+              dci_length = sizeof_DCI1A_5MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_5MHz_FDD_t);
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 50:
+              dci_length = sizeof_DCI1A_10MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_10MHz_FDD_t);
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+
+            case 100:
+              dci_length = sizeof_DCI1A_20MHz_FDD_t;
+              dci_length_bytes = sizeof(DCI1A_20MHz_FDD_t);
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->type             = 1;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->vrb_type         = 1;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rballoc          = computeRIV(eNB->frame_parms.N_RB_DL,0,9);
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->TPC              = TPC;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->harq_pid         = 0;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->mcs             = mcs1;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->ndi             = 0;
+              ((DCI1A_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[k])->rv              = 0;
+              break;
+            }
+          }
+
+          memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu_1[k],dci_length_bytes);
+          dci_alloc[num_dci].dci_length = dci_length;
+          dci_alloc[num_dci].L          = 1;
+          dci_alloc[num_dci].rnti       = SI_RNTI;
+          dci_alloc[num_dci].format     = format1A;
+          dci_alloc[num_dci].firstCCE       = 0;
+          dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+
+          printf("Generating dlsch params for user %d\n",k);
+          generate_eNB_dlsch_params_from_dci(0,
+					     subframe,
+                                             &DLSCH_alloc_pdu_1[0],
+                                             SI_RNTI,
+                                             format1A,
+                                             eNB->dlsch[0],
+                                             &eNB->frame_parms,
+                                             eNB->pdsch_config_dedicated,
+                                             SI_RNTI,
+                                             0,
+                                             P_RNTI,
+                                             eNB->UE_stats[0].DL_pmi_single,
+                                             0);
+
+          num_common_dci++;
+          num_dci++;
+
+        }
+
+        break;
+
+      case 5:
+      case 6:
+        memcpy(&dci_alloc[num_dci].dci_pdu[0],&DLSCH_alloc_pdu2_1E[k],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+        dci_alloc[num_dci].dci_length = sizeof_DCI1E_5MHz_2A_M10PRB_TDD_t;
+        dci_alloc[num_dci].L          = 1;
+        dci_alloc[num_dci].rnti       = n_rnti+k;
+        dci_alloc[num_dci].format     = format1E_2A_M10PRB;
+        dci_alloc[num_dci].firstCCE       = 4*k;
+        printf("Generating dlsch params for user %d\n",k);
+        generate_eNB_dlsch_params_from_dci(0,
+					   subframe,
+                                           &DLSCH_alloc_pdu2_1E[k],
+                                           n_rnti+k,
+                                           format1E_2A_M10PRB,
+                                           eNB->dlsch[k],
+                                           &eNB->frame_parms,
+                                           eNB->pdsch_config_dedicated,
+                                           SI_RNTI,
+                                           0,
+                                           P_RNTI,
+                                           eNB->UE_stats[k].DL_pmi_single,
+                                           0);
+
+        dump_dci(&eNB->frame_parms,&dci_alloc[num_dci]);
+        num_ue_spec_dci++;
+        num_dci++;
+
+        break;
+
+      default:
+        printf("Unsupported Transmission Mode!!!");
+        exit(-1);
+        break;
+      }
+
+
+
+
+      /*
+      memcpy(&dci_alloc[1].dci_pdu[0],&UL_alloc_pdu,sizeof(DCI0_5MHz_TDD0_t));
+      dci_alloc[1].dci_length = sizeof_DCI0_5MHz_TDD_0_t;
+      dci_alloc[1].L          = 2;
+      dci_alloc[1].rnti       = n_rnti;
+      */
+    }
+
+    if (n_frames==1) printf("num_pdcch_symbols %d, numCCE %d => ",num_pdcch_symbols,numCCE);
+
+    numCCE = get_nCCE(num_pdcch_symbols,&eNB->frame_parms,get_mi(&eNB->frame_parms,subframe));
+
+    if (n_frames==1) printf("%d\n",numCCE);
+
+    // apply RNTI-based nCCE allocation
+    memset(CCE_table,0,800*sizeof(int));
+
+    for (i=num_common_dci; i<num_dci; i++) {
+
+      dci_alloc[i].firstCCE = get_nCCE_offset_l1(CCE_table,
+						 1<<dci_alloc[i].L,
+						 numCCE,
+						 (dci_alloc[i].rnti==SI_RNTI)? 1 : 0,
+						 dci_alloc[i].rnti,
+						 subframe);
+
+      if (n_frames==1)
+        printf("dci %d: rnti %x, format %d : nCCE %d/%d\n",i,dci_alloc[i].rnti, dci_alloc[i].format,
+               dci_alloc[i].firstCCE,numCCE);
+    }
+
+    for (k=0; k<n_users; k++) {
+
+      input_buffer_length0 = eNB->dlsch[k][0]->harq_processes[0]->TBS/8;
+      input_buffer0[k] = (unsigned char *)malloc(input_buffer_length0+4);
+      memset(input_buffer0[k],0,input_buffer_length0+4);
+      input_buffer_length1 = eNB->dlsch[k][1]->harq_processes[0]->TBS/8;
+      input_buffer1[k] = (unsigned char *)malloc(input_buffer_length1+4);
+      memset(input_buffer1[k],0,input_buffer_length1+4);
+
+      if (input_trch_file==0) {
+        for (i=0; i<input_buffer_length0; i++) {
+          //input_buffer0[k][i] = (unsigned char)(i&0xff);
+          input_buffer0[k][i] = (unsigned char)(taus()&0xff);
+        }
+
+        for (i=0; i<input_buffer_length1; i++) {
+          input_buffer1[k][i]= (unsigned char)(taus()&0xff);
+        }
+      }
+
+      else {
+        i=0;
+
+        while ((!feof(input_trch_fd)) && (i<input_buffer_length0<<3)) {
+          ret=fscanf(input_trch_fd,"%s",input_trch_val);
+
+          if (input_trch_val[0] == '1')
+            input_buffer0[k][i>>3]+=(1<<(7-(i&7)));
+
+          if (i<16)
+            printf("input_trch_val %d : %c\n",i,input_trch_val[0]);
+
+          i++;
+
+          if (((i%8) == 0) && (i<17))
+            printf("%x\n",input_buffer0[k][(i-1)>>3]);
+        }
+
+        printf("Read in %d bits\n",i);
+      }
+    }
+  }
+
+  // this is for user 0 only
+  coded_bits_per_codeword = get_G(&eNB->frame_parms,
+                                  eNB->dlsch[0][0]->harq_processes[0]->nb_rb,
+                                  eNB->dlsch[0][0]->harq_processes[0]->rb_alloc,
+                                  get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs),
+                                  eNB->dlsch[0][0]->harq_processes[0]->Nl,
+                                  num_pdcch_symbols,
+                                  0,
+ 				  subframe,
+				  (transmission_mode<7?0:transmission_mode));
+
+  uncoded_ber_bit = (short*) malloc(sizeof(short)*coded_bits_per_codeword);
+  printf("uncoded_ber_bit=%p\n",uncoded_ber_bit);
+
+  snr_step = input_snr_step;
+  UE->high_speed_flag = 0; //1
+  UE->ch_est_alpha=0;
+
+  for (ch_realization=0; ch_realization<n_ch_rlz; ch_realization++) {
+    if(abstx) {
+      printf("**********************Channel Realization Index = %d **************************\n", ch_realization);
+    }
+
+    for (SNR=snr0; SNR<snr1; SNR+=snr_step) {
+      UE->proc.proc_rxtx[subframe&1].frame_rx=0;
+      errs[0]=0;
+      errs[1]=0;
+      errs[2]=0;
+      errs[3]=0;
+      errs2[0]=0;
+      errs2[1]=0;
+      errs2[2]=0;
+      errs2[3]=0;
+      round_trials[0] = 0;
+      round_trials[1] = 0;
+      round_trials[2] = 0;
+      round_trials[3] = 0;
+
+      dci_errors=0;
+      //      avg_ber = 0;
+
+      round=0;
+      avg_iter = 0;
+      iter_trials=0;
+      reset_meas(&eNB->phy_proc_tx); // total eNB tx
+      reset_meas(&eNB->dlsch_scrambling_stats);
+      reset_meas(&UE->dlsch_unscrambling_stats);
+      reset_meas(&eNB->ofdm_mod_stats);
+      reset_meas(&eNB->dlsch_modulation_stats);
+      reset_meas(&eNB->dlsch_encoding_stats);
+      reset_meas(&eNB->dlsch_interleaving_stats);
+      reset_meas(&eNB->dlsch_rate_matching_stats);
+      reset_meas(&eNB->dlsch_turbo_encoding_stats);
+
+      reset_meas(&UE->phy_proc_rx); // total UE rx
+      reset_meas(&UE->ofdm_demod_stats);
+      reset_meas(&UE->dlsch_channel_estimation_stats);
+      reset_meas(&UE->dlsch_freq_offset_estimation_stats);
+      reset_meas(&UE->rx_dft_stats);
+      reset_meas(&UE->dlsch_decoding_stats);
+      reset_meas(&UE->dlsch_turbo_decoding_stats);
+      reset_meas(&UE->dlsch_deinterleaving_stats);
+      reset_meas(&UE->dlsch_rate_unmatching_stats);
+      reset_meas(&UE->dlsch_tc_init_stats);
+      reset_meas(&UE->dlsch_tc_alpha_stats);
+      reset_meas(&UE->dlsch_tc_beta_stats);
+      reset_meas(&UE->dlsch_tc_gamma_stats);
+      reset_meas(&UE->dlsch_tc_ext_stats);
+      reset_meas(&UE->dlsch_tc_intl1_stats);
+      reset_meas(&UE->dlsch_tc_intl2_stats);
+      // initialization
+      struct list time_vector_tx;
+      initialize(&time_vector_tx);
+      struct list time_vector_tx_ifft;
+      initialize(&time_vector_tx_ifft);
+      struct list time_vector_tx_mod;
+      initialize(&time_vector_tx_mod);
+      struct list time_vector_tx_enc;
+      initialize(&time_vector_tx_enc);
+
+      struct list time_vector_rx;
+      initialize(&time_vector_rx);
+      struct list time_vector_rx_fft;
+      initialize(&time_vector_rx_fft);
+      struct list time_vector_rx_demod;
+      initialize(&time_vector_rx_demod);
+      struct list time_vector_rx_dec;
+      initialize(&time_vector_rx_dec);
+
+      for (trials = 0; trials<n_frames; trials++) {
+        //  printf("Trial %d\n",trials);
+        fflush(stdout);
+        round=0;
+
+        //if (trials%100==0)
+        eNB2UE[0]->first_run = 1;
+
+        ret = UE->dlsch[0][0]->max_turbo_iterations+1;
+
+        while ((round < num_rounds) && (ret > UE->dlsch[0][0]->max_turbo_iterations)) {
+              //printf("Trial %d, round %d\n",trials,round);
+          round_trials[round]++;
+
+          if(transmission_mode>=5&&transmission_mode<7)
+            pmi_feedback=1;
+          else
+            pmi_feedback=0;
+
+          if (abstx) {
+            if (trials==0 && round==0 && SNR==snr0)  //generate a new channel
+              hold_channel = 0;
+            else
+              hold_channel = 1;
+          } else
+            hold_channel = 0;//(round==0) ? 0 : 1;
+
+PMI_FEEDBACK:
+
+	  //make sure dlsim is called with perfect channel estimation option (for freq_channel)
+	  //fill drs_ch_estimates with data from eNB2UE->chF
+	  for(aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) {
+	    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+	      for (i=0; i<frame_parms->N_RB_DL*12; i++) {
+		for (l=0; l<frame_parms->symbols_per_tti; l++) {
+		  ((int16_t *) eNB->pusch_vars[0]->drs_ch_estimates[0][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size)*2]=(int16_t)(eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP);
+                          //printf("x=%d,AMP=%d\n",eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x,AMP);
+		  ((int16_t *) eNB->pusch_vars[0]->drs_ch_estimates[0][(aa<<1)+aarx])[2*i+1+(l*frame_parms->ofdm_symbol_size)*2]=(int16_t)(eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP);
+		}
+	      }
+	    }
+	  }
+
+	  estimate_DLCSI_from_ULCSI(eNB->dlsch[0][0]->calib_dl_ch_estimates,
+					 &eNB->pusch_vars[0]->drs_ch_estimates[0][0/*position of second DMRS*/],
+					 eNB->common_vars.tdd_calib_coeffs[0],
+					 frame_parms->nb_antennas_tx,
+					 frame_parms->N_RB_DL*12);
+	  
+	  compute_BF_weights(eNB->dlsch[0][0]->ue_spec_bf_weights[0],
+			     eNB->dlsch[0][0]->calib_dl_ch_estimates,
+			     MRT,
+			     frame_parms->nb_antennas_tx,
+			     frame_parms->N_RB_DL*12);
+
+          //printf("Trial %d : Round %d, pmi_feedback %d \n",trials,round,pmi_feedback);
+          for (aa=0; aa<NB_ANTENNA_PORTS_ENB; aa++) {
+            memset(&eNB->common_vars.txdataF[eNB_id][aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t));
+          }
+
+          if (input_fd==NULL) {
+
+            start_meas(&eNB->phy_proc_tx);
+
+            // Simulate HARQ procedures!!!
+            if (common_flag == 0) {
+
+              if (round == 0) {   // First round
+                TB0_active = 1;
+
+                eNB->dlsch[0][0]->harq_processes[0]->rvidx = round&3;
+
+                if (eNB->frame_parms.frame_type == TDD) {
+
+                  switch (transmission_mode) {
+                  case 1:
+                  case 2:
+                  case 7:
+                    switch (eNB->frame_parms.N_RB_DL) {
+                    case 6:
+                      ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_TDD_t));
+                      break;
+
+                    case 25:
+                      ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_TDD_t));
+                      break;
+
+                    case 50:
+                      ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_TDD_t));
+                      break;
+
+                    case 100:
+                      ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_TDD_t));
+                      break;
+                    }
+
+                    break;
+
+                  case 3:
+                    switch (eNB->frame_parms.N_RB_DL) {
+                    case 6:
+                      ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                      ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 0;
+                      ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                      ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_TDD_t));
+                      break;
+
+                    case 25:
+                      ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                      ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 0;
+                      ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                      ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_TDD_t));
+                      break;
+
+                    case 50:
+                      ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                      ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 0;
+                      ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                      ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_TDD_t));
+                      break;
+
+                    case 100:
+                      ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                      ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 0;
+                      ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                      ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_TDD_t));
+                      break;
+                    }
+
+                    break;
+
+                  case 5:
+                    DLSCH_alloc_pdu2_1E[0].ndi             = trials&1;
+                    DLSCH_alloc_pdu2_1E[0].rv              = 0;
+                    memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+                    break;
+
+                  }
+                } else { // FDD
+                  switch (transmission_mode) {
+                  case 1:
+                  case 2:
+                  case 7:
+                    switch (eNB->frame_parms.N_RB_DL) {
+                    case 6:
+                      ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_FDD_t));
+                      break;
+
+                    case 25:
+                      ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_FDD_t));
+                      break;
+
+                    case 50:
+                      ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_FDD_t));
+                      break;
+
+                    case 100:
+                      ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_FDD_t));
+                      break;
+                    }
+
+                    break;
+                  case 3:
+                    switch (eNB->frame_parms.N_RB_DL) {
+                    case 6:
+                      ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                      ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 0;
+                      ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                      ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_FDD_t));
+                      break;
+
+                    case 25:
+                      ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                      ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 0;
+                      ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                      ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_FDD_t));
+                      break;
+
+                    case 50:
+                      ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                      ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 0;
+                      ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                      ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_FDD_t));
+                      break;
+
+                    case 100:
+                      ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                      ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 0;
+                      ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                      ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = 0;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_FDD_t));
+                      break;
+                    }
+
+                    break;
+
+                  case 5:
+                    DLSCH_alloc_pdu2_1E[0].ndi             = trials&1;
+                    DLSCH_alloc_pdu2_1E[0].rv              = 0;
+                    memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+                    break;
+                  }
+
+                }
+              } else {
+                eNB->dlsch[0][0]->harq_processes[0]->rvidx = round&3;
+
+                if (eNB->frame_parms.frame_type == TDD) {
+
+
+                  switch (transmission_mode) {
+                  case 1:
+                  case 2:
+                  case 7:
+                    switch (eNB->frame_parms.N_RB_DL) {
+                    case 6:
+                      ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = round&3;;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_TDD_t));
+                      break;
+
+                    case 25:
+                      ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_5MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = round&3;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_TDD_t));
+                      break;
+
+                    case 50:
+                      ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_10MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = round&3;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_TDD_t));
+                      break;
+
+                    case 100:
+                      ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_20MHz_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = round&3;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_TDD_t));
+                      break;
+                    }
+
+                    break;
+
+                  case 3:
+                    switch (eNB->frame_parms.N_RB_DL) {
+                    case 6:
+                      if (TB0_active==1) {
+                        ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                        ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = round&3;
+                        ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      } else { // deactivate TB0
+                        ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1             = 0;
+                        ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 1;
+                        ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_1_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      }
+
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_TDD_t));
+                      break;
+
+                    case 25:
+                      if (TB0_active==1) {
+                        ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                        ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = round&3;
+                        ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      } else { // deactivate TB0
+                        ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1             = 0;
+                        ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 1;
+                        ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_5MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      }
+
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_TDD_t));
+                      break;
+
+                    case 50:
+                      if (TB0_active==1) {
+                        ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                        ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = round&3;
+                        ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      } else { // deactivate TB0
+                        ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1             = 0;
+                        ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 1;
+                        ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_10MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      }
+
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_TDD_t));
+                      break;
+
+                    case 100:
+                      if (TB0_active==1) {
+                        ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                        ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = round&3;
+                        ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      } else { // deactivate TB0
+                        ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1             = 0;
+                        ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 1;
+                        ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_20MHz_2A_TDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      }
+
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_TDD_t));
+                      break;
+                    }
+
+                    break;
+
+                  case 5:
+                    DLSCH_alloc_pdu2_1E[0].ndi             = trials&1;
+                    DLSCH_alloc_pdu2_1E[0].rv              = round&3;
+                    memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+                    break;
+                  }
+                } else {
+                  switch (transmission_mode) {
+                  case 1:
+                  case 2:
+                  case 7:
+                    switch (eNB->frame_parms.N_RB_DL) {
+                    case 6:
+                      ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = round&3;;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_1_5MHz_FDD_t));
+                      break;
+
+                    case 25:
+                      ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_5MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = round&3;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_5MHz_FDD_t));
+                      break;
+
+                    case 50:
+                      ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_10MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = round&3;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_10MHz_FDD_t));
+                      break;
+
+                    case 100:
+                      ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi             = trials&1;
+                      ((DCI1_20MHz_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv              = round&3;
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI1_20MHz_FDD_t));
+                      break;
+                    }
+
+                    break;
+
+                  case 3:
+                    switch (eNB->frame_parms.N_RB_DL) {
+                    case 6:
+                      if (TB0_active==1) {
+                        ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                        ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = round&3;
+                        ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      } else { // deactivate TB0
+                        ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1             = 0;
+                        ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 1;
+                        ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_1_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      }
+
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_1_5MHz_2A_FDD_t));
+                      break;
+
+                    case 25:
+                      if (TB0_active==1) {
+                        ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                        ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = round&3;
+                        ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      } else { // deactivate TB0
+                        ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1             = 0;
+                        ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 1;
+                        ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_5MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      }
+
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_5MHz_2A_FDD_t));
+                      break;
+
+                    case 50:
+                      if (TB0_active==1) {
+                        ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                        ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = round&3;
+                        ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      } else { // deactivate TB0
+                        ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1             = 0;
+                        ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 1;
+                        ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_10MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      }
+
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_10MHz_2A_FDD_t));
+                      break;
+
+                    case 100:
+                      if (TB0_active==1) {
+                        ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi1             = trials&1;
+                        ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = round&3;
+                        ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      } else { // deactivate TB0
+                        ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->mcs1             = 0;
+                        ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv1              = 1;
+                        ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->ndi2             = trials&1;
+                        ((DCI2A_20MHz_2A_FDD_t *)&DLSCH_alloc_pdu_1[0])->rv2              = round&3;
+                      }
+
+                      memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu_1[0],sizeof(DCI2A_20MHz_2A_FDD_t));
+                      break;
+                    }
+
+                    break;
+
+                  case 5:
+                    DLSCH_alloc_pdu2_1E[0].ndi             = trials&1;
+                    DLSCH_alloc_pdu2_1E[0].rv              = round&3;
+                    memcpy(&dci_alloc[0].dci_pdu[0],&DLSCH_alloc_pdu2_1E[0],sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
+                    break;
+                  }
+                }
+              }
+            }
+	    
+            num_pdcch_symbols_2 = generate_dci_top(num_ue_spec_dci,
+                                                   num_common_dci,
+                                                   dci_alloc,
+                                                   0,
+                                                   AMP,
+                                                   &eNB->frame_parms,
+                                                   eNB->common_vars.txdataF[eNB_id],
+                                                   subframe);
+	    
+            if (num_pdcch_symbols_2 > num_pdcch_symbols) {
+              msg("Error: given num_pdcch_symbols not big enough (%d > %d)\n",num_pdcch_symbols_2,num_pdcch_symbols);
+              exit(-1);
+            }
+
+            for (k=0; k<n_users; k++) {
+              for (int cw=0; cw<Kmimo; cw++) {
+                coded_bits_per_codeword = get_G(&eNB->frame_parms,
+                                                eNB->dlsch[k][cw]->harq_processes[0]->nb_rb,
+                                                eNB->dlsch[k][cw]->harq_processes[0]->rb_alloc,
+                                                get_Qm(eNB->dlsch[k][cw]->harq_processes[0]->mcs),
+                                                eNB->dlsch[k][cw]->harq_processes[0]->Nl,
+                                                num_pdcch_symbols,
+                                                0,
+						subframe,
+						(transmission_mode<7?0:transmission_mode));
+
+#ifdef TBS_FIX   // This is for MESH operation!!!
+                tbs = (double)3*TBStable[get_I_TBS(eNB->dlsch[k][cw]->harq_processes[0]->mcs)][eNB->dlsch[k][cw]->nb_rb-1]/4;
+#else
+                tbs = eNB->dlsch[k][cw]->harq_processes[0]->TBS;
+#endif
+                rate = (double)tbs/(double)coded_bits_per_codeword;
+
+                if ((SNR==snr0) && (trials==0) && (round==0))
+                  printf("User %d, cw %d: Rate = %f (%f bits/dim) (G %d, TBS %d, mod %d, pdcch_sym %d, ndi %d)\n",
+                         k,cw,rate,rate*get_Qm(eNB->dlsch[k][0]->harq_processes[0]->mcs),
+                         coded_bits_per_codeword,
+                         tbs,
+                         get_Qm(eNB->dlsch[k][0]->harq_processes[0]->mcs),
+                         num_pdcch_symbols,
+                         eNB->dlsch[0][0]->harq_processes[0]->round);
+
+                // use the PMI from previous trial
+                if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) {
+                  eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,eNB->frame_parms.N_RB_DL);
+                  UE->dlsch[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&UE->measurements,0,UE->frame_parms.N_RB_DL);
+
+                  if (n_users>1)
+                    eNB->dlsch[1][0]->harq_processes[0]->pmi_alloc = (eNB->dlsch[0][0]->harq_processes[0]->pmi_alloc ^ 0x1555);
+
+                  /*
+                    if ((trials<10) && (round==0)) {
+                    printf("tx PMI UE0 %x (pmi_feedback %d)\n",pmi2hex_2Ar1(eNB->dlsch[0][0]->pmi_alloc),pmi_feedback);
+                    if (transmission_mode ==5)
+                    printf("tx PMI UE1 %x\n",pmi2hex_2Ar1(eNB->dlsch[1][0]->pmi_alloc));
+                    }
+                  */
+                }
+
+
+                start_meas(&eNB->dlsch_encoding_stats);
+
+                if (dlsch_encoding(eNB,
+				   ((cw==0) ? input_buffer0[k] : input_buffer1[k]),
+                                   num_pdcch_symbols,
+                                   eNB->dlsch[k][cw],
+                                   0,subframe,
+                                   &eNB->dlsch_rate_matching_stats,
+                                   &eNB->dlsch_turbo_encoding_stats,
+                                   &eNB->dlsch_interleaving_stats)<0)
+                  exit(-1);
+
+                /*
+                if (transmission_mode == 3) {
+                if (dlsch_encoding(input_buffer1[k],
+                   &eNB->frame_parms,
+                   num_pdcch_symbols,
+                   eNB->dlsch[k][1],
+                   0,subframe,
+                   &eNB->dlsch_rate_matching_stats,
+                   &eNB->dlsch_turbo_encoding_stats,
+                   &eNB->dlsch_interleaving_stats
+                   )<0)
+                exit(-1);
+                }
+                */
+                stop_meas(&eNB->dlsch_encoding_stats);
+
+                eNB->dlsch[k][cw]->rnti = (common_flag==0) ? n_rnti+k : SI_RNTI;
+                start_meas(&eNB->dlsch_scrambling_stats);
+                dlsch_scrambling(&eNB->frame_parms,
+                                 0,
+                                 eNB->dlsch[k][cw],
+                                 coded_bits_per_codeword,
+                                 0,
+                                 subframe<<1);
+                stop_meas(&eNB->dlsch_scrambling_stats);
+
+                if (n_frames==1) {
+                  for (s=0; s<eNB->dlsch[k][cw]->harq_processes[0]->C; s++) {
+                    if (s<eNB->dlsch[k][cw]->harq_processes[0]->Cminus)
+                      Kr = eNB->dlsch[k][cw]->harq_processes[0]->Kminus;
+                    else
+                      Kr = eNB->dlsch[k][cw]->harq_processes[0]->Kplus;
+
+                    Kr_bytes = Kr>>3;
+
+                    for (i=0; i<Kr_bytes; i++)
+                      printf("%d : (%x)\n",i,eNB->dlsch[k][cw]->harq_processes[0]->c[s][i]);
+                  }
+                }
+              }
+              
+              start_meas(&eNB->dlsch_modulation_stats);
+              re_allocated = dlsch_modulation(eNB,
+					      eNB->common_vars.txdataF[eNB_id],
+                                              AMP,
+                                              subframe,
+                                              num_pdcch_symbols,
+                                              eNB->dlsch[k][0],
+                                              eNB->dlsch[k][1]);	      
+              /* avoid gcc warnings */
+              (void)re_allocated;
+
+              stop_meas(&eNB->dlsch_modulation_stats);
+              /*
+              if (trials==0 && round==0)
+              printf("RE count %d\n",re_allocated);
+              */
+            } //n_users
+
+
+            generate_pilots(eNB,
+                            eNB->common_vars.txdataF[eNB_id],
+                            AMP,
+                            LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
+/*
+	    //PSS/SSS
+            if (eNB->frame_parms.frame_type == FDD) {
+              generate_pss(eNB->common_vars.txdataF[0],
+                           AMP,
+                           &eNB->frame_parms,
+                           (eNB->frame_parms.Ncp==NORMAL) ? 6 : 5,
+                           0);
+              generate_sss(eNB->common_vars.txdataF[0],
+                           AMP,
+                           &eNB->frame_parms,
+                           (eNB->frame_parms.Ncp==NORMAL) ? 5 : 4,
+                           0);
+              generate_pss(eNB->common_vars.txdataF[0],
+                           AMP,
+                           &eNB->frame_parms,
+                           (eNB->frame_parms.Ncp==NORMAL) ? 6 : 5,
+                           10);
+              generate_sss(eNB->common_vars.txdataF[0],
+                           AMP,
+                           &eNB->frame_parms,
+                           (eNB->frame_parms.Ncp==NORMAL) ? 5 : 4,
+                           10);
+	    }
+            else if (eNB->frame_parms.frame_type == TDD) {
+              generate_sss(eNB->common_vars.txdataF[0],
+                           AMP,
+                           &eNB->frame_parms,
+                           (eNB->frame_parms.Ncp==NORMAL) ? 6 : 5,
+                           1);
+              generate_pss(eNB->common_vars.txdataF[0],
+                           AMP,
+                           &eNB->frame_parms,
+                           2,
+                           2);
+              generate_sss(eNB->common_vars.txdataF[0],
+                           AMP,
+                           &eNB->frame_parms,
+                           (eNB->frame_parms.Ncp==NORMAL) ? 6 : 5,
+                           11);
+              generate_pss(eNB->common_vars.txdataF[0],
+                           AMP,
+                           &eNB->frame_parms,
+                           2,
+                           12);
+            }
+
+              //PBCH
+              pbch_pdu[2] = 0;
+
+              // FIXME setting pbch_pdu[2] to zero makes the switch statement easier: remove all the or-operators
+              switch (eNB->frame_parms.N_RB_DL) {
+              case 6:
+                pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (0<<5);
+                break;
+
+              case 15:
+                pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (1<<5);
+                break;
+
+              case 25:
+                pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5);
+                break;
+
+              case 50:
+                pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (3<<5);
+                break;
+
+              case 75:
+                pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (4<<5);
+                break;
+
+              case 100:
+                pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (5<<5);
+                break;
+
+              default:
+                // FIXME if we get here, this should be flagged as an error, right?
+                pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5);
+                break;
+              }
+
+              pbch_pdu[2] = (pbch_pdu[2]&0xef) |
+                            ((eNB->frame_parms.phich_config_common.phich_duration << 4)&0x10);
+
+              switch (eNB->frame_parms.phich_config_common.phich_resource) {
+              case oneSixth:
+                pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (0<<2);
+                break;
+
+              case half:
+                pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (1<<2);
+                break;
+
+              case one:
+                pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (2<<2);
+                break;
+
+              case two:
+                pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (3<<2);
+                break;
+
+              default:
+                // unreachable
+                break;
+              
+
+              pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((0>>8)&0x3);
+              pbch_pdu[1] = 0&0xfc;
+              pbch_pdu[0] = 0;
+            }
+
+            generate_pbch(&eNB->lte_eNB_pbch,
+                          eNB->common_vars.txdataF[0],
+                          AMP,
+                          &eNB->frame_parms,
+                          pbch_pdu,
+                          0&3);
+*/
+
+            start_meas(&eNB->ofdm_mod_stats);
+/*
+	    for(i=0;i<20;i++){
+	      
+              do_OFDM_mod_l(eNB->common_vars.txdataF[eNB_id],
+                            eNB->common_vars.txdata[eNB_id],
+                            i,
+                            &eNB->frame_parms);
+ 	      } 
+
+*/
+            do_OFDM_mod_symbol(&eNB->common_vars,
+                          eNB_id,
+                          (subframe*2),
+                          &eNB->frame_parms);
+
+            do_OFDM_mod_symbol(&eNB->common_vars,
+                          eNB_id,
+                          (subframe*2)+1,
+                          &eNB->frame_parms);
+
+            stop_meas(&eNB->ofdm_mod_stats);
+            stop_meas(&eNB->phy_proc_tx);
+
+           /* do_OFDM_mod_l(&eNB->common_vars,
+                          eNB_id,
+                          (subframe*2)+2,
+                          &eNB->frame_parms); */
+
+            if (n_frames==1) {
+              if (transmission_mode<7)
+                write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],
+                             nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+              else if (transmission_mode==7)
+                write_output("txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB_id][5][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],
+                             nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+              write_output("txsigF0_BF.m","txsF0_BF", &eNB->common_vars.txdataF_BF[eNB_id][0][0],
+                           eNB->frame_parms.ofdm_symbol_size,1,1);
+
+              if (eNB->frame_parms.nb_antennas_tx>1)// to be updated
+                write_output("txsigF1.m","txsF1", &eNB->common_vars.txdataF[eNB_id][1][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],
+                             nsymb*eNB->frame_parms.ofdm_symbol_size,1,1);
+            }
+            tx_lev = 0;
+
+            for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) {
+              tx_lev += signal_energy(&eNB->common_vars.txdata[eNB_id][aa]
+                                      [subframe*eNB->frame_parms.samples_per_tti],
+                                      eNB->frame_parms.samples_per_tti);
+            }
+
+            tx_lev_dB = (unsigned int) dB_fixed(tx_lev);
+
+            if (n_frames==1) {
+              printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB);
+              write_output("txsig0.m","txs0", &eNB->common_vars.txdata[eNB_id][0][subframe*eNB->frame_parms.samples_per_tti],eNB->frame_parms.samples_per_tti,1,1);
+              // write_output("txsig0.m","txs0",&eNB->common_vars.txdata[eNB_id][0][0*eNB->frame_parms.samples_per_tti],eNB->frame_parms.samples_per_tti*10,1,1);
+            }
+          }
+
+          /*
+            else {  // Read signal from file
+            i=0;
+            while (!feof(input_fd)) {
+            fscanf(input_fd,"%s %s",input_val_str,input_val_str2);
+
+            if ((i%4)==0) {
+            ((short*)txdata[0])[i/2] = (short)((1<<15)*strtod(input_val_str,NULL));
+            ((short*)txdata[0])[(i/2)+1] = (short)((1<<15)*strtod(input_val_str2,NULL));
+            if ((i/4)<100)
+            printf("sample %d => %e + j%e (%d +j%d)\n",i/4,strtod(input_val_str,NULL),strtod(input_val_str2,NULL),((short*)txdata[0])[i/4],((short*)txdata[0])[(i/4)+1]);//1,input_val2,);
+            }
+            i++;
+            if (i>(FRAME_LENGTH_SAMPLES))
+            break;
+            }
+            printf("Read in %d samples\n",i/4);
+            write_output("txsig0.m","txs0", txdata[0],2*frame_parms->samples_per_tti,1,1);
+            //    write_output("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1);
+            tx_lev = signal_energy(&txdata[0][0],
+            OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES);
+            tx_lev_dB = (unsigned int) dB_fixed(tx_lev);
+            }
+          */
+
+          //    printf("Copying tx ..., nsymb %d (n_tx %d), awgn %d\n",nsymb,eNB->frame_parms.nb_antennas_tx,awgn_flag);
+          for (i=0; i<2*frame_parms->samples_per_tti; i++) {
+            for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) {
+              if (awgn_flag == 0) {
+                s_re[aa][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]);
+                s_im[aa][i] = ((double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]);
+              } else {
+                for (aarx=0; aarx<UE->frame_parms.nb_antennas_rx; aarx++) {
+                  if (aa==0) {
+                    r_re[aarx][i] = (double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)];
+                    r_im[aarx][i] = (double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1];
+                    //printf("r[%d][%d]=> %f, %f\n",aarx,i,r_re[aarx][i],r_im[aarx][i]);
+                  } else {
+                    r_re[aarx][i] += (double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)];
+                    r_im[aarx][i] += (double)(((short *)eNB->common_vars.txdata[eNB_id][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1];
+                  }
+
+                }
+              }
+            }
+          }
+
+          // Multipath channel
+          if (awgn_flag == 0) {
+            multipath_channel(eNB2UE[round],s_re,s_im,r_re,r_im,
+                              2*frame_parms->samples_per_tti,hold_channel);
+
+            //      printf("amc: ****************** eNB2UE[%d]->n_rx = %d,dd %d\n",round,eNB2UE[round]->nb_rx,eNB2UE[round]->channel_offset);
+            if(abstx==1 && num_rounds>1)
+              if(round==0 && hold_channel==0) {
+                random_channel(eNB2UE[1],0);
+                random_channel(eNB2UE[2],0);
+                random_channel(eNB2UE[3],0);
+              }
+	    
+	    if (UE->perfect_ce==1) {
+                  // fill in perfect channel estimates
+                  freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1);
+		  /*
+		  write_output("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8);
+                  write_output("channelF.m","chF",eNB2UE[round]->chF[0],12*UE->frame_parms.N_RB_DL + 1,1,8);
+		  */
+	    }
+	  }
+
+          if(abstx) {
+            if (trials==0 && round==0) {
+              // calculate freq domain representation to compute SINR
+              freq_channel(eNB2UE[0], NB_RB,2*NB_RB + 1);
+              // snr=pow(10.0,.1*SNR);
+              fprintf(csv_fd,"%f,",SNR);
+
+              for (u=0; u<2*NB_RB; u++) {
+                for (aarx=0; aarx<eNB2UE[0]->nb_rx; aarx++) {
+                  for (aatx=0; aatx<eNB2UE[0]->nb_tx; aatx++) {
+                    channelx = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].x;
+                    channely = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].y;
+                    fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
+                  }
+                }
+              }
+
+              if(num_rounds>1) {
+                freq_channel(eNB2UE[1], NB_RB,2*NB_RB + 1);
+
+                for (u=0; u<2*NB_RB; u++) {
+                  for (aarx=0; aarx<eNB2UE[1]->nb_rx; aarx++) {
+                    for (aatx=0; aatx<eNB2UE[1]->nb_tx; aatx++) {
+                      channelx = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].x;
+                      channely = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].y;
+                      fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
+                    }
+                  }
+                }
+
+                freq_channel(eNB2UE[2], NB_RB,2*NB_RB + 1);
+
+                for (u=0; u<2*NB_RB; u++) {
+                  for (aarx=0; aarx<eNB2UE[2]->nb_rx; aarx++) {
+                    for (aatx=0; aatx<eNB2UE[2]->nb_tx; aatx++) {
+                      channelx = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].x;
+                      channely = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].y;
+                      fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
+                    }
+                  }
+                }
+
+                freq_channel(eNB2UE[3], NB_RB,2*NB_RB + 1);
+
+                for (u=0; u<2*NB_RB; u++) {
+                  for (aarx=0; aarx<eNB2UE[3]->nb_rx; aarx++) {
+                    for (aatx=0; aatx<eNB2UE[3]->nb_tx; aatx++) {
+                      channelx = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].x;
+                      channely = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].y;
+                      fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
+                    }
+                  }
+                }
+              }
+            }
+          }
+
+          //AWGN
+          // This is the SNR on the PDSCH for OFDM symbols without pilots -> rho_A
+          sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(NB_RB*12)) - SNR - get_pa_dB(eNB->pdsch_config_dedicated);
+          sigma2 = pow(10,sigma2_dB/10);
+
+          if (n_frames==1)
+            printf("Sigma2 %f (sigma2_dB %f,%f,%f )\n",sigma2,sigma2_dB,10*log10((double)eNB->frame_parms.ofdm_symbol_size/(double)(NB_RB*12)),get_pa_dB(eNB->pdsch_config_dedicated));
+
+          for (i=0; i<2*frame_parms->samples_per_tti; i++) {
+            for (aa=0; aa<eNB->frame_parms.nb_antennas_rx; aa++) {
+              // printf("s_re[0][%d]=> %f , r_re[0][%d]=> %f\n",i,s_re[aa][i],i,r_re[aa][i]);
+              ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] =
+                (short) (r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0));
+              ((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] =
+                (short) (r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0));
+              //((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] = (short) r_re[aa][i];
+              //((short*) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] = (short) r_im[aa][i]; 
+              //printf("rxdata[%d][%d]=> %d, %d\n",aa,subframe*UE->frame_parms.samples_per_tti+i,r_re[aa][i],r_im[aa][i]);
+            }
+          }
+
+
+          //    lte_sync_time_init(eNB->frame_parms,common_vars);
+          //    lte_sync_time(common_vars->rxdata, eNB->frame_parms);
+          //    lte_sync_time_free();
+
+          /*
+            // optional: read rx_frame from file
+            if ((rx_frame_file = fopen("rx_frame.dat","r")) == NULL)
+            {
+            printf("Cannot open rx_frame.m data file\n");
+            exit(0);
+            }
+
+            result = fread((void *)PHY_vars->rx_vars[0].RX_DMA_BUFFER,4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file);
+            printf("Read %d bytes\n",result);
+            result = fread((void *)PHY_vars->rx_vars[1].RX_DMA_BUFFER,4,FRAME_LENGTH_COMPLEX_SAMPLES,rx_frame_file);
+            printf("Read %d bytes\n",result);
+
+            fclose(rx_frame_file);
+          */
+
+          if (n_frames==1) {
+            printf("RX level in null symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2)));
+            printf("RX level in data symbol %d\n",dB_fixed(signal_energy(&UE->common_vars.rxdata[0][160+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)],OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2)));
+            printf("rx_level Null symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES))));
+            printf("rx_level data symbol %f\n",10*log10(signal_energy_fp(r_re,r_im,1,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES/2,256+(2*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES))));
+          }
+
+          if (eNB->frame_parms.Ncp == 0) {  // normal prefix
+            pilot1 = 4;
+            pilot2 = 7;
+            pilot3 = 11;
+          } else { // extended prefix
+            pilot1 = 3;
+            pilot2 = 6;
+            pilot3 = 9;
+          }
+          
+
+          start_meas(&UE->phy_proc_rx);
+
+          // Inner receiver scheduling for 3 slots
+        
+          for (Ns=(2*subframe); Ns<((2*subframe)+3); Ns++) {
+            for (l=0; l<pilot2; l++) {
+              if (n_frames==1)
+                printf("Ns %d, l %d, l2 %d\n",Ns, l, l+(Ns%2)*pilot2);
+
+              /*
+              This function implements the OFDM front end processor (FEP).
+
+              Parameters:
+              frame_parms  LTE DL Frame Parameters
+              ue_common_vars   LTE UE Common Vars
+              l  symbol within slot (0..6/7)
+              Ns   Slot number (0..19)
+              sample_offset  offset within rxdata (points to beginning of subframe)
+              no_prefix  if 1 prefix is removed by HW
+
+              */
+
+              start_meas(&UE->ofdm_demod_stats);
+              slot_fep(UE,
+                       l,
+                       Ns%20,
+                       0,
+                       0,
+		       0);
+              stop_meas(&UE->ofdm_demod_stats);
+
+              if (UE->perfect_ce==1) {
+                if (awgn_flag==0) {
+                  for(k=0; k<NUMBER_OF_eNB_MAX; k++) {
+                    for(aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) {
+                      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+                        for (i=0; i<frame_parms->N_RB_DL*12; i++) {
+                          ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(
+                                eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP);
+                          //printf("x=%d,AMP=%d\n",eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x,AMP);
+                          ((int16_t *) UE->common_vars.dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(
+                                eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP);
+
+                          if (transmission_mode == 7){
+			    //this should include the BF weights! Will not work for a random channel
+                            if (UE->high_speed_flag==0) {
+                              ((int16_t *)UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i]=(int16_t)(
+                                  eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP);
+                              ((int16_t *)UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+1]=(int16_t)(
+                                  eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP);
+                              //printf("**,x=%d,AMP=%d\n",eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x,AMP);
+                            } else  {
+                              ((int16_t *)UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size)*2]=(int16_t)(
+                                  eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].x*AMP);
+                              ((int16_t *)UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size)*2]=(int16_t)(
+                                  eNB2UE[round]->chF[aarx+(aa*frame_parms->nb_antennas_rx)][i].y*AMP);
+                                
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                } else {
+                  for(aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) {
+                    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+                      for (i=0; i<frame_parms->N_RB_DL*12; i++) {
+                          ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP);
+                          ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=0/2;
+                        if (transmission_mode == 7) {
+                          if (UE->high_speed_flag==0){
+                            ((int16_t *) UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i]=(short)(AMP);
+                            ((int16_t *) UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+1]=0/2;
+                          } else {
+                            ((int16_t *) UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size)*2]=(short)(AMP);
+                            ((int16_t *) UE->pdsch_vars[0]->dl_bf_ch_estimates[(aa<<1)+aarx])[2*i+1+((l+(Ns%2)*pilot2)*frame_parms->ofdm_symbol_size)*2]=0/2;
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+
+
+              if ((Ns==((2*subframe))) && (l==0)) {
+                lte_ue_measurements(UE,
+                                    subframe*UE->frame_parms.samples_per_tti,
+                                    1,
+                                    0);
+                /*
+                  debug_msg("RX RSSI %d dBm, digital (%d, %d) dB, linear (%d, %d), avg rx power %d dB (%d lin), RX gain %d dB\n",
+                  UE->measurements.rx_rssi_dBm[0] - ((UE->frame_parms.nb_antennas_rx==2) ? 3 : 0),
+                  UE->measurements.wideband_cqi_dB[0][0],
+                  UE->measurements.wideband_cqi_dB[0][1],
+                  UE->measurements.wideband_cqi[0][0],
+                  UE->measurements.wideband_cqi[0][1],
+                  UE->measurements.rx_power_avg_dB[0],
+                  UE->measurements.rx_power_avg[0],
+                  UE->rx_total_gain_dB);
+                  debug_msg("N0 %d dBm digital (%d, %d) dB, linear (%d, %d), avg noise power %d dB (%d lin)\n",
+                  UE->measurements.n0_power_tot_dBm,
+                  UE->measurements.n0_power_dB[0],
+                  UE->measurements.n0_power_dB[1],
+                  UE->measurements.n0_power[0],
+                  UE->measurements.n0_power[1],
+                  UE->measurements.n0_power_avg_dB,
+                  UE->measurements.n0_power_avg);
+                  debug_msg("Wideband CQI tot %d dB, wideband cqi avg %d dB\n",
+                  UE->measurements.wideband_cqi_tot[0],
+                  UE->measurements.wideband_cqi_avg[0]);
+                */
+
+                if (transmission_mode==5 || transmission_mode==6) {
+                  if (pmi_feedback == 1) {
+                    pmi_feedback = 0;
+                    hold_channel = 1;
+                    goto PMI_FEEDBACK;
+                  }
+                }
+
+              }
+
+
+              if ((Ns==(2*subframe)) && (l==pilot1)) {// process symbols 0,1,2
+
+                if (dci_flag == 1) {
+                  UE->UE_mode[0] = PUSCH;
+                  start_meas(&UE->dlsch_rx_pdcch_stats);
+                  rx_pdcch(&UE->common_vars,
+                           UE->pdcch_vars,
+                           &UE->frame_parms,
+                           subframe,
+                           0,
+                           (UE->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI,
+                           UE->high_speed_flag,
+                           0);
+                  stop_meas(&UE->dlsch_rx_pdcch_stats);
+                  // overwrite number of pdcch symbols
+                  UE->pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols;
+
+                  dci_cnt = dci_decoding_procedure(UE,
+                                                   dci_alloc_rx,1,
+                                                   eNB_id,
+                                                   subframe);
+                  //printf("dci_cnt %d\n",dci_cnt);
+
+                  if (dci_cnt==0) {
+                    dlsch_active = 0;
+
+                    if (round==0) {
+                      dci_errors++;
+                      round=5;
+                      errs[0]++;
+                      //round_trials[0]++;
+
+                      if (n_frames==1)
+                        printf("DCI error trial %d errs[0] %d\n",trials,errs[0]);
+                    }
+
+                    //    for (i=1;i<=round;i++)
+                    //      round_trials[i]--;
+                    //    round=5;
+                  }
+
+                  for (i=0; i<dci_cnt; i++) {
+                    //        printf("Generating dlsch parameters for RNTI %x\n",dci_alloc_rx[i].rnti);
+                    if (round == 0) UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->first_tx=1;
+
+                    if ((dci_alloc_rx[i].rnti == n_rnti) &&
+                        (generate_ue_dlsch_params_from_dci(0,
+							   subframe,
+                                                           dci_alloc_rx[i].dci_pdu,
+                                                           dci_alloc_rx[i].rnti,
+                                                           dci_alloc_rx[i].format,
+                                                           UE->dlsch[0],
+                                                           &UE->frame_parms,
+                                                           UE->pdsch_config_dedicated,
+                                                           SI_RNTI,
+                                                           0,
+                                                           P_RNTI==0,
+                                                           transmission_mode<7?0:transmission_mode))) {
+                      //dump_dci(&UE->frame_parms,&dci_alloc_rx[i]);
+                      coded_bits_per_codeword = get_G(&eNB->frame_parms,
+                                                      UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->nb_rb,
+                                                      UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->rb_alloc_even,
+                                                      get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs),
+                                                      UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->Nl,
+                                                      UE->pdcch_vars[0]->num_pdcch_symbols,
+                                                      0,
+						      subframe,
+						      (transmission_mode<7?0:transmission_mode));
+          	    /*if (transmission_mode==7 && common_flag==0)
+       	    	      UE->dlsch[0][0]->harq_processes[0]->mimo_mode = TM7; */
+
+                      /*
+                      rate = (double)dlsch_tbs25[get_I_TBS(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs)][UE->dlsch[0][0]->nb_rb-1]/(coded_bits_per_codeword);
+                      rate*=get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs);
+                      */
+                      printf("num_pdcch_symbols %d, G %d, TBS %d\n",UE->pdcch_vars[0]->num_pdcch_symbols,coded_bits_per_codeword,
+                             UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->TBS);
+
+                      dlsch_active = 1;
+                    } else {
+                      dlsch_active = 0;
+
+                      if (round==0) {
+                        dci_errors++;
+                        errs[0]++;
+                        //round_trials[0]++;
+                        round=5;
+
+                        if (n_frames==1)
+                          printf("DCI misdetection trial %d\n",trials);
+
+                      }
+
+                      //      for (i=1;i<=round;i++)
+                      //        round_trials[i]--;
+                      //      round=5;
+                    }
+                  }
+                }  // if dci_flag==1
+                else { //dci_flag == 0
+
+                  UE->pdcch_vars[0]->crnti = n_rnti;
+                  UE->pdcch_vars[0]->num_pdcch_symbols = num_pdcch_symbols;
+
+                  if (round == 0) UE->dlsch[0][0]->harq_processes[0]->first_tx=1;
+
+                  switch (transmission_mode) {
+                  case 1:
+                  case 2:
+                  case 7:
+                    generate_ue_dlsch_params_from_dci(0,
+						      subframe,
+                                                      &DLSCH_alloc_pdu_1[0],
+                                                      (common_flag==0)? C_RNTI : SI_RNTI,
+                                                      (common_flag==0)? format1 : format1A,
+                                                      UE->dlsch[0],
+                                                      &UE->frame_parms,
+                                                      UE->pdsch_config_dedicated,
+                                                      SI_RNTI,
+                                                      0,
+                                                      P_RNTI,
+                                                      transmission_mode<7?0:transmission_mode);
+          	    /*if(transmission_mode==7 && common_flag==0)
+       	    	      UE->dlsch[0][0]->harq_processes[0]->mimo_mode = TM7;*/ 
+                    break;
+
+                  case 3:
+                    //        printf("Rate: TM3 (before) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx);
+                    generate_ue_dlsch_params_from_dci(0,
+						      subframe,
+                                                      &DLSCH_alloc_pdu_1[0],
+                                                      (common_flag==0)? C_RNTI : SI_RNTI,
+                                                      (common_flag==0)? format2A : format1A,
+                                                      UE->dlsch[0],
+                                                      &UE->frame_parms,
+                                                      UE->pdsch_config_dedicated,
+                                                      SI_RNTI,
+                                                      0,
+                                                      P_RNTI,
+                                                      0);
+                    //        printf("Rate: TM3 (after) round %d (%d) first_tx %d\n",round,UE->dlsch[0][0]->harq_processes[0]->round,UE->dlsch[0][0]->harq_processes[0]->first_tx);
+                    break;
+
+                  case 4:
+                    generate_ue_dlsch_params_from_dci(0,
+						      subframe,
+                                                      &DLSCH_alloc_pdu_1[0],
+                                                      (common_flag==0)? C_RNTI : SI_RNTI,
+                                                      (common_flag==0)? format2 : format1A,
+                                                      UE->dlsch[0],
+                                                      &UE->frame_parms,
+                                                      UE->pdsch_config_dedicated,
+                                                      SI_RNTI,
+                                                      0,
+                                                      P_RNTI,
+                                                      0);
+                    break;
+
+                  case 5:
+                  case 6:
+                    generate_ue_dlsch_params_from_dci(0,
+						      subframe,
+                                                      &DLSCH_alloc_pdu2_1E[0],
+                                                      C_RNTI,
+                                                      format1E_2A_M10PRB,
+                                                      UE->dlsch[0],
+                                                      &UE->frame_parms,
+                                                      UE->pdsch_config_dedicated,
+                                                      SI_RNTI,
+                                                      0,
+                                                      P_RNTI,
+                                                      0);
+                    break;
+
+                  }
+
+                  dlsch_active = 1;
+                } // if dci_flag == 1
+              }
+
+              if (dlsch_active == 1) {
+                
+		if (transmission_mode==7) {
+		  if (UE->frame_parms.Ncp==0) {
+		    if ((Ns==(2*subframe)   && ((l==3) || (l==6))) ||
+			(Ns==(1+2*subframe) && ((l==2) || (l==5)))) {
+		      if (perfect_ce==0)
+			lte_dl_bf_channel_estimation(UE,eNB_id,0,Ns,5,l+7*(Ns%2==1)); 
+		    }
+		  } else {
+		    msg("Beamforming channel estimation not supported yet for TM7 extented CP.\n");
+		  }
+		}
+
+                if ((Ns==(1+(2*subframe))) && (l==0)) {// process PDSCH symbols 1,2,3,4,5,(6 Normal Prefix)
+
+                  if ((transmission_mode == 5) &&
+                      (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->dl_power_off==0) &&
+                      (UE->use_ia_receiver ==1)) {
+                    dual_stream_UE = 1;
+                  } else {
+                    dual_stream_UE = 0;
+                  }
+
+
+                  start_meas(&UE->dlsch_llr_stats);
+
+                  for (m=UE->pdcch_vars[0]->num_pdcch_symbols;
+                       m<pilot2;
+                       m++) {
+                    if (rx_pdsch(UE,
+                                 PDSCH,
+                                 eNB_id,
+                                 eNB_id_i,
+                                 subframe,
+                                 m,
+                                 (m==UE->pdcch_vars[0]->num_pdcch_symbols)?1:0,
+                                 dual_stream_UE,
+                                 i_mod,
+                                 UE->dlsch[0][0]->current_harq_pid)==-1) {
+                      dlsch_active = 0;
+                      break;
+                    }
+                  }
+
+                  stop_meas(&UE->dlsch_llr_stats);
+                }
+
+                if ((Ns==(1+(2*subframe))) && (l==pilot1)) {
+                  // process symbols (6 Extended Prefix),7,8,9
+                  start_meas(&UE->dlsch_llr_stats);
+
+                  for (m=pilot2;
+                       m<pilot3;
+                       m++) {
+                    if (rx_pdsch(UE,
+                                 PDSCH,
+                                 eNB_id,
+                                 eNB_id_i,
+                                 subframe,
+                                 m,
+                                 0,
+                                 dual_stream_UE,
+                                 i_mod,
+                                 UE->dlsch[0][0]->current_harq_pid)==-1) {
+                      dlsch_active=0;
+                      break;
+                    }
+                  }
+
+                  stop_meas(&UE->dlsch_llr_stats);
+                }
+
+                if ((Ns==(2+(2*subframe))) && (l==0)) { // process symbols 10,11,(12,13 Normal Prefix) do deinterleaving for TTI
+                  start_meas(&UE->dlsch_llr_stats);
+
+                  for (m=pilot3;
+                       m<UE->frame_parms.symbols_per_tti;
+                       m++) {
+                    //printf("m=%d\n",m);
+                    if (rx_pdsch(UE,
+                                 PDSCH,
+                                 eNB_id,
+                                 eNB_id_i,
+                                 subframe,
+                                 m,
+                                 0,
+                                 dual_stream_UE,
+                                 i_mod,
+                                 UE->dlsch[0][0]->current_harq_pid)==-1) {
+                      dlsch_active=0;
+                      break;
+                    }
+                  }
+
+                  stop_meas(&UE->dlsch_llr_stats);
+                }
+
+
+                if (test_perf ==0 ) {
+                  if ((n_frames==1) && (Ns==(2+(2*subframe))) && (l==0))  {
+                    write_output("ch0.m","ch0",eNB2UE[0]->ch[0],eNB2UE[0]->channel_length,1,8);
+
+                    if (eNB->frame_parms.nb_antennas_tx>1)
+                      write_output("ch1.m","ch1",eNB2UE[0]->ch[eNB->frame_parms.nb_antennas_rx],eNB2UE[0]->channel_length,1,8);
+
+                    //common vars
+                    //write_output("rxsig0.m","rxs0", &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1);
+                    write_output("rxsig0.m","rxs0", &UE->common_vars.rxdata[0][subframe*UE->frame_parms.samples_per_tti],UE->frame_parms.samples_per_tti,1,1);
+                    //write_output("rxsigF0.m","rxsF0", &UE->common_vars.rxdataF[0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+                    write_output("rxsigF0.m","rxsF0", &UE->common_vars.rxdataF[0][0],UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+                    if (UE->frame_parms.nb_antennas_rx>1) {
+                      write_output("rxsig1.m","rxs1", UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1);
+                      write_output("rxsigF1.m","rxsF1", UE->common_vars.rxdataF[1],UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+                    }
+
+                    write_output("dlsch00_r0.m","dl00_r0",
+                                 &(UE->common_vars.dl_ch_estimates[eNB_id][0][0]),
+                                 UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+                    if (UE->frame_parms.nb_antennas_rx>1)
+                      write_output("dlsch01_r0.m","dl01_r0",
+                                   &(UE->common_vars.dl_ch_estimates[eNB_id][1][0]),
+                                   UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+                    if (eNB->frame_parms.nb_antennas_tx>1)
+                      write_output("dlsch10_r0.m","dl10_r0",
+                                   &(UE->common_vars.dl_ch_estimates[eNB_id][2][0]),
+                                   UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+                    if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1))
+                      write_output("dlsch11_r0.m","dl11_r0",
+                                   &(UE->common_vars.dl_ch_estimates[eNB_id][3][0]),
+                                   UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1);
+
+                    //pdsch_vars
+                    dump_dlsch2(UE,eNB_id,coded_bits_per_codeword,round);
+                    //dump_dlsch2(UE,eNB_id_i,coded_bits_per_codeword);
+                    write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4);
+
+                    //pdcch_vars
+                    write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1);
+                    write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],300*3,1,1);
+
+                    write_output("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[eNB_id]->rxdataF_comp[0],4*300,1,1);
+                    write_output("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[eNB_id]->llr,2400,1,4);
+
+                  }
+                }
+              }
+            }
+          }
+
+          //saving PMI in case of Transmission Mode > 5
+
+          if(abstx) {
+            if (trials==0 && round==0 && transmission_mode>=5 && transmission_mode<7) {
+              for (iii=0; iii<NB_RB; iii++) {
+                //fprintf(csv_fd, "%d, %d", (UE->pdsch_vars[eNB_id]->pmi_ext[iii]),(UE->pdsch_vars[eNB_id_i]->pmi_ext[iii]));
+                fprintf(csv_fd,"%x,%x,",(UE->pdsch_vars[eNB_id]->pmi_ext[iii]),(UE->pdsch_vars[eNB_id]->pmi_ext[iii]));
+                printf("%x ",(UE->pdsch_vars[eNB_id]->pmi_ext[iii]));
+              }
+            }
+          }
+
+          for (int cw=Kmimo-1; cw>=0; cw--) {
+            UE->dlsch[0][cw]->rnti = (common_flag==0) ? n_rnti: SI_RNTI;
+            coded_bits_per_codeword = get_G(&eNB->frame_parms,
+                                            eNB->dlsch[0][cw]->harq_processes[0]->nb_rb,
+                                            eNB->dlsch[0][cw]->harq_processes[0]->rb_alloc,
+                                            get_Qm(eNB->dlsch[0][cw]->harq_processes[0]->mcs),
+                                            eNB->dlsch[0][cw]->harq_processes[0]->Nl,
+                                            num_pdcch_symbols,
+                                            0,
+					    subframe,
+					    (transmission_mode<7?0:transmission_mode));
+
+            UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid]->G = coded_bits_per_codeword;
+
+
+	                
+            // calculate uncoded BLER
+            uncoded_ber=0;
+            for (i=0;i<coded_bits_per_codeword;i++)
+              if (eNB->dlsch[0][0]->harq_processes[0]->e[i] != (UE->pdsch_vars[0]->llr[0][i]<0)) {
+                uncoded_ber_bit[i] = 1;
+                uncoded_ber++;
+              }
+              else
+                uncoded_ber_bit[i] = 0;
+
+            uncoded_ber/=coded_bits_per_codeword;
+            avg_ber += uncoded_ber;
+
+            if (n_frames==1)
+              write_output("uncoded_ber_bit.m","uncoded_ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0);
+            
+
+            start_meas(&UE->dlsch_unscrambling_stats);
+            dlsch_unscrambling(&UE->frame_parms,
+                               0,
+                               UE->dlsch[0][cw],
+                               coded_bits_per_codeword,
+                               UE->pdsch_vars[eNB_id]->llr[cw],
+                               0,
+                               subframe<<1);
+            stop_meas(&UE->dlsch_unscrambling_stats);
+
+            start_meas(&UE->dlsch_decoding_stats);
+            ret = dlsch_decoding(UE,
+                                 UE->pdsch_vars[eNB_id]->llr[cw],
+                                 &UE->frame_parms,
+                                 UE->dlsch[0][cw],
+                                 UE->dlsch[0][cw]->harq_processes[UE->dlsch[0][cw]->current_harq_pid],
+                                 subframe,
+                                 UE->dlsch[0][cw]->current_harq_pid,
+                                 1,llr8_flag);
+            stop_meas(&UE->dlsch_decoding_stats);
+
+            if (cw==1) {
+              if (ret <= UE->dlsch[0][cw]->max_turbo_iterations) {
+              } else {
+                errs2[round]++;
+              }
+            }
+          }
+
+
+          stop_meas(&UE->phy_proc_rx);
+
+
+          if (ret <= UE->dlsch[0][0]->max_turbo_iterations) {
+
+            avg_iter += ret;
+            iter_trials++;
+
+            if (n_frames==1)
+              printf("No DLSCH errors found (round %d),uncoded ber %f\n",round,uncoded_ber);
+
+            UE->total_TBS[eNB_id] =  UE->total_TBS[eNB_id] + UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->TBS;
+            TB0_active = 0;
+
+            if (UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->mimo_mode == LARGE_CDD) {   //try to decode second stream using SIC
+              /*
+              for (round = 0 ; round < UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->round ; round++) {
+              // re-encoding of first stream
+              dlsch0_ue_harq = UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid];
+              dlsch0_eNB_harq = UE->dlsch[eNB_id]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid];
+              dlsch0_eNB_harq->mimo_mode    = LARGE_CDD;
+              dlsch0_eNB_harq->rb_alloc[0]  = dlsch0_ue_harq->rb_alloc_even[0];
+              dlsch0_eNB_harq->nb_rb        = dlsch0_ue_harq->nb_rb;
+              dlsch0_eNB_harq->mcs          = dlsch0_ue_harq->mcs;
+              dlsch0_eNB_harq->rvidx        = dlsch0_ue_harq->rvidx;
+              dlsch0_eNB_harq->Nl           = dlsch0_ue_harq->Nl;
+
+              dlsch0_eNB_harq->TBS          = dlsch0_ue_harq->TBS;
+              dlsch0_eNB_harq->dl_power_off = dlsch0_ue_harq->dl_power_off;
+              dlsch0_eNB_harq->status       = dlsch0_ue_harq->status;
+
+              UE->dlsch[eNB_id]->active       = UE->dlsch[eNB_id][0]->active;
+              UE->dlsch[eNB_id]->rnti         = UE->dlsch[eNB_id][0]->rnti;
+
+              dlsch_encoding(UE->dlsch[eNB_id][0]->harq_processes[UE->dlsch[eNB_id][0]->current_harq_pid]->b,
+                   &UE->frame_parms,
+                   num_pdcch_symbols,
+                   UE->dlsch[0],
+                   0,subframe,
+                   &UE->dlsch_rate_matching_stats,
+                   &UE->dlsch_turbo_encoding_stats,
+                   &UE->dlsch_interleaving_stats
+                   );
+
+                   //scrambling
+
+              //modulation
+
+              //stripping (from matched filter output?)
+
+              //detection of second stream
+              }
+              */
+            }
+          } else {
+            errs[round]++;
+
+            avg_iter += ret-1;
+            iter_trials++;
+
+            if (n_frames==1) {
+              //if ((n_frames==1) || (SNR>=30)) 
+              printf("DLSCH errors found (round %d), uncoded ber %f\n",round,uncoded_ber);
+
+              for (s=0; s<UE->dlsch[0][0]->harq_processes[0]->C; s++) {
+                if (s<UE->dlsch[0][0]->harq_processes[0]->Cminus)
+                  Kr = UE->dlsch[0][0]->harq_processes[0]->Kminus;
+                else
+                  Kr = UE->dlsch[0][0]->harq_processes[0]->Kplus;
+
+                Kr_bytes = Kr>>3;
+
+                printf("Decoded_output (Segment %d):\n",s);
+
+                for (i=0; i<Kr_bytes; i++)
+                  printf("%d : %x (%x)\n",i,UE->dlsch[0][0]->harq_processes[0]->c[s][i],UE->dlsch[0][0]->harq_processes[0]->c[s][i]^eNB->dlsch[0][0]->harq_processes[0]->c[s][i]);
+              }
+
+              sprintf(fname,"rxsig0_r%d.m",round);
+              sprintf(vname,"rxs0_r%d",round);
+              write_output(fname,vname, &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1);
+              sprintf(fname,"rxsigF0_r%d.m",round);
+              sprintf(vname,"rxs0F_r%d",round);
+              write_output(fname,vname, &UE->common_vars.rxdataF[0][0],2*UE->frame_parms.ofdm_symbol_size*nsymb,2,1);
+	     
+              if (UE->frame_parms.nb_antennas_rx>1) {
+                sprintf(fname,"rxsig1_r%d.m",round);
+                sprintf(vname,"rxs1_r%d.m",round);
+                write_output(fname,vname, UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1);
+                sprintf(fname,"rxsig1F_r%d.m",round);
+                sprintf(vname,"rxs1F_r%d.m",round);
+                write_output(fname,vname, UE->common_vars.rxdataF[1],2*UE->frame_parms.ofdm_symbol_size*nsymb,2,1);
+              }
+
+              sprintf(fname,"dlsch00_r%d.m",round);
+              sprintf(vname,"dl00_r%d",round);
+              write_output(fname,vname,
+                           &(UE->common_vars.dl_ch_estimates[eNB_id][0][0]),
+                           UE->frame_parms.ofdm_symbol_size*nsymb,1,1);
+
+              if (UE->frame_parms.nb_antennas_rx>1) {
+                sprintf(fname,"dlsch01_r%d.m",round);
+                sprintf(vname,"dl01_r%d",round);
+                write_output(fname,vname,
+                             &(UE->common_vars.dl_ch_estimates[eNB_id][1][0]),
+                             UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1);
+              }
+
+              if (eNB->frame_parms.nb_antennas_tx>1) {
+                sprintf(fname,"dlsch10_r%d.m",round);
+                sprintf(vname,"dl10_r%d",round);
+                write_output(fname,vname,
+                             &(UE->common_vars.dl_ch_estimates[eNB_id][2][0]),
+                             UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1);
+              }
+
+              if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1)) {
+                sprintf(fname,"dlsch11_r%d.m",round);
+                sprintf(vname,"dl11_r%d",round);
+                write_output(fname,vname,
+                             &(UE->common_vars.dl_ch_estimates[eNB_id][3][0]),
+                             UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1);
+              }
+
+              //pdsch_vars
+              dump_dlsch2(UE,eNB_id,coded_bits_per_codeword,round);
+              /*
+              write_output("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4);
+              write_output("dlsch_ber_bit.m","ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0);
+              write_output("dlsch_w.m","w",eNB->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,4);
+              write_output("dlsch_w.m","w",UE->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0);
+              */
+
+              if (round == 3) exit(-1);
+            }
+
+            //      printf("round %d errors %d/%d\n",round,errs[round],trials);
+
+            round++;
+            //      UE->dlsch[0][0]->harq_processes[0]->round++;
+          }
+
+	  if (xforms==1) {
+	    phy_scope_UE(form_ue,
+			 UE,
+			 eNB_id,
+			 0,// UE_id
+			 subframe);
+	  }
+
+        }  //round
+
+        //      printf("\n");
+
+        if ((errs[0]>=n_frames/10) && (trials>(n_frames/2)))
+          break;
+
+        //len = chbch_stats_read(stats_buffer,NULL,0,4096);
+        //printf("%s\n\n",stats_buffer);
+
+        if (UE->proc.proc_rxtx[subframe&1].frame_rx % 10 == 0) {
+          UE->bitrate[eNB_id] = (UE->total_TBS[eNB_id] - UE->total_TBS_last[eNB_id])*10;
+          LOG_D(PHY,"[UE %d] Calculating bitrate: total_TBS = %d, total_TBS_last = %d, bitrate = %d kbits/s\n",UE->Mod_id,UE->total_TBS[eNB_id],UE->total_TBS_last[eNB_id],
+                UE->bitrate[eNB_id]/1000);
+          UE->total_TBS_last[eNB_id] = UE->total_TBS[eNB_id];
+        }
+
+
+        UE->proc.proc_rxtx[subframe&1].frame_rx++;
+
+        /* calculate the total processing time for each packet,
+         * get the max, min, and number of packets that exceed t>2000us
+         */
+        double t_tx = (double)eNB->phy_proc_tx.p_time/cpu_freq_GHz/1000.0;
+        double t_tx_ifft = (double)eNB->ofdm_mod_stats.p_time/cpu_freq_GHz/1000.0;
+        double t_tx_mod = (double)eNB->dlsch_modulation_stats.p_time/cpu_freq_GHz/1000.0;
+        double t_tx_enc = (double)eNB->dlsch_encoding_stats.p_time/cpu_freq_GHz/1000.0;
+
+
+        double t_rx = (double)UE->phy_proc_rx.p_time/cpu_freq_GHz/1000.0;
+        double t_rx_fft = (double)UE->ofdm_demod_stats.p_time/cpu_freq_GHz/1000.0;
+        double t_rx_demod = (double)UE->dlsch_rx_pdcch_stats.p_time/cpu_freq_GHz/1000.0;
+        double t_rx_dec = (double)UE->dlsch_decoding_stats.p_time/cpu_freq_GHz/1000.0;
+
+        if (t_tx > t_tx_max)
+          t_tx_max = t_tx;
+
+        if (t_tx < t_tx_min)
+          t_tx_min = t_tx;
+
+        if (t_rx > t_rx_max)
+          t_rx_max = t_rx;
+
+        if (t_rx < t_rx_min)
+          t_rx_min = t_rx;
+
+        if (t_tx > 2000)
+          n_tx_dropped++;
+
+        if (t_rx > 2000)
+          n_rx_dropped++;
+
+        push_front(&time_vector_tx, t_tx);
+        push_front(&time_vector_tx_ifft, t_tx_ifft);
+        push_front(&time_vector_tx_mod, t_tx_mod);
+        push_front(&time_vector_tx_enc, t_tx_enc);
+
+        push_front(&time_vector_rx, t_rx);
+        push_front(&time_vector_rx_fft, t_rx_fft);
+        push_front(&time_vector_rx_demod, t_rx_demod);
+        push_front(&time_vector_rx_dec, t_rx_dec);
+
+
+      }   //trials
+
+      // round_trials[0]: number of code word : goodput the protocol
+      double table_tx[time_vector_tx.size];
+      totable(table_tx, &time_vector_tx);
+      double table_tx_ifft[time_vector_tx_ifft.size];
+      totable(table_tx_ifft, &time_vector_tx_ifft);
+      double table_tx_mod[time_vector_tx_mod.size];
+      totable(table_tx_mod, &time_vector_tx_mod);
+      double table_tx_enc[time_vector_tx_enc.size];
+      totable(table_tx_enc, &time_vector_tx_enc);
+
+      double table_rx[time_vector_rx.size];
+      totable(table_rx, &time_vector_rx);
+      double table_rx_fft[time_vector_rx_fft.size];
+      totable(table_rx_fft, &time_vector_rx_fft);
+      double table_rx_demod[time_vector_rx_demod.size];
+      totable(table_rx_demod, &time_vector_rx_demod);
+      double table_rx_dec[time_vector_rx_dec.size];
+      totable(table_rx_dec, &time_vector_rx_dec);
+
+
+      // sort table
+      qsort (table_tx, time_vector_tx.size, sizeof(double), &compare);
+      qsort (table_rx, time_vector_rx.size, sizeof(double), &compare);
+
+      if (dump_table == 1 ) {
+        set_component_filelog(USIM);  // file located in /tmp/usim.txt
+        int n;
+        LOG_F(USIM,"The transmitter raw data: \n");
+
+        for (n=0; n< time_vector_tx.size; n++) {
+          printf("%f ", table_tx[n]);
+          LOG_F(USIM,"%f ", table_tx[n]);
+        }
+
+        LOG_F(USIM,"\n");
+        LOG_F(USIM,"The receiver raw data: \n");
+
+        for (n=0; n< time_vector_rx.size; n++) {
+          // printf("%f ", table_rx[n]);
+          LOG_F(USIM,"%f ", table_rx[n]);
+        }
+
+        LOG_F(USIM,"\n");
+      }
+
+      double tx_median = table_tx[time_vector_tx.size/2];
+      double tx_q1 = table_tx[time_vector_tx.size/4];
+      double tx_q3 = table_tx[3*time_vector_tx.size/4];
+
+      double tx_ifft_median = table_tx_ifft[time_vector_tx_ifft.size/2];
+      double tx_ifft_q1 = table_tx_ifft[time_vector_tx_ifft.size/4];
+      double tx_ifft_q3 = table_tx_ifft[3*time_vector_tx_ifft.size/4];
+
+      double tx_mod_median = table_tx_mod[time_vector_tx_mod.size/2];
+      double tx_mod_q1 = table_tx_mod[time_vector_tx_mod.size/4];
+      double tx_mod_q3 = table_tx_mod[3*time_vector_tx_mod.size/4];
+
+      double tx_enc_median = table_tx_enc[time_vector_tx_enc.size/2];
+      double tx_enc_q1 = table_tx_enc[time_vector_tx_enc.size/4];
+      double tx_enc_q3 = table_tx_enc[3*time_vector_tx_enc.size/4];
+
+      double rx_median = table_rx[time_vector_rx.size/2];
+      double rx_q1 = table_rx[time_vector_rx.size/4];
+      double rx_q3 = table_rx[3*time_vector_rx.size/4];
+
+      double rx_fft_median = table_rx_fft[time_vector_rx_fft.size/2];
+      double rx_fft_q1 = table_rx_fft[time_vector_rx_fft.size/4];
+      double rx_fft_q3 = table_rx_fft[3*time_vector_rx_fft.size/4];
+
+      double rx_demod_median = table_rx_demod[time_vector_rx_demod.size/2];
+      double rx_demod_q1 = table_rx_demod[time_vector_rx_demod.size/4];
+      double rx_demod_q3 = table_rx_demod[3*time_vector_rx_demod.size/4];
+
+      double rx_dec_median = table_rx_dec[time_vector_rx_dec.size/2];
+      double rx_dec_q1 = table_rx_dec[time_vector_rx_dec.size/4];
+      double rx_dec_q3 = table_rx_dec[3*time_vector_rx_dec.size/4];
+
+      double std_phy_proc_tx=0;
+      double std_phy_proc_tx_ifft=0;
+      double std_phy_proc_tx_mod=0;
+      double std_phy_proc_tx_enc=0;
+
+      double std_phy_proc_rx=0;
+      double std_phy_proc_rx_fft=0;
+      double std_phy_proc_rx_demod=0;
+      double std_phy_proc_rx_dec=0;
+
+      effective_rate = ((double)(round_trials[0]-dci_errors)/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3]));
+
+      printf("\n**********************SNR = %f dB (tx_lev %f, sigma2_dB %f)**************************\n",
+             SNR,
+             (double)tx_lev_dB+10*log10(UE->frame_parms.ofdm_symbol_size/(NB_RB*12)),
+             sigma2_dB);
+
+      printf("Errors (%d(%d)/%d %d/%d %d/%d %d/%d), Pe = (%e,%e,%e,%e), dci_errors %d/%d, Pe = %e => effective rate %f  (%2.1f%%,%f, %f), normalized delay %f (%f)\n",
+             errs[0],
+             errs2[0],
+             round_trials[0],
+             errs[1],
+             round_trials[0],
+             errs[2],
+             round_trials[0],
+             errs[3],
+             round_trials[0],
+             (double)errs[0]/(round_trials[0]),
+             (double)errs[1]/(round_trials[0]),
+             (double)errs[2]/(round_trials[0]),
+             (double)errs[3]/(round_trials[0]),
+             dci_errors,
+             round_trials[0],
+             (double)dci_errors/(round_trials[0]),
+             rate*effective_rate,
+             100*effective_rate,
+             rate,
+             rate*get_Qm(UE->dlsch[0][0]->harq_processes[UE->dlsch[0][0]->current_harq_pid]->mcs),
+             (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/
+             (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
+             (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
+
+      if (print_perf==1) {
+        printf("eNB TX function statistics (per 1ms subframe)\n\n");
+        std_phy_proc_tx = sqrt((double)eNB->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+                               2)/eNB->phy_proc_tx.trials - pow((double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000,2));
+        printf("Total PHY proc tx                 :%f us (%d trials)\n",(double)eNB->phy_proc_tx.diff/eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,eNB->phy_proc_tx.trials);
+        printf("|__ Statistcs                           std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3,
+               n_tx_dropped);
+        std_phy_proc_tx_ifft = sqrt((double)eNB->ofdm_mod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+                                    2)/eNB->ofdm_mod_stats.trials - pow((double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000,2));
+        printf("OFDM_mod time                     :%f us (%d trials)\n",(double)eNB->ofdm_mod_stats.diff/eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,eNB->ofdm_mod_stats.trials);
+        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3);
+        std_phy_proc_tx_mod = sqrt((double)eNB->dlsch_modulation_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+                                   2)/eNB->dlsch_modulation_stats.trials - pow((double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000,2));
+        printf("DLSCH modulation time             :%f us (%d trials)\n",(double)eNB->dlsch_modulation_stats.diff/eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000.0,
+               eNB->dlsch_modulation_stats.trials);
+        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3);
+        printf("DLSCH scrambling time             :%f us (%d trials)\n",(double)eNB->dlsch_scrambling_stats.diff/eNB->dlsch_scrambling_stats.trials/cpu_freq_GHz/1000.0,
+               eNB->dlsch_scrambling_stats.trials);
+        std_phy_proc_tx_enc = sqrt((double)eNB->dlsch_encoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+                                   2)/eNB->dlsch_encoding_stats.trials - pow((double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000,2));
+        printf("DLSCH encoding time               :%f us (%d trials)\n",(double)eNB->dlsch_encoding_stats.diff/eNB->dlsch_encoding_stats.trials/cpu_freq_GHz/1000.0,
+               eNB->dlsch_modulation_stats.trials);
+        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3);
+        printf("|__ DLSCH turbo encoding time         :%f us (%d trials)\n",
+               ((double)eNB->dlsch_turbo_encoding_stats.trials/eNB->dlsch_encoding_stats.trials)*(double)
+               eNB->dlsch_turbo_encoding_stats.diff/eNB->dlsch_turbo_encoding_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_turbo_encoding_stats.trials);
+        printf("|__ DLSCH rate-matching time          :%f us (%d trials)\n",
+               ((double)eNB->dlsch_rate_matching_stats.trials/eNB->dlsch_encoding_stats.trials)*(double)
+               eNB->dlsch_rate_matching_stats.diff/eNB->dlsch_rate_matching_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_rate_matching_stats.trials);
+        printf("|__ DLSCH sub-block interleaving time :%f us (%d trials)\n",
+               ((double)eNB->dlsch_interleaving_stats.trials/eNB->dlsch_encoding_stats.trials)*(double)
+               eNB->dlsch_interleaving_stats.diff/eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,eNB->dlsch_interleaving_stats.trials);
+
+        printf("\n\nUE RX function statistics (per 1ms subframe)\n\n");
+        std_phy_proc_rx = sqrt((double)UE->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+                               2)/UE->phy_proc_rx.trials - pow((double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000,2));
+        printf("Total PHY proc rx                                   :%f us (%d trials)\n",(double)UE->phy_proc_rx.diff/UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0,
+               UE->phy_proc_rx.trials*2/3);
+        printf("|__Statistcs                                            std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median,
+               rx_q1, rx_q3, n_rx_dropped);
+        std_phy_proc_rx_fft = sqrt((double)UE->ofdm_demod_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+                                   2)/UE->ofdm_demod_stats.trials - pow((double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000,2));
+        printf("DLSCH OFDM demodulation and channel_estimation time :%f us (%d trials)\n",(nsymb)*(double)UE->ofdm_demod_stats.diff/UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0,
+               UE->ofdm_demod_stats.trials*2/3);
+        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3);
+        printf("|__ DLSCH rx dft                                        :%f us (%d trials)\n",
+               (nsymb*UE->frame_parms.nb_antennas_rx)*(double)UE->rx_dft_stats.diff/UE->rx_dft_stats.trials/cpu_freq_GHz/1000.0,UE->rx_dft_stats.trials*2/3);
+        printf("|__ DLSCH channel estimation time                       :%f us (%d trials)\n",
+               (4.0)*(double)UE->dlsch_channel_estimation_stats.diff/UE->dlsch_channel_estimation_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_channel_estimation_stats.trials*2/3);
+        printf("|__ DLSCH frequency offset estimation time              :%f us (%d trials)\n",
+               (4.0)*(double)UE->dlsch_freq_offset_estimation_stats.diff/UE->dlsch_freq_offset_estimation_stats.trials/cpu_freq_GHz/1000.0,
+               UE->dlsch_freq_offset_estimation_stats.trials*2/3);
+        printf("DLSCH rx pdcch                                       :%f us (%d trials)\n",(double)UE->dlsch_rx_pdcch_stats.diff/UE->dlsch_rx_pdcch_stats.trials/cpu_freq_GHz/1000.0,
+               UE->dlsch_rx_pdcch_stats.trials);
+        std_phy_proc_rx_demod = sqrt((double)UE->dlsch_llr_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+                                     2)/UE->dlsch_llr_stats.trials - pow((double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000,2));
+        printf("DLSCH Channel Compensation and LLR generation time  :%f us (%d trials)\n",(3)*(double)UE->dlsch_llr_stats.diff/UE->dlsch_llr_stats.trials/cpu_freq_GHz/1000.0,
+               UE->dlsch_llr_stats.trials/3);
+        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_demod, rx_demod_median, rx_demod_q1, rx_demod_q3);
+        printf("DLSCH unscrambling time                             :%f us (%d trials)\n",(double)UE->dlsch_unscrambling_stats.diff/UE->dlsch_unscrambling_stats.trials/cpu_freq_GHz/1000.0,
+               UE->dlsch_unscrambling_stats.trials);
+        std_phy_proc_rx_dec = sqrt((double)UE->dlsch_decoding_stats.diff_square/pow(cpu_freq_GHz,2)/pow(1000,
+                                   2)/UE->dlsch_decoding_stats.trials - pow((double)UE->dlsch_decoding_stats.diff/UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000,2));
+        printf("DLSCH Decoding time (%02.2f Mbit/s, avg iter %1.2f)    :%f us (%d trials, max %f)\n",
+               eNB->dlsch[0][0]->harq_processes[0]->TBS/1000.0,(double)avg_iter/iter_trials,
+               (double)UE->dlsch_decoding_stats.diff/UE->dlsch_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_decoding_stats.trials,
+               (double)UE->dlsch_decoding_stats.max/cpu_freq_GHz/1000.0);
+        printf("|__ Statistcs                           std: %fus median %fus q1 %fus q3 %fus \n",std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3);
+        printf("|__ DLSCH Rate Unmatching                               :%f us (%d trials)\n",
+               (double)UE->dlsch_rate_unmatching_stats.diff/UE->dlsch_rate_unmatching_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_rate_unmatching_stats.trials);
+        printf("|__ DLSCH Turbo Decoding(%d bits)                       :%f us (%d trials)\n",
+               UE->dlsch[0][0]->harq_processes[0]->Cminus ? UE->dlsch[0][0]->harq_processes[0]->Kminus : UE->dlsch[0][0]->harq_processes[0]->Kplus,
+               (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials/cpu_freq_GHz/1000.0,UE->dlsch_turbo_decoding_stats.trials);
+        printf("    |__ init                                            %f us (cycles/iter %f, %d trials)\n",
+               (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/cpu_freq_GHz/1000.0,
+               (double)UE->dlsch_tc_init_stats.diff/UE->dlsch_tc_init_stats.trials/((double)avg_iter/iter_trials),
+               UE->dlsch_tc_init_stats.trials);
+        printf("    |__ alpha                                           %f us (cycles/iter %f, %d trials)\n",
+               (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials/cpu_freq_GHz/1000.0,
+               (double)UE->dlsch_tc_alpha_stats.diff/UE->dlsch_tc_alpha_stats.trials*2,
+               UE->dlsch_tc_alpha_stats.trials);
+        printf("    |__ beta                                            %f us (cycles/iter %f,%d trials)\n",
+               (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials/cpu_freq_GHz/1000.0,
+               (double)UE->dlsch_tc_beta_stats.diff/UE->dlsch_tc_beta_stats.trials*2,
+               UE->dlsch_tc_beta_stats.trials);
+        printf("    |__ gamma                                           %f us (cycles/iter %f,%d trials)\n",
+               (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials/cpu_freq_GHz/1000.0,
+               (double)UE->dlsch_tc_gamma_stats.diff/UE->dlsch_tc_gamma_stats.trials*2,
+               UE->dlsch_tc_gamma_stats.trials);
+        printf("    |__ ext                                             %f us (cycles/iter %f,%d trials)\n",
+               (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials/cpu_freq_GHz/1000.0,
+               (double)UE->dlsch_tc_ext_stats.diff/UE->dlsch_tc_ext_stats.trials*2,
+               UE->dlsch_tc_ext_stats.trials);
+        printf("    |__ intl1                                           %f us (cycles/iter %f,%d trials)\n",
+               (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials/cpu_freq_GHz/1000.0,
+               (double)UE->dlsch_tc_intl1_stats.diff/UE->dlsch_tc_intl1_stats.trials,
+               UE->dlsch_tc_intl1_stats.trials);
+        printf("    |__ intl2+HD+CRC                                    %f us (cycles/iter %f,%d trials)\n",
+               (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials/cpu_freq_GHz/1000.0,
+               (double)UE->dlsch_tc_intl2_stats.diff/UE->dlsch_tc_intl2_stats.trials,
+               UE->dlsch_tc_intl2_stats.trials);
+      }
+
+      if ((transmission_mode != 3) && (transmission_mode != 4)) {
+        fprintf(bler_fd,"%f;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n",
+                SNR,
+                mcs1,
+                eNB->dlsch[0][0]->harq_processes[0]->TBS,
+                rate,
+                errs[0],
+                round_trials[0],
+                errs[1],
+                round_trials[1],
+                errs[2],
+                round_trials[2],
+                errs[3],
+                round_trials[3],
+                dci_errors);
+      } else {
+        fprintf(bler_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n",
+                SNR,
+                mcs1,mcs2,
+                eNB->dlsch[0][0]->harq_processes[0]->TBS,
+                eNB->dlsch[0][1]->harq_processes[0]->TBS,
+                rate,
+                errs[0],
+                round_trials[0],
+                errs[1],
+                round_trials[1],
+                errs[2],
+                round_trials[2],
+                errs[3],
+                round_trials[3],
+                dci_errors);
+      }
+
+
+      if(abstx) { //ABSTRACTION
+        blerr[0] = (double)errs[0]/(round_trials[0]);
+
+        if(num_rounds>1) {
+          blerr[1] = (double)errs[1]/(round_trials[1]);
+          blerr[2] = (double)errs[2]/(round_trials[2]);
+          blerr[3] = (double)errs[3]/(round_trials[3]);
+          fprintf(csv_fd,"%e,%e,%e,%e;\n",blerr[0],blerr[1],blerr[2],blerr[3]);
+        } else {
+          fprintf(csv_fd,"%e;\n",blerr[0]);
+        }
+      } //ABStraction
+
+      if ( (test_perf != 0) && (100 * effective_rate > test_perf )) {
+        //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; err0; trials0; err1; trials1; err2; trials2; err3; trials3; dci_err\n");
+        if ((transmission_mode != 3) && (transmission_mode != 4)) {
+          fprintf(time_meas_fd,"%f;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;",
+                  SNR,
+                  mcs1,
+                  eNB->dlsch[0][0]->harq_processes[0]->TBS,
+                  rate,
+                  errs[0],
+                  round_trials[0],
+                  errs[1],
+                  round_trials[1],
+                  errs[2],
+                  round_trials[2],
+                  errs[3],
+                  round_trials[3],
+                  dci_errors);
+
+          //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n");
+          fprintf(time_meas_fd,"%f;%d;%d;%f; %2.1f%%;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;",
+                  SNR,
+                  mcs1,
+                  eNB->dlsch[0][0]->harq_processes[0]->TBS,
+                  rate*effective_rate,
+                  100*effective_rate,
+                  rate,
+                  (double)avg_iter/iter_trials,
+                  errs[0],
+                  round_trials[0],
+                  errs[1],
+                  round_trials[1],
+                  errs[2],
+                  round_trials[2],
+                  errs[3],
+                  round_trials[3],
+                  (double)errs[0]/(round_trials[0]),
+                  (double)errs[1]/(round_trials[0]),
+                  (double)errs[2]/(round_trials[0]),
+                  (double)errs[3]/(round_trials[0]),
+                  dci_errors,
+                  round_trials[0],
+                  (double)dci_errors/(round_trials[0]),
+                  (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/
+                  (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
+                  (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
+        } else {
+          fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d;",
+                  SNR,
+                  mcs1,mcs2,
+                  eNB->dlsch[0][0]->harq_processes[0]->TBS,
+                  eNB->dlsch[0][1]->harq_processes[0]->TBS,
+                  rate,
+                  errs[0],
+                  round_trials[0],
+                  errs[1],
+                  round_trials[1],
+                  errs[2],
+                  round_trials[2],
+                  errs[3],
+                  round_trials[3],
+                  dci_errors);
+
+          //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n");
+          fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%2.1f;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;",
+                  SNR,
+                  mcs1,mcs2,
+                  eNB->dlsch[0][0]->harq_processes[0]->TBS,
+                  eNB->dlsch[0][1]->harq_processes[0]->TBS,
+                  rate*effective_rate,
+                  100*effective_rate,
+                  rate,
+                  (double)avg_iter/iter_trials,
+                  errs[0],
+                  round_trials[0],
+                  errs[1],
+                  round_trials[1],
+                  errs[2],
+                  round_trials[2],
+                  errs[3],
+                  round_trials[3],
+                  (double)errs[0]/(round_trials[0]),
+                  (double)errs[1]/(round_trials[0]),
+                  (double)errs[2]/(round_trials[0]),
+                  (double)errs[3]/(round_trials[0]),
+                  dci_errors,
+                  round_trials[0],
+                  (double)dci_errors/(round_trials[0]),
+                  (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/
+                  (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
+                  (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
+        }
+
+        //fprintf(time_meas_fd,"eNB_PROC_TX(%d); OFDM_MOD(%d); DL_MOD(%d); DL_SCR(%d); DL_ENC(%d); UE_PROC_RX(%d); OFDM_DEMOD_CH_EST(%d); RX_PDCCH(%d); CH_COMP_LLR(%d); DL_USCR(%d); DL_DECOD(%d);\n",
+        fprintf(time_meas_fd,"%d; %d; %d; %d; %d; %d; %d; %d; %d; %d; %d;",
+                eNB->phy_proc_tx.trials,
+                eNB->ofdm_mod_stats.trials,
+                eNB->dlsch_modulation_stats.trials,
+                eNB->dlsch_scrambling_stats.trials,
+                eNB->dlsch_encoding_stats.trials,
+                UE->phy_proc_rx.trials,
+                UE->ofdm_demod_stats.trials,
+                UE->dlsch_rx_pdcch_stats.trials,
+                UE->dlsch_llr_stats.trials,
+                UE->dlsch_unscrambling_stats.trials,
+                UE->dlsch_decoding_stats.trials
+               );
+        fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;",
+                get_time_meas_us(&eNB->phy_proc_tx),
+                get_time_meas_us(&eNB->ofdm_mod_stats),
+                get_time_meas_us(&eNB->dlsch_modulation_stats),
+                get_time_meas_us(&eNB->dlsch_scrambling_stats),
+                get_time_meas_us(&eNB->dlsch_encoding_stats),
+                get_time_meas_us(&UE->phy_proc_rx),
+                nsymb*get_time_meas_us(&UE->ofdm_demod_stats),
+                get_time_meas_us(&UE->dlsch_rx_pdcch_stats),
+                3*get_time_meas_us(&UE->dlsch_llr_stats),
+                get_time_meas_us(&UE->dlsch_unscrambling_stats),
+                get_time_meas_us(&UE->dlsch_decoding_stats)
+               );
+        //fprintf(time_meas_fd,"eNB_PROC_TX_STD;eNB_PROC_TX_MAX;eNB_PROC_TX_MIN;eNB_PROC_TX_MED;eNB_PROC_TX_Q1;eNB_PROC_TX_Q3;eNB_PROC_TX_DROPPED;\n");
+        fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped);
+
+        //fprintf(time_meas_fd,"IFFT;\n");
+        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_ifft, tx_ifft_median, tx_ifft_q1, tx_ifft_q3);
+
+        //fprintf(time_meas_fd,"MOD;\n");
+        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_mod, tx_mod_median, tx_mod_q1, tx_mod_q3);
+
+        //fprintf(time_meas_fd,"ENC;\n");
+        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_tx_enc, tx_enc_median, tx_enc_q1, tx_enc_q3);
+
+
+        //fprintf(time_meas_fd,"UE_PROC_RX_STD;UE_PROC_RX_MAX;UE_PROC_RX_MIN;UE_PROC_RX_MED;UE_PROC_RX_Q1;UE_PROC_RX_Q3;UE_PROC_RX_DROPPED;\n");
+        fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped);
+
+        //fprintf(time_meas_fd,"FFT;\n");
+        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_rx_fft, rx_fft_median, rx_fft_q1, rx_fft_q3);
+
+        //fprintf(time_meas_fd,"DEMOD;\n");
+        fprintf(time_meas_fd,"%f;%f;%f;%f;", std_phy_proc_rx_demod,rx_demod_median, rx_demod_q1, rx_demod_q3);
+
+        //fprintf(time_meas_fd,"DEC;\n");
+        fprintf(time_meas_fd,"%f;%f;%f;%f\n", std_phy_proc_rx_dec, rx_dec_median, rx_dec_q1, rx_dec_q3);
+
+
+        /*
+        fprintf(time_meas_fd,"%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;",
+        eNB->phy_proc_tx.trials,
+        eNB->ofdm_mod_stats.trials,
+        eNB->dlsch_modulation_stats.trials,
+        eNB->dlsch_scrambling_stats.trials,
+        eNB->dlsch_encoding_stats.trials,
+        UE->phy_proc_rx.trials,
+        UE->ofdm_demod_stats.trials,
+        UE->dlsch_rx_pdcch_stats.trials,
+        UE->dlsch_llr_stats.trials,
+        UE->dlsch_unscrambling_stats.trials,
+        UE->dlsch_decoding_stats.trials);
+        */
+        printf("[passed] effective rate : %f  (%2.1f%%,%f)): log and break \n",rate*effective_rate, 100*effective_rate, rate );
+        break;
+      } else if (test_perf !=0 ) {
+        printf("[continue] effective rate : %f  (%2.1f%%,%f)): increase snr \n",rate*effective_rate, 100*effective_rate, rate);
+      }
+
+      if (((double)errs[0]/(round_trials[0]))<(10.0/n_frames))
+        break;
+    }// SNR
+
+
+  } //ch_realization
+
+
+  fclose(bler_fd);
+
+  if (test_perf !=0)
+    fclose (time_meas_fd);
+
+  //fprintf(tikz_fd,"};\n");
+  //fclose(tikz_fd);
+
+  if (input_trch_file==1)
+    fclose(input_trch_fd);
+
+  if (input_file==1)
+    fclose(input_fd);
+
+  if(abstx) { // ABSTRACTION
+    fprintf(csv_fd,"];");
+    fclose(csv_fd);
+  }
+
+  if (uncoded_ber_bit)
+    free(uncoded_ber_bit);
+
+  uncoded_ber_bit = NULL;
+
+  for (k=0; k<n_users; k++) {
+    free(input_buffer0[k]);
+    free(input_buffer1[k]);
+    input_buffer0[k]=NULL;
+    input_buffer1[k]=NULL;
+  }
+
+  printf("Freeing dlsch structures\n");
+
+  for (i=0; i<2; i++) {
+    printf("eNB %d\n",i);
+    free_eNB_dlsch(eNB->dlsch[0][i]);
+    printf("UE %d\n",i);
+    free_ue_dlsch(UE->dlsch[0][i]);
+  }
+
+
+  printf("Freeing channel I/O\n");
+
+  for (i=0; i<n_tx_phy; i++){
+    free(s_re[i]);
+    free(s_im[i]);
+  }
+
+  for (i=0; i<2; i++) {
+    free(r_re[i]);
+    free(r_im[i]);
+  }
+
+
+  free(s_re);
+  free(s_im);
+  free(r_re);
+  free(r_im);
+
+  //  lte_sync_time_free();
+
+  //  printf("[MUMIMO] mcs %d, mcsi %d, offset %d, bler %f\n",mcs,mcs_i,offset_mumimo_llr_drange_fix,((double)errs[0])/((double)round_trials[0]));
+
+  return(0);
+}
+
+
diff --git a/openair1/SIMULATION/LTE_PHY/framegen.c b/openair1/SIMULATION/LTE_PHY/framegen.c
index 9d6530414e4a95e361bb988c01ad1dff87df7b04..d056bea5d0eaad6fe28fe807658167d3ef60d748 100644
--- a/openair1/SIMULATION/LTE_PHY/framegen.c
+++ b/openair1/SIMULATION/LTE_PHY/framegen.c
@@ -394,7 +394,7 @@ void lte_param_init(  unsigned char transmission_mode,
   lte_frame_parms->Nid_cell           = Nid_cell;
   lte_frame_parms->nushift            = Nid_cell%6;
   lte_frame_parms->nb_antennas_tx     = (transmission_mode == 1) ? 1 : 2;
-  lte_frame_parms->nb_antennas_tx_eNB = (transmission_mode == 1) ? 1 : 2;
+  lte_frame_parms->nb_antenna_ports_eNB = (transmission_mode == 1) ? 1 : 2;
   lte_frame_parms->nb_antennas_rx     = (transmission_mode == 1) ? 1 : 2;
   lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0;
   lte_frame_parms->phich_config_common.phich_resource = oneSixth;
diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c
index 11c1760cb33e9b328e1387b9ac6461934bb2cf54..7849dec1ab4448b5eddc6ed8f1fc975975e1b74d 100644
--- a/openair1/SIMULATION/LTE_PHY/mbmssim.c
+++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c
@@ -238,6 +238,7 @@ int main(int argc, char **argv)
     n_tx=2;
 
   lte_param_init(n_tx,
+                 n_tx,
 		 n_rx,
 		 transmission_mode,
 		 extended_prefix_flag,
@@ -301,7 +302,7 @@ int main(int argc, char **argv)
                                 0);
 
   // Create transport channel structures for 2 transport blocks (MIMO)
-  eNB->dlsch_MCH = new_eNB_dlsch(1,8,Nsoft,N_RB_DL,0);
+  eNB->dlsch_MCH = new_eNB_dlsch(1,8,Nsoft,N_RB_DL,0,&eNB->frame_parms);
 
   if (!eNB->dlsch_MCH) {
     printf("Can't get eNB dlsch structures\n");
@@ -475,11 +476,11 @@ int main(int argc, char **argv)
       }
 
       UE->dlsch_MCH[0]->harq_processes[0]->G = get_G(&UE->frame_parms,
-          UE->dlsch_MCH[0]->harq_processes[0]->nb_rb,
-          UE->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even,
-          get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs),
-          1,2,
-          UE->proc.proc_rxtx[0].frame_tx,subframe);
+						     UE->dlsch_MCH[0]->harq_processes[0]->nb_rb,
+						     UE->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even,
+						     get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs),
+						     1,2,
+						     UE->proc.proc_rxtx[0].frame_tx,subframe,0);
       UE->dlsch_MCH[0]->harq_processes[0]->Qm = get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs);
 
       dlsch_unscrambling(&UE->frame_parms,1,UE->dlsch_MCH[0],
diff --git a/openair1/SIMULATION/LTE_PHY/pbchsim.c b/openair1/SIMULATION/LTE_PHY/pbchsim.c
index f696cc8da4e32d6a11ddccfecfa88ee4e4ccc6f9..83906d73226dd476f2a2a6b472cf0403fb8984de 100644
--- a/openair1/SIMULATION/LTE_PHY/pbchsim.c
+++ b/openair1/SIMULATION/LTE_PHY/pbchsim.c
@@ -325,7 +325,7 @@ int main(int argc, char **argv)
   if (transmission_mode>=2)
     n_tx=2;
 
-  lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,3,N_RB_DL,0,osf,0);
+  lte_param_init(n_tx, n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,3,N_RB_DL,0,osf,0);
 
   eNB1 = malloc(sizeof(PHY_VARS_eNB));
   eNB2 = malloc(sizeof(PHY_VARS_eNB));
diff --git a/openair1/SIMULATION/LTE_PHY/pdcchsim.c b/openair1/SIMULATION/LTE_PHY/pdcchsim.c
index 0b79ec52ba6b3036763819089d90a1992fb238d4..04b9d304b39d21be6cefb42d997d2b2bda9c99d2 100644
--- a/openair1/SIMULATION/LTE_PHY/pdcchsim.c
+++ b/openair1/SIMULATION/LTE_PHY/pdcchsim.c
@@ -694,6 +694,7 @@ int main(int argc, char **argv)
     n_tx=2;
 
   lte_param_init(n_tx,
+                 n_tx,
                  n_rx,
                  transmission_mode,
                  extended_prefix_flag,
@@ -737,7 +738,7 @@ int main(int argc, char **argv)
          subframe,NUMBER_OF_OFDM_CARRIERS,
          eNB->frame_parms.Ncp,eNB->frame_parms.samples_per_tti,nsymb);
 
-  eNB2UE = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx_eNB,
+  eNB2UE = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx,
                                 UE->frame_parms.nb_antennas_rx,
                                 channel_model,
 				N_RB2sampling_rate(eNB->frame_parms.N_RB_DL),
@@ -812,7 +813,7 @@ int main(int argc, char **argv)
     for (trial=0; trial<n_frames; trial++) {
       
       //    printf("DCI (SF %d): txdataF %p (0 %p)\n",subframe,&eNB->common_vars.txdataF[eNb_id][aa][512*14*subframe],&eNB->common_vars.txdataF[eNb_id][aa][0]);
-      for (aa=0; aa<eNB->frame_parms.nb_antennas_tx_eNB; aa++) {
+      for (aa=0; aa<eNB->frame_parms.nb_antennas_tx; aa++) {
         memset(&eNB->common_vars.txdataF[eNb_id][aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t));
 
       }
@@ -951,15 +952,14 @@ int main(int argc, char **argv)
         if (n_frames==1) {
           write_output("txsigF0.m","txsF0", eNB->common_vars.txdataF[eNb_id][0],4*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX,1,1);
 
-          if (eNB->frame_parms.nb_antennas_tx_eNB > 1)
+          if (eNB->frame_parms.nb_antenna_ports_eNB > 1)
             write_output("txsigF1.m","txsF1", eNB->common_vars.txdataF[eNb_id][1],4*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX,1,1);
         }
 
         tx_lev = 0;
 
 
-
-        for (aa=0; aa<eNB->frame_parms.nb_antennas_tx_eNB; aa++) {
+        for (aa=0; aa<eNB->frame_parms.nb_antenna_ports_eNB; aa++) {
           if (eNB->frame_parms.Ncp == 1)
             PHY_ofdm_mod(&eNB->common_vars.txdataF[eNb_id][aa][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],        // input,
                          &txdata[aa][subframe*eNB->frame_parms.samples_per_tti],         // output
@@ -982,7 +982,7 @@ int main(int argc, char **argv)
       }
 
       for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) {
-        for (aa=0; aa<eNB->frame_parms.nb_antennas_tx_eNB; aa++) {
+        for (aa=0; aa<eNB->frame_parms.nb_antenna_ports_eNB; aa++) {
           if (awgn_flag == 0) {
             s_re[aa][i] = ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]);
             s_im[aa][i] = ((double)(((short *)txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)+1]);
@@ -1069,7 +1069,7 @@ int main(int argc, char **argv)
               }
             }
           } else {
-            for(aa=0; aa<frame_parms->nb_antennas_tx_eNB; aa++) {
+            for(aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) {
               for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
                 for (i=0; i<frame_parms->N_RB_DL*12; i++) {
                   ((int16_t *) UE->common_vars.dl_ch_estimates[0][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(short)(AMP);
diff --git a/openair1/SIMULATION/LTE_PHY/prachsim.c b/openair1/SIMULATION/LTE_PHY/prachsim.c
index ad57d17507e092986e8bcbd463e7d9bd9476c36e..7acc07528c4763cc3e23fb4d34bece13be8c7473 100644
--- a/openair1/SIMULATION/LTE_PHY/prachsim.c
+++ b/openair1/SIMULATION/LTE_PHY/prachsim.c
@@ -308,6 +308,7 @@ int main(int argc, char **argv)
     n_tx=2;
 
   lte_param_init(n_tx,
+                 n_tx,
 		 n_rx,
 		 transmission_mode,
 		 extended_prefix_flag,
diff --git a/openair1/SIMULATION/LTE_PHY/pucchsim.c b/openair1/SIMULATION/LTE_PHY/pucchsim.c
index 843cd27a5453919d554fc9296b5bcb4007f39665..77bfcb18cf68682f2d80f87cd371c92c5e45d25d 100644
--- a/openair1/SIMULATION/LTE_PHY/pucchsim.c
+++ b/openair1/SIMULATION/LTE_PHY/pucchsim.c
@@ -296,6 +296,7 @@ int main(int argc, char **argv)
     n_tx=2;
 
   lte_param_init(n_tx,
+                 n_tx,
 		 n_rx,
 		 transmission_mode,
 		 extended_prefix_flag,
diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c
index 2bf96c3020f5e24a7ef34c3ce5e592426509eaa0..cf9e5aaa30ae9e42a850d2111626471ec2111f96 100644
--- a/openair1/SIMULATION/LTE_PHY/ulsim.c
+++ b/openair1/SIMULATION/LTE_PHY/ulsim.c
@@ -20,7 +20,7 @@
  */
 
 /*! \file ulsim.c
- \brief Top-level DL simulator
+ \brief Top-level UL simulator
  \author R. Knopp
  \date 2011 - 2014
  \version 0.1
@@ -554,6 +554,7 @@ int main(int argc, char **argv)
   }
 
   lte_param_init(1,
+                 1, 
 		 n_rx,
 		 1,
 		 extended_prefix_flag,
@@ -679,7 +680,7 @@ int main(int argc, char **argv)
   }
   // Create transport channel structures for 2 transport blocks (MIMO)
   for (i=0; i<2; i++) {
-    eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0);
+    eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0,&eNB->frame_parms);
     UE->dlsch[0][i]  = new_ue_dlsch(1,8,1827072,MAX_TURBO_ITERATIONS,N_RB_DL,0);
 
     if (!eNB->dlsch[0][i]) {
diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h
index c8cd92b0609323a5898d153f508bf3528642b1c3..acc9ae6ba11f466fe95ef90b3a10d0ad2a0ea05c 100644
--- a/openair2/COMMON/as_message.h
+++ b/openair2/COMMON/as_message.h
@@ -211,6 +211,14 @@ typedef struct broadcast_info_ind_s {
 #define AS_HSDUPA           (1 << NET_ACCESS_HSDUPA)
 #define AS_EUTRAN           (1 << NET_ACCESS_EUTRAN)
 
+/*
+ * NAS->AS -K_eNB refresh request
+ * NAS request AS to refresh its KeNB key
+ */
+typedef struct kenb_refresh_req_s {
+  Byte_t kenb[32];
+} kenb_refresh_req_t;
+
 /*
  * NAS->AS - Cell Information request
  * NAS request AS to search for a suitable cell belonging to the selected
diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h
index 18a767843680d77b01db77640f32b019ff603684..04b1182482a137f9db97e3855163b97e4507c4aa 100644
--- a/openair2/COMMON/rrc_messages_def.h
+++ b/openair2/COMMON/rrc_messages_def.h
@@ -56,6 +56,7 @@ MESSAGE_DEF(RRC_STATE_IND,              MESSAGE_PRIORITY_MED,       RrcStateInd,
 MESSAGE_DEF(RRC_CONFIGURATION_REQ,      MESSAGE_PRIORITY_MED,       RrcConfigurationReq,        rrc_configuration_req)
 
 // UE: NAS -> RRC messages
+MESSAGE_DEF(NAS_KENB_REFRESH_REQ,       MESSAGE_PRIORITY_MED,       NasKenbRefreshReq,          nas_kenb_refresh_req)
 MESSAGE_DEF(NAS_CELL_SELECTION_REQ,     MESSAGE_PRIORITY_MED,       NasCellSelectionReq,        nas_cell_selection_req)
 MESSAGE_DEF(NAS_CONN_ESTABLI_REQ,       MESSAGE_PRIORITY_MED,       NasConnEstabliReq,          nas_conn_establi_req)
 MESSAGE_DEF(NAS_UPLINK_DATA_REQ,        MESSAGE_PRIORITY_MED,       NasUlDataReq,               nas_ul_data_req)
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index c2df8bab38704f7479c114104151b56e73cd7270..8a4c27f5ebb913c0d1a07302c879dcedb74fe579 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -62,6 +62,7 @@ typedef UL_DCCH_Message_t       RrcUlDcchMessage;
 
 #define RRC_CONFIGURATION_REQ(mSGpTR)   (mSGpTR)->ittiMsg.rrc_configuration_req
 
+#define NAS_KENB_REFRESH_REQ(mSGpTR)    (mSGpTR)->ittiMsg.nas_kenb_refresh_req
 #define NAS_CELL_SELECTION_REQ(mSGpTR)  (mSGpTR)->ittiMsg.nas_cell_selection_req
 #define NAS_CONN_ESTABLI_REQ(mSGpTR)    (mSGpTR)->ittiMsg.nas_conn_establi_req
 #define NAS_UPLINK_DATA_REQ(mSGpTR)     (mSGpTR)->ittiMsg.nas_ul_data_req
@@ -175,6 +176,7 @@ typedef struct RrcConfigurationReq_s {
 } RrcConfigurationReq;
 
 // UE: NAS -> RRC messages
+typedef kenb_refresh_req_t      NasKenbRefreshReq;
 typedef cell_info_req_t         NasCellSelectionReq;
 typedef nas_establish_req_t     NasConnEstabliReq;
 typedef ul_info_transfer_req_t  NasUlDataReq;
diff --git a/openair2/COMMON/tasks_def.h b/openair2/COMMON/tasks_def.h
index 5fe555e1176c7aaaa216b7ce204b2131ac91ae5f..c9e210fd1f4bc27a1a0e55d85a27088d4a697750 100644
--- a/openair2/COMMON/tasks_def.h
+++ b/openair2/COMMON/tasks_def.h
@@ -55,6 +55,8 @@ TASK_DEF(TASK_X2AP,     TASK_PRIORITY_MED,          200)
 TASK_DEF(TASK_SCTP,     TASK_PRIORITY_MED,          200)
 ///   eNB APP task
 TASK_DEF(TASK_ENB_APP,  TASK_PRIORITY_MED,          200)
+///   eNB Agent task
+TASK_DEF(TASK_FLEXRAN_AGENT,  TASK_PRIORITY_MED,          200)
 
 // UE tasks and sub-tasks:
 //// Layer 2 and Layer 1 sub-tasks
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
new file mode 100644
index 0000000000000000000000000000000000000000..b9cad28278ba60fab4a54d0ce5535d6f5ea5c6d1
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
@@ -0,0 +1,1493 @@
+/*
+ * 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.0  (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 flexran_agent_mac.c
+ * \brief FlexRAN agent message handler for MAC layer
+ * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+#include "flexran_agent_mac.h"
+#include "flexran_agent_extern.h"
+#include "flexran_agent_common.h"
+#include "flexran_agent_mac_internal.h"
+
+#include "LAYER2/MAC/proto.h"
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#include "LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h"
+
+#include "liblfds700.h"
+
+#include "log.h"
+
+
+/*Flags showing if a mac agent has already been registered*/
+unsigned int mac_agent_registered[NUM_MAX_ENB];
+
+/*Array containing the Agent-MAC interfaces*/
+AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
+
+/* Ringbuffer related structs used for maintaining the dl mac config messages */
+//message_queue_t *dl_mac_config_queue;
+struct lfds700_misc_prng_state ps[NUM_MAX_ENB];
+struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB];
+struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB];
+
+
+int flexran_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg){
+
+  // TODO: Must deal with sanitization of input
+  // TODO: Must check if RNTIs and cell ids of the request actually exist
+  // TODO: Must resolve conflicts among stats requests
+
+  int i;
+  void *buffer;
+  int size;
+  err_code_t err_code;
+  xid_t xid;
+  uint32_t usec_interval, sec_interval;
+
+  //TODO: We do not deal with multiple CCs at the moment and eNB id is 0
+  int cc_id = 0;
+  int enb_id = mod_id;
+
+  //eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
+  //UE_list_t *eNB_UE_list=  &eNB->UE_list;
+
+  report_config_t report_config;
+
+  uint32_t ue_flags = 0;
+  uint32_t c_flags = 0;
+
+  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+
+  Protocol__FlexStatsRequest *stats_req = input->stats_request_msg;
+  xid = (stats_req->header)->xid;
+
+  // Check the type of request that is made
+  switch(stats_req->body_case) {
+  case PROTOCOL__FLEX_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST: ;
+    Protocol__FlexCompleteStatsRequest *comp_req = stats_req->complete_stats_request;
+    if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_OFF) {
+      /*Disable both periodic and continuous updates*/
+      flexran_agent_disable_cont_mac_stats_update(mod_id);
+      flexran_agent_destroy_timer_by_task_id(xid);
+      *msg = NULL;
+      return 0;
+    } else { //One-off, periodical or continuous reporting
+      //Set the proper flags
+      ue_flags = comp_req->ue_report_flags;
+      c_flags = comp_req->cell_report_flags;
+      //Create a list of all eNB RNTIs and cells
+
+      //Set the number of UEs and create list with their RNTIs stats configs
+      report_config.nr_ue = flexran_get_num_ues(mod_id); //eNB_UE_list->num_UEs
+      report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t) * report_config.nr_ue);
+      if (report_config.ue_report_type == NULL) {
+	// TODO: Add appropriate error code
+	err_code = -100;
+	goto error;
+      }
+      for (i = 0; i < report_config.nr_ue; i++) {
+	report_config.ue_report_type[i].ue_rnti = flexran_get_ue_crnti(enb_id, i); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].crnti;
+	report_config.ue_report_type[i].ue_report_flags = ue_flags;
+      }
+      //Set the number of CCs and create a list with the cell stats configs
+      report_config.nr_cc = MAX_NUM_CCs;
+      report_config.cc_report_type = (cc_report_type_t *) malloc(sizeof(cc_report_type_t) * report_config.nr_cc);
+      if (report_config.cc_report_type == NULL) {
+	// TODO: Add appropriate error code
+	err_code = -100;
+	goto error;
+      }
+      for (i = 0; i < report_config.nr_cc; i++) {
+	//TODO: Must fill in the proper cell ids
+	report_config.cc_report_type[i].cc_id = i;
+	report_config.cc_report_type[i].cc_report_flags = c_flags;
+      }
+      /* Check if request was periodical */
+      if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_PERIODICAL) {
+	/* Create a one off flexran message as an argument for the periodical task */
+	Protocol__FlexranMessage *timer_msg;
+	stats_request_config_t request_config;
+	request_config.report_type = PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS;
+	request_config.report_frequency = PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE;
+	request_config.period = 0;
+	/* Need to make sure that the ue flags are saved (Bug) */
+	if (report_config.nr_ue == 0) {
+	  report_config.nr_ue = 1;
+	  report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t));
+	   if (report_config.ue_report_type == NULL) {
+	     // TODO: Add appropriate error code
+	     err_code = -100;
+	     goto error;
+	   }
+	   report_config.ue_report_type[0].ue_rnti = 0; // Dummy value
+	   report_config.ue_report_type[0].ue_report_flags = ue_flags;
+	}
+	request_config.config = &report_config;
+	flexran_agent_mac_stats_request(enb_id, xid, &request_config, &timer_msg);
+	/* Create a timer */
+	long timer_id = 0;
+	flexran_agent_timer_args_t *timer_args;
+	timer_args = malloc(sizeof(flexran_agent_timer_args_t));
+	memset (timer_args, 0, sizeof(flexran_agent_timer_args_t));
+	timer_args->mod_id = enb_id;
+	timer_args->msg = timer_msg;
+	/*Convert subframes to usec time*/
+	usec_interval = 1000*comp_req->sf;
+	sec_interval = 0;
+	/*add seconds if required*/
+	if (usec_interval >= 1000*1000) {
+	  sec_interval = usec_interval/(1000*1000);
+	  usec_interval = usec_interval%(1000*1000);
+	}
+	flexran_agent_create_timer(sec_interval, usec_interval, FLEXRAN_AGENT_DEFAULT, enb_id, FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, xid, flexran_agent_handle_timed_task,(void*) timer_args, &timer_id);
+      } else if (comp_req->report_frequency == PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_CONTINUOUS) {
+	/*If request was for continuous updates, disable the previous configuration and
+	  set up a new one*/
+	flexran_agent_disable_cont_mac_stats_update(mod_id);
+	stats_request_config_t request_config;
+	request_config.report_type = PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS;
+	request_config.report_frequency = PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE;
+	request_config.period = 0;
+	/* Need to make sure that the ue flags are saved (Bug) */
+	if (report_config.nr_ue == 0) {
+	  report_config.nr_ue = 1;
+	  report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t));
+	  if (report_config.ue_report_type == NULL) {
+	    // TODO: Add appropriate error code
+	    err_code = -100;
+	    goto error;
+	  }
+	  report_config.ue_report_type[0].ue_rnti = 0; // Dummy value
+	  report_config.ue_report_type[0].ue_report_flags = ue_flags;
+	}
+	request_config.config = &report_config;
+	flexran_agent_enable_cont_mac_stats_update(enb_id, xid, &request_config);
+      }
+    }
+    break;
+  case PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST:;
+    Protocol__FlexCellStatsRequest *cell_req = stats_req->cell_stats_request;
+    // UE report config will be blank
+    report_config.nr_ue = 0;
+    report_config.ue_report_type = NULL;
+    report_config.nr_cc = cell_req->n_cell;
+    report_config.cc_report_type = (cc_report_type_t *) malloc(sizeof(cc_report_type_t) * report_config.nr_cc);
+    if (report_config.cc_report_type == NULL) {
+      // TODO: Add appropriate error code
+      err_code = -100;
+      goto error;
+    }
+    for (i = 0; i < report_config.nr_cc; i++) {
+	//TODO: Must fill in the proper cell ids
+      report_config.cc_report_type[i].cc_id = cell_req->cell[i];
+      report_config.cc_report_type[i].cc_report_flags = cell_req->flags;
+    }
+    break;
+  case PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST:;
+    Protocol__FlexUeStatsRequest *ue_req = stats_req->ue_stats_request;
+    // Cell report config will be blank
+    report_config.nr_cc = 0;
+    report_config.cc_report_type = NULL;
+    report_config.nr_ue = ue_req->n_rnti;
+    report_config.ue_report_type = (ue_report_type_t *) malloc(sizeof(ue_report_type_t) * report_config.nr_ue);
+    if (report_config.ue_report_type == NULL) {
+      // TODO: Add appropriate error code
+      err_code = -100;
+      goto error;
+    }
+    for (i = 0; i < report_config.nr_ue; i++) {
+      report_config.ue_report_type[i].ue_rnti = ue_req->rnti[i];
+      report_config.ue_report_type[i].ue_report_flags = ue_req->flags;
+    }
+    break;
+  default:
+    //TODO: Add appropriate error code
+    err_code = -100;
+    goto error;
+  }
+
+  if (flexran_agent_mac_stats_reply(enb_id, xid, &report_config, msg) < 0 ){
+    err_code = PROTOCOL__FLEXRAN_ERR__MSG_BUILD;
+    goto error;
+  }
+
+  free(report_config.ue_report_type);
+  free(report_config.cc_report_type);
+
+  return 0;
+
+ error :
+  LOG_E(FLEXRAN_AGENT, "errno %d occured\n", err_code);
+  return err_code;
+}
+
+int flexran_agent_mac_stats_request(mid_t mod_id,
+				    xid_t xid,
+				    const stats_request_config_t *report_config,
+				    Protocol__FlexranMessage **msg) {
+  Protocol__FlexHeader *header;
+  int i;
+
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REQUEST, &header) != 0)
+    goto error;
+
+  Protocol__FlexStatsRequest *stats_request_msg;
+  stats_request_msg = malloc(sizeof(Protocol__FlexStatsRequest));
+  if(stats_request_msg == NULL)
+    goto error;
+
+  protocol__flex_stats_request__init(stats_request_msg);
+  stats_request_msg->header = header;
+
+  stats_request_msg->type = report_config->report_type;
+  stats_request_msg->has_type = 1;
+
+  switch (report_config->report_type) {
+  case PROTOCOL__FLEX_STATS_TYPE__FLST_COMPLETE_STATS:
+    stats_request_msg->body_case =  PROTOCOL__FLEX_STATS_REQUEST__BODY_COMPLETE_STATS_REQUEST;
+    Protocol__FlexCompleteStatsRequest *complete_stats;
+    complete_stats = malloc(sizeof(Protocol__FlexCompleteStatsRequest));
+    if(complete_stats == NULL)
+      goto error;
+    protocol__flex_complete_stats_request__init(complete_stats);
+    complete_stats->report_frequency = report_config->report_frequency;
+    complete_stats->has_report_frequency = 1;
+    complete_stats->sf = report_config->period;
+    complete_stats->has_sf = 1;
+    complete_stats->has_cell_report_flags = 1;
+    complete_stats->has_ue_report_flags = 1;
+    if (report_config->config->nr_cc > 0) {
+      complete_stats->cell_report_flags = report_config->config->cc_report_type[0].cc_report_flags;
+    }
+    if (report_config->config->nr_ue > 0) {
+      complete_stats->ue_report_flags = report_config->config->ue_report_type[0].ue_report_flags;
+    }
+    stats_request_msg->complete_stats_request = complete_stats;
+    break;
+  case  PROTOCOL__FLEX_STATS_TYPE__FLST_CELL_STATS:
+    stats_request_msg->body_case = PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST;
+     Protocol__FlexCellStatsRequest *cell_stats;
+     cell_stats = malloc(sizeof(Protocol__FlexCellStatsRequest));
+    if(cell_stats == NULL)
+      goto error;
+    protocol__flex_cell_stats_request__init(cell_stats);
+    cell_stats->n_cell = report_config->config->nr_cc;
+    cell_stats->has_flags = 1;
+    if (cell_stats->n_cell > 0) {
+      uint32_t *cells;
+      cells = (uint32_t *) malloc(sizeof(uint32_t)*cell_stats->n_cell);
+      for (i = 0; i < cell_stats->n_cell; i++) {
+	cells[i] = report_config->config->cc_report_type[i].cc_id;
+      }
+      cell_stats->cell = cells;
+      cell_stats->flags = report_config->config->cc_report_type[i].cc_report_flags;
+    }
+    stats_request_msg->cell_stats_request = cell_stats;
+    break;
+  case PROTOCOL__FLEX_STATS_TYPE__FLST_UE_STATS:
+    stats_request_msg->body_case = PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST;
+     Protocol__FlexUeStatsRequest *ue_stats;
+     ue_stats = malloc(sizeof(Protocol__FlexUeStatsRequest));
+    if(ue_stats == NULL)
+      goto error;
+    protocol__flex_ue_stats_request__init(ue_stats);
+    ue_stats->n_rnti = report_config->config->nr_ue;
+    ue_stats->has_flags = 1;
+    if (ue_stats->n_rnti > 0) {
+      uint32_t *ues;
+      ues = (uint32_t *) malloc(sizeof(uint32_t)*ue_stats->n_rnti);
+      for (i = 0; i < ue_stats->n_rnti; i++) {
+	ues[i] = report_config->config->ue_report_type[i].ue_rnti;
+      }
+      ue_stats->rnti = ues;
+      ue_stats->flags = report_config->config->ue_report_type[i].ue_report_flags;
+    }
+    stats_request_msg->ue_stats_request = ue_stats;
+    break;
+  default:
+    goto error;
+  }
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG;
+  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+  (*msg)->stats_request_msg = stats_request_msg;
+  return 0;
+
+ error:
+  // TODO: Need to make proper error handling
+  if (header != NULL)
+    free(header);
+  if (stats_request_msg != NULL)
+    free(stats_request_msg);
+  if(*msg != NULL)
+    free(*msg);
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_mac_destroy_stats_request(Protocol__FlexranMessage *msg) {
+   if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG)
+    goto error;
+  free(msg->stats_request_msg->header);
+  if (msg->stats_request_msg->body_case == PROTOCOL__FLEX_STATS_REQUEST__BODY_CELL_STATS_REQUEST) {
+    free(msg->stats_request_msg->cell_stats_request->cell);
+  }
+  if (msg->stats_request_msg->body_case == PROTOCOL__FLEX_STATS_REQUEST__BODY_UE_STATS_REQUEST) {
+    free(msg->stats_request_msg->ue_stats_request->rnti);
+  }
+  free(msg->stats_request_msg);
+  free(msg);
+  return 0;
+
+ error:
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_mac_stats_reply(mid_t mod_id,
+				  xid_t xid,
+				  const report_config_t *report_config,
+				  Protocol__FlexranMessage **msg) {
+  Protocol__FlexHeader *header;
+  int i, j, k;
+  int cc_id = 0;
+  int enb_id = mod_id;
+  //eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
+  //UE_list_t *eNB_UE_list=  &eNB->UE_list;
+
+
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REPLY, &header) != 0)
+    goto error;
+
+  Protocol__FlexStatsReply *stats_reply_msg;
+  stats_reply_msg = malloc(sizeof(Protocol__FlexStatsReply));
+  if (stats_reply_msg == NULL)
+    goto error;
+  protocol__flex_stats_reply__init(stats_reply_msg);
+  stats_reply_msg->header = header;
+
+  stats_reply_msg->n_ue_report = report_config->nr_ue;
+  stats_reply_msg->n_cell_report = report_config->nr_cc;
+
+  Protocol__FlexUeStatsReport **ue_report;
+  Protocol__FlexCellStatsReport **cell_report;
+
+
+  /* Allocate memory for list of UE reports */
+  if (report_config->nr_ue > 0) {
+    ue_report = malloc(sizeof(Protocol__FlexUeStatsReport *) * report_config->nr_ue);
+    if (ue_report == NULL)
+      goto error;
+    for (i = 0; i < report_config->nr_ue; i++) {
+      ue_report[i] = malloc(sizeof(Protocol__FlexUeStatsReport));
+      protocol__flex_ue_stats_report__init(ue_report[i]);
+      ue_report[i]->rnti = report_config->ue_report_type[i].ue_rnti;
+      ue_report[i]->has_rnti = 1;
+      ue_report[i]->flags = report_config->ue_report_type[i].ue_report_flags;
+      ue_report[i]->has_flags = 1;
+      /* Check the types of reports that need to be constructed based on flag values */
+
+      /* Check flag for creation of buffer status report */
+      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_BSR) {
+	ue_report[i]->n_bsr = 4;
+	uint32_t *elem;
+	elem = (uint32_t *) malloc(sizeof(uint32_t)*ue_report[i]->n_bsr);
+	if (elem == NULL)
+	  goto error;
+	for (j = 0; j++; j < ue_report[i]->n_bsr) {
+	  // NN: we need to know the cc_id here, consider the first one
+	  elem[j] = flexran_get_ue_bsr (enb_id, i, j); 
+	}
+	ue_report[i]->bsr = elem;
+      }
+
+      /* Check flag for creation of PRH report */
+      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PRH) {
+	ue_report[i]->phr = flexran_get_ue_phr (enb_id, i); // eNB_UE_list->UE_template[UE_PCCID(enb_id,i)][i].phr_info;
+	ue_report[i]->has_phr = 1;
+      }
+
+      /* Check flag for creation of RLC buffer status report */
+      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RLC_BS) {
+	ue_report[i]->n_rlc_report = 3; // Set this to the number of LCs for this UE. This needs to be generalized for for LCs
+	Protocol__FlexRlcBsr ** rlc_reports;
+	rlc_reports = malloc(sizeof(Protocol__FlexRlcBsr *) * ue_report[i]->n_rlc_report);
+	if (rlc_reports == NULL)
+	  goto error;
+
+	// NN: see LAYER2/openair2_proc.c for rlc status
+	for (j = 0; j < ue_report[i]->n_rlc_report; j++) {
+	  rlc_reports[j] = malloc(sizeof(Protocol__FlexRlcBsr));
+	  if (rlc_reports[j] == NULL)
+	    goto error;
+	  protocol__flex_rlc_bsr__init(rlc_reports[j]);
+	  rlc_reports[j]->lc_id = j+1;
+	  rlc_reports[j]->has_lc_id = 1;
+	  rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(enb_id,i,j+1);
+	  rlc_reports[j]->has_tx_queue_size = 1;
+
+	  //TODO:Set tx queue head of line delay in ms
+	  rlc_reports[j]->tx_queue_hol_delay = 100;
+	  rlc_reports[j]->has_tx_queue_hol_delay = 0;
+	  //TODO:Set retransmission queue size in bytes
+	  rlc_reports[j]->retransmission_queue_size = 10;
+	  rlc_reports[j]->has_retransmission_queue_size = 0;
+	  //TODO:Set retransmission queue head of line delay in ms
+	  rlc_reports[j]->retransmission_queue_hol_delay = 100;
+	  rlc_reports[j]->has_retransmission_queue_hol_delay = 0;
+	  //TODO:Set current size of the pending message in bytes
+	  rlc_reports[j]->status_pdu_size = 100;
+	  rlc_reports[j]->has_status_pdu_size = 0;
+	}
+	// Add RLC buffer status reports to the full report
+	if (ue_report[i]->n_rlc_report > 0)
+	  ue_report[i]->rlc_report = rlc_reports;
+      }
+
+      /* Check flag for creation of MAC CE buffer status report */
+      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS) {
+	// TODO: Fill in the actual MAC CE buffer status report
+	ue_report[i]->pending_mac_ces = (flexran_get_MAC_CE_bitmap_TA(enb_id,i,0) | (0 << 1) | (0 << 2) | (0 << 3)) & 15; /* Use as bitmap. Set one or more of the; /* Use as bitmap. Set one or more of the
+					       PROTOCOL__FLEX_CE_TYPE__FLPCET_ values
+					       found in stats_common.pb-c.h. See
+					       flex_ce_type in FlexRAN specification */
+	ue_report[i]->has_pending_mac_ces = 1;
+      }
+
+      /* Check flag for creation of DL CQI report */
+      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
+	// TODO: Fill in the actual DL CQI report for the UE based on its configuration
+	Protocol__FlexDlCqiReport * dl_report;
+	dl_report = malloc(sizeof(Protocol__FlexDlCqiReport));
+	if (dl_report == NULL)
+	  goto error;
+	protocol__flex_dl_cqi_report__init(dl_report);
+
+	dl_report->sfn_sn = flexran_get_sfn_sf(enb_id);
+	dl_report->has_sfn_sn = 1;
+	//Set the number of DL CQI reports for this UE. One for each CC
+	dl_report->n_csi_report = flexran_get_active_CC(enb_id,i);
+
+	//Create the actual CSI reports.
+	Protocol__FlexDlCsi **csi_reports;
+	csi_reports = malloc(sizeof(Protocol__FlexDlCsi *)*dl_report->n_csi_report);
+	if (csi_reports == NULL)
+	  goto error;
+	for (j = 0; j < dl_report->n_csi_report; j++) {
+	  csi_reports[j] = malloc(sizeof(Protocol__FlexDlCsi));
+	  if (csi_reports[j] == NULL)
+	    goto error;
+	  protocol__flex_dl_csi__init(csi_reports[j]);
+	  //The servCellIndex for this report
+	  csi_reports[j]->serv_cell_index = j;
+	  csi_reports[j]->has_serv_cell_index = 1;
+	  //The rank indicator value for this cc
+	  csi_reports[j]->ri = flexran_get_current_RI(enb_id,i,j);
+	  csi_reports[j]->has_ri = 1;
+	  //TODO: the type of CSI report based on the configuration of the UE
+	  //For now we only support type P10, which only needs a wideband value
+	  //The full set of types can be found in stats_common.pb-c.h and
+	  //in the FlexRAN specifications
+    csi_reports[j]->type =  PROTOCOL__FLEX_CSI_TYPE__FLCSIT_P10;
+		  csi_reports[j]->has_type = 1;
+		  csi_reports[j]->report_case = PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI;
+		  if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI){
+			  Protocol__FlexCsiP10 *csi10;
+			  csi10 = malloc(sizeof(Protocol__FlexCsiP10));
+			  if (csi10 == NULL)
+				goto error;
+			  protocol__flex_csi_p10__init(csi10);
+			  //TODO: set the wideband value
+			  // NN: this is also depends on cc_id
+			  csi10->wb_cqi = flexran_get_ue_wcqi (enb_id, i); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].dl_cqi;
+			  csi10->has_wb_cqi = 1;
+			  //Add the type of measurements to the csi report in the proper union type
+			  csi_reports[j]->p10csi = csi10;
+		  }
+		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI){
+
+		  }
+		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI){
+
+		  }
+		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI){
+
+		  }
+		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI){
+
+		  }
+		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI){
+
+		  }
+		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI){
+
+		  }
+		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI){
+
+		  }
+		  else if(csi_reports[j]->report_case == PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI){
+
+		  }
+		}
+	//Add the csi reports to the full DL CQI report
+	dl_report->csi_report = csi_reports;
+	//Add the DL CQI report to the stats report
+	ue_report[i]->dl_cqi_report = dl_report;
+      }
+
+      /* Check flag for creation of paging buffer status report */
+      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
+	//TODO: Fill in the actual paging buffer status report. For this field to be valid, the RNTI
+	//set in the report must be a P-RNTI
+	Protocol__FlexPagingBufferReport *paging_report;
+	paging_report = malloc(sizeof(Protocol__FlexPagingBufferReport));
+	if (paging_report == NULL)
+	  goto error;
+	protocol__flex_paging_buffer_report__init(paging_report);
+	//Set the number of pending paging messages
+	paging_report->n_paging_info = 1;
+	//Provide a report for each pending paging message
+	Protocol__FlexPagingInfo **p_info;
+	p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * paging_report->n_paging_info);
+	if (p_info == NULL)
+	  goto error;
+	for (j = 0; j < paging_report->n_paging_info; j++) {
+	  p_info[j] = malloc(sizeof(Protocol__FlexPagingInfo));
+	  if(p_info[j] == NULL)
+	    goto error;
+	  protocol__flex_paging_info__init(p_info[j]);
+	  //TODO: Set paging index. This index is the same that will be used for the scheduling of the
+	  //paging message by the controller
+	  p_info[j]->paging_index = 10;
+	  p_info[j]->has_paging_index = 0;
+	  //TODO:Set the paging message size
+	  p_info[j]->paging_message_size = 100;
+	  p_info[j]->has_paging_message_size = 0;
+	  //TODO: Set the paging subframe
+	  p_info[j]->paging_subframe = 10;
+	  p_info[j]->has_paging_subframe = 0;
+	  //TODO: Set the carrier index for the pending paging message
+	  p_info[j]->carrier_index = 0;
+	  p_info[j]->has_carrier_index = 0;
+	}
+	//Add all paging info to the paging buffer rerport
+	paging_report->paging_info = p_info;
+	//Add the paging report to the UE report
+	ue_report[i]->pbr = paging_report;
+      }
+
+      /* Check flag for creation of UL CQI report */
+      if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
+	//Fill in the full UL CQI report of the UE
+	Protocol__FlexUlCqiReport *full_ul_report;
+	full_ul_report = malloc(sizeof(Protocol__FlexUlCqiReport));
+	if(full_ul_report == NULL)
+	  goto error;
+	protocol__flex_ul_cqi_report__init(full_ul_report);
+	//TODO:Set the SFN and SF of the generated report
+	full_ul_report->sfn_sn = flexran_get_sfn_sf(enb_id);
+	full_ul_report->has_sfn_sn = 1;
+	//TODO:Set the number of UL measurement reports based on the types of measurements
+	//configured for this UE and on the servCellIndex
+	full_ul_report->n_cqi_meas = 1;
+	Protocol__FlexUlCqi **ul_report;
+	ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas);
+	if(ul_report == NULL)
+	  goto error;
+	//Fill each UL report of the UE for each of the configured report types
+	for(j = 0; j < full_ul_report->n_cqi_meas; j++) {
+	  ul_report[j] = malloc(sizeof(Protocol__FlexUlCqi));
+	  if(ul_report[j] == NULL)
+	  goto error;
+	  protocol__flex_ul_cqi__init(ul_report[j]);
+	  //TODO: Set the type of the UL report. As an example set it to SRS UL report
+	  // See enum flex_ul_cqi_type in FlexRAN specification for more details
+	  ul_report[j]->type = PROTOCOL__FLEX_UL_CQI_TYPE__FLUCT_SRS;
+	  ul_report[j]->has_type = 1;
+	  //TODO:Set the number of SINR measurements based on the report type
+	  //See struct flex_ul_cqi in FlexRAN specification for more details
+	  ul_report[j]->n_sinr = 0;
+	  uint32_t *sinr_meas;
+	  sinr_meas = (uint32_t *) malloc(sizeof(uint32_t) * ul_report[j]->n_sinr);
+	  if (sinr_meas == NULL)
+	    goto error;
+	  //TODO:Set the SINR measurements for the specified type
+	  for (k = 0; k < ul_report[j]->n_sinr; k++) {
+	    sinr_meas[k] = 10;
+	  }
+	  ul_report[j]->sinr = sinr_meas;
+	  //TODO: Set the servCellIndex for this report
+	  ul_report[j]->serv_cell_index = 0;
+	  ul_report[j]->has_serv_cell_index = 1;
+	  
+	  //Set the list of UL reports of this UE to the full UL report
+	  full_ul_report->cqi_meas = ul_report;
+
+	  full_ul_report->n_pucch_dbm = MAX_NUM_CCs;
+	  full_ul_report->pucch_dbm = malloc(sizeof(Protocol__FlexPucchDbm *) * full_ul_report->n_pucch_dbm);
+
+	  for (j = 0; j < MAX_NUM_CCs; j++) {
+	    full_ul_report->pucch_dbm[j] = malloc(sizeof(Protocol__FlexPucchDbm));
+	    protocol__flex_pucch_dbm__init(full_ul_report->pucch_dbm[j]);
+	    full_ul_report->pucch_dbm[j]->has_serv_cell_index = 1;
+	    full_ul_report->pucch_dbm[j]->serv_cell_index = j;
+	    if(flexran_get_p0_pucch_dbm(enb_id,i, j) != -1){
+	      full_ul_report->pucch_dbm[j]->p0_pucch_dbm = flexran_get_p0_pucch_dbm(enb_id,i,j);
+	      full_ul_report->pucch_dbm[j]->has_p0_pucch_dbm = 1;
+	    }
+	  }
+
+	  //Add full UL CQI report to the UE report
+	  ue_report[i]->ul_cqi_report = full_ul_report;
+	}
+      }
+    }
+    /* Add list of all UE reports to the message */
+    stats_reply_msg->ue_report = ue_report;
+  }
+
+  /* Allocate memory for list of cell reports */
+  if (report_config->nr_cc > 0) {
+    cell_report = malloc(sizeof(Protocol__FlexCellStatsReport *) * report_config->nr_cc);
+    if (cell_report == NULL)
+      goto error;
+    // Fill in the Cell reports
+    for (i = 0; i < report_config->nr_cc; i++) {
+      cell_report[i] = malloc(sizeof(Protocol__FlexCellStatsReport));
+      if(cell_report[i] == NULL)
+	goto error;
+      protocol__flex_cell_stats_report__init(cell_report[i]);
+      cell_report[i]->carrier_index = report_config->cc_report_type[i].cc_id;
+      cell_report[i]->has_carrier_index = 1;
+      cell_report[i]->flags = report_config->cc_report_type[i].cc_report_flags;
+      cell_report[i]->has_flags = 1;
+
+      /* Check flag for creation of noise and interference report */
+      if(report_config->cc_report_type[i].cc_report_flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) {
+	// TODO: Fill in the actual noise and interference report for this cell
+	Protocol__FlexNoiseInterferenceReport *ni_report;
+	ni_report = malloc(sizeof(Protocol__FlexNoiseInterferenceReport));
+	if(ni_report == NULL)
+	  goto error;
+	protocol__flex_noise_interference_report__init(ni_report);
+	// Current frame and subframe number
+	ni_report->sfn_sf = flexran_get_sfn_sf(enb_id);
+	ni_report->has_sfn_sf = 1;
+	//TODO:Received interference power in dbm
+	ni_report->rip = 0;
+	ni_report->has_rip = 0;
+	//TODO:Thermal noise power in dbm
+	ni_report->tnp = 0;
+	ni_report->has_tnp = 0;
+
+	ni_report->p0_nominal_pucch = flexran_get_p0_nominal_pucch(enb_id, 0);
+	ni_report->has_p0_nominal_pucch = 1;
+	cell_report[i]->noise_inter_report = ni_report;
+      }
+    }
+    /* Add list of all cell reports to the message */
+    stats_reply_msg->cell_report = cell_report;
+  }
+
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG;
+  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+  (*msg)->stats_reply_msg = stats_reply_msg;
+  return 0;
+
+ error:
+  // TODO: Need to make proper error handling
+  if (header != NULL)
+    free(header);
+  if (stats_reply_msg != NULL)
+    free(stats_reply_msg);
+  if(*msg != NULL)
+    free(*msg);
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_mac_destroy_stats_reply(Protocol__FlexranMessage *msg) {
+  //TODO: Need to deallocate memory for the stats reply message
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG)
+    goto error;
+  free(msg->stats_reply_msg->header);
+  int i, j, k;
+
+  Protocol__FlexStatsReply *reply = msg->stats_reply_msg;
+  Protocol__FlexDlCqiReport *dl_report;
+  Protocol__FlexUlCqiReport *ul_report;
+  Protocol__FlexPagingBufferReport *paging_report;
+
+  // Free the memory for the UE reports
+  for (i = 0; i < reply->n_ue_report; i++) {
+    free(reply->ue_report[i]->bsr);
+    for (j = 0; j < reply->ue_report[i]->n_rlc_report; j++) {
+      free(reply->ue_report[i]->rlc_report[j]);
+    }
+    free(reply->ue_report[i]->rlc_report);
+    // If DL CQI report flag was set
+    if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
+      dl_report = reply->ue_report[i]->dl_cqi_report;
+      // Delete all CSI reports
+      for (j = 0; j < dl_report->n_csi_report; j++) {
+	//Must free memory based on the type of report
+	switch(dl_report->csi_report[j]->report_case) {
+	case PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI:
+	  free(dl_report->csi_report[j]->p10csi);
+	  break;
+	case PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI:
+	  free(dl_report->csi_report[j]->p11csi->wb_cqi);
+	  free(dl_report->csi_report[j]->p11csi);
+	  break;
+	case PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI:
+	  free(dl_report->csi_report[j]->p20csi);
+	  break;
+	case PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI:
+	  free(dl_report->csi_report[j]->p21csi->wb_cqi);
+	  free(dl_report->csi_report[j]->p21csi->sb_cqi);
+	  free(dl_report->csi_report[j]->p21csi);
+	  break;
+	case PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI:
+	  free(dl_report->csi_report[j]->a12csi->wb_cqi);
+	  free(dl_report->csi_report[j]->a12csi->sb_pmi);
+	  free(dl_report->csi_report[j]->a12csi);
+	  break;
+	case PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI:
+	  free(dl_report->csi_report[j]->a22csi->wb_cqi);
+	  free(dl_report->csi_report[j]->a22csi->sb_cqi);
+	  free(dl_report->csi_report[j]->a22csi->sb_list);
+	  free(dl_report->csi_report[j]->a22csi);
+	  break;
+	case PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI:
+	  free(dl_report->csi_report[j]->a20csi->sb_list);
+	  free(dl_report->csi_report[j]->a20csi);
+	  break;
+	case PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI:
+	  free(dl_report->csi_report[j]->a30csi->sb_cqi);
+	  free(dl_report->csi_report[j]->a30csi);
+	  break;
+	case PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI:
+	  free(dl_report->csi_report[j]->a31csi->wb_cqi);
+	  for (k = 0; k < dl_report->csi_report[j]->a31csi->n_sb_cqi; k++) {
+	    free(dl_report->csi_report[j]->a31csi->sb_cqi[k]);
+	  }
+	  free(dl_report->csi_report[j]->a31csi->sb_cqi);
+	  break;
+	}
+
+	free(dl_report->csi_report[j]);
+      }
+      free(dl_report->csi_report);
+      free(dl_report);
+    }
+    // If Paging buffer report flag was set
+    if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
+      paging_report = reply->ue_report[i]->pbr;
+      // Delete all paging buffer reports
+      for (j = 0; j < paging_report->n_paging_info; j++) {
+	free(paging_report->paging_info[j]);
+      }
+      free(paging_report->paging_info);
+      free(paging_report);
+    }
+    // If UL CQI report flag was set
+    if (reply->ue_report[i]->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
+      ul_report = reply->ue_report[i]->ul_cqi_report;
+      for (j = 0; j < ul_report->n_cqi_meas; j++) {
+	free(ul_report->cqi_meas[j]->sinr);
+	free(ul_report->cqi_meas[j]);
+      }
+      free(ul_report->cqi_meas);
+      for (j = 0; j < ul_report->n_pucch_dbm; j++) {
+	free(ul_report->pucch_dbm[j]);
+      }
+      free(ul_report->pucch_dbm);
+    }
+    free(reply->ue_report[i]);
+  }
+  free(reply->ue_report);
+
+  // Free memory for all Cell reports
+  for (i = 0; i < reply->n_cell_report; i++) {
+    free(reply->cell_report[i]->noise_inter_report);
+    free(reply->cell_report[i]);
+  }
+  free(reply->cell_report);
+
+  free(reply);
+  free(msg);
+  return 0;
+
+ error:
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_mac_sr_info(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+  Protocol__FlexHeader *header;
+  int i;
+  const int xid = *((int *)params);
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UL_SR_INFO, &header) != 0)
+    goto error;
+
+  Protocol__FlexUlSrInfo *ul_sr_info_msg;
+  ul_sr_info_msg = malloc(sizeof(Protocol__FlexUlSrInfo));
+  if (ul_sr_info_msg == NULL) {
+    goto error;
+  }
+  protocol__flex_ul_sr_info__init(ul_sr_info_msg);
+
+  ul_sr_info_msg->header = header;
+  ul_sr_info_msg->has_sfn_sf = 1;
+  ul_sr_info_msg->sfn_sf = flexran_get_sfn_sf(mod_id);
+  /*TODO: Set the number of UEs that sent an SR */
+  ul_sr_info_msg->n_rnti = 1;
+  ul_sr_info_msg->rnti = (uint32_t *) malloc(ul_sr_info_msg->n_rnti * sizeof(uint32_t));
+
+  if(ul_sr_info_msg->rnti == NULL) {
+    goto error;
+  }
+  /*TODO:Set the rnti of the UEs that sent an SR */
+  for (i = 0; i < ul_sr_info_msg->n_rnti; i++) {
+    ul_sr_info_msg->rnti[i] = 1;
+  }
+
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG;
+  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+  (*msg)->ul_sr_info_msg = ul_sr_info_msg;
+  return 0;
+
+ error:
+  // TODO: Need to make proper error handling
+  if (header != NULL)
+    free(header);
+  if (ul_sr_info_msg != NULL) {
+    free(ul_sr_info_msg->rnti);
+    free(ul_sr_info_msg);
+  }
+  if(*msg != NULL)
+    free(*msg);
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg) {
+   if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG)
+     goto error;
+
+   free(msg->ul_sr_info_msg->header);
+   free(msg->ul_sr_info_msg->rnti);
+   free(msg->ul_sr_info_msg);
+   free(msg);
+   return 0;
+
+ error:
+   //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+   return -1;
+}
+
+int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+  Protocol__FlexHeader *header;
+  int i,j;
+  const int xid = *((int *)params);
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_SF_TRIGGER, &header) != 0)
+    goto error;
+
+  Protocol__FlexSfTrigger *sf_trigger_msg;
+  sf_trigger_msg = malloc(sizeof(Protocol__FlexSfTrigger));
+  if (sf_trigger_msg == NULL) {
+    goto error;
+  }
+  protocol__flex_sf_trigger__init(sf_trigger_msg);
+
+  frame_t frame;
+  sub_frame_t subframe;
+
+  int ahead_of_time = 1;
+  
+  frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
+  subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
+
+  subframe = ((subframe + ahead_of_time) % 10);
+
+  int full_frames_ahead = ((ahead_of_time / 10) % 10);
+  
+  frame = frame + full_frames_ahead;
+
+  if (subframe < flexran_get_current_subframe(mod_id)) {
+    frame++;
+  }
+
+  sf_trigger_msg->header = header;
+  sf_trigger_msg->has_sfn_sf = 1;
+  sf_trigger_msg->sfn_sf = flexran_get_future_sfn_sf(mod_id, 1);
+
+  /*TODO: Fill in the number of dl HARQ related info, based on the number of currently
+   *transmitting UEs
+   */
+  sf_trigger_msg->n_dl_info = flexran_get_num_ues(mod_id);
+
+  Protocol__FlexDlInfo **dl_info = NULL;
+
+  if (sf_trigger_msg->n_dl_info > 0) {
+    dl_info = malloc(sizeof(Protocol__FlexDlInfo *) * sf_trigger_msg->n_dl_info);
+    if(dl_info == NULL)
+      goto error;
+    //Fill the status of the current HARQ process for each UE
+    for(i = 0; i < sf_trigger_msg->n_dl_info; i++) {
+      dl_info[i] = malloc(sizeof(Protocol__FlexDlInfo));
+      if(dl_info[i] == NULL)
+	goto error;
+      protocol__flex_dl_info__init(dl_info[i]);
+      dl_info[i]->rnti = flexran_get_ue_crnti(mod_id, i);
+      dl_info[i]->has_rnti = 1;
+      /*Fill in the right id of this round's HARQ process for this UE*/
+      int harq_id;
+      int harq_status;
+      flexran_get_harq(mod_id, UE_PCCID(mod_id,i), i, frame, subframe, &harq_id, &harq_status);
+      dl_info[i]->harq_process_id = harq_id;
+      dl_info[i]->has_harq_process_id = 1;
+      /* Fill in the status of the HARQ process (2 TBs)*/
+      dl_info[i]->n_harq_status = 2;
+      dl_info[i]->harq_status = malloc(sizeof(uint32_t) * dl_info[i]->n_harq_status);
+      for (j = 0; j < dl_info[i]->n_harq_status; j++) {
+	// TODO: This should be different per TB
+	if(harq_status == 0)
+	  dl_info[i]->harq_status[j] = PROTOCOL__FLEX_HARQ_STATUS__FLHS_ACK;
+	else if (harq_status > 0)
+	  dl_info[i]->harq_status[j] = PROTOCOL__FLEX_HARQ_STATUS__FLHS_NACK;
+      }
+      /*Fill in the serving cell index for this UE */
+      dl_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
+      dl_info[i]->has_serv_cell_index = 1;
+    }
+  }
+
+  sf_trigger_msg->dl_info = dl_info;
+
+  /* Fill in the number of UL reception status related info, based on the number of currently
+   * transmitting UEs
+   */
+  sf_trigger_msg->n_ul_info = flexran_get_num_ues(mod_id);
+
+  Protocol__FlexUlInfo **ul_info = NULL;
+
+  if (sf_trigger_msg->n_ul_info > 0) {
+    ul_info = malloc(sizeof(Protocol__FlexUlInfo *) * sf_trigger_msg->n_ul_info);
+    if(ul_info == NULL)
+      goto error;
+    //Fill the reception info for each transmitting UE
+    for(i = 0; i < sf_trigger_msg->n_ul_info; i++) {
+      ul_info[i] = malloc(sizeof(Protocol__FlexUlInfo));
+      if(ul_info[i] == NULL)
+	goto error;
+      protocol__flex_ul_info__init(ul_info[i]);
+      ul_info[i]->rnti = flexran_get_ue_crnti(mod_id, i);
+      ul_info[i]->has_rnti = 1;
+      /*Fill in the Tx power control command for this UE (if available)*/
+      if(flexran_get_tpc(mod_id,i) != 1){
+    	  ul_info[i]->tpc = flexran_get_tpc(mod_id,i);
+          ul_info[i]->has_tpc = 1;
+      }
+      else{
+    	  ul_info[i]->tpc = flexran_get_tpc(mod_id,i);
+    	  ul_info[i]->has_tpc = 0;
+      }
+      /*TODO: fill in the amount of data in bytes in the MAC SDU received in this subframe for the
+	given logical channel*/
+      ul_info[i]->n_ul_reception = 0;
+      ul_info[i]->ul_reception = malloc(sizeof(uint32_t) * ul_info[i]->n_ul_reception);
+      for (j = 0; j < ul_info[i]->n_ul_reception; j++) {
+	ul_info[i]->ul_reception[j] = 100;
+      }
+      /*TODO: Fill in the reception status for each UEs data*/
+      ul_info[i]->reception_status = PROTOCOL__FLEX_RECEPTION_STATUS__FLRS_OK;
+      ul_info[i]->has_reception_status = 1;
+      /*Fill in the serving cell index for this UE */
+      ul_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
+      ul_info[i]->has_serv_cell_index = 1;
+    }
+  }
+
+  sf_trigger_msg->ul_info = ul_info;
+
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG;
+  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+  (*msg)->sf_trigger_msg = sf_trigger_msg;
+  return 0;
+
+ error:
+  if (header != NULL)
+    free(header);
+  if (sf_trigger_msg != NULL) {
+    for (i = 0; i < sf_trigger_msg->n_dl_info; i++) {
+      free(sf_trigger_msg->dl_info[i]->harq_status);
+    }
+    free(sf_trigger_msg->dl_info);
+    for (i = 0; i < sf_trigger_msg->n_ul_info; i++) {
+      free(sf_trigger_msg->ul_info[i]->reception_status);
+    }
+    free(sf_trigger_msg->ul_info);
+    free(sf_trigger_msg);
+  }
+  if(*msg != NULL)
+    free(*msg);
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_mac_destroy_sf_trigger(Protocol__FlexranMessage *msg) {
+  int i;
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG)
+    goto error;
+
+  free(msg->sf_trigger_msg->header);
+  for (i = 0; i < msg->sf_trigger_msg->n_dl_info; i++) {
+    free(msg->sf_trigger_msg->dl_info[i]->harq_status);
+    free(msg->sf_trigger_msg->dl_info[i]);
+  }
+  free(msg->sf_trigger_msg->dl_info);
+  for (i = 0; i < msg->sf_trigger_msg->n_ul_info; i++) {
+    free(msg->sf_trigger_msg->ul_info[i]->ul_reception);
+    free(msg->sf_trigger_msg->ul_info[i]);
+  }
+  free(msg->sf_trigger_msg->ul_info);
+  free(msg->sf_trigger_msg);
+  free(msg);
+
+  return 0;
+
+ error:
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_mac_create_empty_dl_config(mid_t mod_id, Protocol__FlexranMessage **msg) {
+
+  int xid = 0;
+  Protocol__FlexHeader *header;
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_DL_MAC_CONFIG, &header) != 0)
+    goto error;
+
+  Protocol__FlexDlMacConfig *dl_mac_config_msg;
+  dl_mac_config_msg = malloc(sizeof(Protocol__FlexDlMacConfig));
+  if (dl_mac_config_msg == NULL) {
+    goto error;
+  }
+  protocol__flex_dl_mac_config__init(dl_mac_config_msg);
+
+  dl_mac_config_msg->header = header;
+  dl_mac_config_msg->has_sfn_sf = 1;
+  dl_mac_config_msg->sfn_sf = flexran_get_sfn_sf(mod_id);
+
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG;
+  (*msg)->msg_dir =  PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+  (*msg)->dl_mac_config_msg = dl_mac_config_msg;
+
+  return 0;
+
+ error:
+  return -1;
+}
+
+int flexran_agent_mac_destroy_dl_config(Protocol__FlexranMessage *msg) {
+  int i,j, k;
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG)
+    goto error;
+
+  Protocol__FlexDlDci *dl_dci;
+
+  free(msg->dl_mac_config_msg->header);
+  for (i = 0; i < msg->dl_mac_config_msg->n_dl_ue_data; i++) {
+    free(msg->dl_mac_config_msg->dl_ue_data[i]->ce_bitmap);
+    for (j = 0; j < msg->dl_mac_config_msg->dl_ue_data[i]->n_rlc_pdu; j++) {
+      for (k = 0; k <  msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->n_rlc_pdu_tb; k++) {
+	free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb[k]);
+      }
+      free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]->rlc_pdu_tb);
+      free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu[j]);
+    }
+    free(msg->dl_mac_config_msg->dl_ue_data[i]->rlc_pdu);
+    dl_dci = msg->dl_mac_config_msg->dl_ue_data[i]->dl_dci;
+    free(dl_dci->tbs_size);
+    free(dl_dci->mcs);
+    free(dl_dci->ndi);
+    free(dl_dci->rv);
+    free(dl_dci);
+    free(msg->dl_mac_config_msg->dl_ue_data[i]);
+  }
+  free(msg->dl_mac_config_msg->dl_ue_data);
+
+  for (i = 0; i <  msg->dl_mac_config_msg->n_dl_rar; i++) {
+    dl_dci = msg->dl_mac_config_msg->dl_rar[i]->rar_dci;
+    free(dl_dci->tbs_size);
+    free(dl_dci->mcs);
+    free(dl_dci->ndi);
+    free(dl_dci->rv);
+    free(dl_dci);
+    free(msg->dl_mac_config_msg->dl_rar[i]);
+  }
+  free(msg->dl_mac_config_msg->dl_rar);
+
+  for (i = 0; i < msg->dl_mac_config_msg->n_dl_broadcast; i++) {
+    dl_dci = msg->dl_mac_config_msg->dl_broadcast[i]->broad_dci;
+    free(dl_dci->tbs_size);
+    free(dl_dci->mcs);
+    free(dl_dci->ndi);
+    free(dl_dci->rv);
+    free(dl_dci);
+    free(msg->dl_mac_config_msg->dl_broadcast[i]);
+  }
+  free(msg->dl_mac_config_msg->dl_broadcast);
+
+    for ( i = 0; i < msg->dl_mac_config_msg->n_ofdm_sym; i++) {
+    free(msg->dl_mac_config_msg->ofdm_sym[i]);
+  }
+  free(msg->dl_mac_config_msg->ofdm_sym);
+  free(msg->dl_mac_config_msg);
+  free(msg);
+
+  return 0;
+
+ error:
+  return -1;
+}
+
+void flexran_agent_get_pending_dl_mac_config(mid_t mod_id, Protocol__FlexranMessage **msg) {
+
+  struct lfds700_misc_prng_state ls;
+  
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+  lfds700_misc_prng_init(&ls);
+  
+  if (lfds700_ringbuffer_read(&ringbuffer_state[mod_id], NULL, (void **) msg, &ls) == 0) {
+    *msg = NULL;
+  }
+}
+
+int flexran_agent_mac_handle_dl_mac_config(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+  struct lfds700_misc_prng_state ls;
+  enum lfds700_misc_flag overwrite_occurred_flag;
+  Protocol__FlexranMessage *overwritten_dl_config;
+   
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+  lfds700_misc_prng_init(&ls);
+  
+  lfds700_ringbuffer_write( &ringbuffer_state[mod_id],
+			    NULL,
+			    (void *) params,
+			    &overwrite_occurred_flag,
+			    NULL,
+			    (void **)&overwritten_dl_config,
+			    &ls);
+
+  if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
+    // Delete unmanaged dl_config
+    flexran_agent_mac_destroy_dl_config(overwritten_dl_config);
+  }
+  *msg = NULL;
+  return 2;
+
+ error:
+  *msg = NULL;
+  return -1;
+}
+
+void flexran_agent_init_mac_agent(mid_t mod_id) {
+  lfds700_misc_library_init_valid_on_current_logical_core();
+  lfds700_misc_prng_init(&ps[mod_id]);
+  int num_elements = RINGBUFFER_SIZE + 1;
+  //Allow RINGBUFFER_SIZE messages to be stored in the ringbuffer at any time
+  dl_mac_config_array[mod_id] = malloc( sizeof(struct lfds700_ringbuffer_element) *  num_elements);
+  lfds700_ringbuffer_init_valid_on_current_logical_core( &ringbuffer_state[mod_id], dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL );
+}
+
+/***********************************************
+ * FlexRAN agent - technology mac API implementation
+ ***********************************************/
+
+void flexran_agent_send_sr_info(mid_t mod_id) {
+  int size;
+  Protocol__FlexranMessage *msg;
+  void *data;
+  int priority;
+  err_code_t err_code;
+
+  int xid = 0;
+
+  /*TODO: Must use a proper xid*/
+  err_code = flexran_agent_mac_sr_info(mod_id, (void *) &xid, &msg);
+  if (err_code < 0) {
+    goto error;
+  }
+
+  if (msg != NULL){
+    data=flexran_agent_pack_message(msg, &size);
+    /*Send sr info using the MAC channel of the eNB*/
+    if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) {
+      err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+      goto error;
+    }
+
+    LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+    return;
+  }
+ error:
+  LOG_D(FLEXRAN_AGENT, "Could not send sr message\n");
+}
+
+void flexran_agent_send_sf_trigger(mid_t mod_id) {
+  int size;
+  Protocol__FlexranMessage *msg;
+  void *data;
+  int priority;
+  err_code_t err_code;
+
+  int xid = 0;
+
+  /*TODO: Must use a proper xid*/
+  err_code = flexran_agent_mac_sf_trigger(mod_id, (void *) &xid, &msg);
+  if (err_code < 0) {
+    goto error;
+  }
+
+  if (msg != NULL){
+    data=flexran_agent_pack_message(msg, &size);
+    /*Send sr info using the MAC channel of the eNB*/
+    if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) {
+      err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+      goto error;
+    }
+
+    LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+    return;
+  }
+ error:
+  LOG_D(FLEXRAN_AGENT, "Could not send sf trigger message\n");
+}
+
+void flexran_agent_send_update_mac_stats(mid_t mod_id) {
+
+  Protocol__FlexranMessage *current_report = NULL, *msg;
+  void *data;
+  int size;
+  err_code_t err_code;
+  int priority;
+
+  mac_stats_updates_context_t stats_context = mac_stats_context[mod_id];
+  
+  if (pthread_mutex_lock(mac_stats_context[mod_id].mutex)) {
+    goto error;
+  }
+
+  if (mac_stats_context[mod_id].cont_update == 1) {
+  
+    /*Create a fresh report with the required flags*/
+    err_code = flexran_agent_mac_handle_stats(mod_id, (void *) mac_stats_context[mod_id].stats_req, &current_report);
+    if (err_code < 0) {
+      goto error;
+    }
+  }
+  /* /\*TODO:Check if a previous reports exists and if yes, generate a report */
+  /*  *that is the diff between the old and the new report, */
+  /*  *respecting the thresholds. Otherwise send the new report*\/ */
+  /* if (mac_stats_context[mod_id].prev_stats_reply != NULL) { */
+
+  /*   msg = flexran_agent_generate_diff_mac_stats_report(current_report, mac_stats_context[mod_id].prev_stats_reply); */
+
+  /*   /\*Destroy the old stats*\/ */
+  /*    flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].prev_stats_reply); */
+  /* } */
+  /* /\*Use the current report for future comparissons*\/ */
+  /* mac_stats_context[mod_id].prev_stats_reply = current_report; */
+
+
+  if (pthread_mutex_unlock(mac_stats_context[mod_id].mutex)) {
+    goto error;
+  }
+
+  if (current_report != NULL){
+    data=flexran_agent_pack_message(current_report, &size);
+    /*Send any stats updates using the MAC channel of the eNB*/
+    if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_MAC, data, size, priority)) {
+      err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+      goto error;
+    }
+
+    LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+    return;
+  }
+ error:
+  LOG_D(FLEXRAN_AGENT, "Could not send sf trigger message\n");
+}
+
+int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) {
+  if (mac_agent_registered[mod_id]) {
+    LOG_E(MAC, "MAC agent for eNB %d is already registered\n", mod_id);
+    return -1;
+  }
+
+  //xface->agent_ctxt = &shared_ctxt[mod_id];
+  xface->flexran_agent_send_sr_info = flexran_agent_send_sr_info;
+  xface->flexran_agent_send_sf_trigger = flexran_agent_send_sf_trigger;
+  xface->flexran_agent_send_update_mac_stats = flexran_agent_send_update_mac_stats;
+  xface->flexran_agent_schedule_ue_spec = flexran_schedule_ue_spec_default;
+  //xface->flexran_agent_schedule_ue_spec = flexran_schedule_ue_spec_remote;
+  xface->flexran_agent_get_pending_dl_mac_config = flexran_agent_get_pending_dl_mac_config;
+  xface->flexran_agent_notify_ue_state_change = flexran_agent_ue_state_change;
+  
+  xface->dl_scheduler_loaded_lib = NULL;
+
+  mac_agent_registered[mod_id] = 1;
+  agent_mac_xface[mod_id] = xface;
+
+  return 0;
+}
+
+int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) {
+
+  //xface->agent_ctxt = NULL;
+  xface->flexran_agent_send_sr_info = NULL;
+  xface->flexran_agent_send_sf_trigger = NULL;
+  xface->flexran_agent_send_update_mac_stats = NULL;
+  xface->flexran_agent_schedule_ue_spec = NULL;
+  xface->flexran_agent_get_pending_dl_mac_config = NULL;
+  xface->flexran_agent_notify_ue_state_change = NULL;
+
+  xface->dl_scheduler_loaded_lib = NULL;
+
+  mac_agent_registered[mod_id] = 0;
+  agent_mac_xface[mod_id] = NULL;
+
+  return 0;
+}
+
+
+/******************************************************
+ *Implementations of flexran_agent_mac_internal.h functions
+ ******************************************************/
+
+err_code_t flexran_agent_init_cont_mac_stats_update(mid_t mod_id) {
+
+  /*Initialize the Mac stats update structure*/
+  /*Initially the continuous update is set to false*/
+  mac_stats_context[mod_id].cont_update = 0;
+  mac_stats_context[mod_id].is_initialized = 1;
+  mac_stats_context[mod_id].stats_req = NULL;
+  mac_stats_context[mod_id].prev_stats_reply = NULL;
+  mac_stats_context[mod_id].mutex = calloc(1, sizeof(pthread_mutex_t));
+  if (mac_stats_context[mod_id].mutex == NULL)
+    goto error;
+  if (pthread_mutex_init(mac_stats_context[mod_id].mutex, NULL))
+    goto error;;
+
+  return 0;
+
+ error:
+  return -1;
+}
+
+err_code_t flexran_agent_destroy_cont_mac_stats_update(mid_t mod_id) {
+  /*Disable the continuous updates for the MAC*/
+  mac_stats_context[mod_id].cont_update = 0;
+  mac_stats_context[mod_id].is_initialized = 0;
+  flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].stats_req);
+  flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].prev_stats_reply);
+  free(mac_stats_context[mod_id].mutex);
+
+  mac_agent_registered[mod_id] = NULL;
+  return 1;
+}
+
+
+err_code_t flexran_agent_enable_cont_mac_stats_update(mid_t mod_id,
+						      xid_t xid, stats_request_config_t *stats_req) {
+  /*Enable the continuous updates for the MAC*/
+  if (pthread_mutex_lock(mac_stats_context[mod_id].mutex)) {
+    goto error;
+  }
+
+  Protocol__FlexranMessage *req_msg;
+
+  flexran_agent_mac_stats_request(mod_id, xid, stats_req, &req_msg);
+  mac_stats_context[mod_id].stats_req = req_msg;
+  mac_stats_context[mod_id].prev_stats_reply = NULL;
+
+  mac_stats_context[mod_id].cont_update = 1;
+  mac_stats_context[mod_id].xid = xid;
+
+  if (pthread_mutex_unlock(mac_stats_context[mod_id].mutex)) {
+    goto error;
+  }
+  return 0;
+
+ error:
+  LOG_E(FLEXRAN_AGENT, "mac_stats_context for eNB %d is not initialized\n", mod_id);
+  return -1;
+}
+
+err_code_t flexran_agent_disable_cont_mac_stats_update(mid_t mod_id) {
+  /*Disable the continuous updates for the MAC*/
+  if (pthread_mutex_lock(mac_stats_context[mod_id].mutex)) {
+    goto error;
+  }
+  mac_stats_context[mod_id].cont_update = 0;
+  mac_stats_context[mod_id].xid = 0;
+  if (mac_stats_context[mod_id].stats_req != NULL) {
+    flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].stats_req);
+  }
+  if (mac_stats_context[mod_id].prev_stats_reply != NULL) {
+    flexran_agent_destroy_flexran_message(mac_stats_context[mod_id].prev_stats_reply);
+  }
+  if (pthread_mutex_unlock(mac_stats_context[mod_id].mutex)) {
+    goto error;
+  }
+  return 0;
+
+ error:
+  LOG_E(FLEXRAN_AGENT, "mac_stats_context for eNB %d is not initialized\n", mod_id);
+  return -1;
+
+}
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2378e93119264517ab2a1c2815e3eddb242d918
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h
@@ -0,0 +1,122 @@
+/*
+ * 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.0  (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 flexran_agent_mac.h
+ * \brief FlexRAN agent message handler APIs for MAC layer
+ * \author  Xenofon Foukas, Mohamed Kassem and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_MAC_H_
+#define FLEXRAN_AGENT_MAC_H_
+
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+#include "stats_messages.pb-c.h"
+#include "stats_common.pb-c.h"
+
+#include "flexran_agent_common.h"
+#include "flexran_agent_extern.h"
+
+/* These types will be used to give
+   instructions for the type of stats reports
+   we need to create */
+typedef struct {
+  uint16_t ue_rnti;
+  uint32_t ue_report_flags; /* Indicates the report elements
+			       required for this UE id. See
+			       FlexRAN specification 1.2.4.2 */
+} ue_report_type_t;
+
+typedef struct {
+  uint16_t cc_id;
+  uint32_t cc_report_flags; /* Indicates the report elements
+			      required for this CC index. See
+			      FlexRAN specification 1.2.4.3 */
+} cc_report_type_t;
+
+typedef struct {
+  int nr_ue;
+  ue_report_type_t *ue_report_type;
+  int nr_cc;
+  cc_report_type_t *cc_report_type;
+} report_config_t;
+
+typedef struct stats_request_config_s{
+  uint8_t report_type;
+  uint8_t report_frequency;
+  uint16_t period; /*In number of subframes*/
+  report_config_t *config;
+} stats_request_config_t;
+
+/* Initialization function for the agent structures etc */
+void flexran_agent_init_mac_agent(mid_t mod_id);
+
+int flexran_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+
+/* Statistics request protocol message constructor and destructor */
+int flexran_agent_mac_stats_request(mid_t mod_id, xid_t xid, const stats_request_config_t *report_config, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_stats_request(Protocol__FlexranMessage *msg);
+
+/* Statistics reply protocol message constructor and destructor */
+int flexran_agent_mac_stats_reply(mid_t mod_id, xid_t xid, const report_config_t *report_config, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_stats_reply(Protocol__FlexranMessage *msg);
+
+/* Scheduling request information protocol message constructor and estructor */
+int flexran_agent_mac_sr_info(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg);
+
+/* Subframe trigger protocol msssage constructor and destructor */
+int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_sf_trigger(Protocol__FlexranMessage *msg);
+
+/* DL MAC scheduling decision protocol message constructor (empty command) and destructor */ 
+int flexran_agent_mac_create_empty_dl_config(mid_t mod_id, Protocol__FlexranMessage **msg);
+int flexran_agent_mac_destroy_dl_config(Protocol__FlexranMessage *msg);
+
+int flexran_agent_mac_handle_dl_mac_config(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+
+
+/**********************************
+ * FlexRAN agent - technology mac API
+ **********************************/
+
+/*Inform controller about received scheduling requests during a subframe*/
+void flexran_agent_send_sr_info(mid_t mod_id);
+
+/*Inform the controller about the current UL/DL subframe*/
+void flexran_agent_send_sf_trigger(mid_t mod_id);
+
+/// Send to the controller all the mac stat updates that occured during this subframe
+/// based on the stats request configuration
+void flexran_agent_send_update_mac_stats(mid_t mod_id);
+
+/// Provide to the scheduler a pending dl_mac_config message
+void flexran_agent_get_pending_dl_mac_config(mid_t mod_id, Protocol__FlexranMessage **msg);
+
+/*Register technology specific interface callbacks*/
+int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface);
+
+/*Unregister technology specific callbacks*/
+int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface*xface);
+
+#endif
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..bb6aed1d8e9fadda1a37339fa993635b39de7956
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_defs.h
@@ -0,0 +1,75 @@
+/*
+ * 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.0  (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 flexran_agent_mac_defs.h
+ * \brief FlexRAN agent - mac interface primitives
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ * \mail x.foukas@sms.ed.ac.uk
+ */
+
+#ifndef __FLEXRAN_AGENT_MAC_PRIMITIVES_H__
+#define __FLEXRAN_AGENT_MAC_PRIMITIVES_H__
+
+#include "flexran_agent_defs.h"
+#include "flexran.pb-c.h"
+#include "header.pb-c.h"
+
+#define RINGBUFFER_SIZE 100
+
+/* FLEXRAN AGENT-MAC Interface */
+typedef struct {
+  //msg_context_t *agent_ctxt;
+
+  /// Inform the controller about the scheduling requests received during the subframe
+  void (*flexran_agent_send_sr_info)(mid_t mod_id);
+  
+  /// Inform the controller about the current UL/DL subframe
+  void (*flexran_agent_send_sf_trigger)(mid_t mod_id);
+
+  /// Send to the controller all the mac stat updates that occured during this subframe
+  /// based on the stats request configuration
+  void (*flexran_agent_send_update_mac_stats)(mid_t mod_id);
+
+  /// Provide to the scheduler a pending dl_mac_config message
+  void (*flexran_agent_get_pending_dl_mac_config)(mid_t mod_id,
+						  Protocol__FlexranMessage **msg);
+  
+  /// Run the UE DL scheduler and fill the Protocol__FlexranMessage. Assumes that
+  /// dl_info is already initialized as flex_dl_mac_config and fills the
+  /// flex_dl_data part of it
+  void (*flexran_agent_schedule_ue_spec)(mid_t mod_id, uint32_t frame, uint32_t subframe,
+					 int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
+  
+
+  /// Notify the controller for a state change of a particular UE, by sending the proper
+  /// UE state change message (ACTIVATION, DEACTIVATION, HANDOVER)
+  void (*flexran_agent_notify_ue_state_change)(mid_t mod_id, uint32_t rnti,
+					       uint32_t state_change);
+  
+  
+  void *dl_scheduler_loaded_lib;
+  /*TODO: Fill in with the rest of the MAC layer technology specific callbacks (UL/DL scheduling, RACH info etc)*/
+
+} AGENT_MAC_xface;
+
+#endif
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..a63225e657cc725f42124ccf60fcfafb228c7f45
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
@@ -0,0 +1,794 @@
+/*
+ * 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.0  (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 flexran_agent_mac_internal.c
+ * \brief Helper functions for the MAC agent
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#include <string.h>
+#include <dlfcn.h>
+
+#include "flexran_agent_mac_internal.h"
+
+Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
+									Protocol__FlexranMessage *old_message) {
+
+  int i, j;
+  
+  Protocol__FlexStatsReply *old_report, *new_report;
+
+  Protocol__FlexStatsReply *stats_reply_msg = NULL;
+  Protocol__FlexranMessage *msg = NULL;
+  
+  Protocol__FlexUeStatsReport **ue_report;
+  Protocol__FlexUeStatsReport *tmp_ue_report[NUM_MAX_UE];
+  Protocol__FlexCellStatsReport **cell_report;
+  Protocol__FlexCellStatsReport *tmp_cell_report[NUM_MAX_UE];
+  
+  old_report = old_message->stats_reply_msg;
+  new_report = new_message->stats_reply_msg;
+
+  /*Flags to designate changes in various levels of the message*/
+  int stats_had_changes = 0;
+  int ue_had_change = 0;
+  int cell_had_change = 0;
+
+  /*See how many and which UE reports should be included in the final stats message*/
+  int n_ue_report = 0;
+  int ue_found = 0;
+  
+  /*Go through each RNTI of the new report and see if it exists in the old one*/
+  for (i = 0; i < new_report->n_ue_report; i++) {
+    for (j = 0; j < old_report->n_ue_report; i++) {
+     if (new_report->ue_report[i]->rnti == old_report->ue_report[j]->rnti) {
+  	ue_found = 1;
+	/*Need to check if something changed*/
+	if (compare_ue_stats_reports(new_report->ue_report[i], old_report->ue_report[j]) != 0) {
+	  tmp_ue_report[n_ue_report] = copy_ue_stats_report(new_report->ue_report[i]);
+	  n_ue_report++;
+	}
+	break;
+     }
+    }
+    if (!ue_found) {
+      tmp_ue_report[n_ue_report] = copy_ue_stats_report(new_report->ue_report[i]);
+      n_ue_report++;
+    }
+    ue_found = 0;
+  }
+
+  /*See how many and which cell reports should be included in the final stats message*/
+  int n_cell_report = 0;
+  int cell_found = 0;
+  
+  /*Go through each cell of the new report and see if it exists in the old one*/
+  for (i = 0; i < new_report->n_cell_report; i++) {
+    for (j = 0; j < old_report->n_cell_report; i++) {
+     if (new_report->cell_report[i]->carrier_index == old_report->cell_report[j]->carrier_index) {
+  	cell_found = 1;
+	/*Need to check if something changed*/
+	if (compare_cell_stats_reports(new_report->cell_report[i], old_report->cell_report[j]) != 0) {
+	  tmp_cell_report[n_cell_report] = copy_cell_stats_report(new_report->cell_report[i]);
+	  n_cell_report++;
+	}
+	break;
+     }
+    }
+    if (!cell_found) {
+      tmp_cell_report[n_cell_report] = copy_cell_stats_report(new_report->cell_report[i]);
+      n_cell_report++;
+    }
+    cell_found = 0;
+  }
+
+  /*TODO: create the reply message based on the findings*/
+  /*Create ue report list*/
+  if (n_ue_report > 0) {
+    ue_report = malloc(sizeof(Protocol__FlexUeStatsReport *));
+    for (i = 0; i<n_ue_report; i++) {
+      ue_report[i] = tmp_ue_report[i];
+    }
+  }
+
+  /*Create cell report list*/
+  if (n_cell_report > 0) {
+    cell_report = malloc(sizeof(Protocol__FlexCellStatsReport *));
+    for (i = 0; i<n_cell_report; i++) {
+      cell_report[i] = tmp_cell_report[i];
+    }
+  }
+  
+  if (n_cell_report > 0 || n_ue_report > 0) {
+    /*Create header*/
+    int xid = old_report->header->xid;
+    Protocol__FlexHeader *header;
+    if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REPLY, &header) != 0) {
+    goto error;
+    }
+    stats_reply_msg = malloc(sizeof(Protocol__FlexStatsReply));
+    protocol__flex_stats_reply__init(stats_reply_msg);
+    stats_reply_msg->header = header;
+    stats_reply_msg->n_ue_report = n_ue_report;
+    stats_reply_msg->ue_report = ue_report;
+    stats_reply_msg->n_cell_report = n_cell_report;
+    stats_reply_msg->cell_report = cell_report;
+    msg = malloc(sizeof(Protocol__FlexranMessage));
+    if(msg == NULL)
+      goto error;
+    protocol__flexran_message__init(msg);
+    msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG;
+    msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+    msg->stats_reply_msg = stats_reply_msg;
+  }
+  return msg;
+  
+ error:
+   return NULL;
+}
+
+int compare_ue_stats_reports(Protocol__FlexUeStatsReport *rep1,
+			    Protocol__FlexUeStatsReport *rep2) {
+  return 1;
+}
+
+int compare_cell_stats_reports(Protocol__FlexCellStatsReport *rep1,
+			      Protocol__FlexCellStatsReport *rep2) {
+  return 1;
+}
+
+Protocol__FlexUeStatsReport * copy_ue_stats_report(Protocol__FlexUeStatsReport * original) {
+  int i;
+  Protocol__FlexUeStatsReport *copy =  malloc(sizeof(Protocol__FlexUeStatsReport));
+  if (copy == NULL)
+    goto error;
+  protocol__flex_ue_stats_report__init(copy);
+  copy->rnti = original->rnti;
+  copy->has_rnti = original->has_rnti;
+  copy->flags = original->flags;
+  copy->has_flags = original->has_flags;
+  
+  if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_BSR) {
+    copy->n_bsr = original->n_bsr;
+    if (copy->n_bsr > 0) {
+      uint32_t *elem;
+      elem = (uint32_t *) malloc(sizeof(uint32_t)*copy->n_bsr);
+      if (elem == NULL)
+	goto error;
+      for (i = 0; i < original->n_bsr; i++) {
+	elem[i] = original->bsr[i];
+      }
+      copy->bsr = elem;
+    }
+  }
+
+  if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PRH) {
+    copy->has_phr = original->has_phr;
+    copy->phr = original->phr;
+  }
+
+  if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RLC_BS) {
+    copy->n_rlc_report = original->n_rlc_report; 
+    if (copy->n_rlc_report > 0) {
+      Protocol__FlexRlcBsr ** rlc_reports;
+      rlc_reports = malloc(sizeof(Protocol__FlexRlcBsr) * copy->n_rlc_report);
+      if (rlc_reports == NULL)
+	goto error;
+      for (i = 0; i < copy->n_rlc_report; i++) {
+	rlc_reports[i] = copy_rlc_report(original->rlc_report[i]);
+      }
+      copy->rlc_report = rlc_reports;
+    }
+  }
+
+  if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS) {
+    copy->has_pending_mac_ces = original->has_pending_mac_ces;
+    copy->pending_mac_ces = original->pending_mac_ces;
+  
+  }
+  
+  if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
+    copy->dl_cqi_report = copy_dl_cqi_report(original->dl_cqi_report);
+  }
+
+  if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {  
+    /*Copy the Paging Buffer report*/
+    copy->pbr = copy_paging_buffer_report(original->pbr);
+  }
+
+  if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
+    /*TODO: Copy the UL report*/  
+    copy->ul_cqi_report = copy_ul_cqi_report(original->ul_cqi_report);
+  }
+
+  return copy;
+
+ error:
+  return NULL;
+}
+
+Protocol__FlexRlcBsr * copy_rlc_report(Protocol__FlexRlcBsr * original) {
+  Protocol__FlexRlcBsr * copy = malloc(sizeof(Protocol__FlexRlcBsr));
+  if (copy == NULL)
+    goto error;
+  protocol__flex_rlc_bsr__init(copy);
+  copy->lc_id = original->lc_id;
+  copy->has_lc_id = original->has_lc_id;
+  copy->tx_queue_size = original->tx_queue_size;
+  copy->has_tx_queue_size = original->has_tx_queue_size;
+  copy->tx_queue_hol_delay = original->tx_queue_hol_delay;
+  copy->has_tx_queue_hol_delay = original->has_tx_queue_hol_delay;
+  copy->retransmission_queue_size = original->retransmission_queue_size;
+  copy->has_retransmission_queue_size = original->has_retransmission_queue_size;
+  copy->retransmission_queue_hol_delay = original->retransmission_queue_hol_delay;
+  copy->has_retransmission_queue_hol_delay = original->has_retransmission_queue_hol_delay;
+  copy->status_pdu_size = original->status_pdu_size;
+  copy->has_status_pdu_size = original->has_status_pdu_size;
+  
+  return copy;
+
+ error:
+  return NULL;
+}
+
+Protocol__FlexUlCqiReport * copy_ul_cqi_report(Protocol__FlexUlCqiReport * original) {
+  int i, j;
+  
+  //Fill in the full UL CQI report of the UE
+  Protocol__FlexUlCqiReport *full_ul_report;
+  full_ul_report = malloc(sizeof(Protocol__FlexUlCqiReport));
+  if(full_ul_report == NULL) {
+    goto error;
+  }
+  protocol__flex_ul_cqi_report__init(full_ul_report);
+  //TODO:Set the SFN and SF of the generated report
+  full_ul_report->sfn_sn = original->sfn_sn;
+  full_ul_report->has_sfn_sn = original->has_sfn_sn;
+  full_ul_report->n_cqi_meas = original->n_cqi_meas;
+
+  Protocol__FlexUlCqi **ul_report;
+  ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas);
+  if(ul_report == NULL)
+    goto error;
+  for(i = 0; i++; i < full_ul_report->n_cqi_meas) {
+    ul_report[i] = malloc(sizeof(Protocol__FlexUlCqi));
+    if(ul_report[i] == NULL)
+      goto error;
+    protocol__flex_ul_cqi__init(ul_report[i]);
+    ul_report[i]->type = original->cqi_meas[i]->type;
+    ul_report[i]->has_type = original->cqi_meas[i]->has_type;
+    ul_report[i]->n_sinr = original->cqi_meas[i]->n_sinr;
+    uint32_t *sinr_meas;
+    sinr_meas = (uint32_t *) malloc(sizeof(uint32_t) * ul_report[i]->n_sinr);
+    if (sinr_meas == NULL)
+      goto error;
+    for (j = 0; j < ul_report[i]->n_sinr; j++) {
+      sinr_meas[j] = original->cqi_meas[i]->sinr[j];
+    }
+    ul_report[i]->sinr = sinr_meas;
+    ul_report[i]->serv_cell_index = original->cqi_meas[i]->serv_cell_index;
+    ul_report[i]->has_serv_cell_index = original->cqi_meas[i]->has_serv_cell_index;
+  }
+  full_ul_report->cqi_meas = ul_report;
+
+  return full_ul_report;
+  
+  error:
+    return NULL;
+}
+
+Protocol__FlexDlCqiReport * copy_dl_cqi_report(Protocol__FlexDlCqiReport * original) {
+  int i;
+  /*Copy the DL report*/
+  Protocol__FlexDlCqiReport * dl_report;
+  dl_report = malloc(sizeof(Protocol__FlexDlCqiReport));
+  if (dl_report == NULL)
+    goto error;
+  protocol__flex_dl_cqi_report__init(dl_report);
+
+  dl_report->sfn_sn = original->sfn_sn;
+  dl_report->has_sfn_sn = original->has_sfn_sn;
+  dl_report->n_csi_report = original->n_csi_report;
+
+  Protocol__FlexDlCsi **csi_reports;
+  csi_reports = malloc(sizeof(Protocol__FlexDlCsi *) * dl_report->n_csi_report);
+  if (csi_reports == NULL)
+    goto error;
+  
+  for (i = 0; i < dl_report->n_csi_report; i++) {
+    csi_reports[i] = copy_csi_report(original->csi_report[i]); 
+  }
+  dl_report->csi_report = csi_reports;
+  return dl_report;
+
+ error:
+  /*TODO: Must free memory properly*/
+  return NULL;
+}
+
+Protocol__FlexPagingBufferReport * copy_paging_buffer_report(Protocol__FlexPagingBufferReport *original) {
+  
+  int i;
+  Protocol__FlexPagingBufferReport *copy;
+  copy = malloc(sizeof(Protocol__FlexPagingBufferReport));
+  if (copy == NULL)
+    goto error;
+  
+  protocol__flex_paging_buffer_report__init(copy);
+  copy->n_paging_info = original->n_paging_info;
+  
+  Protocol__FlexPagingInfo **p_info;
+  p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * copy->n_paging_info);
+  if (p_info == NULL)
+    goto error;
+  for (i = 0; i < copy->n_paging_info; i++) {
+    p_info[i] = malloc(sizeof(Protocol__FlexPagingInfo));
+    if(p_info[i] == NULL)
+      goto error;
+    protocol__flex_paging_info__init(p_info[i]);
+    p_info[i]->paging_index = original->paging_info[i]->paging_index;
+    p_info[i]->has_paging_index = original->paging_info[i]->has_paging_index;;
+    p_info[i]->paging_message_size = original->paging_info[i]->paging_message_size;
+    p_info[i]->has_paging_message_size =  original->paging_info[i]->has_paging_message_size;
+    p_info[i]->paging_subframe = original->paging_info[i]->paging_subframe;
+    p_info[i]->has_paging_subframe = original->paging_info[i]->has_paging_subframe;
+    p_info[i]->carrier_index = original->paging_info[i]->carrier_index;
+    p_info[i]->has_carrier_index = original->paging_info[i]->has_carrier_index;
+  }
+  copy->paging_info = p_info;
+  return copy;
+
+ error:
+  /*TODO: free memory properly*/
+  return NULL;
+}
+
+Protocol__FlexDlCsi * copy_csi_report(Protocol__FlexDlCsi * original) {
+  int i, j;
+  Protocol__FlexDlCsi *copy = malloc(sizeof(Protocol__FlexDlCsi));
+  if (copy == NULL)
+    goto error;
+  protocol__flex_dl_csi__init(copy);
+  copy->serv_cell_index = original->serv_cell_index;
+  copy->has_serv_cell_index = original->has_serv_cell_index;
+  copy->ri = original->ri;
+  copy->has_ri = original->ri;
+
+  copy->type = original->type;
+  copy->has_type = original->has_type;
+  copy->report_case = original->report_case;
+  
+  switch (copy->report_case) {
+  case PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI:
+    copy->p10csi->wb_cqi = original->p10csi->wb_cqi;
+    copy->p10csi->has_wb_cqi = original->p10csi->has_wb_cqi;
+    break;
+  case PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI:
+    copy->p11csi->n_wb_cqi = original->p11csi->n_wb_cqi;
+    copy->p11csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->p11csi->n_wb_cqi);
+    for (i = 0; i < copy->p11csi->n_wb_cqi; i++) {
+      copy->p11csi->wb_cqi[i] = original->p11csi->wb_cqi[i];
+    }
+    copy->p11csi->has_wb_pmi = original->p11csi->has_wb_pmi;
+    copy->p11csi->wb_pmi = original->p11csi->wb_pmi;
+    break;
+  case PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI:
+    copy->p20csi->has_wb_cqi = original->p20csi->has_wb_cqi;
+    copy->p20csi->wb_cqi = original->p20csi->wb_cqi;
+    copy->p20csi->has_sb_cqi = original->p20csi->has_sb_cqi;
+    copy->p20csi->sb_cqi = original->p20csi->sb_cqi;
+    copy->p20csi->has_bandwidth_part_index = original->p20csi->has_bandwidth_part_index;
+    copy->p20csi->bandwidth_part_index = original->p20csi->bandwidth_part_index;
+    copy->p20csi->has_sb_index = original->p20csi->has_sb_index;
+    copy->p20csi->sb_index = original->p20csi->sb_index;
+    break;
+  case PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI:
+    copy->p21csi->n_wb_cqi = original->p21csi->n_wb_cqi;
+    copy->p21csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->p21csi->n_wb_cqi);
+    for (i = 0; i < copy->p21csi->n_wb_cqi; i++) {
+      copy->p21csi->wb_cqi[i] = original->p21csi->wb_cqi[i];
+    }
+    copy->p21csi->has_wb_pmi = original->p21csi->has_wb_pmi;
+    copy->p21csi->wb_pmi = original->p21csi->wb_pmi;
+    copy->p21csi->n_sb_cqi = original->p21csi->n_sb_cqi;
+    copy->p21csi->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->p21csi->n_sb_cqi);
+    for (i = 0; i < copy->p21csi->n_sb_cqi; i++) {
+      copy->p21csi->sb_cqi[i] = original->p21csi->sb_cqi[i];
+    }
+     copy->p21csi->has_badwidth_part_index = original->p21csi->has_badwidth_part_index;
+    copy->p21csi->badwidth_part_index = original->p21csi->badwidth_part_index;
+    copy->p21csi->has_sb_index = original->p21csi->has_sb_index;
+    copy->p21csi->sb_index = original->p21csi->sb_index;
+    break;
+  case PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI:
+    copy->a12csi->n_wb_cqi = original->a12csi->n_wb_cqi;
+    copy->a12csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a12csi->n_wb_cqi);
+    for (i = 0; i < copy->a12csi->n_wb_cqi; i++) {
+      copy->a12csi->wb_cqi[i] = original->a12csi->wb_cqi[i];
+    }
+    copy->a12csi->n_sb_pmi = original->a12csi->n_sb_pmi;
+    copy->a12csi->sb_pmi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a12csi->n_sb_pmi);
+    for (i = 0; i < copy->a12csi->n_sb_pmi; i++) {
+      copy->a12csi->sb_pmi[i] = original->a12csi->sb_pmi[i];
+    }
+    break;
+  case PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI:
+    copy->a22csi->n_wb_cqi = original->a22csi->n_wb_cqi;
+    copy->a22csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a22csi->n_wb_cqi);
+    for (i = 0; i < copy->a22csi->n_wb_cqi; i++) {
+      copy->a22csi->wb_cqi[i] = original->a22csi->wb_cqi[i];
+    }
+    copy->a22csi->n_sb_cqi = original->a22csi->n_sb_cqi;
+    copy->a22csi->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a22csi->n_sb_cqi);
+    for (i = 0; i < copy->a22csi->n_sb_cqi; i++) {
+      copy->a22csi->sb_cqi[i] = original->a22csi->sb_cqi[i];
+    }
+    copy->a22csi->has_wb_pmi = original->a22csi->has_wb_pmi;
+    copy->a22csi->wb_pmi = original->a22csi->wb_pmi;
+    copy->a22csi->has_sb_pmi = original->a22csi->has_sb_pmi;
+    copy->a22csi->sb_pmi = original->a22csi->sb_pmi;
+    copy->a22csi->n_sb_list = original->a22csi->n_sb_list;
+    copy->a22csi->sb_list = (uint32_t *) malloc(sizeof(uint32_t) * copy->a22csi->n_sb_list);
+    for (i = 0; i < copy->a22csi->n_sb_list; i++) {
+      copy->a22csi->sb_list[i] = original->a22csi->sb_list[i];
+    }
+    break;
+  case PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI:
+    copy->a20csi->has_wb_cqi = original->a20csi->has_wb_cqi;
+    copy->a20csi->wb_cqi = original->a20csi->wb_cqi;
+    copy->a20csi->has_sb_cqi = original->a20csi->has_sb_cqi;
+    copy->a20csi->sb_cqi = original->a20csi->sb_cqi;
+    copy->a20csi->n_sb_list = original->a20csi->n_sb_list;
+    copy->a20csi->sb_list = (uint32_t *) malloc(sizeof(uint32_t) * copy->a20csi->n_sb_list);
+    for (i = 0; i < copy->a20csi->n_sb_list; i++) {
+      copy->a20csi->sb_list[i] = original->a20csi->sb_list[i];
+    }
+    break;
+  case PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI:
+    copy->a30csi->has_wb_cqi = original->a30csi->has_wb_cqi;
+    copy->a30csi->wb_cqi = original->a30csi->wb_cqi;
+    copy->a30csi->n_sb_cqi = original->a30csi->n_sb_cqi;
+    copy->a30csi->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a30csi->n_sb_cqi);
+    for (i = 0; i < copy->a30csi->n_sb_cqi; i++) {
+      copy->a30csi->sb_cqi[i] = original->a30csi->sb_cqi[i];
+    }
+    break;
+  case PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI:
+    copy->a31csi->n_wb_cqi = original->a31csi->n_wb_cqi;
+    copy->a31csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a31csi->n_wb_cqi);
+    for (i = 0; i < copy->a31csi->n_wb_cqi; i++) {
+      copy->a31csi->wb_cqi[i] = original->a31csi->wb_cqi[i];
+    }
+    copy->a31csi->has_wb_pmi = original->a31csi->has_wb_pmi;
+    copy->a31csi->wb_pmi = original->a31csi->wb_pmi;
+    copy->a31csi->n_sb_cqi = original->a31csi->n_sb_cqi;
+    copy->a31csi->sb_cqi = malloc(sizeof(Protocol__FlexMsbCqi *) * copy->a31csi->n_sb_cqi);
+    if (copy->a31csi == NULL) {
+      goto error;
+    }
+    for (i = 0; i < copy->a31csi->n_sb_cqi; i++) {
+      copy->a31csi->sb_cqi[i] = malloc(sizeof(Protocol__FlexMsbCqi));
+      if (copy->a31csi->sb_cqi[i] == NULL) {
+	goto error;
+      }
+      protocol__flex_msb_cqi__init(copy->a31csi->sb_cqi[i]);
+      copy->a31csi->sb_cqi[i]->n_sb_cqi = original->a31csi->sb_cqi[i]->n_sb_cqi;
+      copy->a31csi->sb_cqi[i]->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a31csi->sb_cqi[i]->n_sb_cqi);
+      for (j = 0; j < copy->a31csi->sb_cqi[i]->n_sb_cqi; j++) {
+	copy->a31csi->sb_cqi[i]->sb_cqi[j] = original->a31csi->sb_cqi[i]->sb_cqi[j];
+      }
+    }
+    break;
+  default:
+    goto error;
+  }
+  return copy;
+
+ error:
+  return NULL;
+}
+
+Protocol__FlexCellStatsReport * copy_cell_stats_report(Protocol__FlexCellStatsReport *original) {
+ 
+  Protocol__FlexCellStatsReport * copy =  malloc(sizeof(Protocol__FlexCellStatsReport));
+  
+  if(copy == NULL) {
+    goto error;
+  }
+  protocol__flex_cell_stats_report__init(copy);
+  copy->carrier_index = original->carrier_index;
+  copy->has_carrier_index = original->has_carrier_index;
+  copy->flags = original->flags;
+  copy->has_flags = original->has_flags;
+
+   if(copy->flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) {
+     copy->noise_inter_report = copy_noise_inter_report(original->noise_inter_report);
+   }
+
+   return copy;
+
+ error:
+   return NULL;
+}
+
+Protocol__FlexNoiseInterferenceReport * copy_noise_inter_report(Protocol__FlexNoiseInterferenceReport *original) {
+  Protocol__FlexNoiseInterferenceReport *ni_report;
+  ni_report = malloc(sizeof(Protocol__FlexNoiseInterferenceReport));
+  if(ni_report == NULL) {
+    goto error;
+  }
+  protocol__flex_noise_interference_report__init(ni_report);
+  // Current frame and subframe number
+  ni_report->sfn_sf = original->sfn_sf;
+  ni_report->has_sfn_sf = original->sfn_sf;
+  // Received interference power in dbm
+  ni_report->rip = original->rip;
+  ni_report->has_rip = original->has_rip;
+  // Thermal noise power in dbm
+  ni_report->tnp = original->tnp;
+  ni_report->has_tnp = original->has_tnp;
+  
+  return ni_report;
+  
+ error:
+  return NULL;
+}
+
+
+int parse_mac_config(mid_t mod_id, yaml_parser_t *parser) {
+  
+  yaml_event_t event;
+  
+  int done = 0;
+
+  int sequence_started = 0;
+  int mapping_started = 0;
+
+  while (!done) {
+
+    if (!yaml_parser_parse(parser, &event))
+      goto error;
+   
+    switch (event.type) {
+    case YAML_SEQUENCE_START_EVENT:
+      LOG_D(ENB_APP, "A sequence just started as expected\n");
+      sequence_started = 1;
+      break;
+    case YAML_SEQUENCE_END_EVENT:
+      LOG_D(ENB_APP, "A sequence ended\n");
+      sequence_started = 0;
+      break;
+    case YAML_MAPPING_START_EVENT:
+      if (!sequence_started) {
+	goto error;
+      }
+      LOG_D(ENB_APP, "A mapping started\n");
+      mapping_started = 1;
+      break;
+    case YAML_MAPPING_END_EVENT:
+      if (!mapping_started) {
+	goto error;
+      }
+      LOG_D(ENB_APP, "A mapping ended\n");
+      mapping_started = 0;
+      break;
+    case YAML_SCALAR_EVENT:
+      if (!mapping_started) {
+	goto error;
+      }
+      // Check the types of subsystems offered and handle their values accordingly
+      if (strcmp(event.data.scalar.value, "dl_scheduler") == 0) {
+	LOG_D(ENB_APP, "This is for the dl_scheduler subsystem\n");
+	// Call the proper handler
+	if (parse_dl_scheduler_config(mod_id, parser) == -1) {
+	  LOG_D(ENB_APP, "An error occured\n");
+	  goto error;
+	}
+      } else if (strcmp(event.data.scalar.value, "ul_scheduler") == 0) {
+	// Call the proper handler
+	LOG_D(ENB_APP, "This is for the ul_scheduler subsystem\n");
+	goto error;
+	// TODO
+      } else if (strcmp(event.data.scalar.value, "ra_scheduler") == 0) {
+	// Call the proper handler
+	// TODO
+      } else if (strcmp(event.data.scalar.value, "page_scheduler") == 0) {
+	// Call the proper handler
+	// TODO
+      } else {
+	// Unknown subsystem
+	goto error;
+      }
+      break;
+    default: // We expect nothing else at this level of the hierarchy
+      goto error;
+    }
+   
+    done = (event.type == YAML_SEQUENCE_END_EVENT);
+
+    yaml_event_delete(&event);
+ 
+  }
+  
+  return 0;
+
+  error:
+  yaml_event_delete(&event);
+  return -1;
+
+}
+
+int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser) {
+  
+  yaml_event_t event;
+
+  int done = 0;
+  int mapping_started = 0;
+
+  while (!done) {
+    
+    if (!yaml_parser_parse(parser, &event))
+      goto error;
+
+    switch (event.type) {
+      // We are expecting a mapping (behavior and parameters)
+    case YAML_MAPPING_START_EVENT:
+      LOG_D(ENB_APP, "The mapping of the subsystem started\n");
+      mapping_started = 1;
+      break;
+    case YAML_MAPPING_END_EVENT:
+      LOG_D(ENB_APP, "The mapping of the subsystem ended\n");
+      mapping_started = 0;
+      break;
+    case YAML_SCALAR_EVENT:
+      if (!mapping_started) {
+	goto error;
+      }
+      // Check what key needs to be set
+      if (strcmp(event.data.scalar.value, "behavior") == 0) {
+	LOG_I(ENB_APP, "Time to set the behavior attribute\n");
+	yaml_event_delete(&event);
+	if (!yaml_parser_parse(parser, &event)) {
+	  goto error;
+	}
+	if (event.type == YAML_SCALAR_EVENT) {
+	  if (load_dl_scheduler_function(mod_id, event.data.scalar.value) == -1) {
+	    goto error;
+	  } 
+	} else {
+	  goto error;
+	}
+      } else if (strcmp(event.data.scalar.value, "parameters") == 0) {
+	LOG_D(ENB_APP, "Now it is time to set the parameters for this subsystem\n");
+	if (parse_dl_scheduler_parameters(mod_id, parser) == -1) {
+	  goto error;
+	}
+      }
+      break;
+    default:
+      goto error;
+    }
+
+    done = (event.type == YAML_MAPPING_END_EVENT);
+    yaml_event_delete(&event);
+  }
+
+  return 0;
+
+ error:
+  yaml_event_delete(&event);
+  return -1;
+}
+
+int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser) {
+  yaml_event_t event;
+  
+  void *param;
+  
+  int done = 0;
+  int mapping_started = 0;
+
+  while (!done) {
+    
+    if (!yaml_parser_parse(parser, &event))
+      goto error;
+
+    switch (event.type) {
+      // We are expecting a mapping of parameters
+    case YAML_MAPPING_START_EVENT:
+      LOG_D(ENB_APP, "The mapping of the parameters started\n");
+      mapping_started = 1;
+      break;
+    case YAML_MAPPING_END_EVENT:
+      LOG_D(ENB_APP, "The mapping of the parameters ended\n");
+      mapping_started = 0;
+      break;
+    case YAML_SCALAR_EVENT:
+      if (!mapping_started) {
+	goto error;
+      }
+      // Check what key needs to be set
+      if (mac_agent_registered[mod_id]) {
+	LOG_D(ENB_APP, "Setting parameter %s\n", event.data.scalar.value);
+	param = dlsym(agent_mac_xface[mod_id]->dl_scheduler_loaded_lib,
+		      event.data.scalar.value);
+	if (param == NULL) {
+	  goto error;
+	}
+	apply_parameter_modification(param, parser);
+      } else {
+	goto error;
+      }
+      break;
+    default:
+      goto error;
+    }
+
+    done = (event.type == YAML_MAPPING_END_EVENT);
+    yaml_event_delete(&event);
+  }
+
+  return 0;
+  
+ error:
+  yaml_event_delete(&event);
+  return -1;
+}
+
+int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
+  void *lib;
+
+  char lib_name[120];
+  char target[512];
+  snprintf(lib_name, sizeof(lib_name), "/%s.so", function_name);
+  strcpy(target, local_cache);
+  strcat(target, lib_name);
+  
+  LOG_I(FLEXRAN_AGENT, "Opening pushed code: %s\n", target);
+  lib = dlopen(target, RTLD_NOW);
+  if (lib == NULL) {
+    LOG_I(FLEXRAN_AGENT, "Could not load library\n");
+    goto error;
+  }
+  
+  LOG_I(FLEXRAN_AGENT, "Loading function: %s\n", function_name);
+  void *loaded_scheduler = dlsym(lib, function_name);
+  if (loaded_scheduler) {
+    if (mac_agent_registered[mod_id]) {
+      agent_mac_xface[mod_id]->flexran_agent_schedule_ue_spec = loaded_scheduler;
+      if (agent_mac_xface[mod_id]->dl_scheduler_loaded_lib != NULL) {
+	dlclose(agent_mac_xface[mod_id]->dl_scheduler_loaded_lib);
+      }
+      agent_mac_xface[mod_id]->dl_scheduler_loaded_lib = lib;
+      LOG_I(FLEXRAN_AGENT, "New DL UE scheduler: %s\n", function_name);
+    }
+  } else {
+    LOG_I(FLEXRAN_AGENT, "Scheduler could not be loaded\n");
+  }
+
+  return 0;
+
+ error:
+  return -1;
+  
+}
diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a7d4a8555b070fde7f389e30b46d256f84bc278
--- /dev/null
+++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h
@@ -0,0 +1,106 @@
+/*
+ * 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.0  (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 flexran_agent_mac_internal.h
+ * \brief Implementation specific definitions for the FlexRAN MAC agent
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_MAC_INTERNAL_H_
+#define FLEXRAN_AGENT_MAC_INTERNAL_H_
+
+#include <pthread.h>
+
+#include <yaml.h>
+
+#include "flexran_agent_mac.h"
+#include "flexran_agent_common.h"
+#include "flexran_agent_defs.h"
+
+/*This will be used for producing continuous status updates for the MAC
+ *Needs to be thread-safe
+ */
+typedef struct {
+  /*Flag showing if continuous mac stats update is enabled*/
+  uint8_t is_initialized;
+  volatile uint8_t cont_update;
+  xid_t xid;
+  Protocol__FlexranMessage *stats_req;
+  Protocol__FlexranMessage *prev_stats_reply;
+
+  pthread_mutex_t *mutex;
+} mac_stats_updates_context_t;
+
+/*Array holding the last stats reports for each eNB. Used for continuous reporting*/
+mac_stats_updates_context_t mac_stats_context[NUM_MAX_ENB];
+
+/*Functions to initialize and destroy the struct required for the
+ *continuous stats update report*/
+err_code_t flexran_agent_init_cont_mac_stats_update(mid_t mod_id);
+
+err_code_t flexran_agent_destroy_cont_mac_stats_update(mid_t mod_id);
+
+
+/*Enable/Disable the continuous stats update service for the MAC*/
+err_code_t flexran_agent_enable_cont_mac_stats_update(mid_t mod_id, xid_t xid,
+						  stats_request_config_t *stats_req);
+
+err_code_t flexran_agent_disable_cont_mac_stats_update(mid_t mod_id);
+
+Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_report,
+								    Protocol__FlexranMessage *old_report);
+
+Protocol__FlexUeStatsReport * copy_ue_stats_report(Protocol__FlexUeStatsReport * original);
+
+Protocol__FlexCellStatsReport * copy_cell_stats_report(Protocol__FlexCellStatsReport *original);
+
+Protocol__FlexRlcBsr * copy_rlc_report(Protocol__FlexRlcBsr * original);
+
+Protocol__FlexUlCqiReport * copy_ul_cqi_report(Protocol__FlexUlCqiReport * original);
+
+Protocol__FlexDlCqiReport * copy_dl_cqi_report(Protocol__FlexDlCqiReport * original);
+
+Protocol__FlexPagingBufferReport * copy_paging_buffer_report(Protocol__FlexPagingBufferReport *original);
+
+Protocol__FlexDlCsi * copy_csi_report(Protocol__FlexDlCsi * original);
+
+Protocol__FlexNoiseInterferenceReport * copy_noise_inter_report(Protocol__FlexNoiseInterferenceReport *original);
+
+int compare_ue_stats_reports(Protocol__FlexUeStatsReport *rep1,
+			    Protocol__FlexUeStatsReport *rep2);
+
+int compare_cell_stats_reports(Protocol__FlexCellStatsReport *rep1,
+			    Protocol__FlexCellStatsReport *rep2);
+
+
+/* Functions for parsing the MAC agent policy reconfiguration command */
+
+int parse_mac_config(mid_t mod_id, yaml_parser_t *parser);
+
+int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser);
+
+int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser);
+
+int load_dl_scheduler_function(mid_t mod_id, const char *function_name);
+
+#endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/
diff --git a/openair2/ENB_APP/MESSAGES/V2/config_common.proto b/openair2/ENB_APP/MESSAGES/V2/config_common.proto
new file mode 100644
index 0000000000000000000000000000000000000000..51ae7112770a701d9212ebc2801e3fb6f8753322
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/config_common.proto
@@ -0,0 +1,180 @@
+//'syntax = "proto2";'
+package protocol;
+
+//
+// Cell config related structures and enums
+//
+
+message flex_si_config {
+       optional uint32 sfn = 1;
+       optional uint32 sib1_length = 2;		// The length of SIB1 in bytes
+       optional uint32 si_window_length = 3; 	// The scheduling window for all SIs in SF
+       repeated flex_si_message si_message = 4;	// List of SI messages to be sent.
+       						// The index identifies the type of an SI message
+						// 0 - SIB1
+						// 1..31 - SIx
+						// 32..63 - PCCH
+}
+
+message flex_si_message {
+	optional uint32 periodicity = 1;		// Periodicity of SI msg in radio frames
+	optional uint32 length = 2;			// The length of the SI message in bytes
+}
+
+enum flex_hopping_mode {
+     FLHM_INTER = 0;
+     FLHM_INTERINTRA = 1;
+}
+
+enum flex_phich_resource {
+     FLPR_ONE_SIXTH = 0;
+     FLPR_HALF = 1;
+     FLPR_ONE = 2;
+     FLPR_TWO = 3;
+}
+
+enum flex_phich_duration {
+     FLPD_NORMAL = 0;
+     FLPD_EXTENDED = 1;
+}
+
+enum flex_ul_cyclic_prefix_length {
+     FLUCPL_NORMAL = 0;
+     FLUCPL_EXTENDED = 1;
+}
+
+enum flex_dl_cyclic_prefix_length {
+     FLDCPL_NORMAL = 0;
+     FLDCPL_EXTENDED = 1;
+}
+
+enum flex_duplex_mode {
+     FLDM_TDD = 0;
+     FLDM_FDD = 1;
+}
+
+enum flex_qam {
+     FLEQ_MOD_16QAM = 0;
+     FLEQ_MOD_64QAM = 1;
+}
+
+//
+// UE config related structures and enums
+//
+
+message flex_drx_config {
+	optional uint32 on_duration_timer = 1;		// Timer in SF. See TS 36.321
+	optional uint32 drx_inactivity_timer = 2;	// Timer in SF. See TS 36.321
+	optional uint32 drx_retransmission_timer = 3;	// Timer in SF. See TS 36.321
+	optional uint32 long_drx_cycle = 4;		// In SF. See TS 36.321
+	optional uint32 long_drx_cycle_start_offset = 5;// See TS 36.321
+	optional uint32 short_drx_cycle = 6;		// In SF
+	optional uint32 drx_short_cycle_timer = 7;	// Timer in subframes. See TS 36.321
+}
+
+message flex_sps_config {
+	optional uint32 semi_persistent_sched_interval_UL = 1; // SPS UL scheduling interval in SF
+	optional uint32 semi_persistent_sched_interval_DL = 2; // SPS DL scheduling interval in SF
+	optional uint32 num_of_conf_sps_proc = 3;	   // Number of SPS HARQ processes. See TS 36.321
+	repeated uint32 n1_PUCCH_AN_persistent_element = 4;// See TS36.213. Ignored when config is used
+		 					   // as part of FLPT_SET_UE_CONFIG
+	optional uint32 implicit_release_after = 5;		   // number of empty transmissions before release of SPS
+}
+
+message flex_sr_config {
+	optional uint32 sr_action = 1;			// Indicates if SR config should be changed or released
+		 					// One of the FLSRA_* enum values
+	optional uint32 sched_interval = 2;		// SR scheduling interval in SF
+	optional uint32 dsr_trans_max = 3;		// See TS 36.213
+}
+
+message flex_cqi_config {
+	optional uint32 cqi_action = 1;			// Indicats if CQI changed or released.
+		 					// One of the FLSRA_* enum values
+	optional uint32 cqi_sched_interval = 2;		// CQI scheduling interval in SF
+	optional uint32 ri_sched_interval = 3;		// RI scheduling interval in SF
+}
+
+message flex_ue_capabilities {
+	optional uint32 half_duplex = 1;		// Boolean value. Only half duplex support. FDD operation
+	optional uint32 intra_SF_hopping = 2;		// Support for intra-subframe hopping. Boolean value
+	optional uint32 type2_sb_1 = 3;			// Support for type 2 hopping with n_sb > 1
+	optional uint32 ue_category = 4;
+	optional uint32 res_alloc_type1 = 5;		// Boolean value. UE support for resource allocation type 1
+}
+
+message flex_scell_config {
+	optional uint32 carrier_index = 1;		// Id of the carrier component
+	optional uint32 scell_index = 2;		// Index of this Scell (RRC SCellIndex)
+	optional uint32 use_ccs = 3;			// Boolean value. Indicates if cross-carrier scheduling
+		 					// is used by this SCell
+	optional uint32 sched_cell_index = 4;		// Index of the cell responsible for scheduling
+		 					// this SCell if cross-carrier scheduling is enabled
+	optional uint32 pdsch_start = 5;		// Starting OFDM symbol of PDSCH data region for this SCell
+}
+
+enum flex_meas_gap_config_pattern {
+     FLMGCP_GP1 = 0;
+     FLMGCP_GP2 = 1;
+     FLMGCP_OFF = 2;
+}
+
+enum flex_setup_release_action {
+     FLSRA_SETUP = 0;
+     FLSRA_RELEASE = 1;
+}
+
+enum flex_ue_transmission_antenna {
+     FLUTA_NONE = 0;
+     FLUTA_OPEN_LOOP = 1;
+     FLUTA_CLOSED_LOOP = 2;
+}
+
+enum flex_aperiodic_cqi_report_mode {
+     FLACRM_RM12 = 0;
+     FLACRM_RM20 = 1;
+     FLACRM_RM22 = 2;
+     FLACRM_RM30 = 3;
+     FLACRM_RM31 = 4;
+     FLACRM_NONE = 5;
+}
+
+enum flex_tdd_ack_nack_feedback_mode {
+     FLTANFM_BUNDLING = 0;
+     FLTANFM_MULTIPLEXING = 1;
+}
+
+//
+// Logical channel config related structures and enums
+//
+
+message flex_lc_config {
+	optional uint32 lcid = 1;	// The logical channel id
+	optional uint32 lcg = 2;	// The logical channel group (0..3) the LC is mapped to
+	optional uint32 direction = 3;	// The LC direction. One of the FLLCD_* enum values
+	optional uint32 qos_bearer_type = 4;// GBR or NGBR bearer. One of the FLQBT_* enum values
+	optional uint32 qci = 5;	// The QCI defined in TS 23.203, coded as defined in TS 36.413
+		 			// One less than the actual QCI value
+	optional uint64 e_RAB_max_bitrate_UL = 6; // In bps (GBR only)
+	optional uint64 e_RAB_max_bitrate_DL = 7; // In bps (GBR only)
+	optional uint64 e_RAB_guaranteed_bitrate_UL = 8; // In bps (GBR only)
+	optional uint64 e_RAB_guaranteed_bitrate_DL = 9;  // In bps (GBR only)
+}
+
+enum flex_lc_direction {
+     FLLCD_UL = 0;
+     FLLCD_DL = 1;
+     FLLCD_BOTH = 2;
+}
+
+enum flex_qos_bearer_type {
+     FLQBT_NON_GBR = 0;
+     FLQBT_GBR = 1;
+}
+
+enum flex_ue_state_change_type {
+     FLUESC_UPDATED = 0;
+     FLUESC_ACTIVATED = 1;
+     FLUESC_DEACTIVATED = 2;
+     FLUESC_MOVED = 3;
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto
new file mode 100644
index 0000000000000000000000000000000000000000..441e193569343b1b3a619ce3e97da437d55bc9d1
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto
@@ -0,0 +1,88 @@
+//'syntax = "proto2";'
+package protocol;
+
+import "config_common.proto";
+
+message flex_cell_config {
+	optional uint32 phy_cell_id = 1;		// The PCI of this cell
+	optional uint32 cell_id = 2;			// The PLMN cell id of this cell
+	optional uint32 pusch_hopping_offset = 3;	// PUSCH resources in RBs for hopping
+	optional uint32 hopping_mode = 4;		// One of the FLHM_* enum values
+	optional uint32 n_sb = 5;			// The number of subbands
+	optional uint32 phich_resource = 6;		// The number of REGs used for PHICH
+		 					// One of the FLPR_* enum values
+	optional uint32 phich_duration = 7;		// One of the FLPD_* enum values
+	optional uint32 init_nr_PDCCH_OFDM_sym = 8; 	// See TS 36.211, section 6.9
+	optional flex_si_config si_config = 9;	 	// The SI configuration
+	optional uint32 dl_bandwidth = 10;		// The DL transmission bandwidth in RBs
+	optional uint32 ul_bandwidth = 11;		// The UL transmission bandwidth in RBs
+	optional uint32 ul_cyclic_prefix_length = 13;	// One of the FLUCPL_* enum values
+	optional uint32 dl_cyclic_prefix_length = 14;	// One of the FLDCPL_* enum values
+	optional uint32 antenna_ports_count = 15;	// Number of cell specific antenna ports
+	optional uint32 duplex_mode = 16;		// One of the FLDM_* enum values
+	optional uint32 subframe_assignment = 17;	// DL/UL subframe assignment. TDD only
+	optional uint32	special_subframe_patterns = 18; // TDD only. See TS 36.211, table 4.2.1
+	repeated uint32 mbsfn_subframe_config_rfperiod = 19; // The MBSFN radio frame period (Optional)
+	repeated uint32 mbsfn_subframe_config_rfoffset = 20; // The radio frame offset (Optional)
+	repeated uint32 mbsfn_subframe_config_sfalloc = 21; // Bitmap indicating the MBSFN subframes (Optional)
+	optional uint32 prach_config_index = 22;	// See TS 36.211, section 5.7.1
+	optional uint32 prach_freq_offset = 23;	// See TS 36.211, section 5.7.1
+	optional uint32 ra_response_window_size = 24; // The duration of the RA response window in SF
+	optional uint32 mac_contention_resolution_timer = 25; // Timer for RA
+	optional uint32 max_HARQ_Msg3Tx = 26;		// See TS 36.321
+	optional uint32 n1PUCCH_AN = 27;		// See TS 36.213, section 10.1
+	optional uint32 deltaPUCCH_shift = 28;		// See TS 36.211, section 5.4
+	optional uint32 nRB_cqi = 29;			// See TS 36.211, section 5.4
+	optional uint32 srs_subframe_config = 30;	// See TS 36.211, table 5.5.3.3-1 and 2
+	optional uint32 srs_bw_config = 31;		// See TS 36.211, section 5.5.3.2
+	optional uint32 srs_mac_up_pts = 32;		// Boolean value. See TS 36.211, section 5.5.3.2. TDD only
+	optional uint32 enable_64QAM = 33;		// One of the FLEQ_* enum values
+	optional uint32 carrier_index = 34;		// Carrier component index
+}
+
+message flex_ue_config {
+	optional uint32 rnti = 1;
+	optional flex_drx_config drx_config = 2;		// The DRX configuration (Optional)
+	optional uint32 time_alignment_timer = 3;	// Timer in SF. Control the synchronization
+		 					// status of the UE, not the actual advance procedure
+							// See TS 36.321
+	optional uint32 meas_gap_config_pattern = 4;	// Measurement gap configuration.
+		 				  	// One of the FLMGCP_* enum values
+		 					// See TS 36.133
+	optional uint32 meas_gap_config_sf_offset = 5;	// Measurement gap offset if applicable
+	optional flex_sps_config sps_config = 6;	    	// The SPS configuration (Optional)
+	optional flex_sr_config sr_config = 7;		// The SR configuration (Optional)
+	optional flex_cqi_config cqi_config = 8;		// The CQI configuration (Optional)
+	optional uint32 transmission_mode = 9;		// The UE transmission mode
+	optional uint64 ue_aggregated_max_bitrate_UL = 10; // Aggregated bit-rate of non-gbr bearer
+                                		       	   // per UE. See TS 36.413
+	optional uint64 ue_aggregated_max_bitrate_DL = 11; // Aggregated bit-rate of non-gbr bearer
+		 				       	   // per UE. See TS 36.413
+	optional flex_ue_capabilities capabilities = 12;
+	optional uint32 ue_transmission_antenna = 13;	// One of the FLUTA_* enum values
+	optional uint32 tti_bundling = 14;		// Boolean value. See TS 36.321
+	optional uint32 max_HARQ_tx = 15;		// The max HARQ retransmission for UL
+	optional uint32 beta_offset_ACK_index = 16; 	// See TS 36.213
+	optional uint32 beta_offset_RI_index = 17;	// See TS 36.213
+	optional uint32 beta_offset_CQI_index = 18;	// See TS 36.213
+	optional uint32 ack_nack_simultaneous_trans = 19;// Boolean. See TS 36.213
+	optional uint32 simultaneous_ack_nack_cqi = 20; // Boolean. See TS 36.213
+	optional uint32 aperiodic_cqi_rep_mode = 21;    // One of the FLACRM_* enum values
+	optional uint32 tdd_ack_nack_feedback = 22;     // One of the FLTANFM_* enum values
+	optional uint32 ack_nack_repetition_factor = 23;// See TS 36.213, section 10.1
+	optional uint32 extended_bsr_size = 24;	     	// Boolean for extended BSR size
+	optional uint32 ca_support = 25;    		// Boolean. Support for carrier aggregation
+	optional uint32 cross_carrier_sched_support = 26; // Boolean value
+	optional uint32 pcell_carrier_index = 27;     // Index of primary cell
+	repeated flex_scell_config scell_config = 28;  // Secondary cells configuration
+	optional uint32 scell_deactivation_timer = 29;// Deactivation timer for secondary cell
+}
+
+message flex_lc_ue_config {
+	optional uint32 rnti = 1;
+	repeated flex_lc_config lc_config = 2;	// A list of LC configurations for the given UE
+}
+
+
+
+
diff --git a/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto
new file mode 100644
index 0000000000000000000000000000000000000000..3a5efaf7d40d427d6b1fa3185eba77f36d460ff2
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto
@@ -0,0 +1,6 @@
+//'syntax = "proto2";'
+package protocol;
+
+enum flex_control_delegation_type {
+     FLCDT_MAC_DL_UE_SCHEDULER = 1;		// DL UE scheduler delegation
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto b/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto
new file mode 100644
index 0000000000000000000000000000000000000000..cbec332b304085d4389d7b3498556fc29a9803dd
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/controller_commands.proto
@@ -0,0 +1,58 @@
+package protocol;
+
+import "mac_primitives.proto";
+
+//
+// Body of UE DL MAC scheduling configuration info
+//
+
+message flex_dl_data {
+	optional uint32 rnti = 1;
+	optional flex_dl_dci dl_dci = 2;
+	repeated uint32 ce_bitmap = 3; // list of 2 MAC CEs, one for each TB
+	repeated flex_rlc_pdu rlc_pdu = 4; // list of parameters for the creation of RLC PDUs. One for each lcid
+	optional uint32 serv_cell_index = 5;
+	optional uint32 act_deact_ce = 6; //Hex content of MAC CE for Activation/Deactivation in CA
+}
+
+//
+// Body of the RAR scheduler configuration
+//
+message flex_dl_rar {
+	optional uint32 rnti = 1;
+	optional uint32 grant = 2;	// The 20-bit UL grant. TS 36.213, sec 6.2
+	optional flex_dl_dci rar_dci = 3;
+	optional uint32 carrier_index = 4; // The carrier index for the RAR
+}
+
+//
+// Body of the paging/broadcast configuration message
+//
+
+message flex_dl_broadcast {
+	optional uint32 type = 1;	// The FLBT_* values
+	optional uint32 index = 2;	// Index of the broadcast message:
+		       	       		// 0 - SIB1,
+                                    	// 1..31 - Six,
+                                     	// 32..63 - PCCH (PCCH index obtained from  flex_paging_info)
+	optional flex_dl_dci broad_dci = 3;
+	optional uint32 carrier_index = 4; // Index of the carrier for broadcast
+}
+
+//
+// Body of the OFDM symbol count message
+//
+
+message flex_pdcch_ofdm_sym_count {
+	optional uint32 carrier_index = 1;
+	optional uint32 num_pdcch_ofdm_symbols = 2;
+}
+
+//
+// Types of commands related enums
+//
+
+enum flex_broadcast_type {
+     FLBT_BCCH = 0;
+     FLBT_PCCH = 1;
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto
new file mode 100644
index 0000000000000000000000000000000000000000..3a1d40bca69479daaafa42f055e690add87426ef
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto
@@ -0,0 +1,210 @@
+//'syntax = "proto2";' 
+package protocol;
+
+import "stats_messages.proto";
+import "header.proto";
+import "time_common.proto";
+import "config_messages.proto";
+import "controller_commands.proto";
+import "control_delegation.proto";
+
+message flexran_message {
+       optional flexran_direction msg_dir = 100;
+	oneof msg {
+              flex_hello hello_msg = 1;
+              flex_echo_request echo_request_msg = 2;
+	      flex_echo_reply echo_reply_msg = 3;
+	      flex_stats_request stats_request_msg = 4;
+	      flex_stats_reply stats_reply_msg = 5;
+	      flex_sf_trigger sf_trigger_msg = 6;
+	      flex_ul_sr_info ul_sr_info_msg = 7;
+	      flex_enb_config_request enb_config_request_msg = 8;
+	      flex_enb_config_reply enb_config_reply_msg = 9;
+	      flex_ue_config_request ue_config_request_msg = 10;
+	      flex_ue_config_reply ue_config_reply_msg = 11;
+	      flex_lc_config_request lc_config_request_msg = 12;
+	      flex_lc_config_reply lc_config_reply_msg = 13;
+	      flex_dl_mac_config dl_mac_config_msg = 14;
+	      flex_ue_state_change ue_state_change_msg = 15;
+	      flex_control_delegation control_delegation_msg = 16;
+	      flex_agent_reconfiguration agent_reconfiguration_msg = 17;
+	}
+}
+
+enum flexran_direction {
+     //option allow_alias = true;
+     NOT_SET = 0;
+     INITIATING_MESSAGE = 1;
+     SUCCESSFUL_OUTCOME=2;
+     UNSUCCESSFUL_OUTCOME=3;	
+}
+	
+enum flexran_err {
+        option allow_alias = true;
+	// message errors
+	NO_ERR = 0;	
+	MSG_DEQUEUING = -1;
+	MSG_ENQUEUING = -2;
+	MSG_DECODING = -3;
+	MSG_ENCODING = -4;
+	MSG_BUILD = -5;
+	MSG_NOT_SUPPORTED = -6; 
+	MSG_NOT_HANDLED = -7;
+	MSG_NOT_VALIDATED = -8;
+	MSG_OUT_DATED = -9;
+
+	
+	// other erros
+	UNEXPECTED = -100;	
+}	
+
+//
+// Maintenance and discovery messages
+//
+
+message flex_hello {
+	optional flex_header header = 1;
+}
+
+message flex_echo_request {
+	optional flex_header header = 1;
+	extensions 100 to 199;
+}
+
+
+message flex_echo_reply {
+	optional flex_header header = 1;
+	extensions 100 to 199;
+}
+
+
+//
+// Statistics request and reply message
+//
+
+message flex_stats_request {
+	optional flex_header header = 1;
+	optional flex_stats_type type = 2;
+	oneof body {
+	      flex_complete_stats_request complete_stats_request = 3;
+	      flex_cell_stats_request cell_stats_request = 4;
+	      flex_ue_stats_request ue_stats_request = 5;
+	}
+}
+
+message flex_stats_reply {
+	optional flex_header header = 1;
+	repeated flex_ue_stats_report ue_report = 2;
+	repeated flex_cell_stats_report cell_report = 3;
+}
+
+//
+// Time indication messages
+//
+
+message flex_sf_trigger {
+	optional flex_header header = 1;
+	optional uint32 sfn_sf = 2;
+	repeated flex_dl_info dl_info = 3;
+	repeated flex_ul_info ul_info = 4;	
+}
+
+//
+// Asynchronous messages
+//
+
+message flex_ul_sr_info {
+	optional flex_header header = 1;
+	optional uint32 sfn_sf = 2;
+	repeated uint32 rnti = 3;
+}
+
+//
+// eNB configuration messages
+//
+message flex_enb_config_request {
+	optional flex_header header = 1;
+}
+
+message flex_enb_config_reply {
+	optional flex_header header = 1;
+	optional uint32 eNB_id = 2;		// Unique id to distinguish the eNB
+	repeated flex_cell_config cell_config = 3;
+}
+
+message flex_ue_config_request {
+	optional flex_header header = 1;
+}
+
+message flex_ue_config_reply {
+	optional flex_header header = 1;
+	repeated flex_ue_config ue_config = 2;
+}
+
+message flex_lc_config_request {
+	optional flex_header header = 1;
+}
+
+message flex_lc_config_reply {
+	optional flex_header header = 1;
+	repeated flex_lc_ue_config lc_ue_config = 2;
+}
+
+//
+// Controller command messages
+//
+
+message flex_dl_mac_config {
+	optional flex_header header = 1;
+	optional uint32 sfn_sf = 2;
+	repeated flex_dl_data dl_ue_data = 3;
+	repeated flex_dl_rar dl_rar = 4;
+	repeated flex_dl_broadcast dl_broadcast = 5;
+	repeated flex_pdcch_ofdm_sym_count ofdm_sym = 6; // OFDM symbol count for each CC
+}
+
+//
+// UE state change message
+//
+
+message flex_ue_state_change {
+	optional flex_header header = 1;
+	optional uint32 type = 2;		// One of the FLUESC_* values
+	optional flex_ue_config config = 3;	// Body of the message (based on type)
+}
+
+//
+// Control delegation message
+//
+
+message flex_control_delegation {
+	optional flex_header header = 1;
+	optional uint32 delegation_type = 2;	// Bitmap of FLCDT_* flags
+	optional bytes payload = 3;	  	// Byte array of shared lib containing the delegated functions
+	optional string name = 4;		// The delegated functions names ordered based on bitmap flags
+}
+
+//
+// Agent reconfiguration message
+//
+
+message flex_agent_reconfiguration {
+	optional flex_header header = 1;
+	optional string policy = 2;		// The policy changes using YAML syntax in string format
+}
+
+// Extensions of the echo request and reply
+// messages for carrying a latency value in ms
+message flex_echo_request_latency {
+	extend flex_echo_request {
+	       optional uint32 latency = 100;
+	}
+}
+
+message flex_echo_reply_latency {
+	extend flex_echo_reply {
+	       optional uint32 latency = 100;
+	}
+}
+
+
diff --git a/openair2/ENB_APP/MESSAGES/V2/header.proto b/openair2/ENB_APP/MESSAGES/V2/header.proto
new file mode 100644
index 0000000000000000000000000000000000000000..dfd5ea6c9951ef2b266677413a4aec128c839b24
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/header.proto
@@ -0,0 +1,43 @@
+package protocol;
+
+message flex_header {
+	optional uint32 version = 1;
+	optional uint32 type = 2;
+	optional uint32 xid = 4;
+}
+
+enum flex_type {
+     // Discovery and maintenance messages
+     FLPT_HELLO = 0;
+     FLPT_ECHO_REQUEST = 1;
+     FLPT_ECHO_REPLY = 2;
+
+     // Statistics and measurement messages
+     FLPT_STATS_REQUEST = 3;
+     FLPT_STATS_REPLY = 4;
+     
+     // Time indication messages
+     FLPT_SF_TRIGGER = 5;
+
+     // Asynchronous messages
+     FLPT_UL_SR_INFO = 6;
+
+     // eNB configuration messages
+     FLPT_GET_ENB_CONFIG_REQUEST = 7;
+     FLPT_GET_ENB_CONFIG_REPLY = 8;
+     FLPT_GET_UE_CONFIG_REQUEST = 9;
+     FLPT_GET_UE_CONFIG_REPLY = 10;
+     FLPT_GET_LC_CONFIG_REQUEST = 11;
+     FLPT_GET_LC_CONFIG_REPLY = 12;
+
+     //Controller command messages
+     FLPT_DL_MAC_CONFIG = 13;
+
+     // UE state change messages
+     FLPT_UE_STATE_CHANGE = 14;
+
+     // Control delegation messages
+     FLPT_DELEGATE_CONTROL = 15;
+     FLPT_RECONFIGURE_AGENT = 16;
+}
+
diff --git a/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto b/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto
new file mode 100644
index 0000000000000000000000000000000000000000..be7c72ab7b07a4dd69bc99d5f7c4b9765d79c1c9
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/mac_primitives.proto
@@ -0,0 +1,76 @@
+package protocol;
+
+//
+// Message containing the DL DCI info
+//
+
+message flex_dl_dci {
+	optional uint32 rnti = 1;
+	optional uint32 res_alloc = 2;		// Type of resource allocation
+	optional uint32 rb_bitmap = 3;		// Bitmap for RB allocation
+	optional uint32 rb_shift = 4;		// See TS 36.214, section 7.1.6.2
+	repeated uint32 tbs_size = 5;		// The size of each TBS
+	repeated uint32 mcs = 6;   		// The MCS of each TB
+	repeated uint32 ndi = 7;		// New data indicator of each TB
+	repeated uint32 rv = 8;			// Redundancy version of each TB
+	optional uint32 cce_index = 9;		// CCE index used to send the DCI
+	optional uint32 aggr_level = 10;
+	optional uint32 precoding_info = 11;	// 2 antenna ports:0..6,
+		 			 	// 4 antenna ports:0..50
+	optional uint32 format = 12;		// DCI format. A FLDCIF_* value
+	optional uint32 tpc = 13;		// TS 36.213, sec 5.1.1.1
+	optional uint32 harq_process = 14; 	// HARQ process ID
+	optional uint32 dai = 15;      		// TDD only
+	optional uint32 vrb_format = 16; 	// One of the FLVRBF_* values
+	optional uint32 tb_swap = 17;	 	// Boolean. TB to codeword swap flag
+	optional uint32 sps_release = 18;   	// Flag value
+	optional uint32 pdcch_order = 19;
+	optional uint32 preamble_index = 20;	// Only valid if pdcch_order = 1
+	optional uint32 prach_mask_index = 21;	// Only valid if pdcch_order = 1
+	optional uint32 n_gap = 22;	   	// One of the FLNGV_* values
+	optional uint32 tbs_idx = 23;		// The TBS index for Format 1A
+	optional uint32 dl_power_offset = 24;	// For format 1D
+	optional uint32 pdcch_power_offset = 25; // DL PDCCH power boosting in dB
+	optional uint32 cif_present = 26;    	// Boolean. Indication of CIF field
+	optional uint32 cif = 27;     		// CIF for cross-carrier scheduling
+}
+
+//
+// Messages related to the creation of RLC PDUs
+//
+
+message flex_rlc_pdu {
+	repeated flex_rlc_pdu_tb rlc_pdu_tb = 1; // list of parameters for the creation of RLC PDUs. One for each TB
+}
+
+message flex_rlc_pdu_tb {
+	optional uint32 logical_channel_id = 1;
+	optional uint32 size = 2;	   // Maximum RLC PDU to be created in bytes
+}
+
+//
+// MAC content types related enums
+//
+
+enum flex_dci_format {
+     FLDCIF_1 = 0;
+     FLDCIF_1A = 1;
+     FLDCIF_1B = 2;
+     FLDCIF_1C = 3;
+     FLDCIF_1D = 4;
+     FLDCIF_2 = 5;
+     FLDCIF_2A = 6;
+     FLDCIF_2B = 7;
+     FLDCIF_3 = 8;
+     FLDCIF_3A = 9;
+}
+
+enum flex_vrb_format {
+     FLVRBF_LOCALIZED = 0;
+     FLVRBF_DISTRIBUTED = 1;
+}
+
+enum flex_ngap_val {
+     FLNGV_1 = 0;
+     FLNGV_2 = 1;
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/stats_common.proto b/openair2/ENB_APP/MESSAGES/V2/stats_common.proto
new file mode 100644
index 0000000000000000000000000000000000000000..70f99618ac3f4d959fe698c2644da9aecb17ddae
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/stats_common.proto
@@ -0,0 +1,182 @@
+package protocol;
+
+//
+// UE related statistics
+//
+
+// RLC buffer status for a specific logical channel of a UE
+message flex_rlc_bsr {
+	optional uint32 lc_id = 1;
+	optional uint32 tx_queue_size = 2;
+	optional uint32 tx_queue_hol_delay = 3;
+	optional uint32 retransmission_queue_size = 4;
+	optional uint32 retransmission_queue_hol_delay = 5;
+	optional uint32 status_pdu_size = 6;
+}
+
+// Flags for MAC Control Elements
+enum flex_ce_type {
+     FLPCET_TA = 1;
+     FLPCET_DRX = 2;
+     FLPCET_CR = 4;
+     FLPCET_CA = 8;
+}
+
+// Types of DL CSI reports
+enum flex_csi_type {
+     FLCSIT_P10 = 0;
+     FLCSIT_P11 = 1;
+     FLCSIT_P20 = 2;
+     FLCSIT_P21 = 3;
+     FLCSIT_A12 = 4;
+     FLCSIT_A22 = 5;
+     FLCSIT_A20 = 6;
+     FLCSIT_A30 = 7;
+     FLCSIT_A31 = 8;
+}
+
+// CSI type P10
+message flex_csi_p10 {
+	optional uint32 wb_cqi = 1;
+}
+
+// CSI type P11
+message flex_csi_p11 {
+	repeated uint32 wb_cqi = 1;
+	optional uint32 wb_pmi = 2;
+}
+
+// CSI type P20
+message flex_csi_p20 {
+	optional uint32 wb_cqi = 1;
+	optional uint32 sb_cqi = 2;
+	optional uint32 bandwidth_part_index = 3;
+	optional uint32 sb_index = 4;
+}
+
+// CSI type P21
+message flex_csi_p21 {
+	repeated uint32 wb_cqi = 1;
+	optional uint32 wb_pmi = 2;
+	repeated uint32 sb_cqi = 3;
+	optional uint32 badwidth_part_index = 4;
+	optional uint32 sb_index = 5;
+}
+
+// CSI type A12
+message flex_csi_a12 {
+	repeated uint32 wb_cqi = 1;
+	repeated uint32 sb_pmi = 2;
+}
+
+// CSI type A22
+message flex_csi_a22 {
+	repeated uint32 wb_cqi = 1;
+	repeated uint32 sb_cqi = 2;
+	optional uint32 wb_pmi = 3;
+	optional uint32 sb_pmi = 4;
+	repeated uint32 sb_list = 5;
+}
+
+// CSI type A20
+message flex_csi_a20 {
+	optional uint32 wb_cqi = 1;
+	optional uint32 sb_cqi = 2;
+	repeated uint32 sb_list = 3;
+}
+
+// CSI type A30
+message flex_csi_a30 {
+	optional uint32 wb_cqi = 1;
+	repeated uint32 sb_cqi = 2;
+}
+
+// CSI type A31
+message flex_csi_a31 {
+	repeated uint32 wb_cqi = 1;
+	repeated flex_msb_cqi sb_cqi = 2;
+	optional uint32 wb_pmi = 3;
+}
+
+// The CQI for the M-preffered subband
+message flex_msb_cqi {
+	repeated uint32 sb_cqi = 1;
+}
+
+// The CSI report of the UE for a specific servCellIndex
+message flex_dl_csi {
+	optional uint32 serv_cell_index = 1;
+	optional uint32 ri = 2;
+	optional flex_csi_type type = 3;
+	oneof report {
+	      flex_csi_p10 p10csi = 4;
+	      flex_csi_p11 p11csi = 5;
+	      flex_csi_p20 p20csi = 6;
+	      flex_csi_p21 p21csi = 7;
+	      flex_csi_a12 a12csi = 8;
+	      flex_csi_a22 a22csi = 9;
+	      flex_csi_a20 a20csi = 10;
+	      flex_csi_a30 a30csi = 11;
+	      flex_csi_a31 a31csi = 12;
+	}
+}
+
+// The full DL CQI report for all CC of a UE
+message flex_dl_cqi_report {
+	optional uint32 sfn_sn = 1;
+	repeated flex_dl_csi csi_report = 2;
+}
+
+// Paging message info
+message flex_paging_info {
+	optional uint32 paging_index = 1;
+	optional uint32 paging_message_size = 2;
+	optional uint32 paging_subframe = 3;
+	optional uint32 carrier_index = 4;
+}
+
+// Report for the paging buffer status
+message flex_paging_buffer_report {
+	repeated flex_paging_info paging_info = 1;
+}
+
+// The type of UL CQI
+enum flex_ul_cqi_type {
+     FLUCT_SRS = 0;
+     FLUCT_PUSCH = 1;
+     FLUCT_PUCCH_1 = 2;
+     FLUCT_PUCCH_2 = 3;
+     FLUCT_PRACH = 4;
+}
+
+// UL CQI report for a specific UE for a given report type
+message flex_ul_cqi {
+	optional flex_ul_cqi_type type = 1;
+	repeated uint32 sinr = 2;
+	optional uint32 serv_cell_index = 3;
+}
+
+// Full UL CQI report for a specific UE
+message flex_ul_cqi_report {
+	optional uint32 sfn_sn = 1;
+	repeated flex_ul_cqi cqi_meas = 2;
+	repeated flex_pucch_dbm pucch_dbm = 3;
+}
+
+message flex_pucch_dbm {
+	optional int32 p0_pucch_dbm = 1;
+	optional uint32 serv_cell_index = 2;
+}
+
+//
+// Cell related statistics
+//
+
+// The UL noise and interference report for a UE
+message flex_noise_interference_report {
+	optional uint32 sfn_sf = 1;
+	optional uint32 rip = 2;
+	optional uint32 tnp = 3;
+	optional int32 p0_nominal_pucch = 4;
+}
+
diff --git a/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto b/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto
new file mode 100644
index 0000000000000000000000000000000000000000..1b1567dda1e4b87b9f5b41bcdd05d0d2badf8af7
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/stats_messages.proto
@@ -0,0 +1,86 @@
+package protocol;
+
+//import "header.proto";
+import "stats_common.proto";
+
+//
+// Bodies of statistics report requests
+//
+
+message flex_complete_stats_request {
+	optional flex_stats_report_freq report_frequency = 1;
+	optional uint32 sf = 2;
+	optional uint32 cell_report_flags = 3;
+	optional uint32 ue_report_flags = 4;
+}
+
+message flex_cell_stats_request {
+	repeated uint32 cell = 1;
+	optional uint32 flags = 2;
+}
+
+message flex_ue_stats_request {
+	repeated uint32 rnti = 1;
+	optional uint32 flags = 2;
+}
+
+//
+// Bodies of statistics reports
+//
+
+// The full statistics report for a specific cell
+message flex_cell_stats_report {
+	optional uint32 carrier_index = 1;
+	optional uint32 flags = 2;
+	optional flex_noise_interference_report noise_inter_report = 3;
+}
+
+// Statistics report for a specific UE
+message flex_ue_stats_report {
+	optional uint32 rnti = 1;
+	optional uint32 flags = 2;
+	repeated uint32 bsr = 3;
+	optional uint32 phr = 4;
+	repeated flex_rlc_bsr rlc_report = 5;
+	optional uint32 pending_mac_ces = 6;
+	optional flex_dl_cqi_report dl_cqi_report = 7;
+	optional flex_paging_buffer_report pbr = 8;
+	optional flex_ul_cqi_report ul_cqi_report = 9;
+}
+
+//
+// Types of statistics related enums
+//
+
+
+//Types of statistics requested by the controller
+enum flex_stats_type {
+     FLST_COMPLETE_STATS = 0;
+     FLST_CELL_STATS = 1;
+     FLST_UE_STATS = 2;
+}
+
+// Report frequency for the requested statistics
+enum flex_stats_report_freq {
+     FLSRF_ONCE = 0;
+     FLSRF_PERIODICAL = 1;
+     FLSRF_CONTINUOUS = 2;
+     FLSRF_OFF = 3;
+}
+
+// Flags for cell statistics
+enum flex_cell_stats_type {
+     FLCST_NOISE_INTERFERENCE = 1;
+}
+
+// Flags for UE-related statistics
+enum flex_ue_stats_type {
+     FLUST_BSR = 1;
+     FLUST_PRH = 2;
+     FLUST_RLC_BS = 4;
+     FLUST_MAC_CE_BS = 8;
+     FLUST_DL_CQI = 16;
+     FLUST_PBS = 32;
+     FLUST_UL_CQI = 64;
+     // To be extended with more types of stats
+}
\ No newline at end of file
diff --git a/openair2/ENB_APP/MESSAGES/V2/time_common.proto b/openair2/ENB_APP/MESSAGES/V2/time_common.proto
new file mode 100644
index 0000000000000000000000000000000000000000..30a56bb776957d245e673ac44e8e2ca255408c71
--- /dev/null
+++ b/openair2/ENB_APP/MESSAGES/V2/time_common.proto
@@ -0,0 +1,29 @@
+package protocol;
+
+enum flex_harq_status {
+     FLHS_ACK = 0;
+     FLHS_NACK = 1;
+     FLHS_DTX = 2;
+}
+
+enum flex_reception_status {
+     FLRS_OK = 0;
+     FLRS_NOT_OK = 1;
+     FLRS_NOT_VALID = 2;
+}
+
+message flex_dl_info {
+	optional uint32 rnti = 1;
+	optional uint32 harq_process_id = 2;
+	repeated uint32 harq_status = 3;
+	optional uint32 serv_cell_index = 4;
+}
+
+message flex_ul_info {
+	optional uint32 rnti = 1;
+	repeated uint32 ul_reception = 2;
+	optional uint32 reception_status = 3;
+	optional uint32 tpc = 4;
+	optional uint32 serv_cell_index = 5; 
+}
+
diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c
index 217f44fcf5a6e0fbac06a8506e2ba38ccbcc10e6..3734bc4a2b11d9c66ab09b074dbffa78216f591b 100644
--- a/openair2/ENB_APP/enb_app.c
+++ b/openair2/ENB_APP/enb_app.c
@@ -49,6 +49,10 @@
 #   include "gtpv1u_eNB_task.h"
 # endif
 
+#if defined(FLEXRAN_AGENT_SB_IF)
+#   include "flexran_agent.h"
+#endif
+
 extern unsigned char NB_eNB_INST;
 #endif
 
@@ -287,7 +291,7 @@ void *eNB_app_task(void *args_p)
 
   itti_mark_task_ready (TASK_ENB_APP);
 
-# if defined(ENABLE_USE_MME)
+  # if defined(ENABLE_ITTI)
 #   if defined(OAI_EMU)
   enb_nb =        oai_emulation.info.nb_enb_local;
   enb_id_start =  oai_emulation.info.first_enb_local;
@@ -297,7 +301,7 @@ void *eNB_app_task(void *args_p)
                "Last eNB index is greater or equal to maximum eNB index (%d/%d)!",
                enb_id_end, NUMBER_OF_eNB_MAX);
 #   endif
-# endif
+  # endif
 
   enb_properties_p = enb_config_get();
 
@@ -310,6 +314,14 @@ void *eNB_app_task(void *args_p)
     configure_rrc(enb_id, enb_properties_p);
   }
 
+#if defined (FLEXRAN_AGENT_SB_IF)
+  
+  for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
+    printf("\n start enb agent %d\n", enb_id);
+    flexran_agent_start(enb_id, enb_properties_p);
+  }
+#endif 
+
 # if defined(ENABLE_USE_MME)
   /* Try to register each eNB */
   registered_enb = 0;
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index eb31e62362a054e909abbd0b959aba21a78debb0..fb4c6266cae811568d6b1e132ebcf8c04fb7b2ef 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -190,6 +190,12 @@
 #define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U         "ENB_IPV4_ADDRESS_FOR_S1U"
 #define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U              "ENB_PORT_FOR_S1U"
 
+#define ENB_CONFIG_STRING_NETWORK_CONTROLLER_CONFIG     "NETWORK_CONTROLLER"
+#define ENB_CONFIG_STRING_FLEXRAN_AGENT_INTERFACE_NAME      "FLEXRAN_AGENT_INTERFACE_NAME"
+#define ENB_CONFIG_STRING_FLEXRAN_AGENT_IPV4_ADDRESS        "FLEXRAN_AGENT_IPV4_ADDRESS"
+#define ENB_CONFIG_STRING_FLEXRAN_AGENT_PORT                "FLEXRAN_AGENT_PORT"
+#define ENB_CONFIG_STRING_FLEXRAN_AGENT_CACHE               "FLEXRAN_AGENT_CACHE"
+
 #define ENB_CONFIG_STRING_RRH_GW_CONFIG                   "rrh_gw_config"
 #define ENB_CONFIG_STRING_RRH_GW_LOCAL_IF_NAME            "local_if_name"
 #define ENB_CONFIG_STRING_RRH_GW_LOCAL_ADDRESS            "local_address"
@@ -335,6 +341,15 @@ void enb_config_display(void)
       }
     }
 
+#if defined(FLEXRAN_AGENT_SB_IF)
+    printf( "\nFLEXRAN AGENT CONFIG : \n\n");
+    printf( "\tInterface name:           \t%s:\n",enb_properties.properties[i]->flexran_agent_interface_name);
+    printf( "\tInterface IP Address:     \t%s:\n",enb_properties.properties[i]->flexran_agent_ipv4_address);
+    printf( "\tInterface PORT:           \t%d:\n\n",enb_properties.properties[i]->flexran_agent_port);
+    printf( "\tCache directory:          \t%s:\n",enb_properties.properties[i]->flexran_agent_cache);
+    
+#endif 
+
     for (j=0; j< enb_properties.properties[i]->nb_cc; j++) {
       // CC_ID node function/timing
       printf( "\n\tnode_function for CC %d:      \t%s:\n",j,eNB_functions[enb_properties.properties[i]->cc_node_function[j]]);
@@ -659,6 +674,10 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
   char             *address                       = NULL;
   char             *cidr                          = NULL;
   char             *astring                       = NULL;
+  char*             flexran_agent_interface_name      = NULL;
+  char*             flexran_agent_ipv4_address        = NULL;
+  libconfig_int     flexran_agent_port                = 0;
+  char*             flexran_agent_cache               = NULL;
   libconfig_int     otg_ue_id                     = 0;
   char*             otg_app_type                  = NULL;
   char*             otg_bg_traffic                = NULL;
@@ -1053,14 +1072,14 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
 
               if ((nb_antennas_tx <1) || (nb_antennas_tx > 64))
                 AssertFatal (0,
-                             "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antennas_tx choice: 1..4 !\n",
+                             "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antennas_tx choice: 1..64 !\n",
                              lib_config_file_name_pP, i, nb_antennas_tx);
 
               enb_properties.properties[enb_properties_index]->nb_antennas_rx[j] = nb_antennas_rx;
 
-              if ((nb_antennas_rx <1) || (nb_antennas_rx > 4))
+              if ((nb_antennas_rx <1) || (nb_antennas_rx > 64))
                 AssertFatal (0,
-                             "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antennas_rx choice: 1..4 !\n",
+                             "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for nb_antennas_rx choice: 1..64 !\n",
                              lib_config_file_name_pP, i, nb_antennas_rx);
 
               enb_properties.properties[enb_properties_index]->tx_gain[j] = tx_gain;
@@ -2456,6 +2475,35 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
               }
             }
           }
+	  
+	  // Network Controller 
+	  subsetting = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_NETWORK_CONTROLLER_CONFIG);
+
+          if (subsetting != NULL) {
+            if (  (
+                   config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_INTERFACE_NAME,
+                                                 (const char **)&flexran_agent_interface_name)
+                   && config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_IPV4_ADDRESS,
+                                                    (const char **)&flexran_agent_ipv4_address)
+                   && config_setting_lookup_int(subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_PORT,
+                                                &flexran_agent_port)
+		   && config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_CACHE,
+						    (const char **)&flexran_agent_cache)
+                 )
+              ) {
+              enb_properties.properties[enb_properties_index]->flexran_agent_interface_name = strdup(flexran_agent_interface_name);
+              cidr = flexran_agent_ipv4_address;
+              address = strtok(cidr, "/");
+	      enb_properties.properties[enb_properties_index]->flexran_agent_ipv4_address = strdup(address);
+	      /*  if (address) {
+                IPV4_STR_ADDR_TO_INT_NWBO (address, enb_properties.properties[enb_properties_index]->flexran_agent_ipv4_address, "BAD IP ADDRESS FORMAT FOR eNB Agent !\n" );
+		}*/
+
+              enb_properties.properties[enb_properties_index]->flexran_agent_port = flexran_agent_port;
+	      enb_properties.properties[enb_properties_index]->flexran_agent_cache = strdup(flexran_agent_cache);
+            }
+          }
+	  
 
           // OTG _CONFIG
           setting_otg = config_setting_get_member (setting_enb, ENB_CONF_STRING_OTG_CONFIG);
diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h
index 9e53af172d64e6347ac073a1f04ca0ba6545808f..fd53395311c4e3eeef5fda3bb42062c60687b7e8 100644
--- a/openair2/ENB_APP/enb_config.h
+++ b/openair2/ENB_APP/enb_config.h
@@ -228,6 +228,10 @@ typedef struct Enb_properties_s {
   char               *enb_interface_name_for_S1_MME;
   in_addr_t           enb_ipv4_address_for_S1_MME;
 
+  char               *flexran_agent_interface_name;
+  in_addr_t           flexran_agent_ipv4_address;
+  tcp_udp_port_t      flexran_agent_port;
+  char               *flexran_agent_cache;
 
   /* Nb of RRH to connect to */
   uint8_t             nb_rrh_gw;
diff --git a/openair2/ENB_APP/flexran_agent.c b/openair2/ENB_APP/flexran_agent.c
new file mode 100644
index 0000000000000000000000000000000000000000..beca1062bd6aa0fbd82a20ad5a0c39c0d0dfa899
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent.c
@@ -0,0 +1,319 @@
+/*
+ * 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.0  (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 flexran_agent.h
+ * \brief top level flexran agent receive thread and itti task
+ * \author Xenofon Foukas and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+#include "flexran_agent_common.h"
+#include "log.h"
+#include "flexran_agent.h"
+#include "flexran_agent_mac_defs.h"
+
+#include "flexran_agent_extern.h"
+
+#include "assertions.h"
+
+#include "flexran_agent_net_comm.h"
+#include "flexran_agent_async.h"
+
+//#define TEST_TIMER
+
+flexran_agent_instance_t flexran_agent[NUM_MAX_ENB];
+
+char in_ip[40];
+static uint16_t in_port;
+char local_cache[40];
+
+void *send_thread(void *args);
+void *receive_thread(void *args);
+pthread_t new_thread(void *(*f)(void *), void *b);
+Protocol__FlexranMessage *flexran_agent_timeout(void* args);
+
+
+int agent_task_created = 0;
+/* 
+ * enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller 
+ * and can interact with other itti tasks
+*/
+void *flexran_agent_task(void *args){
+
+  //flexran_agent_instance_t         *d = (flexran_agent_instance_t *) args;
+  Protocol__FlexranMessage *msg;
+  void *data;
+  int size;
+  err_code_t err_code;
+  int                   priority;
+
+  MessageDef                     *msg_p           = NULL;
+  const char                     *msg_name        = NULL;
+  instance_t                      instance;
+  int                             result;
+  struct flexran_agent_timer_element_s * elem = NULL;
+
+  itti_mark_task_ready(TASK_FLEXRAN_AGENT);
+
+  do {
+    // Wait for a message
+    itti_receive_msg (TASK_FLEXRAN_AGENT, &msg_p);
+    DevAssert(msg_p != NULL);
+    msg_name = ITTI_MSG_NAME (msg_p);
+    instance = ITTI_MSG_INSTANCE (msg_p);
+
+    switch (ITTI_MSG_ID(msg_p)) {
+    case TERMINATE_MESSAGE:
+      itti_exit_task ();
+      break;
+
+    case MESSAGE_TEST:
+      LOG_I(FLEXRAN_AGENT, "Received %s\n", ITTI_MSG_NAME(msg_p));
+      break;
+    
+    case TIMER_HAS_EXPIRED:
+      msg = flexran_agent_process_timeout(msg_p->ittiMsg.timer_has_expired.timer_id, msg_p->ittiMsg.timer_has_expired.arg);
+      if (msg != NULL){
+	data=flexran_agent_pack_message(msg,&size);
+	elem = get_timer_entry(msg_p->ittiMsg.timer_has_expired.timer_id);
+	if (flexran_agent_msg_send(elem->agent_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
+	  err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+	  goto error;
+	}
+
+	LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+      }
+      break;
+
+    default:
+      LOG_E(FLEXRAN_AGENT, "Received unexpected message %s\n", msg_name);
+      break;
+    }
+
+    result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
+    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    continue;
+  error:
+    LOG_E(FLEXRAN_AGENT,"flexran_agent_task: error %d occured\n",err_code);
+  } while (1);
+
+  return NULL;
+}
+
+void *receive_thread(void *args) {
+
+  flexran_agent_instance_t         *d = args;
+  void                  *data;
+  int                   size;
+  int                   priority;
+  err_code_t             err_code;
+
+  Protocol__FlexranMessage *msg;
+  
+  while (1) {
+
+    while (flexran_agent_msg_recv(d->enb_id, FLEXRAN_AGENT_DEFAULT, &data, &size, &priority) == 0) {
+      
+      LOG_D(FLEXRAN_AGENT,"received message with size %d\n", size);
+  
+      // Invoke the message handler
+      msg=flexran_agent_handle_message(d->enb_id, data, size);
+
+      free(data);
+    
+      // check if there is something to send back to the controller
+      if (msg != NULL){
+	data=flexran_agent_pack_message(msg,&size);
+
+	if (flexran_agent_msg_send(d->enb_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
+	  err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+	  goto error;
+	}
+      
+	LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+      } 
+    }
+  }
+    
+  return NULL;
+
+error:
+  LOG_E(FLEXRAN_AGENT,"receive_thread: error %d occured\n",err_code);
+  return NULL;
+}
+
+
+/* utility function to create a thread */
+pthread_t new_thread(void *(*f)(void *), void *b) {
+  pthread_t t;
+  pthread_attr_t att;
+
+  if (pthread_attr_init(&att)){ 
+    fprintf(stderr, "pthread_attr_init err\n"); 
+    exit(1); 
+  }
+
+  struct sched_param sched_param_recv_thread;
+
+  sched_param_recv_thread.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1;
+  pthread_attr_setschedparam(&att, &sched_param_recv_thread);
+  pthread_attr_setschedpolicy(&att, SCHED_FIFO);
+
+  if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) { 
+    fprintf(stderr, "pthread_attr_setdetachstate err\n"); 
+    exit(1); 
+  }
+  if (pthread_create(&t, &att, f, b)) { 
+    fprintf(stderr, "pthread_create err\n"); 
+    exit(1); 
+  }
+  if (pthread_attr_destroy(&att)) { 
+    fprintf(stderr, "pthread_attr_destroy err\n"); 
+    exit(1); 
+  }
+
+  return t;
+}
+
+int channel_container_init = 0;
+int flexran_agent_start(mid_t mod_id, const Enb_properties_array_t* enb_properties){
+  
+  int channel_id;
+  
+  flexran_set_enb_vars(mod_id, RAN_LTE_OAI);
+  flexran_agent[mod_id].enb_id = mod_id;
+  
+  /* 
+   * check the configuration
+   */ 
+  if (enb_properties->properties[mod_id]->flexran_agent_cache != NULL) {
+    strncpy(local_cache, enb_properties->properties[mod_id]->flexran_agent_cache, sizeof(local_cache));
+    local_cache[sizeof(local_cache) - 1] = 0;
+  } else {
+    strcpy(local_cache, DEFAULT_FLEXRAN_AGENT_CACHE);
+  }
+  
+  if (enb_properties->properties[mod_id]->flexran_agent_ipv4_address != NULL) {
+    strncpy(in_ip, enb_properties->properties[mod_id]->flexran_agent_ipv4_address, sizeof(in_ip) );
+    in_ip[sizeof(in_ip) - 1] = 0; // terminate string
+  } else {
+    strcpy(in_ip, DEFAULT_FLEXRAN_AGENT_IPv4_ADDRESS ); 
+  }
+  
+  if (enb_properties->properties[mod_id]->flexran_agent_port != 0 ) {
+    in_port = enb_properties->properties[mod_id]->flexran_agent_port;
+  } else {
+    in_port = DEFAULT_FLEXRAN_AGENT_PORT ;
+  }
+  LOG_I(FLEXRAN_AGENT,"starting enb agent client for module id %d on ipv4 %s, port %d\n",  
+	flexran_agent[mod_id].enb_id,
+	in_ip,
+	in_port);
+
+  /*
+   * Initialize the channel container
+   */
+  if (!channel_container_init) {
+    flexran_agent_init_channel_container();
+    channel_container_init = 1;
+  }
+  /*Create the async channel info*/
+  flexran_agent_instance_t *channel_info = flexran_agent_async_channel_info(mod_id, in_ip, in_port);
+
+  /*Create a channel using the async channel info*/
+  channel_id = flexran_agent_create_channel((void *) channel_info, 
+					flexran_agent_async_msg_send, 
+					flexran_agent_async_msg_recv,
+					flexran_agent_async_release);
+
+  
+  if (channel_id <= 0) {
+    goto error;
+  }
+
+  flexran_agent_channel_t *channel = get_channel(channel_id);
+  
+  if (channel == NULL) {
+    goto error;
+  }
+
+  /*Register the channel for all underlying agents (use FLEXRAN_AGENT_MAX)*/
+  flexran_agent_register_channel(mod_id, channel, FLEXRAN_AGENT_MAX);
+
+  /*Example of registration for a specific agent(MAC):
+   *flexran_agent_register_channel(mod_id, channel, FLEXRAN_AGENT_MAC);
+   */
+
+  /*Initialize the continuous MAC stats update mechanism*/
+  flexran_agent_init_cont_mac_stats_update(mod_id);
+  
+  new_thread(receive_thread, &flexran_agent[mod_id]);
+
+  /*Initialize and register the mac xface. Must be modified later
+   *for more flexibility in agent management */
+
+  AGENT_MAC_xface *mac_agent_xface = (AGENT_MAC_xface *) malloc(sizeof(AGENT_MAC_xface));
+  flexran_agent_register_mac_xface(mod_id, mac_agent_xface);
+  
+  /* 
+   * initilize a timer 
+   */ 
+  
+  flexran_agent_init_timer();
+
+  /*
+   * Initialize the mac agent
+   */
+  flexran_agent_init_mac_agent(mod_id);
+  
+  /* 
+   * start the enb agent task for tx and interaction with the underlying network function
+   */ 
+  if (!agent_task_created) {
+    if (itti_create_task (TASK_FLEXRAN_AGENT, flexran_agent_task, (void *) &flexran_agent[mod_id]) < 0) {
+      LOG_E(FLEXRAN_AGENT, "Create task for FlexRAN Agent failed\n");
+      return -1;
+    }
+    agent_task_created = 1;
+  }
+  
+  LOG_I(FLEXRAN_AGENT,"client ends\n");
+  return 0;
+
+error:
+  LOG_I(FLEXRAN_AGENT,"there was an error\n");
+  return 1;
+
+}
+
+Protocol__FlexranMessage *flexran_agent_timeout(void* args){
+
+  //  flexran_agent_timer_args_t *timer_args = calloc(1, sizeof(*timer_args));
+  //memcpy (timer_args, args, sizeof(*timer_args));
+  flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
+  
+  LOG_I(FLEXRAN_AGENT, "flexran_agent %d timeout\n", timer_args->mod_id);
+  //LOG_I(FLEXRAN_AGENT, "eNB action %d ENB flags %d \n", timer_args->cc_actions,timer_args->cc_report_flags);
+  //LOG_I(FLEXRAN_AGENT, "UE action %d UE flags %d \n", timer_args->ue_actions,timer_args->ue_report_flags);
+  
+  return NULL;
+}
diff --git a/openair2/ENB_APP/flexran_agent.h b/openair2/ENB_APP/flexran_agent.h
new file mode 100644
index 0000000000000000000000000000000000000000..21ea21aafcf336551b9c276ef51d0e9976a34b8e
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent.h
@@ -0,0 +1,46 @@
+/*
+ * 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.0  (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 flexran_agent.h
+ * \brief top level flexran agent  
+ * \author Navid Nikaein and Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_H_
+#define FLEXRAN_AGENT_H_
+
+#include "enb_config.h" // for enb properties
+#include "flexran_agent_common.h"
+
+
+/* Initiation and termination of the eNodeB agent */
+int flexran_agent_start(mid_t mod_id, const Enb_properties_array_t* enb_properties);
+int flexran_agent_stop(mid_t mod_id);
+
+/* 
+ * enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller 
+ * and can interact with other itti tasks
+*/
+void *flexran_agent_task(void *args);
+
+#endif
diff --git a/openair2/ENB_APP/flexran_agent_async.c b/openair2/ENB_APP/flexran_agent_async.c
new file mode 100644
index 0000000000000000000000000000000000000000..978b44929d7607b0b1a384447255d506e6de10c1
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_async.c
@@ -0,0 +1,99 @@
+/*
+ * 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.0  (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 flexran_agent_async.c
+ * \brief channel implementation for async interface
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#include "flexran_agent_async.h"
+#include "flexran_agent_defs.h"
+
+#include "log.h"
+
+flexran_agent_async_channel_t * flexran_agent_async_channel_info(mid_t mod_id, char *dst_ip, uint16_t dst_port) {
+
+  flexran_agent_async_channel_t *channel;
+  channel = (flexran_agent_async_channel_t *) malloc(sizeof(flexran_agent_channel_t));
+  
+  if (channel == NULL)
+    goto error;
+
+  channel->enb_id = mod_id;
+  /*Create a socket*/
+  channel->link = new_link_client(dst_ip, dst_port);
+  if (channel->link == NULL) goto error;
+  
+  LOG_I(FLEXRAN_AGENT,"starting enb agent client for module id %d on ipv4 %s, port %d\n",  
+	channel->enb_id,
+	dst_ip,
+	dst_port);
+  
+   /* 
+   * create a message queue
+   */ 
+  // Set size of queues statically for now
+  channel->send_queue = new_message_queue(500);
+  if (channel->send_queue == NULL) goto error;
+  channel->receive_queue = new_message_queue(500);
+  if (channel->receive_queue == NULL) goto error;
+  
+   /* 
+   * create a link manager 
+   */  
+  channel->manager = create_link_manager(channel->send_queue, channel->receive_queue, channel->link);
+  if (channel->manager == NULL) goto error;
+  
+  return channel;
+
+ error:
+  LOG_I(FLEXRAN_AGENT,"there was an error\n");
+  return 1;
+}
+
+int flexran_agent_async_msg_send(void *data, int size, int priority, void *channel_info) {
+  flexran_agent_async_channel_t *channel;
+  channel = (flexran_agent_channel_t *)channel_info;
+
+  return message_put(channel->send_queue, data, size, priority);
+}
+
+int flexran_agent_async_msg_recv(void **data, int *size, int *priority, void *channel_info) {
+  flexran_agent_async_channel_t *channel;
+  channel = (flexran_agent_async_channel_t *)channel_info;
+
+  return message_get(channel->receive_queue, data, size, priority);
+}
+
+void flexran_agent_async_release(flexran_agent_channel_t *channel) {
+  flexran_agent_async_channel_t *channel_info;
+  channel_info = (flexran_agent_async_channel_t *) channel->channel_info;
+
+  destroy_link_manager(channel_info->manager);
+  
+  destroy_message_queue(channel_info->send_queue);
+  destroy_message_queue(channel_info->receive_queue);
+  
+  close_link(channel_info->link);
+  free(channel_info);
+}
diff --git a/openair2/ENB_APP/flexran_agent_async.h b/openair2/ENB_APP/flexran_agent_async.h
new file mode 100644
index 0000000000000000000000000000000000000000..b097b15c2590885648a32d010e8287626022f562
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_async.h
@@ -0,0 +1,55 @@
+/*
+ * 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.0  (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 flexran_agent_async.h
+ * \brief channel implementation for async interface
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_ASYNC_H_
+#define FLEXRAN_AGENT_ASYNC_H_
+
+#include "flexran_agent_net_comm.h"
+
+typedef struct {
+  mid_t            enb_id;
+  socket_link_t   *link;
+  message_queue_t *send_queue;
+  message_queue_t *receive_queue;
+  link_manager_t  *manager;
+} flexran_agent_async_channel_t;
+
+/* Create a new channel for a given destination ip and destination port */
+flexran_agent_async_channel_t * flexran_agent_async_channel_info(mid_t mod_id, char *dst_ip, uint16_t dst_port);
+
+/* Send a message to the given channel */
+int flexran_agent_async_msg_send(void *data, int size, int priority, void *channel_info);
+
+/* Receive a message from a given channel */
+int flexran_agent_async_msg_recv(void **data, int *size, int *priority, void *channel_info);
+
+/* Release a channel */
+void flexran_agent_async_release(flexran_agent_channel_t *channel);
+
+
+#endif /*FLEXRAN_AGENT_ASYNC_H_*/
diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ccca6602b5d8f2fd60a4f3f37b3f71dd01b6476
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_common.c
@@ -0,0 +1,2279 @@
+/*
+ * 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.0  (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 flexran_agent_common.c
+ * \brief common primitives for all agents 
+ * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+#include<stdio.h>
+#include <time.h>
+
+#include "flexran_agent_common.h"
+#include "flexran_agent_common_internal.h"
+#include "flexran_agent_extern.h"
+#include "PHY/extern.h"
+#include "log.h"
+
+#include "SCHED/defs.h"
+#include "RRC/LITE/extern.h"
+#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
+#include "rrc_eNB_UE_context.h"
+
+void * enb[NUM_MAX_ENB];
+void * enb_ue[NUM_MAX_ENB];
+void * enb_rrc[NUM_MAX_ENB];
+
+/*
+ * message primitives
+ */
+
+int flexran_agent_serialize_message(Protocol__FlexranMessage *msg, void **buf, int *size) {
+
+  *size = protocol__flexran_message__get_packed_size(msg);
+  
+  *buf = malloc(*size);
+  if (buf == NULL)
+    goto error;
+  
+  protocol__flexran_message__pack(msg, *buf);
+  
+  return 0;
+  
+ error:
+  LOG_E(FLEXRAN_AGENT, "an error occured\n"); // change the com
+  return -1;
+}
+
+
+
+/* We assume that the buffer size is equal to the message size.
+   Should be chekced durint Tx/Rx */
+int flexran_agent_deserialize_message(void *data, int size, Protocol__FlexranMessage **msg) {
+  *msg = protocol__flexran_message__unpack(NULL, size, data);
+  if (*msg == NULL)
+    goto error;
+
+  return 0;
+  
+ error:
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+
+int flexran_create_header(xid_t xid, Protocol__FlexType type,  Protocol__FlexHeader **header) {
+  
+  *header = malloc(sizeof(Protocol__FlexHeader));
+  if(*header == NULL)
+    goto error;
+  
+  protocol__flex_header__init(*header);
+  (*header)->version = FLEXRAN_VERSION;
+  (*header)->has_version = 1; 
+  // check if the type is set
+  (*header)->type = type;
+  (*header)->has_type = 1;
+  (*header)->xid = xid;
+  (*header)->has_xid = 1;
+  return 0;
+
+ error:
+  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+int flexran_agent_hello(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+ 
+  Protocol__FlexHeader *header;
+  /*TODO: Need to set random xid or xid from received hello message*/
+  xid_t xid = 1;
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_HELLO, &header) != 0)
+    goto error;
+
+  Protocol__FlexHello *hello_msg;
+  hello_msg = malloc(sizeof(Protocol__FlexHello));
+  if(hello_msg == NULL)
+    goto error;
+  protocol__flex_hello__init(hello_msg);
+  hello_msg->header = header;
+
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_HELLO_MSG;
+  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+  (*msg)->has_msg_dir = 1;
+  (*msg)->hello_msg = hello_msg;
+  return 0;
+  
+ error:
+  if(header != NULL)
+    free(header);
+  if(hello_msg != NULL)
+    free(hello_msg);
+  if(*msg != NULL)
+    free(*msg);
+  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+int flexran_agent_destroy_hello(Protocol__FlexranMessage *msg) {
+  
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_HELLO_MSG)
+    goto error;
+  
+  free(msg->hello_msg->header);
+  free(msg->hello_msg);
+  free(msg);
+  return 0;
+
+ error:
+  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+int flexran_agent_echo_request(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg) {
+  Protocol__FlexHeader *header;
+  /*TODO: Need to set a random xid*/
+  xid_t xid = 1;
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_ECHO_REQUEST, &header) != 0)
+    goto error;
+
+  Protocol__FlexEchoRequest *echo_request_msg;
+  echo_request_msg = malloc(sizeof(Protocol__FlexEchoRequest));
+  if(echo_request_msg == NULL)
+    goto error;
+  protocol__flex_echo_request__init(echo_request_msg);
+  echo_request_msg->header = header;
+
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REQUEST_MSG;
+  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+  (*msg)->echo_request_msg = echo_request_msg;
+  return 0;
+
+ error:
+  if(header != NULL)
+    free(header);
+  if(echo_request_msg != NULL)
+    free(echo_request_msg);
+  if(*msg != NULL)
+    free(*msg);
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+int flexran_agent_destroy_echo_request(Protocol__FlexranMessage *msg) {
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REQUEST_MSG)
+    goto error;
+  
+  free(msg->echo_request_msg->header);
+  free(msg->echo_request_msg);
+  free(msg);
+  return 0;
+  
+ error:
+  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+
+int flexran_agent_echo_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+  
+  xid_t xid;
+  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+  Protocol__FlexEchoRequest *echo_req = input->echo_request_msg;
+  xid = (echo_req->header)->xid;
+
+  Protocol__FlexHeader *header;
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_ECHO_REPLY, &header) != 0)
+    goto error;
+
+  Protocol__FlexEchoReply *echo_reply_msg;
+  echo_reply_msg = malloc(sizeof(Protocol__FlexEchoReply));
+  if(echo_reply_msg == NULL)
+    goto error;
+  protocol__flex_echo_reply__init(echo_reply_msg);
+  echo_reply_msg->header = header;
+
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REPLY_MSG;
+  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+  (*msg)->has_msg_dir = 1;
+  (*msg)->echo_reply_msg = echo_reply_msg;
+  return 0;
+
+ error:
+  if(header != NULL)
+    free(header);
+  if(echo_reply_msg != NULL)
+    free(echo_reply_msg);
+  if(*msg != NULL)
+    free(*msg);
+  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+int flexran_agent_destroy_echo_reply(Protocol__FlexranMessage *msg) {
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REPLY_MSG)
+    goto error;
+  
+  free(msg->echo_reply_msg->header);
+  free(msg->echo_reply_msg);
+  free(msg);
+  return 0;
+  
+ error:
+  LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG)
+    goto error;
+  free(msg->enb_config_reply_msg->header);
+  int i, j;
+  Protocol__FlexEnbConfigReply *reply = msg->enb_config_reply_msg;
+  
+  for(i = 0; i < reply->n_cell_config;i++) {
+    free(reply->cell_config[i]->mbsfn_subframe_config_rfoffset);
+    free(reply->cell_config[i]->mbsfn_subframe_config_rfperiod);
+    free(reply->cell_config[i]->mbsfn_subframe_config_sfalloc);
+    if (reply->cell_config[i]->si_config != NULL) {
+      for(j = 0; j < reply->cell_config[i]->si_config->n_si_message;j++){
+	free(reply->cell_config[i]->si_config->si_message[j]);
+      }
+      free(reply->cell_config[i]->si_config->si_message);
+      free(reply->cell_config[i]->si_config);
+    }
+    free(reply->cell_config[i]);
+  }
+  free(reply->cell_config);
+  free(reply);
+  free(msg);
+  
+  return 0;
+ error:
+  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_destroy_ue_config_reply(Protocol__FlexranMessage *msg) {
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG)
+    goto error;
+  free(msg->ue_config_reply_msg->header);
+  int i, j;
+  Protocol__FlexUeConfigReply *reply = msg->ue_config_reply_msg;
+  
+  for(i = 0; i < reply->n_ue_config;i++){
+    free(reply->ue_config[i]->capabilities);
+    free(reply->ue_config[i]);
+  }
+  free(reply->ue_config);
+  free(reply);
+  free(msg);
+
+  return 0;
+ error:
+  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_destroy_lc_config_reply(Protocol__FlexranMessage *msg) {
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG)
+    goto error;
+
+  int i, j;
+  free(msg->lc_config_reply_msg->header);
+  for (i = 0; i < msg->lc_config_reply_msg->n_lc_ue_config; i++) {
+    for (j = 0; j < msg->lc_config_reply_msg->lc_ue_config[i]->n_lc_config; j++) {
+      free(msg->lc_config_reply_msg->lc_ue_config[i]->lc_config[j]);
+    }
+    free(msg->lc_config_reply_msg->lc_ue_config[i]->lc_config);
+    free(msg->lc_config_reply_msg->lc_ue_config[i]);
+  }
+  free(msg->lc_config_reply_msg->lc_ue_config);
+  free(msg->lc_config_reply_msg);
+  free(msg);
+  return 0;
+ error:
+  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg) {
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG)
+    goto error;
+  free(msg->ue_state_change_msg->header);
+  //TODO: Free the contents of the UE config structure
+  free(msg->ue_state_change_msg);
+  free(msg);
+  return 0;
+
+ error:
+  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_destroy_enb_config_request(Protocol__FlexranMessage *msg) {
+  if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG)
+    goto error;
+  free(msg->enb_config_request_msg->header);
+  free(msg->enb_config_request_msg);
+  free(msg);
+  return 0;
+  
+ error:
+  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int flexran_agent_destroy_ue_config_request(Protocol__FlexranMessage *msg) {
+  /* TODO: Deallocate memory for a dynamically allocated UE config message */
+  return 0;
+}
+
+int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg) {
+  /* TODO: Deallocate memory for a dynamically allocated LC config message */
+  return 0;
+}
+
+// call this function to start a nanosecond-resolution timer
+struct timespec timer_start(){
+    struct timespec start_time;
+    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
+    return start_time;
+}
+
+// call this function to end a timer, returning nanoseconds elapsed as a long
+long timer_end(struct timespec start_time){
+    struct timespec end_time;
+    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
+    long diffInNanos = end_time.tv_nsec - start_time.tv_nsec;
+    return diffInNanos;
+}
+
+int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+  Protocol__FlexControlDelegation *control_delegation_msg = input->control_delegation_msg;
+
+  uint32_t delegation_type = control_delegation_msg->delegation_type;
+
+  int i;
+
+  struct timespec vartime = timer_start();
+  
+  //Write the payload lib into a file in the cache and load the lib
+  char lib_name[120];
+  char target[512];
+  snprintf(lib_name, sizeof(lib_name), "/%s.so", control_delegation_msg->name);
+  strcpy(target, local_cache);
+  strcat(target, lib_name);
+
+  FILE *f;
+  f = fopen(target, "wb");
+  fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
+  fclose(f);
+
+  long time_elapsed_nanos = timer_end(vartime);
+  *msg = NULL;
+  return 0;
+
+ error:
+  return -1;
+}
+
+int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) {
+  /*TODO: Dealocate memory for a dynamically allocated control delegation message*/
+}
+
+int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+  Protocol__FlexAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg;
+
+  apply_reconfiguration_policy(mod_id, agent_reconfiguration_msg->policy, strlen(agent_reconfiguration_msg->policy));
+
+  *msg = NULL;
+  return 0;
+}
+
+int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg) {
+  /*TODO: Dealocate memory for a dynamically allocated agent reconfiguration message*/
+}
+
+
+/*
+ * get generic info from RAN
+ */
+
+void flexran_set_enb_vars(mid_t mod_id, ran_name_t ran){
+
+  switch (ran){
+  case RAN_LTE_OAI :
+    enb[mod_id] =  (void *)&eNB_mac_inst[mod_id];
+    enb_ue[mod_id] = (void *)&eNB_mac_inst[mod_id].UE_list;
+    enb_rrc[mod_id] = (void *)&eNB_rrc_inst[mod_id];
+    break;
+  default :
+    goto error;
+  }
+
+  return; 
+
+ error:
+  LOG_E(FLEXRAN_AGENT, "unknown RAN name %d\n", ran);
+}
+
+int flexran_get_current_time_ms (mid_t mod_id, int subframe_flag){
+
+  if (subframe_flag == 1){
+    return ((eNB_MAC_INST *)enb[mod_id])->frame*10 + ((eNB_MAC_INST *)enb[mod_id])->subframe;
+  }else {
+    return ((eNB_MAC_INST *)enb[mod_id])->frame*10;
+  }
+   
+}
+
+unsigned int flexran_get_current_frame (mid_t mod_id) {
+
+  #warning "SFN will not be in [0-1023] when oaisim is used"
+  return ((eNB_MAC_INST *)enb[mod_id])->frame;
+  
+}
+
+unsigned int flexran_get_current_system_frame_num(mid_t mod_id) {
+  return (flexran_get_current_frame(mod_id) %1024);
+}
+
+unsigned int flexran_get_current_subframe (mid_t mod_id) {
+
+  return ((eNB_MAC_INST *)enb[mod_id])->subframe;
+  
+}
+
+uint16_t flexran_get_sfn_sf (mid_t mod_id) {
+  
+  frame_t frame;
+  sub_frame_t subframe;
+  uint16_t sfn_sf, frame_mask, sf_mask;
+  
+  frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
+  subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
+  frame_mask = ((1<<12) - 1);
+  sf_mask = ((1<<4) - 1);
+  sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
+  
+  return sfn_sf;
+}
+
+uint16_t flexran_get_future_sfn_sf (mid_t mod_id, int ahead_of_time) {
+  
+  frame_t frame;
+  sub_frame_t subframe;
+  uint16_t sfn_sf, frame_mask, sf_mask;
+  
+  frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
+  subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
+
+  subframe = ((subframe + ahead_of_time) % 10);
+
+  int full_frames_ahead = ((ahead_of_time / 10) % 10);
+  
+  frame = frame + full_frames_ahead;
+
+  if (subframe < flexran_get_current_subframe(mod_id)) {
+    frame++;
+  }
+
+  frame_mask = ((1<<12) - 1);
+  sf_mask = ((1<<4) - 1);
+  sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
+  
+  return sfn_sf;
+}
+
+int flexran_get_num_ues (mid_t mod_id){
+
+  return  ((UE_list_t *)enb_ue[mod_id])->num_UEs;
+}
+
+int flexran_get_ue_crnti (mid_t mod_id, mid_t ue_id) {
+
+  return  UE_RNTI(mod_id, ue_id);
+}
+
+int flexran_get_ue_bsr (mid_t mod_id, mid_t ue_id, lcid_t lcid) {
+
+  return ((UE_list_t *)enb_ue[mod_id])->UE_template[UE_PCCID(mod_id,ue_id)][ue_id].bsr_info[lcid];
+}
+
+int flexran_get_ue_phr (mid_t mod_id, mid_t ue_id) {
+
+  return ((UE_list_t *)enb_ue[mod_id])->UE_template[UE_PCCID(mod_id,ue_id)][ue_id].phr_info;
+}
+
+int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id) {
+  return ((UE_list_t *)enb_ue[mod_id])->eNB_UE_stats[UE_PCCID(mod_id,ue_id)][ue_id].dl_cqi;
+}
+
+int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
+	rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+	uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
+	mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,ENB_FLAG_YES,MBMS_FLAG_NO,channel_id,0);
+	return rlc_status.bytes_in_buffer;
+}
+
+int flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id) {
+  
+  UE_list_t *UE_list=&eNB_mac_inst[mod_id].UE_list;
+  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];
+  int rnti;
+
+  rnti = flexran_get_ue_crnti(mod_id, ue_id);
+  if (ue_sched_ctl->ta_timer == 0) {
+
+    // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...                                                                         
+    LTE_eNB_UE_stats		*eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+    ue_sched_ctl->ta_timer		      = 20;	// wait 20 subframes before taking TA measurement from PHY                                         
+    switch (PHY_vars_eNB_g[mod_id][CC_id]->frame_parms.N_RB_DL) {
+    case 6:
+      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update;
+      break;
+
+    case 15:
+      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/2;
+      break;
+
+    case 25:
+      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/4;
+      break;
+
+    case 50:
+      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/8;
+      break;
+
+    case 75:
+      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/12;
+      break;
+
+    case 100:
+      ue_sched_ctl->ta_update		      = eNB_UE_stats->timing_advance_update/16;
+      break;
+    }
+    // clear the update in case PHY does not have a new measurement after timer expiry                                               
+    eNB_UE_stats->timing_advance_update	      = 0;
+  }
+  else {
+    ue_sched_ctl->ta_timer--;
+    ue_sched_ctl->ta_update		      = 0;	// don't trigger a timing advance command                                                          
+  }
+
+  return ue_sched_ctl->ta_update	      = 0;
+
+}
+
+int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id,int CC_id) {
+  
+  UE_list_t			*UE_list      = &eNB_mac_inst[mod_id].UE_list;
+  UE_sched_ctrl			*ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];
+
+  rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+  LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
+  
+  if (eNB_UE_stats == NULL) {
+    return 0;
+  }
+
+  if (ue_sched_ctl->ta_update == 0) {
+    return 1;
+  } else {
+    return 0;
+  }
+
+}
+
+int flexran_get_active_CC(mid_t mod_id, mid_t ue_id) {
+	return ((UE_list_t *)enb_ue[mod_id])->numactiveCCs[ue_id];
+}
+
+int flexran_get_current_RI(mid_t mod_id, mid_t ue_id, int CC_id) {
+	LTE_eNB_UE_stats	*eNB_UE_stats = NULL;
+
+	int			 pCCid	      = UE_PCCID(mod_id,ue_id);
+	rnti_t			 rnti	      = flexran_get_ue_crnti(mod_id,ue_id);
+
+	eNB_UE_stats			      = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
+	
+	if (eNB_UE_stats == NULL) {
+	  return 0;
+	}
+
+	return eNB_UE_stats[CC_id].rank;
+}
+
+int flexran_get_tpc(mid_t mod_id, mid_t ue_id) {
+	LTE_eNB_UE_stats	*eNB_UE_stats = NULL;
+	int32_t			 normalized_rx_power, target_rx_power;
+	int			 tpc	      = 1;
+
+	int			 pCCid	      = UE_PCCID(mod_id,ue_id);
+	rnti_t			 rnti	      = flexran_get_ue_crnti(mod_id,ue_id);
+
+	eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, pCCid, rnti);
+
+	target_rx_power = mac_xface->get_target_pusch_rx_power(mod_id,pCCid);
+
+	if (eNB_UE_stats == NULL) {
+	  normalized_rx_power = target_rx_power;
+	} else if (eNB_UE_stats->UL_rssi != NULL) {
+	  normalized_rx_power = eNB_UE_stats->UL_rssi[0];
+	} else {
+	  normalized_rx_power = target_rx_power;
+	}
+
+	if (normalized_rx_power>(target_rx_power+1)) {
+		tpc = 0;	//-1
+	} else if (normalized_rx_power<(target_rx_power-1)) {
+		tpc = 2;	//+1
+	} else {
+		tpc = 1;	//0
+	}
+	return tpc;
+}
+
+int flexran_get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id, const int frame, const uint8_t subframe, int *id, int *round)	{ //flag_id_status = 0 then id, else status
+	/*TODO: Add int TB in function parameters to get the status of the second TB. This can be done to by editing in
+	 * get_ue_active_harq_pid function in line 272 file: phy_procedures_lte_eNB.c to add
+	 * DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch_eNB[(uint32_t)UE_id][1];*/
+
+  uint8_t harq_pid;
+  uint8_t harq_round;
+  
+
+  uint16_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+  mac_xface->get_ue_active_harq_pid(mod_id,CC_id,rnti,frame,subframe,&harq_pid,&harq_round,openair_harq_DL);
+
+  *id = harq_pid;
+  *round = harq_round;
+  /* if (round > 0) { */
+  /*   *status = 1; */
+  /* } else { */
+  /*   *status = 0; */
+  /* } */
+
+  /* return 0; */
+  return round;
+}
+
+int flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, int CC_id) {
+	LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+	uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+	eNB_UE_stats =  mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+	
+	if (eNB_UE_stats == NULL) {
+	  return -1;
+	}
+	
+	if(eNB_UE_stats->Po_PUCCH_update == 1) {
+		return eNB_UE_stats->Po_PUCCH_dBm;
+	}
+	else
+		return -1;
+}
+
+int flexran_get_p0_nominal_pucch(mid_t mod_id, int CC_id) {
+	int32_t pucch_rx_received = mac_xface->get_target_pucch_rx_power(mod_id, CC_id);
+	return pucch_rx_received;
+}
+
+int flexran_get_p0_pucch_status(mid_t mod_id, mid_t ue_id, int CC_id) {
+        LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+	uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+	eNB_UE_stats =  mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+	return eNB_UE_stats->Po_PUCCH_update;
+}
+
+int flexran_update_p0_pucch(mid_t mod_id, mid_t ue_id, int CC_id) {
+          LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+	uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
+
+	eNB_UE_stats =  mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+	eNB_UE_stats->Po_PUCCH_update = 0;
+
+	return 0;
+}
+
+
+/*
+ * ************************************
+ * Get Messages for eNB Configuration Reply
+ * ************************************
+ */
+
+int flexran_get_hopping_offset(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->pusch_config_common.pusch_HoppingOffset;
+}
+
+int flexran_get_hopping_mode(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->pusch_config_common.hoppingMode;
+}
+
+int flexran_get_n_SB(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->pusch_config_common.n_SB;
+}
+
+int flexran_get_enable64QAM(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->pusch_config_common.enable64QAM;
+}
+
+int flexran_get_phich_duration(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->phich_config_common.phich_duration;
+}
+
+int flexran_get_phich_resource(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	if(frame_parms->phich_config_common.phich_resource == oneSixth)
+		return 0;
+	else if(frame_parms->phich_config_common.phich_resource == half)
+		return 1;
+	else if(frame_parms->phich_config_common.phich_resource == one)
+		return 2;
+	else if(frame_parms->phich_config_common.phich_resource == two)
+		return 3;
+
+	return -1;
+}
+
+int flexran_get_n1pucch_an(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->pucch_config_common.n1PUCCH_AN;
+}
+
+int flexran_get_nRB_CQI(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->pucch_config_common.nRB_CQI;
+}
+
+int flexran_get_deltaPUCCH_Shift(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->pucch_config_common.deltaPUCCH_Shift;
+}
+
+int flexran_get_prach_ConfigIndex(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
+}
+
+int flexran_get_prach_FreqOffset(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset;
+}
+
+int flexran_get_maxHARQ_Msg3Tx(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->maxHARQ_Msg3Tx;
+}
+
+int flexran_get_ul_cyclic_prefix_length(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->Ncp_UL;
+}
+
+int flexran_get_dl_cyclic_prefix_length(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->Ncp;
+}
+
+int flexran_get_cell_id(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->Nid_cell;
+}
+
+int flexran_get_srs_BandwidthConfig(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->soundingrs_ul_config_common.srs_BandwidthConfig;
+}
+
+int flexran_get_srs_SubframeConfig(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
+}
+
+int flexran_get_srs_MaxUpPts(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->soundingrs_ul_config_common.srs_MaxUpPts;
+}
+
+int flexran_get_N_RB_DL(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->N_RB_DL;
+}
+
+int flexran_get_N_RB_UL(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->N_RB_UL;
+}
+
+int flexran_get_N_RBG(mid_t mod_id, int CC_id) {
+  	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->N_RBG;
+}
+
+int flexran_get_subframe_assignment(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->tdd_config;
+}
+
+int flexran_get_special_subframe_assignment(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	return frame_parms->tdd_config_S;
+}
+
+int flexran_get_ra_ResponseWindowSize(mid_t mod_id, int CC_id) {
+	Enb_properties_array_t *enb_properties;
+	enb_properties = enb_config_get();
+	return enb_properties->properties[mod_id]->rach_raResponseWindowSize[CC_id];
+}
+
+int flexran_get_mac_ContentionResolutionTimer(mid_t mod_id, int CC_id) {
+	Enb_properties_array_t *enb_properties;
+	enb_properties = enb_config_get();
+	return enb_properties->properties[mod_id]->rach_macContentionResolutionTimer[CC_id];
+}
+
+int flexran_get_duplex_mode(mid_t mod_id, int CC_id) {
+	LTE_DL_FRAME_PARMS   *frame_parms;
+
+	frame_parms = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+	if(frame_parms->frame_type == TDD)
+		return PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD;
+	else if (frame_parms->frame_type == FDD)
+		return PROTOCOL__FLEX_DUPLEX_MODE__FLDM_FDD;
+
+	return -1;
+}
+
+long flexran_get_si_window_length(mid_t mod_id, int CC_id) {
+	return  ((eNB_RRC_INST *)enb_rrc[mod_id])->carrier[CC_id].sib1->si_WindowLength;
+}
+
+int flexran_get_sib1_length(mid_t mod_id, int CC_id) {
+	return  ((eNB_RRC_INST *)enb_rrc[mod_id])->carrier[CC_id].sizeof_SIB1;
+}
+
+int flexran_get_num_pdcch_symb(mid_t mod_id, int CC_id) {
+  /* TODO: This should return the number of PDCCH symbols initially used by the cell CC_id */
+  return 0;
+  //(PHY_vars_UE_g[mod_id][CC_id]->lte_ue_pdcch_vars[mod_id]->num_pdcch_symbols);
+}
+
+
+
+/*
+ * ************************************
+ * Get Messages for UE Configuration Reply
+ * ************************************
+ */
+
+
+int flexran_get_time_alignment_timer(mid_t mod_id, mid_t ue_id) {
+	struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+	uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+	ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+	if(ue_context_p != NULL) {
+	  if(ue_context_p->ue_context.mac_MainConfig != NULL)
+	    return ue_context_p->ue_context.mac_MainConfig->timeAlignmentTimerDedicated;
+	}
+	else
+	  return -1;
+}
+
+int flexran_get_meas_gap_config(mid_t mod_id, mid_t ue_id) {
+  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+  if(ue_context_p != NULL) {
+    if(ue_context_p->ue_context.measGapConfig != NULL) {
+      if(ue_context_p->ue_context.measGapConfig->present == MeasGapConfig_PR_setup) {
+	if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) {
+	  return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP1;
+	} else if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1) {
+	  return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_GP2;
+	} else {
+	  return PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF;
+	}
+      }
+    }
+  }
+  return -1;
+}
+
+
+int flexran_get_meas_gap_config_offset(mid_t mod_id, mid_t ue_id) {
+  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+  
+  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+  
+  if(ue_context_p != NULL) {
+    if(ue_context_p->ue_context.measGapConfig != NULL){
+      if(ue_context_p->ue_context.measGapConfig->present == MeasGapConfig_PR_setup) {
+	if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) {
+	  return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp0;
+	} else if (ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1) {
+	  return ue_context_p->ue_context.measGapConfig->choice.setup.gapOffset.choice.gp0;
+	} 
+      }
+    }
+  }
+  return -1;
+}
+
+int flexran_get_ue_aggregated_max_bitrate_dl (mid_t mod_id, mid_t ue_id) {
+	return ((UE_list_t *)enb_ue[mod_id])->UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL;
+}
+
+int flexran_get_ue_aggregated_max_bitrate_ul (mid_t mod_id, mid_t ue_id) {
+	return ((UE_list_t *)enb_ue[mod_id])->UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL;
+}
+
+int flexran_get_half_duplex(mid_t ue_id) {
+  // TODO
+	//int halfduplex = 0;
+	//int bands_to_scan = ((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;
+	//for (int i =0; i < bands_to_scan; i++){
+		//if(((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->halfDuplex > 0)
+		//	halfduplex = 1;
+	//}
+	//return halfduplex;
+}
+
+int flexran_get_intra_sf_hopping(mid_t ue_id) {
+	//TODO:Get proper value
+	//temp = (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->featureGroupIndicators->buf);
+	//return (0 & ( 1 << (31)));
+}
+
+int flexran_get_type2_sb_1(mid_t ue_id) {
+	//TODO:Get proper value
+	//uint8_t temp = 0;
+	//temp = (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->featureGroupIndicators->buf);
+	//return (temp & ( 1 << (11)));
+}
+
+int flexran_get_ue_category(mid_t ue_id) {
+	//TODO:Get proper value
+	//return (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->ue_Category);
+}
+
+int flexran_get_res_alloc_type1(mid_t ue_id) {
+	//TODO:Get proper value
+	//uint8_t temp = 0;
+	//temp = (((UE_RRC_INST *)enb_ue_rrc[ue_id])->UECap->UE_EUTRA_Capability->featureGroupIndicators->buf);
+	//return (temp & ( 1 << (30)));
+}
+
+int flexran_get_ue_transmission_mode(mid_t mod_id, mid_t ue_id) {
+	struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+	uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+	ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+
+	if(ue_context_p != NULL) {
+	  if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+	    return ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode;
+	  }
+	}
+	else
+	  return -1;
+}
+
+int flexran_get_tti_bundling(mid_t mod_id, mid_t ue_id) {
+	struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+	uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+	ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+	if(ue_context_p != NULL) {
+	  if(ue_context_p->ue_context.mac_MainConfig != NULL){
+	    return ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->ttiBundling;
+	  }
+	}
+	else
+	  return -1;
+}
+
+int flexran_get_maxHARQ_TX(mid_t mod_id, mid_t ue_id) {
+  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+  
+  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+  if(ue_context_p != NULL) {
+    if(ue_context_p->ue_context.mac_MainConfig != NULL){
+      return *ue_context_p->ue_context.mac_MainConfig->ul_SCH_Config->maxHARQ_Tx;
+    }
+  }
+  return -1;
+}
+
+int flexran_get_beta_offset_ack_index(mid_t mod_id, mid_t ue_id) {
+	struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+	uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+	ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+	if(ue_context_p != NULL) {
+	  if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+	    return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_ACK_Index;
+	  }
+	}
+	else
+	  return -1;
+}
+
+int flexran_get_beta_offset_ri_index(mid_t mod_id, mid_t ue_id) {
+	struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+	uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+	ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+	if(ue_context_p != NULL) {
+	  if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+	    return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
+	  }
+	}
+	else
+	  return -1;
+}
+
+int flexran_get_beta_offset_cqi_index(mid_t mod_id, mid_t ue_id) {
+	struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+	uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+	ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+	if(ue_context_p != NULL) {
+	  if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+	    return ue_context_p->ue_context.physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
+	  }
+	}
+	else
+	  return -1;
+}
+
+int flexran_get_simultaneous_ack_nack_cqi(mid_t mod_id, mid_t ue_id) {
+  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+  
+  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+  if(ue_context_p != NULL) {
+    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+      if (ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic != NULL) {
+	return ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic->choice.setup.simultaneousAckNackAndCQI;
+      }
+    }
+  }
+  return -1;
+}
+
+int flexran_get_ack_nack_simultaneous_trans(mid_t mod_id,mid_t ue_id) {
+	return (&eNB_rrc_inst[mod_id])->carrier[0].sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission;
+}
+
+int flexran_get_aperiodic_cqi_rep_mode(mid_t mod_id,mid_t ue_id) {
+  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+  
+  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+  
+  if(ue_context_p != NULL) {
+    if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+      return *ue_context_p->ue_context.physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic;
+    }
+  }
+  return -1;
+}
+
+int flexran_get_tdd_ack_nack_feedback(mid_t mod_id, mid_t ue_id) {
+	struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+	uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+	ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+
+	if(ue_context_p != NULL) {
+	  if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+	    return ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode;
+	  }
+	}
+	else
+	  return -1;
+}
+
+int flexran_get_ack_nack_repetition_factor(mid_t mod_id, mid_t ue_id) {
+	struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+	uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+	ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+	if(ue_context_p != NULL) {
+	  if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+	    return ue_context_p->ue_context.physicalConfigDedicated->pucch_ConfigDedicated->ackNackRepetition.choice.setup.repetitionFactor;
+	  }
+	}
+	else
+	  return -1;
+}
+
+int flexran_get_extended_bsr_size(mid_t mod_id, mid_t ue_id) {
+  //TODO: need to double check
+  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+  uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+  ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+  if(ue_context_p != NULL) {
+    if(ue_context_p->ue_context.mac_MainConfig != NULL){
+      if(ue_context_p->ue_context.mac_MainConfig->ext2 != NULL){
+	long val = (*(ue_context_p->ue_context.mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10));
+	if (val > 0) {
+	  return 1;
+	}
+      }
+    }
+  }
+  return -1;
+}
+
+int flexran_get_ue_transmission_antenna(mid_t mod_id, mid_t ue_id) {
+	struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+	uint32_t rntiP = flexran_get_ue_crnti(mod_id,ue_id);
+
+	ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id],rntiP);
+
+	if(ue_context_p != NULL) {
+	  if(ue_context_p->ue_context.physicalConfigDedicated != NULL){
+	    if(ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.setup == AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_closedLoop)
+	      return 2;
+	    else if(ue_context_p->ue_context.physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.setup == AntennaInfoDedicated__ue_TransmitAntennaSelection__setup_openLoop)
+	      return 1;
+	    else
+	      return 0;
+	  }
+	}
+	else
+	  return -1;
+}
+
+int flexran_get_lcg(mid_t ue_id, mid_t lc_id) {
+  if (UE_mac_inst == NULL) {
+    return -1;
+  }
+  if(UE_mac_inst[ue_id].logicalChannelConfig[lc_id] != NULL) {
+    return *UE_mac_inst[ue_id].logicalChannelConfig[lc_id]->ul_SpecificParameters->logicalChannelGroup;
+  } else {
+    return -1;
+  }
+}
+
+int flexran_get_direction(mid_t ue_id, mid_t lc_id) {
+	/*TODO: fill with the value for the rest of LCID*/
+  if(lc_id == DCCH | lc_id == DCCH1)
+    return 2;
+  else if(lc_id == DTCH)
+    return 1;
+}
+
+int flexran_agent_ue_state_change(mid_t mod_id, uint32_t rnti, uint8_t state_change) {
+  int size;
+  Protocol__FlexranMessage *msg;
+  Protocol__FlexHeader *header;
+  void *data;
+  int priority;
+  err_code_t err_code;
+
+  int xid = 0;
+
+  if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_UE_STATE_CHANGE, &header) != 0)
+    goto error;
+
+  Protocol__FlexUeStateChange *ue_state_change_msg;
+  ue_state_change_msg = malloc(sizeof(Protocol__FlexUeStateChange));
+  if(ue_state_change_msg == NULL) {
+    goto error;
+  }
+  protocol__flex_ue_state_change__init(ue_state_change_msg);
+  ue_state_change_msg->has_type = 1;
+  ue_state_change_msg->type = state_change;
+
+  Protocol__FlexUeConfig *config;
+  config = malloc(sizeof(Protocol__FlexUeConfig));
+  if (config == NULL) {
+    goto error;
+  }
+  protocol__flex_ue_config__init(config);
+  if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED) {
+    // Simply set the rnti of the UE
+    config->has_rnti = 1;
+    config->rnti = rnti;
+  } else if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED
+	     || state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED) {
+	  	  int i = find_UE_id(mod_id, rnti);
+		  config->has_rnti = 1;
+		  config->rnti = rnti;
+	  	  if(flexran_get_time_alignment_timer(mod_id,i) != -1) {
+	  		  config->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
+	  		  config->has_time_alignment_timer = 1;
+	  	  }
+	  	  if(flexran_get_meas_gap_config(mod_id,i) != -1){
+	  		  config->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
+	  	  	  config->has_meas_gap_config_pattern = 1;
+	  	  }
+	  	  if(config->has_meas_gap_config_pattern == 1 &&
+		     config->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
+		    config->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
+		    config->has_meas_gap_config_sf_offset = 1;
+	  	  }
+	  	  //TODO: Set the SPS configuration (Optional)
+	  	  //Not supported for now, so we do not set it
+
+	  	  //TODO: Set the SR configuration (Optional)
+	  	  //We do not set it for now
+
+	  	  //TODO: Set the CQI configuration (Optional)
+	  	  //We do not set it for now
+		  
+		  if(flexran_get_ue_transmission_mode(mod_id,i) != -1) {
+	  		  config->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
+	  		  config->has_transmission_mode = 1;
+	  	  }
+
+		  config->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
+	  	  config->has_ue_aggregated_max_bitrate_ul = 1;
+
+		  config->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
+	  	  config->has_ue_aggregated_max_bitrate_dl = 1;
+
+	  	  //TODO: Set the UE capabilities
+	  	  Protocol__FlexUeCapabilities *c_capabilities;
+	  	  c_capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
+	  	  protocol__flex_ue_capabilities__init(c_capabilities);
+	  	  //TODO: Set half duplex (FDD operation)
+	  	  c_capabilities->has_half_duplex = 0;
+	  	  c_capabilities->half_duplex = 1;//flexran_get_half_duplex(i);
+	  	  //TODO: Set intra-frame hopping flag
+	  	  c_capabilities->has_intra_sf_hopping = 0;
+	  	  c_capabilities->intra_sf_hopping = 1;//flexran_get_intra_sf_hopping(i);
+	  	  //TODO: Set support for type 2 hopping with n_sb > 1
+	  	  c_capabilities->has_type2_sb_1 = 0;
+	  	  c_capabilities->type2_sb_1 = 1;//flexran_get_type2_sb_1(i);
+	  	  //TODO: Set ue category
+	  	  c_capabilities->has_ue_category = 0;
+	  	  c_capabilities->ue_category = 1;//flexran_get_ue_category(i);
+	  	  //TODO: Set UE support for resource allocation type 1
+	  	  c_capabilities->has_res_alloc_type1 = 0;
+	  	  c_capabilities->res_alloc_type1 = 1;//flexran_get_res_alloc_type1(i);
+	  	  //Set the capabilites to the message
+	  	  config->capabilities = c_capabilities;
+		  
+	  	  if(flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
+		    config->has_ue_transmission_antenna = 1;
+		    config->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_tti_bundling(mod_id,i) != -1) {
+		    config->has_tti_bundling = 1;
+		    config->tti_bundling = flexran_get_tti_bundling(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_maxHARQ_TX(mod_id,i) != -1){
+		    config->has_max_harq_tx = 1;
+		    config->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
+		    config->has_beta_offset_ack_index = 1;
+		    config->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
+		    config->has_beta_offset_ri_index = 1;
+		    config->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
+		    config->has_beta_offset_cqi_index = 1;
+		    config->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_ack_nack_simultaneous_trans(mod_id,i) != -1) {
+		    config->has_ack_nack_simultaneous_trans = 1;
+		    config->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
+		    config->has_simultaneous_ack_nack_cqi = 1;
+		    config->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
+		    config->has_aperiodic_cqi_rep_mode = 1;
+		    int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
+		    if (mode > 4) {
+		      config->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
+		    } else {
+		      config->aperiodic_cqi_rep_mode = mode;
+		    }
+	  	  }
+
+	  	  if(flexran_get_tdd_ack_nack_feedback(mod_id, i) != -1) {
+		    config->has_tdd_ack_nack_feedback = 1;
+		    config->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
+		    config->has_ack_nack_repetition_factor = 1;
+		    config->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
+	  	  }
+
+	  	  if(flexran_get_extended_bsr_size(mod_id, i) != -1) {
+		    config->has_extended_bsr_size = 1;
+		    config->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
+	  	  }
+
+		  config->has_pcell_carrier_index = 1;
+		  config->pcell_carrier_index = UE_PCCID(mod_id, i);
+	  	  //TODO: Set carrier aggregation support (boolean)
+	  	  config->has_ca_support = 0;
+	  	  config->ca_support = 0;
+	  	  if(config->has_ca_support){
+		    //TODO: Set cross carrier scheduling support (boolean)
+		    config->has_cross_carrier_sched_support = 1;
+		    config->cross_carrier_sched_support = 0;
+		    //TODO: Set secondary cells configuration
+		    // We do not set it for now. No carrier aggregation support
+		    
+		    //TODO: Set deactivation timer for secondary cell
+		    config->has_scell_deactivation_timer = 0;
+		    config->scell_deactivation_timer = 0;
+	  	  }
+  } else if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_MOVED) {
+    // TODO: Not supported for now. Leave blank
+  }
+
+  ue_state_change_msg->config = config;
+  msg = malloc(sizeof(Protocol__FlexranMessage));
+  if (msg == NULL) {
+    goto error;
+  }
+  protocol__flexran_message__init(msg);
+  msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG;
+  msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+  msg->ue_state_change_msg = ue_state_change_msg;
+
+  data = flexran_agent_pack_message(msg, &size);
+  /*Send sr info using the MAC channel of the eNB*/
+  if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
+    err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
+    goto error;
+  }
+
+  LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
+  return;
+ error:
+  LOG_D(FLEXRAN_AGENT, "Could not send UE state message\n");
+}
+
+
+
+int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+  xid_t xid;
+  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+  Protocol__FlexLcConfigRequest *lc_config_request_msg = input->lc_config_request_msg;
+  xid = (lc_config_request_msg->header)->xid;
+
+  int i, j;
+  Protocol__FlexHeader *header;
+  if(flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_GET_LC_CONFIG_REPLY, &header) != 0)
+    goto error;
+
+  Protocol__FlexLcConfigReply *lc_config_reply_msg;
+  lc_config_reply_msg = malloc(sizeof(Protocol__FlexLcConfigReply));
+  if(lc_config_reply_msg == NULL)
+    goto error;
+  protocol__flex_lc_config_reply__init(lc_config_reply_msg);
+  lc_config_reply_msg->header = header;
+
+  lc_config_reply_msg->n_lc_ue_config = flexran_get_num_ues(mod_id);
+
+  Protocol__FlexLcUeConfig **lc_ue_config;
+  if (lc_config_reply_msg->n_lc_ue_config > 0) {
+    lc_ue_config = malloc(sizeof(Protocol__FlexLcUeConfig *) * lc_config_reply_msg->n_lc_ue_config);
+    if (lc_ue_config == NULL) {
+      goto error;
+    }
+    // Fill the config for each UE
+    for (i = 0; i < lc_config_reply_msg->n_lc_ue_config; i++) {
+      lc_ue_config[i] = malloc(sizeof(Protocol__FlexLcUeConfig));
+      protocol__flex_lc_ue_config__init(lc_ue_config[i]);
+
+      lc_ue_config[i]->has_rnti = 1;
+      lc_ue_config[i]->rnti = flexran_get_ue_crnti(mod_id,i);
+
+      //TODO: Set the number of LC configurations that will be reported for this UE
+      //Set this according to the current state of the UE. This is only a temporary fix
+      int status = 0;
+      status = mac_eNB_get_rrc_status(mod_id, flexran_get_ue_crnti(mod_id, i));
+      if (status < RRC_CONNECTED) {
+	lc_ue_config[i]->n_lc_config = 0;
+      } else if (status == RRC_CONNECTED) {
+	lc_ue_config[i]->n_lc_config = 1;
+      } else {
+	lc_ue_config[i]->n_lc_config = 3;
+      }
+
+      Protocol__FlexLcConfig **lc_config;
+      if (lc_ue_config[i]->n_lc_config > 0) {
+	lc_config = malloc(sizeof(Protocol__FlexLcConfig *) * lc_ue_config[i]->n_lc_config);
+	if (lc_config == NULL) {
+	  goto error;
+	}
+	for (j = 0; j < lc_ue_config[i]->n_lc_config; j++) {
+	  lc_config[j] = malloc(sizeof(Protocol__FlexLcConfig));
+	  protocol__flex_lc_config__init(lc_config[j]);
+	 
+	  lc_config[j]->has_lcid = 1;
+	  lc_config[j]->lcid = j+1;
+	 
+	  int lcg = flexran_get_lcg(i, j+1);
+	  if (lcg >= 0 && lcg <= 3) {
+	    lc_config[j]->has_lcg = 1;
+	    lc_config[j]->lcg = flexran_get_lcg(i,j+1);
+	  }
+	 
+	  lc_config[j]->has_direction = 1;
+	  lc_config[j]->direction = flexran_get_direction(i,j+1);
+	  //TODO: Bearer type. One of FLQBT_* values. Currently only default bearer supported
+	  lc_config[j]->has_qos_bearer_type = 1;
+	  lc_config[j]->qos_bearer_type = PROTOCOL__FLEX_QOS_BEARER_TYPE__FLQBT_NON_GBR;
+
+	  //TODO: Set the QCI defined in TS 23.203, coded as defined in TS 36.413
+	  // One less than the actual QCI value. Needs to be generalized
+	  lc_config[j]->has_qci = 1;
+	  lc_config[j]->qci = 1;
+	  if (lc_config[j]->direction == PROTOCOL__FLEX_QOS_BEARER_TYPE__FLQBT_GBR) {
+	    //TODO: Set the max bitrate (UL)
+	    lc_config[j]->has_e_rab_max_bitrate_ul = 0;
+	    lc_config[j]->e_rab_max_bitrate_ul = 0;
+	    //TODO: Set the max bitrate (DL)
+	    lc_config[j]->has_e_rab_max_bitrate_dl = 0;
+	    lc_config[j]->e_rab_max_bitrate_dl = 0;
+	    //TODO: Set the guaranteed bitrate (UL)
+	    lc_config[j]->has_e_rab_guaranteed_bitrate_ul = 0;
+	    lc_config[j]->e_rab_guaranteed_bitrate_ul = 0;
+	    //TODO: Set the guaranteed bitrate (DL)
+	    lc_config[j]->has_e_rab_guaranteed_bitrate_dl = 0;
+	    lc_config[j]->e_rab_guaranteed_bitrate_dl = 0;
+	  }
+	}
+	lc_ue_config[i]->lc_config = lc_config;
+      }
+    } // end for UE
+    lc_config_reply_msg->lc_ue_config = lc_ue_config;
+  } // lc_config_reply_msg->n_lc_ue_config > 0
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if (*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG;
+  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+  (*msg)->lc_config_reply_msg = lc_config_reply_msg;
+
+  return 0;
+
+ error:
+  // TODO: Need to make proper error handling
+  if (header != NULL)
+    free(header);
+  if (lc_config_reply_msg != NULL)
+    free(lc_config_reply_msg);
+  if(*msg != NULL)
+    free(*msg);
+  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+/*
+ * ************************************
+ * UE Configuration Reply
+ * ************************************
+ */
+
+int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+  xid_t xid;
+  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+  Protocol__FlexUeConfigRequest *ue_config_request_msg = input->ue_config_request_msg;
+  xid = (ue_config_request_msg->header)->xid;
+
+  int i;
+
+  Protocol__FlexHeader *header;
+  if(flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_GET_UE_CONFIG_REPLY, &header) != 0)
+    goto error;
+
+  Protocol__FlexUeConfigReply *ue_config_reply_msg;
+  ue_config_reply_msg = malloc(sizeof(Protocol__FlexUeConfigReply));
+  if(ue_config_reply_msg == NULL)
+    goto error;
+  protocol__flex_ue_config_reply__init(ue_config_reply_msg);
+  ue_config_reply_msg->header = header;
+
+  ue_config_reply_msg->n_ue_config = flexran_get_num_ues(mod_id);
+
+  Protocol__FlexUeConfig **ue_config;
+  if (ue_config_reply_msg->n_ue_config > 0) {
+    ue_config = malloc(sizeof(Protocol__FlexUeConfig *) * ue_config_reply_msg->n_ue_config);
+    if (ue_config == NULL) {
+      goto error;
+    }
+    for (i = 0; i < ue_config_reply_msg->n_ue_config; i++) {
+      ue_config[i] = malloc(sizeof(Protocol__FlexUeConfig));
+      protocol__flex_ue_config__init(ue_config[i]);
+
+      ue_config[i]->rnti = flexran_get_ue_crnti(mod_id,i);
+      ue_config[i]->has_rnti = 1;
+      //TODO: Set the DRX configuration (optional)
+      //Not supported for now, so we do not set it
+
+      if (flexran_get_time_alignment_timer(mod_id,i) != -1) {
+    	  ue_config[i]->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
+    	  ue_config[i]->has_time_alignment_timer = 1;
+      }
+
+      if (flexran_get_meas_gap_config(mod_id,i) != -1) {
+    	  ue_config[i]->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
+    	  ue_config[i]->has_meas_gap_config_pattern = 1;
+      }
+ 
+      if (ue_config[i]->has_meas_gap_config_pattern == 1 &&
+	 ue_config[i]->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
+	ue_config[i]->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
+	ue_config[i]->has_meas_gap_config_sf_offset = 1;
+      }
+      //TODO: Set the SPS configuration (Optional)
+      //Not supported for noe, so we do not set it
+
+      //TODO: Set the SR configuration (Optional)
+      //We do not set it for now
+
+      //TODO: Set the CQI configuration (Optional)
+      //We do not set it for now
+
+      if (flexran_get_ue_transmission_mode(mod_id,i) != -1) {
+	ue_config[i]->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
+	ue_config[i]->has_transmission_mode = 1;
+      }
+
+      ue_config[i]->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
+      ue_config[i]->has_ue_aggregated_max_bitrate_ul = 1;
+
+      ue_config[i]->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
+      ue_config[i]->has_ue_aggregated_max_bitrate_dl = 1;
+
+      Protocol__FlexUeCapabilities *capabilities;
+      capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
+      protocol__flex_ue_capabilities__init(capabilities);
+      //TODO: Set half duplex (FDD operation)
+      capabilities->has_half_duplex = 0;
+      capabilities->half_duplex = 0;//flexran_get_half_duplex(i);
+      //TODO: Set intra-frame hopping flag
+      capabilities->has_intra_sf_hopping = 0;
+      capabilities->intra_sf_hopping = 1;//flexran_get_intra_sf_hopping(i);
+      //TODO: Set support for type 2 hopping with n_sb > 1
+      capabilities->has_type2_sb_1 = 0;
+      capabilities->type2_sb_1 = 1;//flexran_get_type2_sb_1(i);
+      //TODO: Set ue category
+      capabilities->has_ue_category = 0;
+      capabilities->ue_category = 1;//flexran_get_ue_category(i);
+      //TODO: Set UE support for resource allocation type 1
+      capabilities->has_res_alloc_type1 = 0;
+      capabilities->res_alloc_type1 = 1;//flexran_get_res_alloc_type1(i);
+      //Set the capabilites to the message
+      ue_config[i]->capabilities = capabilities;
+
+      if (flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
+	ue_config[i]->has_ue_transmission_antenna = 1;
+	ue_config[i]->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
+      }
+
+      if (flexran_get_tti_bundling(mod_id,i) != -1) {
+	ue_config[i]->has_tti_bundling = 1;
+	ue_config[i]->tti_bundling = flexran_get_tti_bundling(mod_id,i);
+      }
+
+      if (flexran_get_maxHARQ_TX(mod_id,i) != -1) {
+	ue_config[i]->has_max_harq_tx = 1;
+	ue_config[i]->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
+      }
+
+      if (flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
+	ue_config[i]->has_beta_offset_ack_index = 1;
+	ue_config[i]->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
+      }
+
+      if (flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
+	ue_config[i]->has_beta_offset_ri_index = 1;
+    	  ue_config[i]->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
+      }
+
+      if (flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
+	ue_config[i]->has_beta_offset_cqi_index = 1;
+	ue_config[i]->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
+      }
+      
+      if (flexran_get_ack_nack_simultaneous_trans(mod_id,i) != -1) {
+	ue_config[i]->has_ack_nack_simultaneous_trans = 1;
+	ue_config[i]->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id,i);
+      }
+      
+      if (flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
+	ue_config[i]->has_simultaneous_ack_nack_cqi = 1;
+	ue_config[i]->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
+      }
+      
+      if (flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
+	ue_config[i]->has_aperiodic_cqi_rep_mode = 1;
+	int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
+	if (mode > 4) {
+	  ue_config[i]->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
+	} else {
+	  ue_config[i]->aperiodic_cqi_rep_mode = mode;
+	}
+      }
+      
+      if (flexran_get_tdd_ack_nack_feedback(mod_id, i) != -1) {
+	ue_config[i]->has_tdd_ack_nack_feedback = 1;
+	ue_config[i]->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback(mod_id,i);
+      }
+      
+      if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
+	ue_config[i]->has_ack_nack_repetition_factor = 1;
+	ue_config[i]->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
+      }
+      
+      if (flexran_get_extended_bsr_size(mod_id, i) != -1) {
+	ue_config[i]->has_extended_bsr_size = 1;
+	ue_config[i]->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
+      }
+      //TODO: Set carrier aggregation support (boolean)
+      ue_config[i]->has_ca_support = 0;
+      ue_config[i]->ca_support = 0;
+
+      ue_config[i]->has_pcell_carrier_index = 1;
+      ue_config[i]->pcell_carrier_index = UE_PCCID(mod_id, i);
+      if(ue_config[i]->has_ca_support){
+	//TODO: Set cross carrier scheduling support (boolean)
+	ue_config[i]->has_cross_carrier_sched_support = 0;
+	ue_config[i]->cross_carrier_sched_support = 0;
+	//TODO: Set secondary cells configuration
+	// We do not set it for now. No carrier aggregation support
+	//TODO: Set deactivation timer for secondary cell
+	ue_config[i]->has_scell_deactivation_timer = 0;
+	ue_config[i]->scell_deactivation_timer = 0;
+      }
+    }
+    ue_config_reply_msg->ue_config = ue_config;
+  }
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if (*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG;
+  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+  (*msg)->ue_config_reply_msg = ue_config_reply_msg;
+  return 0;
+
+ error:
+  // TODO: Need to make proper error handling
+  if (header != NULL)
+    free(header);
+  if (ue_config_reply_msg != NULL)
+    free(ue_config_reply_msg);
+  if(*msg != NULL)
+    free(*msg);
+  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+/*
+ * ************************************
+ * eNB Configuration Request and Reply
+ * ************************************
+ */
+
+int flexran_agent_enb_config_request(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg) {
+
+	Protocol__FlexHeader *header;
+	xid_t xid = 1;
+	if(flexran_create_header(xid,PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REQUEST, &header) != 0)
+	  goto error;
+
+	Protocol__FlexEnbConfigRequest *enb_config_request_msg;
+	enb_config_request_msg = malloc(sizeof(Protocol__FlexEnbConfigRequest));
+
+	if(enb_config_request_msg == NULL)
+	  goto error;
+
+	protocol__flex_enb_config_request__init(enb_config_request_msg);
+	enb_config_request_msg->header = header;
+
+	*msg = malloc(sizeof(Protocol__FlexranMessage));
+	if(*msg == NULL)
+	  goto error;
+
+	protocol__flexran_message__init(*msg);
+	(*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG;
+	(*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE;
+	(*msg)->enb_config_request_msg = enb_config_request_msg;
+	return 0;
+
+	error:
+	  // TODO: Need to make proper error handling
+	  if (header != NULL)
+	    free(header);
+	  if (enb_config_request_msg != NULL)
+	    free(enb_config_request_msg);
+	  if(*msg != NULL)
+	    free(*msg);
+	  //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+	  return -1;
+}
+
+int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
+
+  xid_t xid;
+  Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
+  Protocol__FlexEnbConfigRequest *enb_config_req_msg = input->enb_config_request_msg;
+  xid = (enb_config_req_msg->header)->xid;
+  
+  int i, j, k;
+  int cc_id = 0;
+  int enb_id = mod_id;
+  
+  Protocol__FlexHeader *header;
+  if(flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REPLY, &header) != 0)
+    goto error;
+  
+   Protocol__FlexEnbConfigReply *enb_config_reply_msg;
+  enb_config_reply_msg = malloc(sizeof(Protocol__FlexEnbConfigReply));
+  if(enb_config_reply_msg == NULL)
+    goto error;
+  protocol__flex_enb_config_reply__init(enb_config_reply_msg);
+  enb_config_reply_msg->header = header;
+  
+  enb_config_reply_msg->enb_id = mod_id;
+  
+  
+  enb_config_reply_msg->n_cell_config = MAX_NUM_CCs;
+  
+  Protocol__FlexCellConfig **cell_conf;
+  if(enb_config_reply_msg->n_cell_config > 0){
+    cell_conf = malloc(sizeof(Protocol__FlexCellConfig *) * enb_config_reply_msg->n_cell_config);
+    if(cell_conf == NULL)
+      goto error;
+    for(i = 0; i < enb_config_reply_msg->n_cell_config; i++){
+      cell_conf[i] = malloc(sizeof(Protocol__FlexCellConfig));
+      protocol__flex_cell_config__init(cell_conf[i]);
+
+      cell_conf[i]->phy_cell_id = 1;
+      cell_conf[i]->has_phy_cell_id = flexran_get_cell_id(enb_id,i);
+
+      cell_conf[i]->cell_id = i;
+      cell_conf[i]->has_cell_id = 1;
+
+      cell_conf[i]->pusch_hopping_offset = flexran_get_hopping_offset(enb_id,i);
+      cell_conf[i]->has_pusch_hopping_offset = 1;
+
+      if (flexran_get_hopping_mode(enb_id,i) == 0) {
+	cell_conf[i]->hopping_mode = PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTER;
+      } else if(flexran_get_hopping_mode(enb_id,i) == 1) {
+	cell_conf[i]->hopping_mode = PROTOCOL__FLEX_HOPPING_MODE__FLHM_INTERINTRA;
+      }
+      cell_conf[i]->has_hopping_mode = 1;
+
+      cell_conf[i]->n_sb = flexran_get_n_SB(enb_id,i);
+      cell_conf[i]->has_n_sb = 1;
+
+      if (flexran_get_phich_resource(enb_id,i) == 0) {
+	cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE_SIXTH; //0
+      } else if (flexran_get_phich_resource(enb_id,i) == 1) {
+	cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_HALF; //1
+      } else if (flexran_get_phich_resource(enb_id,i) == 2) {
+	cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_ONE; // 2
+      } else if (flexran_get_phich_resource(enb_id,i) == 3) {
+	cell_conf[i]->phich_resource = PROTOCOL__FLEX_PHICH_RESOURCE__FLPR_TWO;//3
+      }
+      cell_conf[i]->has_phich_resource = 1;
+
+      if (flexran_get_phich_duration(enb_id,i) == 0) {
+    	cell_conf[i]->phich_duration = PROTOCOL__FLEX_PHICH_DURATION__FLPD_NORMAL;
+      } else if(flexran_get_phich_duration(enb_id,i) == 1) {
+	cell_conf[i]->phich_duration = PROTOCOL__FLEX_PHICH_DURATION__FLPD_EXTENDED;
+      }
+      cell_conf[i]->has_phich_duration = 1;
+      //TODO: Fill in with actual value, See TS 36.211, section 6.9
+      cell_conf[i]->init_nr_pdcch_ofdm_sym = flexran_get_num_pdcch_symb(enb_id,i);
+      cell_conf[i]->has_init_nr_pdcch_ofdm_sym = 0;
+      //TODO: Fill in with actual value
+      /* Protocol__FlexSiConfig *si_config; */
+      /* si_config = malloc(sizeof(Protocol__FlexSiConfig)); */
+      /* if(si_config == NULL) */
+      /* 	goto error; */
+      /* protocol__flex_si_config__init(si_config); */
+      /* //TODO: Fill in with actual value, Frame number to apply the SI configuration */
+      /* si_config->sfn = 1; */
+      /* si_config->has_sfn = 1; */
+      /* //TODO: Fill in with actual value, the length of SIB1 in bytes */
+      /* si_config->sib1_length = get_sib1_length(enb_id,i); */
+      /* si_config->has_sib1_length = 1; */
+      /* //TODO: Fill in with actual value, Scheduling window for all SIs in SF */
+      /* si_config->si_window_length = (uint32_t) get_si_window_length(enb_id,i); */
+      /* si_config->has_si_window_length = 1; */
+      /* //TODO: Fill in with actual value, the number of SI messages */
+      /* si_config->n_si_message=1; */
+      /* Protocol__FlexSiMessage **si_message; */
+      /* si_message = malloc(sizeof(Protocol__FlexSiMessage *) * si_config->n_si_message); */
+      /* if(si_message == NULL) */
+      /* 	goto error; */
+      /* for(j = 0; j < si_config->n_si_message; j++){ */
+      /* 	si_message[j] = malloc(sizeof(Protocol__FlexSiMessage)); */
+      /* 	if(si_message[j] == NULL) */
+      /* 	  goto error; */
+      /* 	protocol__flex_si_message__init(si_message[j]); */
+      /* 	//TODO: Fill in with actual value, Periodicity of SI msg in radio frames */
+      /* 	si_message[j]->periodicity = 1;				//SIPeriod */
+      /* 	si_message[j]->has_periodicity = 1; */
+      /* 	//TODO: Fill in with actual value, rhe length of the SI message in bytes */
+      /* 	si_message[j]->length = 10; */
+      /* 	si_message[j]->has_length = 1; */
+      /* } */
+      /* if(si_config->n_si_message > 0){ */
+      /* 	si_config->si_message = si_message; */
+      /* } */
+      /* cell_conf[i]->si_config = si_config; */
+      
+      cell_conf[i]->dl_bandwidth = flexran_get_N_RB_DL(enb_id,i);
+      cell_conf[i]->has_dl_bandwidth = 1;
+
+      cell_conf[i]->ul_bandwidth = flexran_get_N_RB_UL(enb_id,i);
+      cell_conf[i]->has_ul_bandwidth = 1;
+
+      if (flexran_get_ul_cyclic_prefix_length(enb_id, i) == 0) {
+	cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_NORMAL;
+      } else if(flexran_get_ul_cyclic_prefix_length(enb_id, i) == 1) {
+	cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_UL_CYCLIC_PREFIX_LENGTH__FLUCPL_EXTENDED;      
+      }
+      cell_conf[i]->has_ul_cyclic_prefix_length = 1;
+
+      if (flexran_get_ul_cyclic_prefix_length(enb_id,i) == 0) {
+	cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_NORMAL;
+      } else if (flexran_get_ul_cyclic_prefix_length(enb_id,i) == 1) {
+	cell_conf[i]->ul_cyclic_prefix_length = PROTOCOL__FLEX_DL_CYCLIC_PREFIX_LENGTH__FLDCPL_EXTENDED;
+      }
+
+      cell_conf[i]->has_dl_cyclic_prefix_length = 1;
+      //TODO: Fill in with actual value, number of cell specific antenna ports. Currently single port support
+      cell_conf[i]->antenna_ports_count = 1;
+      cell_conf[i]->has_antenna_ports_count = 1;
+
+      if (flexran_get_duplex_mode(enb_id,i) == 1) {
+	cell_conf[i]->duplex_mode = PROTOCOL__FLEX_DUPLEX_MODE__FLDM_FDD;
+      } else if(flexran_get_duplex_mode(enb_id,i) == 0) {
+	cell_conf[i]->duplex_mode = PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD;
+      }
+      cell_conf[i]->has_duplex_mode = 1;
+      //TODO: Fill in with actual value, DL/UL subframe assignment. TDD only
+      cell_conf[i]->subframe_assignment = flexran_get_subframe_assignment(enb_id, i);
+      cell_conf[i]->has_subframe_assignment = 0;
+      //TODO: Fill in with actual value, TDD only. See TS 36.211, table 4.2.1
+      cell_conf[i]->special_subframe_patterns = flexran_get_special_subframe_assignment(enb_id,i);
+      cell_conf[i]->has_special_subframe_patterns = 0;
+      //TODO: Fill in with actual value, The MBSFN radio frame period
+      cell_conf[i]->n_mbsfn_subframe_config_rfperiod = 0;
+      uint32_t *elem_rfperiod;
+      elem_rfperiod = (uint32_t *) malloc(sizeof(uint32_t) *cell_conf[i]->n_mbsfn_subframe_config_rfperiod);
+      if(elem_rfperiod == NULL)
+	goto error;
+      for(j = 0; j < cell_conf[i]->n_mbsfn_subframe_config_rfperiod; j++){
+	elem_rfperiod[j] = 1;
+      }
+      cell_conf[i]->mbsfn_subframe_config_rfperiod = elem_rfperiod;
+      
+      //TODO: Fill in with actual value, The MBSFN radio frame offset
+      cell_conf[i]->n_mbsfn_subframe_config_rfoffset = 0;
+      uint32_t *elem_rfoffset;
+      elem_rfoffset = (uint32_t *) malloc(sizeof(uint32_t) *cell_conf[i]->n_mbsfn_subframe_config_rfoffset);
+      if(elem_rfoffset == NULL)
+	goto error;
+      for(j = 0; j < cell_conf[i]->n_mbsfn_subframe_config_rfoffset; j++){
+	elem_rfoffset[j] = 1;
+      }
+      cell_conf[i]->mbsfn_subframe_config_rfoffset = elem_rfoffset;
+      
+      //TODO: Fill in with actual value, Bitmap indicating the MBSFN subframes
+      cell_conf[i]->n_mbsfn_subframe_config_sfalloc = 0;
+      uint32_t *elem_sfalloc;
+      elem_sfalloc = (uint32_t *) malloc(sizeof(uint32_t) *cell_conf[i]->n_mbsfn_subframe_config_sfalloc);
+      if(elem_sfalloc == NULL)
+	goto error;
+      for(j = 0; j < cell_conf[i]->n_mbsfn_subframe_config_sfalloc; j++){
+	elem_sfalloc[j] = 1;
+      }
+      cell_conf[i]->mbsfn_subframe_config_sfalloc = elem_sfalloc;
+      
+      cell_conf[i]->prach_config_index = flexran_get_prach_ConfigIndex(enb_id,i);
+      cell_conf[i]->has_prach_config_index = 1;
+
+      cell_conf[i]->prach_freq_offset = flexran_get_prach_FreqOffset(enb_id,i);
+      cell_conf[i]->has_prach_freq_offset = 1;
+
+      cell_conf[i]->ra_response_window_size = flexran_get_ra_ResponseWindowSize(enb_id,i);
+      cell_conf[i]->has_ra_response_window_size = 1;
+
+      cell_conf[i]->mac_contention_resolution_timer = flexran_get_mac_ContentionResolutionTimer(enb_id,i);
+      cell_conf[i]->has_mac_contention_resolution_timer = 1;
+
+      cell_conf[i]->max_harq_msg3tx = flexran_get_maxHARQ_Msg3Tx(enb_id,i);
+      cell_conf[i]->has_max_harq_msg3tx = 1;
+
+      cell_conf[i]->n1pucch_an = flexran_get_n1pucch_an(enb_id,i);
+      cell_conf[i]->has_n1pucch_an = 1;
+
+      cell_conf[i]->deltapucch_shift = flexran_get_deltaPUCCH_Shift(enb_id,i);
+      cell_conf[i]->has_deltapucch_shift = 1;
+
+      cell_conf[i]->nrb_cqi = flexran_get_nRB_CQI(enb_id,i);
+      cell_conf[i]->has_nrb_cqi = 1;
+
+      cell_conf[i]->srs_subframe_config = flexran_get_srs_SubframeConfig(enb_id,i);
+      cell_conf[i]->has_srs_subframe_config = 1;
+
+      cell_conf[i]->srs_bw_config = flexran_get_srs_BandwidthConfig(enb_id,i);
+      cell_conf[i]->has_srs_bw_config = 1;
+
+      cell_conf[i]->srs_mac_up_pts = flexran_get_srs_MaxUpPts(enb_id,i);
+      cell_conf[i]->has_srs_mac_up_pts = 1;
+
+      if (flexran_get_enable64QAM(enb_id,i) == 0) {
+	cell_conf[i]->enable_64qam = PROTOCOL__FLEX_QAM__FLEQ_MOD_16QAM;
+      } else if(flexran_get_enable64QAM(enb_id,i) == 1) {
+	cell_conf[i]->enable_64qam = PROTOCOL__FLEX_QAM__FLEQ_MOD_64QAM;
+      }
+      cell_conf[i]->has_enable_64qam = 1;
+      
+      cell_conf[i]->carrier_index = i;
+      cell_conf[i]->has_carrier_index = 1;
+    }
+    enb_config_reply_msg->cell_config=cell_conf;
+  }
+  *msg = malloc(sizeof(Protocol__FlexranMessage));
+  if(*msg == NULL)
+    goto error;
+  protocol__flexran_message__init(*msg);
+  (*msg)->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG;
+  (*msg)->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+  (*msg)->enb_config_reply_msg = enb_config_reply_msg;
+  
+  return 0;
+  
+ error:
+  // TODO: Need to make proper error handling
+  if (header != NULL)
+    free(header);
+  if (enb_config_reply_msg != NULL)
+    free(enb_config_reply_msg);
+  if(*msg != NULL)
+    free(*msg);
+  //LOG_E(FLEXRAN_AGENT, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+
+
+/*
+ * timer primitives
+ */
+
+//struct flexran_agent_map agent_map;
+flexran_agent_timer_instance_t timer_instance;
+int agent_timer_init = 0;
+err_code_t flexran_agent_init_timer(void){
+  
+  LOG_I(FLEXRAN_AGENT, "init RB tree\n");
+  if (!agent_timer_init) {
+    RB_INIT(&timer_instance.flexran_agent_head);
+    agent_timer_init = 1;
+  }
+ 
+ return PROTOCOL__FLEXRAN_ERR__NO_ERR;
+}
+
+RB_GENERATE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
+
+/* The timer_id might not be the best choice for the comparison */
+int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b){
+
+  if (a->timer_id < b->timer_id) return -1;
+  if (a->timer_id > b->timer_id) return 1;
+
+  // equal timers
+  return 0;
+}
+
+err_code_t flexran_agent_create_timer(uint32_t interval_sec,
+				      uint32_t interval_usec,
+				      agent_id_t     agent_id,
+				      instance_t     instance,
+				      uint32_t timer_type,
+				      xid_t xid,
+				      flexran_agent_timer_callback_t cb,
+				      void*    timer_args,
+				      long *timer_id){
+  
+  struct flexran_agent_timer_element_s *e = calloc(1, sizeof(*e));
+  DevAssert(e != NULL);
+  
+//uint32_t timer_id;
+  int ret=-1;
+  
+  if ((interval_sec == 0) && (interval_usec == 0 ))
+    return TIMER_NULL;
+  
+  if (timer_type >= FLEXRAN_AGENT_TIMER_TYPE_MAX)
+    return TIMER_TYPE_INVALIDE;
+  
+  if (timer_type  ==   FLEXRAN_AGENT_TIMER_TYPE_ONESHOT){ 
+    ret = timer_setup(interval_sec, 
+		      interval_usec, 
+		      TASK_FLEXRAN_AGENT, 
+		      instance, 
+		      TIMER_ONE_SHOT,
+		      timer_args,
+		      timer_id);
+    
+    e->type = TIMER_ONE_SHOT;
+  }
+  else if (timer_type  ==   FLEXRAN_AGENT_TIMER_TYPE_PERIODIC ){
+    ret = timer_setup(interval_sec, 
+		      interval_usec, 
+		      TASK_FLEXRAN_AGENT, 
+		      instance, 
+		      TIMER_PERIODIC,
+		      timer_args,
+		      timer_id);
+    
+    e->type = TIMER_PERIODIC;
+  }
+  
+  if (ret < 0 ) {
+    return TIMER_SETUP_FAILED; 
+  }
+
+  e->agent_id = agent_id;
+  e->instance = instance;
+  e->state = FLEXRAN_AGENT_TIMER_STATE_ACTIVE;
+  e->timer_id = *timer_id;
+  e->xid = xid;
+  e->timer_args = timer_args; 
+  e->cb = cb;
+  /*element should be a real pointer*/
+  RB_INSERT(flexran_agent_map, &timer_instance.flexran_agent_head, e); 
+  
+  LOG_I(FLEXRAN_AGENT,"Created a new timer with id 0x%lx for agent %d, instance %d \n",
+	e->timer_id, e->agent_id, e->instance);
+  
+  return 0; 
+}
+
+err_code_t flexran_agent_destroy_timer(long timer_id){
+  
+  struct flexran_agent_timer_element_s *e = get_timer_entry(timer_id);
+
+  if (e != NULL ) {
+    RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
+    flexran_agent_destroy_flexran_message(e->timer_args->msg);
+    free(e);
+  }
+  
+  if (timer_remove(timer_id) < 0 ) 
+    goto error;
+  
+  return 0;
+
+ error:
+  LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
+  return TIMER_REMOVED_FAILED ;
+}
+
+err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid) {
+  struct flexran_agent_timer_element_s *e = NULL;
+  long timer_id;
+  RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
+    if (e->xid == xid) {
+      timer_id = e->timer_id;
+      RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
+      flexran_agent_destroy_flexran_message(e->timer_args->msg);
+      free(e);
+      if (timer_remove(timer_id) < 0 ) { 
+	goto error;
+      }
+    }
+  }
+  return 0;
+
+ error:
+  LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
+  return TIMER_REMOVED_FAILED ;
+}
+
+err_code_t flexran_agent_destroy_timers(void){
+  
+  struct flexran_agent_timer_element_s *e = NULL;
+  
+  RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
+    RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
+    timer_remove(e->timer_id);
+    flexran_agent_destroy_flexran_message(e->timer_args->msg);
+    free(e);
+  }  
+
+  return 0;
+
+}
+
+void flexran_agent_sleep_until(struct timespec *ts, int delay) {
+  ts->tv_nsec += delay;
+  if(ts->tv_nsec >= 1000*1000*1000){
+    ts->tv_nsec -= 1000*1000*1000;
+    ts->tv_sec++;
+  }
+  clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts,  NULL);
+}
+
+
+err_code_t flexran_agent_stop_timer(long timer_id){
+  
+  struct flexran_agent_timer_element_s *e=NULL;
+  struct flexran_agent_timer_element_s search;
+  memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
+  search.timer_id = timer_id;
+
+  e = RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search);
+
+  if (e != NULL ) {
+    e->state =  FLEXRAN_AGENT_TIMER_STATE_STOPPED;
+  }
+  
+  timer_remove(timer_id);
+  
+  return 0;
+}
+
+struct flexran_agent_timer_element_s * get_timer_entry(long timer_id) {
+  
+  struct flexran_agent_timer_element_s search;
+  memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
+  search.timer_id = timer_id;
+
+  return  RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search); 
+}
diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..56a52cd0b674480425fbace461cd23a838780615
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_common.h
@@ -0,0 +1,496 @@
+/*
+ * 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.0  (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 flexran_agent_common.h
+ * \brief common message primitves and utilities 
+ * \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+
+
+#ifndef FLEXRAN_AGENT_COMMON_H_
+#define FLEXRAN_AGENT_COMMON_H_
+
+#include <time.h>
+
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+#include "stats_messages.pb-c.h"
+#include "stats_common.pb-c.h"
+
+#include "flexran_agent_defs.h"
+#include "enb_config.h"
+
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/RLC/rlc.h"
+
+# include "tree.h"
+# include "intertask_interface.h"
+# include "timer.h"
+
+#define FLEXRAN_VERSION 0
+
+typedef int (*flexran_agent_message_decoded_callback)(
+	mid_t mod_id,
+       	const void *params,
+	Protocol__FlexranMessage **msg
+);
+
+typedef int (*flexran_agent_message_destruction_callback)(
+	Protocol__FlexranMessage *msg
+);
+
+/**********************************
+ * FlexRAN protocol messages helper 
+ * functions and generic handlers
+ **********************************/
+
+/* Helper functions for message (de)serialization */
+int flexran_agent_serialize_message(Protocol__FlexranMessage *msg, void **buf, int *size);
+int flexran_agent_deserialize_message(void *data, int size, Protocol__FlexranMessage **msg);
+
+/* Serialize message and then destroy the input flexran msg. Should be called when protocol
+   message is created dynamically */
+void * flexran_agent_pack_message(Protocol__FlexranMessage *msg, 
+			      uint32_t * size);
+
+/* Calls destructor of the given message */
+err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg);
+
+/* Function to create the header for any FlexRAN protocol message */
+int flexran_create_header(xid_t xid, Protocol__FlexType type, Protocol__FlexHeader **header);
+
+/* Hello protocol message constructor and destructor */
+int flexran_agent_hello(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_hello(Protocol__FlexranMessage *msg);
+
+/* Echo request protocol message constructor and destructor */
+int flexran_agent_echo_request(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_echo_request(Protocol__FlexranMessage *msg);
+
+/* Echo reply protocol message constructor and destructor */
+int flexran_agent_echo_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_echo_reply(Protocol__FlexranMessage *msg);
+
+/* eNodeB configuration reply message constructor and destructor */
+int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg);
+
+/* UE configuration reply message constructor and destructor */
+int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_ue_config_reply(Protocol__FlexranMessage *msg);
+
+/* Logical channel reply configuration message constructor and destructor */
+int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_lc_config_reply(Protocol__FlexranMessage *msg);
+
+/* eNodeB configuration request message constructor and destructor */
+int flexran_agent_enb_config_request(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_enb_config_request(Protocol__FlexranMessage *msg);
+
+/* UE configuration request message constructor */
+/* TODO: Need to define and implement destructor */
+int flexran_agent_destroy_ue_config_request(Protocol__FlexranMessage *msg);
+
+/* Logical channel configuration request message constructor */
+/* TODO: Need to define and implement destructor */
+int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg);
+
+/* UE state change message constructor and destructor */
+int flexran_agent_ue_state_change(mid_t mod_id, uint32_t rnti, uint8_t state_change);
+int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg);
+
+/* Control delegation message constructor and destructor */
+int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg);
+
+/* Policy reconfiguration message constructor and destructor */
+int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
+int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg);
+
+/* FlexRAN protocol message dispatcher function */
+Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id, 
+						    uint8_t *data, 
+						    uint32_t size);
+
+/* Function to be used to send a message to a dispatcher once the appropriate event is triggered. */
+Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args);
+
+
+
+
+/****************************
+ * get generic info from RAN
+ ****************************/
+
+void flexran_set_enb_vars(mid_t mod_id, ran_name_t ran);
+
+int flexran_get_current_time_ms (mid_t mod_id, int subframe_flag);
+
+/*Return the current frame number
+ *Could be using implementation specific numbering of frames
+ */
+unsigned int flexran_get_current_frame(mid_t mod_id);
+
+/*Return the current SFN (0-1023)*/ 
+unsigned int flexran_get_current_system_frame_num(mid_t mod_id);
+
+unsigned int flexran_get_current_subframe(mid_t mod_id);
+
+/*Return the frame and subframe number in compact 16-bit format.
+  Bits 0-3 subframe, rest for frame. Required by FlexRAN protocol*/
+uint16_t flexran_get_sfn_sf (mid_t mod_id);
+
+/* Return a future frame and subframe number that is ahead_of_time
+   subframes later in compact 16-bit format. Bits 0-3 subframe,
+   rest for frame */
+uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time);
+
+/* Return the number of attached UEs */
+int flexran_get_num_ues(mid_t mod_id);
+
+/* Get the rnti of a UE with id ue_id */
+int flexran_get_ue_crnti (mid_t mod_id, mid_t ue_id);
+
+/* Get the RLC buffer status report of a ue for a designated
+   logical channel id */
+int flexran_get_ue_bsr (mid_t mod_id, mid_t ue_id, lcid_t lcid);
+
+/* Get power headroom of UE with id ue_id */
+int flexran_get_ue_phr (mid_t mod_id, mid_t ue_id);
+
+/* Get the UE wideband CQI */
+int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id);
+
+/* Get the transmission queue size for a UE with a channel_id logical channel id */
+int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id);
+
+/* Update the timing advance status (find out whether a timing advance command is required) */
+int flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id);
+
+/* Return timing advance MAC control element for a designated cell and UE */
+int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id, int CC_id);
+
+/* Get the number of active component carriers for a specific UE */
+int flexran_get_active_CC(mid_t mod_id, mid_t ue_id);
+
+/* Get the rank indicator for a designated cell and UE */
+int flexran_get_current_RI(mid_t mod_id, mid_t ue_id, int CC_id);
+
+/* See TS 36.213, section 10.1 */
+int flexran_get_n1pucch_an(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.4 */
+int flexran_get_nRB_CQI(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.4 */
+int flexran_get_deltaPUCCH_Shift(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.7.1 */
+int flexran_get_prach_ConfigIndex(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.7.1 */
+int flexran_get_prach_FreqOffset(mid_t mod_id, int CC_id);
+
+/* See TS 36.321 */
+int flexran_get_maxHARQ_Msg3Tx(mid_t mod_id, int CC_id);
+
+/* Get the length of the UL cyclic prefix */
+int flexran_get_ul_cyclic_prefix_length(mid_t mod_id, int CC_id);
+
+/* Get the length of the DL cyclic prefix */
+int flexran_get_dl_cyclic_prefix_length(mid_t mod_id, int CC_id);
+
+/* Get the physical cell id of a cell */
+int flexran_get_cell_id(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, section 5.5.3.2 */
+int flexran_get_srs_BandwidthConfig(mid_t mod_id, int CC_id);
+
+/* See TS 36.211, table 5.5.3.3-1 and 2 */
+int flexran_get_srs_SubframeConfig(mid_t mod_id, int CC_id);
+
+/* Boolean value. See TS 36.211,
+   section 5.5.3.2. TDD only */
+int flexran_get_srs_MaxUpPts(mid_t mod_id, int CC_id);
+
+/* Get number of DL resource blocks */
+int flexran_get_N_RB_DL(mid_t mod_id, int CC_id);
+
+/* Get number of UL resource blocks */
+int flexran_get_N_RB_UL(mid_t mod_id, int CC_id);
+
+/* Get number of resource block groups */
+int flexran_get_N_RBG(mid_t mod_id, int CC_id);
+
+/* Get DL/UL subframe assignment. TDD only */
+int flexran_get_subframe_assignment(mid_t mod_id, int CC_id);
+
+/* TDD only. See TS 36.211, table 4.2.1 */
+int flexran_get_special_subframe_assignment(mid_t mod_id, int CC_id);
+
+/* Get the duration of the random access response window in subframes */
+int flexran_get_ra_ResponseWindowSize(mid_t mod_id, int CC_id);
+
+/* Get timer used for random access */
+int flexran_get_mac_ContentionResolutionTimer(mid_t mod_id, int CC_id);
+
+/* Get type of duplex mode (FDD/TDD) */
+int flexran_get_duplex_mode(mid_t mod_id, int CC_id);
+
+/* Get the SI window length */
+long flexran_get_si_window_length(mid_t mod_id, int CC_id);
+
+/* Get the number of PDCCH symbols configured for the cell */
+int flexran_get_num_pdcch_symb(mid_t mod_id, int CC_id);
+
+/* See TS 36.213, sec 5.1.1.1 */
+int flexran_get_tpc(mid_t mod_id, mid_t ue_id);
+
+/* Get the first available HARQ process for a specific cell and UE during 
+   a designated frame and subframe. Returns 0 for success. The id and the 
+   status of the HARQ process are stored in id and status respectively */
+int flexran_get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id,
+		     const int frame, const uint8_t subframe, int *id, int *round);
+
+/* Uplink power control management*/
+int flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, int CC_id);
+
+int flexran_get_p0_nominal_pucch(mid_t mod_id, int CC_id);
+
+int flexran_get_p0_pucch_status(mid_t mod_id, mid_t ue_id, int CC_id);
+
+int flexran_update_p0_pucch(mid_t mod_id, mid_t ue_id, int CC_id);
+
+
+/*
+ * ************************************
+ * Get Messages for UE Configuration Reply
+ * ************************************
+ */
+
+/* Get timer in subframes. Controls the synchronization
+   status of the UE, not the actual timing 
+   advance procedure. See TS 36.321 */
+int flexran_get_time_alignment_timer(mid_t mod_id, mid_t ue_id);
+
+/* Get measurement gap configuration. See TS 36.133 */
+int flexran_get_meas_gap_config(mid_t mod_id, mid_t ue_id);
+
+/* Get measurement gap configuration offset if applicable */
+int flexran_get_meas_gap_config_offset(mid_t mod_id, mid_t ue_id);
+
+/* DL aggregated bit-rate of non-gbr bearer
+   per UE. See TS 36.413 */
+int flexran_get_ue_aggregated_max_bitrate_dl (mid_t mod_id, mid_t ue_id);
+
+/* UL aggregated bit-rate of non-gbr bearer
+   per UE. See TS 36.413 */
+int flexran_get_ue_aggregated_max_bitrate_ul (mid_t mod_id, mid_t ue_id);
+
+/* Only half-duplex support. FDD
+   operation. Boolean value */
+int flexran_get_half_duplex(mid_t ue_id);
+
+/* Support of intra-subframe hopping.
+   Boolean value */
+int flexran_get_intra_sf_hopping(mid_t ue_id);
+
+/* UE support for type 2 hopping with
+   n_sb>1 */
+int flexran_get_type2_sb_1(mid_t ue_id);
+
+/* Get the UE category */
+int flexran_get_ue_category(mid_t ue_id);
+
+/* UE support for resource allocation
+   type 1 */
+int flexran_get_res_alloc_type1(mid_t ue_id);
+
+/* Get UE transmission mode */
+int flexran_get_ue_transmission_mode(mid_t mod_id, mid_t ue_id);
+
+/* Boolean value. See TS 36.321 */
+int flexran_get_tti_bundling(mid_t mod_id, mid_t ue_id);
+
+/* The max HARQ retransmission for UL.
+   See TS 36.321 */
+int flexran_get_maxHARQ_TX(mid_t mod_id, mid_t ue_id);
+
+/* See TS 36.213 */
+int flexran_get_beta_offset_ack_index(mid_t mod_id, mid_t ue_id);
+
+/* See TS 36.213 */
+int flexran_get_beta_offset_ri_index(mid_t mod_id, mid_t ue_id);
+
+/* See TS 36.213 */
+int flexran_get_beta_offset_cqi_index(mid_t mod_id, mid_t ue_id);
+
+/* Boolean. See TS36.213, Section 10.1 */
+int flexran_get_simultaneous_ack_nack_cqi(mid_t mod_id, mid_t ue_id);
+
+/* Boolean. See TS 36.213, Section 8.2 */
+int flexran_get_ack_nack_simultaneous_trans(mid_t mod_id,mid_t ue_id);
+
+/* Get aperiodic CQI report mode */
+int flexran_get_aperiodic_cqi_rep_mode(mid_t mod_id,mid_t ue_id);
+
+/* Get ACK/NACK feedback mode. TDD only */
+int flexran_get_tdd_ack_nack_feedback(mid_t mod_id, mid_t ue_id);
+
+/* See TS36.213, section 10.1 */
+int flexran_get_ack_nack_repetition_factor(mid_t mod_id, mid_t ue_id);
+
+/* Boolean. Extended buffer status report size */
+int flexran_get_extended_bsr_size(mid_t mod_id, mid_t ue_id);
+
+/* Get number of UE transmission antennas */
+int flexran_get_ue_transmission_antenna(mid_t mod_id, mid_t ue_id);
+
+/* Get logical channel group of a channel with id lc_id */
+int flexran_get_lcg(mid_t ue_id, mid_t lc_id);
+
+/* Get direction of logical channel with id lc_id */
+int flexran_get_direction(mid_t ue_id, mid_t lc_id);
+
+/*******************
+ * timer primitves
+ *******************/
+
+#define TIMER_NULL                 -1 
+#define TIMER_TYPE_INVALIDE        -2
+#define	TIMER_SETUP_FAILED         -3
+#define	TIMER_REMOVED_FAILED       -4
+#define	TIMER_ELEMENT_NOT_FOUND    -5
+
+
+/* Type of the callback executed when the timer expired */
+typedef Protocol__FlexranMessage *(*flexran_agent_timer_callback_t)(void*);
+
+typedef enum {
+  /* oneshot timer:  */
+  FLEXRAN_AGENT_TIMER_TYPE_ONESHOT = 0x0,
+
+  /* periodic timer  */
+  FLEXRAN_AGENT_TIMER_TYPE_PERIODIC = 0x1,
+
+  /* Inactive state: initial state for any timer. */
+  FLEXRAN_AGENT_TIMER_TYPE_EVENT_DRIVEN = 0x2,
+  
+  /* Max number of states available */
+  FLEXRAN_AGENT_TIMER_TYPE_MAX,
+} flexran_agent_timer_type_t;
+
+typedef enum {
+  /* Inactive state: initial state for any timer. */
+  FLEXRAN_AGENT_TIMER_STATE_INACTIVE = 0x0,
+
+  /* Inactive state: initial state for any timer. */
+  FLEXRAN_AGENT_TIMER_STATE_ACTIVE = 0x1,
+
+  /* Inactive state: initial state for any timer. */
+  FLEXRAN_AGENT_TIMER_STATE_STOPPED = 0x2,
+  
+  /* Max number of states available */
+  FLEXRAN_AGENT_TIMER_STATE_MAX,
+} flexran_agent_timer_state_t;
+
+typedef struct flexran_agent_timer_args_s{
+  mid_t            mod_id;
+  Protocol__FlexranMessage *msg;
+} flexran_agent_timer_args_t;
+
+
+
+typedef struct flexran_agent_timer_element_s{
+  RB_ENTRY(flexran_agent_timer_element_s) entry;
+
+  agent_id_t             agent_id;
+  instance_t       instance;
+  
+  flexran_agent_timer_type_t  type;
+  flexran_agent_timer_state_t state;
+
+  uint32_t interval_sec;
+  uint32_t interval_usec;
+
+  long timer_id;  /* Timer id returned by the timer API*/
+  xid_t xid; /*The id of the task as received by the controller
+	       message*/
+  
+  flexran_agent_timer_callback_t cb;
+  flexran_agent_timer_args_t *timer_args;
+  
+} flexran_agent_timer_element_t;
+
+typedef struct flexran_agent_timer_instance_s{
+  RB_HEAD(flexran_agent_map, flexran_agent_timer_element_s) flexran_agent_head;
+}flexran_agent_timer_instance_t;
+
+
+err_code_t flexran_agent_init_timer(void);
+
+/* Create a timer for some agent related event with id xid. Will store the id 
+   of the generated timer in timer_id */
+err_code_t flexran_agent_create_timer(uint32_t interval_sec,
+				  uint32_t interval_usec,
+				  agent_id_t     agent_id,
+				  instance_t     instance,
+				  uint32_t timer_type,
+				  xid_t xid,
+				  flexran_agent_timer_callback_t cb,
+				  void*    timer_args,
+				  long *timer_id);
+
+/* Destroy all existing timers */
+err_code_t flexran_agent_destroy_timers(void);
+
+/* Destroy the timer with the given timer_id */
+err_code_t flexran_agent_destroy_timer(long timer_id);
+
+/* Destroy the timer for task with id xid */
+err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid);
+
+/* Stop a timer */
+err_code_t flexran_agent_stop_timer(long timer_id);
+
+/* Restart the given timer */
+err_code_t flexran_agent_restart_timer(long *timer_id);
+
+/* Find the timer with the given timer_id */
+struct flexran_agent_timer_element_s * get_timer_entry(long timer_id);
+
+/* Obtain the protocol message stored in the given expired timer */
+Protocol__FlexranMessage * flexran_agent_process_timeout(long timer_id, void* timer_args);
+
+/* Comparator function comparing two timers. Decides the ordering of the timers */
+int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b);
+
+/*Specify a delay in nanoseconds to timespec and sleep until then*/
+void flexran_agent_sleep_until(struct timespec *ts, int delay);
+
+/* RB_PROTOTYPE is for .h files */
+RB_PROTOTYPE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
+
+
+#endif
diff --git a/openair2/ENB_APP/flexran_agent_common_internal.c b/openair2/ENB_APP/flexran_agent_common_internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..3026190863e4cd32469b84d03f8c3874b52d2b6a
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_common_internal.c
@@ -0,0 +1,392 @@
+/*
+ * 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.0  (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 flexran_agent_common_internal.c
+ * \brief internal functions for common message primitves and utilities 
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "flexran_agent_common_internal.h"
+#include "flexran_agent_mac_internal.h"
+
+int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length) {
+
+  yaml_parser_t parser;
+  yaml_event_t event;
+
+  int done = 0;
+  int mapping_started = 0;
+
+  LOG_I(ENB_APP, "Time to apply a new policy \n");
+
+  yaml_parser_initialize(&parser);
+
+  yaml_parser_set_input_string(&parser, policy, strlen(policy));
+
+  while (!done) {
+    if (!yaml_parser_parse(&parser, &event))
+      goto error;
+ 
+    switch (event.type) {
+    case YAML_STREAM_START_EVENT:
+    case YAML_STREAM_END_EVENT:
+    case YAML_DOCUMENT_START_EVENT:
+    case YAML_DOCUMENT_END_EVENT:
+      break;
+    case YAML_MAPPING_START_EVENT:
+      mapping_started = 1;
+      break;
+    case YAML_MAPPING_END_EVENT:
+      mapping_started = 0;
+      break;
+    case YAML_SCALAR_EVENT:
+      // Check the system name and call the proper handler
+      if (strcmp(event.data.scalar.value, "mac") == 0) {
+	LOG_D(ENB_APP, "This is intended for the mac system\n");
+	// Call the mac handler
+	if (parse_mac_config(mod_id, &parser) == -1) {
+	  goto error;
+	}
+      } else if (strcmp(event.data.scalar.value, "rlc") == 0) {
+	// Call the RLC handler
+	LOG_D(ENB_APP, "This is intended for the rlc system\n");
+	// TODO : Just skip it for now
+	if (skip_system_section(&parser) == -1) {
+	  goto error;
+	}
+      } else if (strcmp(event.data.scalar.value, "pdcp") == 0) {
+	// Call the PDCP handler
+	LOG_D(ENB_APP, "This is intended for the pdcp system\n");
+	// TODO : Just skip it for now
+	if (skip_system_section(&parser) == -1) {
+	  goto error;
+	}
+      } else if (strcmp(event.data.scalar.value, "rrc") == 0) {
+	// Call the RRC handler
+	LOG_D(ENB_APP, "This is intended for the rrc system\n");
+	// TODO : Just skip it for now
+	if (skip_system_section(&parser) == -1) {
+	  goto error;
+	}
+      } else {
+	goto error;
+      }
+      break;
+    default:
+      // We are not expecting to find any other type of event at this level
+      // of the hierarchy
+      yaml_event_delete(&event);
+      goto error;
+    }
+    
+    done = (event.type == YAML_STREAM_END_EVENT);
+
+    yaml_event_delete(&event);
+  }
+
+  return 0;
+
+ error:
+  yaml_parser_delete(&parser);
+  return -1;
+
+}
+
+int skip_system_section(yaml_parser_t *parser) {
+  yaml_event_t event;
+  
+  int done = 0;
+
+  int sequence_started = 0;
+  int mapping_started = 0;
+
+  while (!done) {
+    if (!yaml_parser_parse(parser, &event))
+      goto error;
+   
+    switch (event.type) {
+      
+      case YAML_SEQUENCE_START_EVENT:
+      LOG_D(ENB_APP, "A sequence just started as expected\n");
+      sequence_started = 1;
+      break;
+    case YAML_SEQUENCE_END_EVENT:
+      LOG_D(ENB_APP, "A sequence ended\n");
+      sequence_started = 0;
+      break;
+    case YAML_MAPPING_START_EVENT:
+      if (!sequence_started) {
+	goto error;
+      }
+      LOG_D(ENB_APP, "A mapping started\n");
+      mapping_started = 1;
+      break;
+    case YAML_MAPPING_END_EVENT:
+      if (!mapping_started) {
+	goto error;
+      }
+      LOG_D(ENB_APP, "A mapping ended\n");
+      mapping_started = 0;
+      break;
+    case YAML_SCALAR_EVENT:
+      if (!mapping_started) {
+	goto error;
+      }
+      // Entered a subsystem section. Let's skip it
+      if (skip_subsystem_section(parser) == -1) {
+	goto error;
+      }
+    }
+    
+    done = (event.type == YAML_SEQUENCE_END_EVENT);
+
+    yaml_event_delete(&event);
+    
+  }
+
+  return 0;
+
+ error:
+  yaml_event_delete(&event);
+  return -1;
+}
+
+int skip_subsystem_section(yaml_parser_t *parser) {
+  
+  yaml_event_t event;
+
+  int done = 0;
+  int mapping_started = 0;
+
+  while (!done) {
+    if (!yaml_parser_parse(parser, &event))
+      goto error;
+
+    switch (event.type) {
+    case YAML_MAPPING_START_EVENT:
+      LOG_D(ENB_APP, "The mapping of the subsystem started\n");
+      mapping_started = 1;
+      break;
+    case YAML_MAPPING_END_EVENT:
+      LOG_D(ENB_APP, "The mapping of the subsystem ended\n");
+      mapping_started = 0;
+      break;
+    case YAML_SCALAR_EVENT:
+      if (!mapping_started) {
+	goto error;
+      }
+      // Check what key needs to be set
+      if (strcmp(event.data.scalar.value, "behavior") == 0) {
+	LOG_D(ENB_APP, "Skipping the behavior attribute\n");
+	yaml_event_delete(&event);
+	if (!yaml_parser_parse(parser, &event)) {
+	  goto error;
+	}
+	if (event.type == YAML_SCALAR_EVENT) {
+	  break;
+	} else {
+	  goto error;
+	}
+      } else if (strcmp(event.data.scalar.value, "parameters") == 0) {
+	LOG_D(ENB_APP, "Skipping the parameters for this subsystem\n");
+	if (skip_subsystem_parameters_config(parser) == -1) {
+	  goto error;
+	}
+      }
+      break;
+    default:
+      goto error;
+    }
+    
+    done = (event.type == YAML_MAPPING_END_EVENT);
+    yaml_event_delete(&event);
+  }
+
+  return 0;
+
+ error:
+  yaml_event_delete(&event);
+  return -1;
+}
+
+int skip_subsystem_parameters_config(yaml_parser_t *parser) {
+  yaml_event_t event;
+  
+  void *param;
+  
+  int done = 0;
+  int mapping_started = 0;
+
+  while (!done) {
+    
+    if (!yaml_parser_parse(parser, &event))
+      goto error;
+
+    switch (event.type) {
+      // We are expecting a mapping of parameters
+    case YAML_MAPPING_START_EVENT:
+      LOG_D(ENB_APP, "The mapping of the parameters started\n");
+      mapping_started = 1;
+      break;
+    case YAML_MAPPING_END_EVENT:
+      LOG_D(ENB_APP, "The mapping of the parameters ended\n");
+      mapping_started = 0;
+      break;
+    case YAML_SCALAR_EVENT:
+      if (!mapping_started) {
+	goto error;
+      }
+      // Check what key needs to be set
+      LOG_D(ENB_APP, "Skipping parameter %s\n", event.data.scalar.value);
+      if (skip_parameter_modification(parser) == -1 ) {
+	goto error;
+      }
+      break;
+    default:
+      goto error;
+    }
+
+    done = (event.type == YAML_MAPPING_END_EVENT);
+    yaml_event_delete(&event);
+  }
+
+  return 0;
+  
+ error:
+  yaml_event_delete(&event);
+  return -1;
+}
+
+
+int skip_parameter_modification(yaml_parser_t *parser) {
+  yaml_event_t event;
+  
+  int done = 0;
+  int is_array = 0;
+  int i = 0;
+
+  while (!done) {
+    if (!yaml_parser_parse(parser, &event)) {
+      goto error;
+    }
+    
+    // Expecting either a scalar or a sequence
+    switch (event.type) {
+    case YAML_SEQUENCE_START_EVENT:
+      is_array = 1;
+      break;
+    case YAML_SCALAR_EVENT:
+      if ((strcmp(event.data.scalar.tag, YAML_INT_TAG) == 0) ||
+	  (strcmp(event.data.scalar.tag, YAML_FLOAT_TAG) == 0) ||
+	  (strcmp(event.data.scalar.tag, YAML_STR_TAG) == 0) ||
+	  (strcmp(event.data.scalar.tag, YAML_BOOL_TAG) == 0)) {
+	// Do nothing
+      } else {
+	// No other type is supported at the moment, so it should be considered an error
+	// if we reach here
+	goto error;
+      }
+      if (is_array) {
+	i++;
+      } else {
+	done = 1;
+      }
+      break;
+    case YAML_SEQUENCE_END_EVENT:
+      done = 1;
+      break;
+    default:
+      goto error;
+    }
+    yaml_event_delete(&event);
+  }
+
+  return 0;
+
+ error:
+  yaml_event_delete(&event);
+  return -1;
+}
+
+int apply_parameter_modification(void *parameter, yaml_parser_t *parser) {
+  yaml_event_t event;
+  
+  int done = 0;
+  int is_array = 0;
+  int i = 0;
+
+  char *endptr;
+
+  while (!done) {
+    if (!yaml_parser_parse(parser, &event)) {
+      goto error;
+    }
+    
+    // Expecting either a scalar or a sequence
+    switch (event.type) {
+    case YAML_SEQUENCE_START_EVENT:
+      is_array = 1;
+      break;
+    case YAML_SCALAR_EVENT:
+      if (strcmp(event.data.scalar.tag, YAML_INT_TAG) == 0) {
+	((int *) parameter)[i] = strtol(event.data.scalar.value, &endptr, 10);
+      } else if (strcmp(event.data.scalar.tag, YAML_FLOAT_TAG) == 0) {
+	((float *) parameter)[i] = strtof(event.data.scalar.value, &endptr);
+      } else if (strcmp(event.data.scalar.tag, YAML_STR_TAG) == 0) {
+	strncpy(&((char *) parameter)[i], event.data.scalar.value, event.data.scalar.length);
+      } else if (strcmp(event.data.scalar.tag, YAML_BOOL_TAG) == 0) {
+	if (strcmp(event.data.scalar.value, "true") == 0) {
+	  ((int *) parameter)[i] = 1;
+	} else {
+	  ((int *) parameter)[i] = 0;
+	}
+      } else {
+	// No other type is supported at the moment, so it should be considered an error
+	// if we reach here
+	goto error;
+      }
+      if (is_array) {
+	i++;
+      } else {
+	done = 1;
+      }
+      break;
+    case YAML_SEQUENCE_END_EVENT:
+      done = 1;
+      break;
+    default:
+      goto error;
+    }
+    yaml_event_delete(&event);
+  }
+
+  return 0;
+
+ error:
+  yaml_event_delete(&event);
+  return -1;
+  
+}
diff --git a/openair2/ENB_APP/flexran_agent_common_internal.h b/openair2/ENB_APP/flexran_agent_common_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..c8f78aafe90a251c37911b398faaf457aa245c58
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_common_internal.h
@@ -0,0 +1,56 @@
+/*
+ * 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.0  (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 flexran_agent_common_internal.h
+ * \brief internal agent functions for common message primitves and utilities
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef FLEXRAN_AGENT_COMMON_INTERNAL_H_
+#define FLEXRAN_AGENT_COMMON_INTERNAL_H_
+
+#include <yaml.h>
+
+#include "flexran_agent_defs.h"
+
+int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length);
+
+int apply_parameter_modification(void *parameter, yaml_parser_t *parser);
+
+// This can be used when parsing for a specific system that is not yet implmeneted
+// in order to skip its configuration, without affecting the rest
+int skip_system_section(yaml_parser_t *parser);
+
+// This can be used when parsing for a specific subsystem that is not yet implmeneted
+// in order to skip its configuration, without affecting the rest
+int skip_subsystem_section(yaml_parser_t *parser);
+
+// This can be used when parsing for the parameters of a specific subsystem 
+//that is not yet implmeneted in order to skip its configuration, without affecting the rest
+int skip_subsystem_parameters_config(yaml_parser_t *parser);
+
+// This can be used when configuring the parameters of a specific subsystem 
+//that is not yet implmeneted in order to skip its configuration, without affecting the rest
+int skip_parameter_modification(yaml_parser_t *parser);
+
+#endif
diff --git a/openair2/ENB_APP/flexran_agent_defs.h b/openair2/ENB_APP/flexran_agent_defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..d60510b0c782bbf39fc17a3b650bc4aa9edc2a03
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_defs.h
@@ -0,0 +1,125 @@
+/*
+ * 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.0  (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 flexran_agent_defs.h
+ * \brief FlexRAN agent common definitions 
+ * \author Navid Nikaein and Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+#ifndef FLEXRAN_AGENT_DEFS_H_
+#define FLEXRAN_AGENT_DEFS_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+
+#include "link_manager.h"
+
+#define NUM_MAX_ENB 2
+#define NUM_MAX_UE 2048
+#define DEFAULT_FLEXRAN_AGENT_IPv4_ADDRESS "127.0.0.1"
+#define DEFAULT_FLEXRAN_AGENT_PORT          2210
+#define DEFAULT_FLEXRAN_AGENT_CACHE        "/mnt/oai_agent_cache"
+
+typedef enum {
+  
+  FLEXRAN_AGENT_DEFAULT=0,
+  
+  FLEXRAN_AGENT_PHY=1,
+  FLEXRAN_AGENT_MAC=2,
+  FLEXRAN_AGENT_RLC=3,
+  FLEXRAN_AGENT_PDCP=4,
+  FLEXRAN_AGENT_RRC=5,
+  FLEXRAN_AGENT_S1AP=6,
+  FLEXRAN_AGENT_GTP=7,
+  FLEXRAN_AGENT_X2AP=8,
+
+  FLEXRAN_AGENT_MAX=9,
+    
+} agent_id_t;
+
+typedef enum {
+  /* no action  */
+  FLEXRAN_AGENT_ACTION_NONE = 0x0,
+
+  /* send action  */
+  FLEXRAN_AGENT_ACTION_SEND = 0x1,
+
+ /* apply action  */
+  FLEXRAN_AGENT_ACTION_APPLY = 0x2,
+
+  /* clear action  */
+  FLEXRAN_AGENT_ACTION_CLEAR = 0x4,
+
+  /* write action  */
+  FLEXRAN_AGENT_ACTION_WRITE = 0x8,
+
+  /* filter action  */
+  FLEXRAN_AGENT_ACTION_FILTER = 0x10,
+
+  /* preprocess action  */
+  FLEXRAN_AGENT_ACTION_PREPROCESS = 0x20,
+
+  /* meter action  */
+  FLEXRAN_AGENT_ACTION_METER = 0x40,
+  
+  /* Max number of states available */
+  FLEXRAN_AGENT_ACTION_MAX = 0x7f,
+} agent_action_t;
+
+
+typedef enum {
+  
+  RAN_LTE_OAI= 0,
+  
+ /* Max number of states available */
+ RAN_NAME_MAX = 0x7f,
+} ran_name_t;
+
+typedef uint8_t xid_t;  
+typedef uint8_t mid_t;  // module or enb id 
+typedef uint8_t lcid_t;
+typedef int32_t  err_code_t; 
+
+
+
+typedef struct {
+  /* general info */ 
+ 
+  /* stats */
+
+  uint32_t total_rx_msg;
+  uint32_t total_tx_msg;
+   
+  uint32_t rx_msg[NUM_MAX_ENB];
+  uint32_t tx_msg[NUM_MAX_ENB];
+
+} flexran_agent_info_t;
+
+typedef struct {
+  mid_t enb_id;
+  flexran_agent_info_t agent_info;
+  
+} flexran_agent_instance_t;
+
+#endif 
diff --git a/openair2/ENB_APP/flexran_agent_extern.h b/openair2/ENB_APP/flexran_agent_extern.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a03239e6fe5c0845c74e2ac724fe875eaa78404
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_extern.h
@@ -0,0 +1,48 @@
+/*
+ * 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.0  (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 ENB_APP/extern.h
+ * \brief FlexRAN agent - mac interface primitives
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ * \mail x.foukas@sms.ed.ac.uk
+ */
+
+#ifndef __FLEXRAN_AGENT_EXTERN_H__
+#define __FLEXRAN_AGENT_EXTERN_H__
+
+#include "flexran_agent_defs.h"
+#include "flexran_agent_mac_defs.h"
+
+
+//extern msg_context_t shared_ctxt[NUM_MAX_ENB][FLEXRAN_AGENT_MAX];
+
+/* full path of the local cache for storing VSFs */
+extern char local_cache[40];
+
+/* Control module interface for the communication of the MAC Control Module with the agent */
+extern AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
+
+/* Flag indicating whether the VSFs for the MAC control module have been registered */
+extern unsigned int mac_agent_registered[NUM_MAX_ENB];
+
+#endif
diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c
new file mode 100644
index 0000000000000000000000000000000000000000..4967e4692334d0b8fe86a379be929c99e854f5ac
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_handler.c
@@ -0,0 +1,189 @@
+/*
+ * 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.0  (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 flexran_agent_handler.c
+ * \brief FlexRAN agent tx and rx message handler 
+ * \author Xenofon Foukas and Navid Nikaein
+ * \date 2016
+ * \version 0.1
+ */
+
+
+#include "flexran_agent_common.h"
+#include "flexran_agent_mac.h"
+#include "log.h"
+
+#include "assertions.h"
+
+flexran_agent_message_decoded_callback agent_messages_callback[][3] = {
+  {flexran_agent_hello, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_HELLO_MSG*/
+  {flexran_agent_echo_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REQUEST_MSG*/
+  {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REPLY_MSG*/ //Must add handler when receiving echo reply
+  {flexran_agent_mac_handle_stats, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG*/
+  {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG*/
+  {0, 0, 0}, /*PROTOCOK__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG*/
+  {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG*/
+  {flexran_agent_enb_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG*/
+  {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG*/
+  {flexran_agent_ue_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REQUEST_MSG*/
+  {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG*/
+  {flexran_agent_lc_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REQUEST_MSG*/
+  {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG*/
+  {flexran_agent_mac_handle_dl_mac_config, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG*/
+  {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG*/
+  {flexran_agent_control_delegation, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DELEGATION_MSG*/
+  {flexran_agent_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_AGENT_RECONFIGURATION_MSG*/
+};
+
+flexran_agent_message_destruction_callback message_destruction_callback[] = {
+  flexran_agent_destroy_hello,
+  flexran_agent_destroy_echo_request,
+  flexran_agent_destroy_echo_reply,
+  flexran_agent_mac_destroy_stats_request,
+  flexran_agent_mac_destroy_stats_reply,
+  flexran_agent_mac_destroy_sf_trigger,
+  flexran_agent_mac_destroy_sr_info,
+  flexran_agent_destroy_enb_config_request,
+  flexran_agent_destroy_enb_config_reply,
+  flexran_agent_destroy_ue_config_request,
+  flexran_agent_destroy_ue_config_reply,
+  flexran_agent_destroy_lc_config_request,
+  flexran_agent_destroy_lc_config_reply,
+  flexran_agent_mac_destroy_dl_config,
+  flexran_agent_destroy_ue_state_change,
+  flexran_agent_destroy_control_delegation,
+  flexran_agent_destroy_agent_reconfiguration,
+};
+
+static const char *flexran_agent_direction2String[] = {
+  "", /* not_set  */
+  "originating message", /* originating message */
+  "successfull outcome", /* successfull outcome */
+  "unsuccessfull outcome", /* unsuccessfull outcome */
+};
+
+
+Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id,
+							uint8_t *data, 
+							uint32_t size){
+  
+  Protocol__FlexranMessage *decoded_message, *reply_message;
+  err_code_t err_code;
+  DevAssert(data != NULL);
+
+  if (flexran_agent_deserialize_message(data, size, &decoded_message) < 0) {
+    err_code= PROTOCOL__FLEXRAN_ERR__MSG_DECODING;
+    goto error; 
+  }
+  
+  if ((decoded_message->msg_case > sizeof(agent_messages_callback) / (3 * sizeof(flexran_agent_message_decoded_callback))) || 
+      (decoded_message->msg_dir > PROTOCOL__FLEXRAN_DIRECTION__UNSUCCESSFUL_OUTCOME)){
+    err_code= PROTOCOL__FLEXRAN_ERR__MSG_NOT_HANDLED;
+    goto error;
+  }
+    
+  if (agent_messages_callback[decoded_message->msg_case-1][decoded_message->msg_dir-1] == NULL) {
+    err_code= PROTOCOL__FLEXRAN_ERR__MSG_NOT_SUPPORTED;
+    goto error;
+
+  }
+
+  err_code = ((*agent_messages_callback[decoded_message->msg_case-1][decoded_message->msg_dir-1])(mod_id, (void *) decoded_message, &reply_message));
+  if ( err_code < 0 ){
+    goto error;
+  } else if (err_code == 1) { //If err_code > 1, we do not want to dispose the message yet
+    protocol__flexran_message__free_unpacked(decoded_message, NULL);
+  }
+  return reply_message;
+  
+error:
+  LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
+  return NULL;
+
+}
+
+
+
+void * flexran_agent_pack_message(Protocol__FlexranMessage *msg, 
+				  uint32_t * size){
+
+  void * buffer;
+  err_code_t err_code = PROTOCOL__FLEXRAN_ERR__NO_ERR;
+  
+  if (flexran_agent_serialize_message(msg, &buffer, size) < 0 ) {
+    err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENCODING;
+    goto error;
+  }
+  
+  // free the msg --> later keep this in the data struct and just update the values
+  //TODO call proper destroy function
+  err_code = ((*message_destruction_callback[msg->msg_case-1])(msg));
+  
+  DevAssert(buffer !=NULL);
+  
+  LOG_D(FLEXRAN_AGENT,"Serilized the enb mac stats reply (size %d)\n", *size);
+  
+  return buffer;
+  
+ error : 
+  LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
+  
+  return NULL;   
+}
+
+Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args) {
+  err_code_t err_code;
+  flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
+
+  Protocol__FlexranMessage *timed_task, *reply_message;
+  timed_task = timer_args->msg;
+  err_code = ((*agent_messages_callback[timed_task->msg_case-1][timed_task->msg_dir-1])(timer_args->mod_id, (void *) timed_task, &reply_message));
+  if ( err_code < 0 ){
+    goto error;
+  }
+
+  return reply_message;
+  
+ error:
+  LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
+  return NULL;
+}
+
+Protocol__FlexranMessage* flexran_agent_process_timeout(long timer_id, void* timer_args){
+    
+  struct flexran_agent_timer_element_s *found = get_timer_entry(timer_id);
+ 
+  if (found == NULL ) goto error;
+  LOG_I(FLEXRAN_AGENT, "Found the entry (%p): timer_id is 0x%lx  0x%lx\n", found, timer_id, found->timer_id);
+  
+  if (timer_args == NULL)
+    LOG_W(FLEXRAN_AGENT,"null timer args\n");
+  
+  return found->cb(timer_args);
+
+ error:
+  LOG_E(FLEXRAN_AGENT, "can't get the timer element\n");
+  return TIMER_ELEMENT_NOT_FOUND;
+}
+
+err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg) {
+  return ((*message_destruction_callback[msg->msg_case-1])(msg));
+}
diff --git a/openair2/ENB_APP/flexran_agent_net_comm.c b/openair2/ENB_APP/flexran_agent_net_comm.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e39d6089f2fbb261c0bd5e71693a8aaf2db9a6f
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_net_comm.c
@@ -0,0 +1,192 @@
+/*
+ * 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.0  (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 flexran_agent_net_comm.c
+ * \brief FlexRAN agent network interface abstraction 
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#include "flexran_agent_net_comm.h"
+#include "log.h"
+
+flexran_agent_channel_t *agent_channel[NUM_MAX_ENB][FLEXRAN_AGENT_MAX];
+flexran_agent_channel_instance_t channel_instance;
+int flexran_agent_channel_id = 0;
+
+int flexran_agent_msg_send(mid_t mod_id, agent_id_t agent_id, void *data, int size, int priority) {
+  /*Check if agent id is valid*/
+  if (agent_id >= FLEXRAN_AGENT_MAX || agent_id < 0) {
+    goto error;
+  }
+  flexran_agent_channel_t *channel;
+  channel = agent_channel[mod_id][agent_id];
+  
+  /*Check if agent has a channel registered*/
+  if (channel == NULL) {
+    goto error;
+  }
+
+  return channel->msg_send(data, size, priority, channel->channel_info);
+  
+ error:
+  LOG_E(FLEXRAN_AGENT, "No channel registered for agent with id %d\n", agent_id);
+  return -1;
+}
+
+int flexran_agent_msg_recv(mid_t mod_id, agent_id_t agent_id, void **data, int *size, int *priority) {
+  /*Check if agent id is valid*/
+  if (agent_id >= FLEXRAN_AGENT_MAX || agent_id < 0) {
+    goto error;
+  }
+  flexran_agent_channel_t *channel;
+  channel = agent_channel[mod_id][agent_id];
+  
+  /*Check if agent has a channel registered*/
+  if (channel == NULL) {
+    goto error;
+  }
+  
+  return channel->msg_recv(data, size, priority, channel->channel_info);
+  
+ error:
+  LOG_E(FLEXRAN_AGENT, "No channel registered for agent with id %d\n", agent_id);
+  return -1;
+}
+
+int flexran_agent_register_channel(mid_t mod_id, flexran_agent_channel_t *channel, agent_id_t agent_id) {
+  int i;
+
+  if (channel == NULL) {
+    return -1;
+  }
+
+  if (agent_id == FLEXRAN_AGENT_MAX) {
+    for (i = 0; i < FLEXRAN_AGENT_MAX; i++) {
+      agent_channel[mod_id][i] = channel;
+    }
+  } else {
+    agent_channel[mod_id][agent_id] = channel;
+  }
+  return 0;
+}
+
+void flexran_agent_unregister_channel(mid_t mod_id, agent_id_t agent_id) {
+  int i;
+
+  if (agent_id == FLEXRAN_AGENT_MAX) {
+    for (i = 0; i < FLEXRAN_AGENT_MAX; i++) {
+      agent_channel[mod_id][i] = NULL;
+    }
+  } else {
+    agent_channel[mod_id][agent_id] = NULL;
+  }
+}
+
+int flexran_agent_create_channel(void *channel_info,
+				 int (*msg_send)(void *data, int size, int priority, void *channel_info),
+				 int (*msg_recv)(void **data, int *size, int *priority, void *channel_info),
+				 void (*release)(flexran_agent_channel_t *channel)) {
+  
+  int channel_id = ++flexran_agent_channel_id;
+  flexran_agent_channel_t *channel = (flexran_agent_channel_t *) malloc(sizeof(flexran_agent_channel_t));
+  channel->channel_id = channel_id;
+  channel->channel_info = channel_info;
+  channel->msg_send = msg_send;
+  channel->msg_recv = msg_recv;
+  channel->release = release;
+  
+  /*element should be a real pointer*/
+  RB_INSERT(flexran_agent_channel_map, &channel_instance.flexran_agent_head, channel); 
+  
+  LOG_I(FLEXRAN_AGENT,"Created a new channel with id 0x%lx\n", channel->channel_id);
+ 
+  return channel_id; 
+}
+
+int flexran_agent_destroy_channel(int channel_id) {
+  int i, j;
+
+  /*Check to see if channel exists*/
+  struct flexran_agent_channel_s *e = NULL;
+  struct flexran_agent_channel_s search;
+  memset(&search, 0, sizeof(struct flexran_agent_channel_s));
+
+  e = RB_FIND(flexran_agent_channel_map, &channel_instance.flexran_agent_head, &search);
+
+  if (e == NULL) {
+    return -1;
+  }
+
+  /*Unregister the channel from all agents*/
+  for (i = 0; i < NUM_MAX_ENB; i++) {
+    for (j = 0; j < FLEXRAN_AGENT_MAX; j++) {
+      if (agent_channel[i][j] != NULL) {
+	if (agent_channel[i][j]->channel_id == e->channel_id) {
+	  agent_channel[i][j] == NULL;
+	}
+      }
+    }
+  }
+
+  /*Remove the channel from the tree and free memory*/
+  RB_REMOVE(flexran_agent_channel_map, &channel_instance.flexran_agent_head, e);
+  e->release(e);
+  free(e);
+
+  return 0;
+}
+
+err_code_t flexran_agent_init_channel_container(void) {
+  int i, j;
+  LOG_I(FLEXRAN_AGENT, "init RB tree for channel container\n");
+
+  RB_INIT(&channel_instance.flexran_agent_head);
+  
+  for (i = 0; i < NUM_MAX_ENB; i++) {
+    for (j = 0; j < FLEXRAN_AGENT_MAX; j++) {
+    agent_channel[i][j] == NULL;
+    }
+  }
+
+  return 0;
+}
+
+RB_GENERATE(flexran_agent_channel_map, flexran_agent_channel_s, entry, flexran_agent_compare_channel);
+
+int flexran_agent_compare_channel(struct flexran_agent_channel_s *a, struct flexran_agent_channel_s *b) {
+  if (a->channel_id < b->channel_id) return -1;
+  if (a->channel_id > b->channel_id) return 1;
+
+  // equal timers
+  return 0;
+}
+
+flexran_agent_channel_t * get_channel(int channel_id) {
+  
+  struct flexran_agent_channel_s search;
+  memset(&search, 0, sizeof(struct flexran_agent_channel_s));
+  search.channel_id = channel_id;
+  
+  return  RB_FIND(flexran_agent_channel_map, &channel_instance.flexran_agent_head, &search);
+  
+}
diff --git a/openair2/ENB_APP/flexran_agent_net_comm.h b/openair2/ENB_APP/flexran_agent_net_comm.h
new file mode 100644
index 0000000000000000000000000000000000000000..e4aa854c70c9f0cbb454662eaaac89de752a49c6
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_net_comm.h
@@ -0,0 +1,81 @@
+/*
+ * 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.0  (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 flexran_agent_net_comm.h
+ * \brief FlexRAN agent network interface abstraction 
+ * \autho Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+#ifndef FLEXRAN_AGENT_NET_COMM_H_
+#define FLEXRAN_AGENT_NET_COMM_H_
+
+#include "flexran_agent_defs.h"
+
+#include "tree.h"
+
+/*Channel related information used for Tx/Rx of protocol messages*/
+typedef struct flexran_agent_channel_s {
+  RB_ENTRY(flexran_agent_channel_s) entry;
+int channel_id;
+void *channel_info;
+/*Callbacks for channel message Tx and Rx*/
+int (*msg_send)(void *data, int size, int priority, void *channel_info);
+int (*msg_recv)(void **data, int *size, int *priority, void *channel_info);
+void (*release)(struct flexran_agent_channel_s *channel);
+} flexran_agent_channel_t;
+
+typedef struct flexran_agent_channel_instance_s{
+  RB_HEAD(flexran_agent_channel_map, flexran_agent_channel_s) flexran_agent_head;
+} flexran_agent_channel_instance_t;
+
+/*Send and receive messages using the channel registered for a specific agent*/
+int flexran_agent_msg_send(mid_t mod_id, agent_id_t agent_id, void *data, int size, int priority);
+int flexran_agent_msg_recv(mid_t mod_id, agent_id_t agent_id, void **data, int *size, int *priority);
+
+/*Register a channel to an agent. Use FLEXRAN_AGENT_MAX to register the
+ *same channel to all agents*/
+int flexran_agent_register_channel(mid_t mod_id, flexran_agent_channel_t *channel, agent_id_t agent_id);
+
+/*Unregister the current channel of an agent. Use FLEXRAN_AGENT_MAX to unregister all channels*/
+void flexran_agent_unregister_channel(mid_t mod_id, agent_id_t agent_id);
+
+/*Create a new channel. Returns the id of the new channel or negative number otherwise*/
+int flexran_agent_create_channel(void *channel_info,
+				 int (*msg_send)(void *data, int size, int priority, void *channel_info),
+				 int (*msg_recv)(void **data, int *size, int *priority, void *channel_info),
+				 void (*release)(flexran_agent_channel_t *channel));
+
+/*Unregister a channel from all agents and destroy it. Returns 0 in case of success*/
+int flexran_agent_destroy_channel(int channel_id);
+
+/*Return an agent communication channel based on its id*/
+flexran_agent_channel_t * get_channel(int channel_id);
+
+/*Should be called before performing any channel operations*/
+err_code_t flexran_agent_init_channel_container(void);
+
+int flexran_agent_compare_channel(struct flexran_agent_channel_s *a, struct flexran_agent_channel_s *b);
+
+/* RB_PROTOTYPE is for .h files */
+RB_PROTOTYPE(flexran_agent_channel_map, flexran_agent_channel_s, entry, flexran_agent_compare_channel);
+
+#endif /*FLEXRAN_AGENT_COMM_H_*/
diff --git a/openair2/ENB_APP/flexran_agent_task_manager.c b/openair2/ENB_APP/flexran_agent_task_manager.c
new file mode 100644
index 0000000000000000000000000000000000000000..eaa6a58af8d0cfcf2f6019f3674bcfa964df6c5f
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_task_manager.c
@@ -0,0 +1,304 @@
+/*
+ * 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.0  (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 flexran_agent_task_manager.h
+ * \brief Implementation of scheduled tasks manager for the FlexRAN agent
+ * \author Xenofon Foukas
+ * \date January 2016
+ * \version 0.1
+ * \email: x.foukas@sms.ed.ac.uk
+ * @ingroup _mac
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "flexran_agent_task_manager.h"
+#include "flexran_agent_common.c"
+
+
+/* Util macros */
+#define LEFT(x) (2 * (x) + 1)
+#define RIGHT(x) (2 * (x) + 2)
+#define PARENT(x) ((x - 1) / 2)
+
+flexran_agent_task_t *flexran_agent_task_create(Protocol__FlexranMessage *msg,
+						uint16_t frame_num, uint8_t subframe_num) {
+  flexran_agent_task_t *task = NULL;
+  task = malloc(sizeof(flexran_agent_task_t));
+
+  if (task == NULL)
+    goto error;
+
+  task->frame_num = frame_num;
+  task->subframe_num = subframe_num;
+  task->task = msg;
+  
+  return task;
+  
+ error:
+  return NULL;
+}
+
+void flexran_agent_task_destroy(flexran_agent_task_t *task) {
+  if (task == NULL)
+    return;
+
+  /* TODO: must free the task properly */
+  free(task->task);
+  free(task);
+}
+
+flexran_agent_task_queue_t *flexran_agent_task_queue_init(mid_t mod_id, size_t capacity,
+							  int (*cmp)(mid_t mod_id, const flexran_agent_task_t *t1,
+								     const flexran_agent_task_t *t2)) {
+  flexran_agent_task_queue_t *queue = NULL;
+
+  queue = malloc(sizeof(flexran_agent_task_queue_t));
+  if (queue == NULL)
+    goto error;
+
+  /* If no comparator was given, use the default one */
+  if (cmp == NULL)
+    queue->cmp = _flexran_agent_task_queue_cmp;
+  else
+    queue->cmp = cmp;
+  
+  queue->mod_id = mod_id;
+
+  queue->first_frame = 0;
+  queue->first_subframe = 0;
+  
+  queue->task = malloc(capacity * sizeof(flexran_agent_task_t *));
+  if (queue->task == NULL)
+    goto error;
+
+  queue->count = 0;
+  queue->capacity = capacity;
+  
+  queue->mutex = malloc(sizeof(pthread_mutex_t));
+  if (queue->mutex == NULL)
+    goto error;
+  if (pthread_mutex_init(queue->mutex, NULL))
+    goto error;
+
+  return queue;
+
+ error:
+  if (queue != NULL) {
+    free(queue->mutex);
+    free(queue->task);
+    free(queue);
+  }
+  return NULL;
+}
+
+flexran_agent_task_queue_t *flexran_agent_task_queue_default_init(mid_t mod_id) {
+  return flexran_agent_task_queue_init(mod_id, DEFAULT_CAPACITY, NULL);
+}
+
+void flexran_agent_task_queue_destroy(flexran_agent_task_queue_t *queue) {
+  int i;
+  
+  if (queue == NULL)
+    return;
+
+  for (i = 0; i < queue->count; i++) {
+    flexran_agent_task_destroy(queue->task[i]);
+  }
+  free(queue->task);
+  free(queue->mutex);
+  free(queue);
+}
+
+int flexran_agent_task_queue_put(flexran_agent_task_queue_t *queue, flexran_agent_task_t *task) {
+  size_t i;
+  flexran_agent_task_t *tmp = NULL;
+  int realloc_status, err_code;
+
+  if (pthread_mutex_lock(queue->mutex)) {
+    /*TODO*/
+    err_code = -1;
+    goto error;
+  }
+
+  if (queue->count >= queue->capacity) {
+    /*TODO: need to call realloc heap*/
+    realloc_status = _flexran_agent_task_queue_realloc_heap(queue);
+    if (realloc_status != HEAP_OK) {
+      err_code = realloc_status;
+      goto error;
+    }
+  }
+
+  queue->task[queue->count] = task;
+  i = queue->count;
+  queue->count++;
+  /*Swap elements to maintain heap properties*/
+  while(i > 0 && queue->cmp(queue->mod_id, queue->task[i], queue->task[PARENT(i)]) > 0) {
+    tmp = queue->task[i];
+    queue->task[i] = queue->task[PARENT(i)];
+    queue->task[PARENT(i)] = tmp;
+    i = PARENT(i);
+  }  
+  
+  if (pthread_mutex_unlock(queue->mutex)) {
+    // LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+  return 0;
+
+ error:
+  /*TODO*/
+  return err_code;
+}
+
+
+int flexran_agent_task_queue_get_current_task(flexran_agent_task_queue_t *queue, flexran_agent_task_t **task) {
+  int err_code;
+  
+  if (pthread_mutex_lock(queue->mutex)) {
+    /*TODO*/
+    err_code = -1;
+    goto error;
+  }
+  
+  if (queue->count < 1) {         
+    /* Priority Queue is empty */         
+    err_code = HEAP_EMPTY;
+    goto error;
+  }
+
+  /* Find current frame and subframe number */
+  uint16_t curr_frame = flexran_get_current_frame(queue->mod_id);
+  uint8_t curr_subframe = flexran_get_current_subframe(queue->mod_id);
+
+  /* If no task is scheduled for the current subframe, return without any task */
+  if(queue->task[0]->frame_num != curr_frame || queue->task[0]->subframe_num != curr_subframe) {
+    *task = NULL;
+    return 0;
+  }
+  /* Otherwise, the first task should be returned */
+  *task = queue->task[0];
+  queue->task[0] = queue->task[queue->count-1];
+  queue->count--;
+  /* Restore heap property */
+  _flexran_agent_task_queue_heapify(queue, 0);
+  
+  /*If queue has no element*/
+  if (queue->count < 1) {
+    queue->first_frame = 0;
+    queue->first_subframe = 0;
+  } else {
+    queue->first_frame = queue->task[0]->frame_num;
+    queue->first_subframe = queue->task[0]->subframe_num;
+  }
+  
+  if (pthread_mutex_unlock(queue->mutex)) {
+    // LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+  return HEAP_OK;
+
+ error:
+  /*TODO*/
+  return err_code;
+}
+
+/*Warning: Internal function. Should not be called as API function. Not thread safe*/
+void _flexran_agent_task_queue_heapify(flexran_agent_task_queue_t *queue, size_t idx) {
+  /* left index, right index, largest */
+  flexran_agent_task_t *tmp = NULL;
+  size_t l_idx, r_idx, lrg_idx;
+
+  l_idx = LEFT(idx);
+  r_idx = RIGHT(idx);
+
+  /* Left child exists, compare left child with its parent */
+  if (l_idx < queue->count && queue->cmp(queue->mod_id, queue->task[l_idx], queue->task[idx]) > 0) {
+    lrg_idx = l_idx;
+  } else {
+    lrg_idx = idx;
+  }
+
+  /* Right child exists, compare right child with the largest element */
+  if (r_idx < queue->count && queue->cmp(queue->mod_id, queue->task[r_idx], queue->task[lrg_idx]) > 0) {
+    lrg_idx = r_idx;
+  }
+
+  /* At this point largest element was determined */
+  if (lrg_idx != idx) {
+    /* Swap between the index at the largest element */
+    tmp = queue->task[lrg_idx];
+    queue->task[lrg_idx] = queue->task[idx];
+    queue->task[idx] = tmp;
+    /* Heapify again */
+    _flexran_agent_task_queue_heapify(queue, lrg_idx);
+  }
+}
+
+/*Warning: Internal function. Should not be called as API function. Not thread safe*/
+int _flexran_agent_task_queue_realloc_heap(flexran_agent_task_queue_t *queue) {
+  flexran_agent_task_t **resized_task_heap;
+  if (queue->count >= queue->capacity) {
+    size_t task_size = sizeof(flexran_agent_task_t);
+
+    resized_task_heap = realloc(queue->task, (2*queue->capacity) * task_size);
+    if (resized_task_heap != NULL) {
+      queue->capacity *= 2;
+      queue->task = (flexran_agent_task_t **) resized_task_heap;
+      return HEAP_OK;
+    } else return HEAP_REALLOCERROR;
+  }
+  return HEAP_NOREALLOC;
+}
+
+int _flexran_agent_task_queue_cmp(mid_t mod_id, const flexran_agent_task_t *t1, const flexran_agent_task_t *t2) {
+  if ((t1->frame_num == t2->frame_num) && (t1->subframe_num == t2->subframe_num))
+    return 0;
+
+  uint16_t curr_frame = flexran_get_current_frame(mod_id);
+  uint8_t curr_subframe = flexran_get_current_subframe(mod_id);
+
+  int f_offset, sf_offset, tmp1, tmp2;
+
+  /*Check if the offsets have the same sign and compare the tasks position frame-wise*/
+  tmp1 = t1->frame_num - curr_frame;
+  tmp2 = t2->frame_num - curr_frame;
+  if ((tmp1 >= 0) ^ (tmp2 < 0)) {
+    f_offset = tmp2 - tmp1;
+  }
+  else {
+    f_offset = tmp1 - tmp2;
+  }
+  /*Do the same for the subframe*/
+  tmp1 = t1->subframe_num - curr_subframe;
+  tmp2 = t2->subframe_num - curr_subframe;
+  if ((tmp1 >= 0) ^ (tmp2 < 0))
+    sf_offset = tmp2 - tmp1;
+  else
+    sf_offset = tmp1 - tmp2;
+
+  /*Subframe position matters only if f_offset is 0. Multiply f_offset by 100
+    to be the only comparisson parameter in all other cases */
+  return f_offset*100 + sf_offset;
+}
diff --git a/openair2/ENB_APP/flexran_agent_task_manager.h b/openair2/ENB_APP/flexran_agent_task_manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b14f1f6f6754d6e45d5201a40650f54146a8eac
--- /dev/null
+++ b/openair2/ENB_APP/flexran_agent_task_manager.h
@@ -0,0 +1,156 @@
+/*
+ * 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.0  (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 flexran_agent_task_manager.h
+ * \brief Implementation of scheduled tasks manager for the FlexRAN agent
+ * \author Xenofon Foukas
+ * \date January 2016
+ * \version 0.1
+ * \email: x.foukas@sms.ed.ac.uk
+ * @ingroup _mac
+ */
+
+#ifndef FLEXRAN_AGENT_TASK_MANAGER_
+#define FLEXRAN_AGENT_TASK_MANAGER_
+
+#include <stdint.h>
+#include <pthread.h>
+
+#include "flexran.pb-c.h"
+
+#include "flexran_agent_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEFAULT_CAPACITY 512
+  
+/**
+ * The structure containing the enb agent task to be executed
+ */
+typedef struct flexran_agent_task_s {
+  /* The frame in which the task needs to be executed */
+  uint16_t frame_num;
+  /* The subframe in which the task needs to be executed */
+  uint8_t subframe_num;
+  /* The task to be executed in the form of a Protocol__FlexranMessage */
+  Protocol__FlexranMessage *task;
+} flexran_agent_task_t;
+
+/**
+ * Priority Queue Structure for tasks
+ */
+typedef struct flexran_agent_task_queue_s {
+  mid_t mod_id;
+  /* The amount of allocated memory for agent tasks in the heap*/
+  volatile size_t capacity;
+  /* The actual size of the tasks heap at a certain time */
+  volatile size_t count;
+  /* The earliest frame that has a pending task */
+  volatile uint16_t first_frame;
+  /* The earliest subframe within the frame that has a pending task */
+  volatile uint8_t first_subframe;
+  /* An array of prioritized tasks stored in a heap */
+  flexran_agent_task_t **task;
+  /* A pointer to a comparator function, used to prioritize elements */
+  int (*cmp)(mid_t mod_id, const flexran_agent_task_t *t1, const flexran_agent_task_t *t2);
+  pthread_mutex_t *mutex;
+} flexran_agent_task_queue_t;
+
+typedef enum {
+  HEAP_OK = 0,
+  HEAP_EMPTY,
+  HEAP_FAILED,
+  HEAP_REALLOCERROR,
+  HEAP_NOREALLOC,
+  HEAP_FATAL,
+} heapstatus_e;
+  
+/**
+ * Allocate memory for a task in the queue
+ */
+flexran_agent_task_t *flexran_agent_task_create(Protocol__FlexranMessage *msg,
+						uint16_t frame_num, uint8_t subframe_num);
+  
+/**
+ * Free memory for a task of the queue
+ */
+void flexran_agent_task_destroy(flexran_agent_task_t *task);
+  
+/**
+ * Allocate initial memory for storing the tasks
+ */
+  flexran_agent_task_queue_t *flexran_agent_task_queue_init(mid_t mod_id, size_t capacity,
+							    int (*cmp)(mid_t mod_id, const flexran_agent_task_t *t1, 
+								       const flexran_agent_task_t *t2));
+
+/**
+ * Allocate initial memory for storing the tasks using default parameters
+ */
+flexran_agent_task_queue_t *flexran_agent_task_queue_default_init(mid_t mod_id);  
+  
+/**
+ * De-allocate memory for the tasks queue
+ */
+void flexran_agent_task_queue_destroy(flexran_agent_task_queue_t *queue);
+  
+/**
+ * Insert task into the queue
+ */
+int flexran_agent_task_queue_put(flexran_agent_task_queue_t *queue, flexran_agent_task_t *task); 
+
+/**
+ * Remove the task with the highest priority from the queue
+ * task becomes NULL if there is no task for the current frame and subframe
+ */
+int flexran_agent_task_queue_get_current_task(flexran_agent_task_queue_t *queue, flexran_agent_task_t **task);
+
+/**
+ * Check if the top priority task is for a specific frame and subframe
+ */
+int flexran_agent_task_queue_has_upcoming_task (flexran_agent_task_queue_t *queue,
+						const uint16_t frame, const uint8_t subframe);
+
+/**
+ * Restructure heap after modifications
+ */
+void _flexran_agent_task_queue_heapify(flexran_agent_task_queue_t *queue, size_t idx);
+
+/**
+ * Reallocate memory once the heap reaches max size
+ */
+int _flexran_agent_task_queue_realloc_heap(flexran_agent_task_queue_t *queue);
+
+/**
+ * Compare two agent tasks based on frame and subframe
+ * returns 0 if tasks t1, t2 have the same priority
+ * return negative value if t1 needs to be executed after t2
+ * return positive value if t1 preceeds t2
+ * Need to give eNB id for the comparisson based on the current frame-subframe
+ */
+  int _flexran_agent_task_queue_cmp(mid_t mod_id, const flexran_agent_task_t *t1, const flexran_agent_task_t *t2);
+
+#ifdef __cplusplus
+}
+#endif
+  
+#endif  /*FLEXRAN_AGENT_TASK_MANAGER_*/
diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c
index 3fbcadafbbd1f1e75ddd3ed35a41b7d7784949fa..e4252ed50049afbc0f19362697f10e11956fe301 100644
--- a/openair2/LAYER2/MAC/config.c
+++ b/openair2/LAYER2/MAC/config.c
@@ -70,6 +70,9 @@ void ue_mac_reset(module_id_t module_idP,uint8_t eNB_index)
   UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
   UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
 
+//Set BSR Trigger Bmp and remove timer flags
+  UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
+
   // stop ongoing RACH procedure
 
   // discard explicitly signaled ra_PreambleIndex and ra_RACH_MaskIndex, if any
@@ -178,8 +181,14 @@ rrc_mac_config_req(
       if (logicalChannelConfig->ul_SpecificParameters) {
         UE_mac_inst[Mod_idP].scheduling_info.bucket_size[logicalChannelIdentity]=logicalChannelConfig->ul_SpecificParameters->prioritisedBitRate *
             logicalChannelConfig->ul_SpecificParameters->bucketSizeDuration; // set the max bucket size
-        UE_mac_inst[Mod_idP].scheduling_info.LCGID[logicalChannelIdentity]=*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup;
-        LOG_D(MAC,"[CONFIG][UE %d] LCID %d is attached to the LCGID %d\n",Mod_idP,logicalChannelIdentity,*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup);
+        if (logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup != NULL) {
+            UE_mac_inst[Mod_idP].scheduling_info.LCGID[logicalChannelIdentity]=*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup;
+            LOG_D(MAC,"[CONFIG][UE %d] LCID %d is attached to the LCGID %d\n",Mod_idP,logicalChannelIdentity,*logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup);
+        }
+        else {
+        	UE_mac_inst[Mod_idP].scheduling_info.LCGID[logicalChannelIdentity] = MAX_NUM_LCGID;
+        }
+        UE_mac_inst[Mod_idP].scheduling_info.LCID_buffer_remain[logicalChannelIdentity] = 0;
       } else {
         LOG_E(MAC,"[CONFIG][UE %d] LCID %d NULL ul_SpecificParameters\n",Mod_idP,logicalChannelIdentity);
         mac_xface->macphy_exit("NULL ul_SpecificParameters");
@@ -212,6 +221,7 @@ rrc_mac_config_req(
         } else {
           UE_mac_inst[Mod_idP].scheduling_info.maxHARQ_Tx     = (uint16_t) MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
         }
+        mac_xface->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     = (uint16_t) mac_MainConfig->ul_SCH_Config->retxBSR_Timer;
@@ -225,12 +235,34 @@ rrc_mac_config_req(
       if (mac_MainConfig->ext1 && mac_MainConfig->ext1->sr_ProhibitTimer_r9) {
         UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer  = (uint16_t) *mac_MainConfig->ext1->sr_ProhibitTimer_r9;
       } else {
-        UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer  = (uint16_t) 0;
+        UE_mac_inst[Mod_idP].scheduling_info.sr_ProhibitTimer  = 0;
       }
 
+      if (mac_MainConfig->ext2 && mac_MainConfig->ext2->mac_MainConfig_v1020) {
+        if (mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10) {
+          UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = (uint16_t) *mac_MainConfig->ext2->mac_MainConfig_v1020->extendedBSR_Sizes_r10;
+        } else {
+          UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = (uint16_t)0;
+        }
+        if (mac_MainConfig->ext2->mac_MainConfig_v1020->extendedPHR_r10) {
+          UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = (uint16_t) *mac_MainConfig->ext2->mac_MainConfig_v1020->extendedPHR_r10;
+        } else {
+          UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = (uint16_t)0;
+        }
+      } else {
+        UE_mac_inst[Mod_idP].scheduling_info.extendedBSR_Sizes_r10 = (uint16_t)0;
+        UE_mac_inst[Mod_idP].scheduling_info.extendedPHR_r10 = (uint16_t)0;
+      }
 #endif
-      UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF  = get_sf_periodicBSRTimer(UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_Timer);
-      UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF     = get_sf_retxBSRTimer(UE_mac_inst[Mod_idP].scheduling_info.retxBSR_Timer);
+      UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF  = MAC_UE_BSR_TIMER_NOT_RUNNING;
+      UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF     = MAC_UE_BSR_TIMER_NOT_RUNNING;
+
+       UE_mac_inst[Mod_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
+
+      LOG_D(MAC,"[UE %d]: periodic BSR %d (SF), retx BSR %d (SF)\n",
+            Mod_idP,
+            UE_mac_inst[Mod_idP].scheduling_info.periodicBSR_SF,
+            UE_mac_inst[Mod_idP].scheduling_info.retxBSR_SF);
 
       UE_mac_inst[Mod_idP].scheduling_info.drx_config     = mac_MainConfig->drx_Config;
       UE_mac_inst[Mod_idP].scheduling_info.phr_config     = mac_MainConfig->phr_Config;
@@ -252,6 +284,7 @@ rrc_mac_config_req(
       UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_SF =  get_sf_perioidicPHR_Timer(UE_mac_inst[Mod_idP].scheduling_info.periodicPHR_Timer);
       UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_SF =  get_sf_prohibitPHR_Timer(UE_mac_inst[Mod_idP].scheduling_info.prohibitPHR_Timer);
       UE_mac_inst[Mod_idP].scheduling_info.PathlossChange_db =  get_db_dl_PathlossChange(UE_mac_inst[Mod_idP].scheduling_info.PathlossChange);
+      UE_mac_inst[Mod_idP].PHR_reporting_active = 0;
       LOG_D(MAC,"[UE %d] config PHR (%d): periodic %d (SF) prohibit %d (SF)  pathlosschange %d (db) \n",
             Mod_idP,
             (mac_MainConfig->phr_Config)?mac_MainConfig->phr_Config->present:-1,
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index 2235c3e1c41a01a2b66009692ac4a72a021a82c4..15c0f3fb0e826dcbba8486d31483ceb0decdca61 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -133,10 +133,18 @@
 /*!\brief maximum value for channel quality indicator */
 #define MAX_CQI_VALUE  15
 
+/*!\brief value for indicating BSR Timer is not running */
+#define MAC_UE_BSR_TIMER_NOT_RUNNING   (0xFFFF)
 
 #define LCID_EMPTY 0
 #define LCID_NOT_EMPTY 1
 
+/*!\brief minimum RLC PDU size to be transmitted = min RLC Status PDU or RLC UM PDU SN 5 bits */
+#define MIN_RLC_PDU_SIZE    (2)
+
+/*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */
+#define MIN_MAC_HDR_RLC_SIZE    (1 + MIN_RLC_PDU_SIZE)
+
 /* 
  * eNB part 
  */ 
@@ -222,11 +230,10 @@ typedef struct {
 typedef BSR_SHORT BSR_TRUNCATED;
 /*!\brief  mac control element: long buffer status report for all logical channel group ID*/
 typedef struct {
-  uint32_t Buffer_size3:6;
-  uint32_t Buffer_size2:6;
-  uint32_t Buffer_size1:6;
-  uint32_t Buffer_size0:6;
-  uint32_t padding:8;
+  uint8_t Buffer_size3:6;
+  uint8_t Buffer_size2:6;
+  uint8_t Buffer_size1:6;
+  uint8_t Buffer_size0:6;
 } __attribute__((__packed__))BSR_LONG;
 
 #define BSR_LONG_SIZE  (sizeof(BSR_LONG))
@@ -336,6 +343,12 @@ typedef struct {
 #define SHORT_BSR 29
 /*!\brief LCID of long BSR for ULSCH */
 #define LONG_BSR 30
+/*!\bitmaps for BSR Triggers */
+#define	BSR_TRIGGER_NONE		(0)			/* No BSR Trigger */
+#define	BSR_TRIGGER_REGULAR		(1)			/* For Regular and ReTxBSR Expiry Triggers */
+#define	BSR_TRIGGER_PERIODIC	(2)			/* For BSR Periodic Timer Expiry Trigger */
+#define	BSR_TRIGGER_PADDING		(4)			/* For Padding BSR Trigger */
+
 
 /*! \brief Downlink SCH PDU Structure */
 typedef struct {
@@ -462,6 +475,13 @@ typedef struct {
   //
   uint32_t total_ulsch_pdus_rx;
   
+  
+  /// MAC agent-related stats
+  /// total number of scheduling decisions
+  int sched_decisions;
+  /// missed deadlines
+  int missed_deadlines;
+
 } eNB_STATS;
 /*! \brief eNB statistics for the connected UEs*/
 typedef struct {
@@ -602,6 +622,12 @@ typedef struct {
   /// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received)
   boolean_t configured;
 
+  /// MCS from last scheduling
+  uint8_t mcs[8];
+
+  /// TPC from last scheduling
+  uint8_t oldTPC[8];
+
   // PHY interface info
 
   /// DCI format for DLSCH
@@ -945,8 +971,12 @@ typedef enum {
 typedef struct {
   /// buffer status for each lcgid
   uint8_t  BSR[MAX_NUM_LCGID]; // should be more for mesh topology
-  /// keep the number of bytes in rlc buffer for each lcid
-  uint16_t  BSR_bytes[MAX_NUM_LCGID];
+  /// keep the number of bytes in rlc buffer for each lcgid
+  int32_t  BSR_bytes[MAX_NUM_LCGID];
+  /// after multiplexing buffer remain for each lcid
+  int32_t  LCID_buffer_remain[MAX_NUM_LCID];
+  /// sum of all lcid buffer size
+  uint16_t  All_lcid_buffer_size_lastTTI;
   /// buffer status for each lcid
   uint8_t  LCID_status[MAX_NUM_LCID];
   /// SR pending as defined in 36.321
@@ -958,11 +988,11 @@ typedef struct {
   /// retxBSR-Timer, default value is sf2560
   uint16_t retxBSR_Timer;
   /// retxBSR_SF, number of subframe before triggering a regular BSR
-  int16_t retxBSR_SF;
+  uint16_t retxBSR_SF;
   /// periodicBSR-Timer, default to infinity
   uint16_t periodicBSR_Timer;
   /// periodicBSR_SF, number of subframe before triggering a periodic BSR
-  int16_t periodicBSR_SF;
+  uint16_t periodicBSR_SF;
   /// default value is 0: not configured
   uint16_t sr_ProhibitTimer;
   /// sr ProhibitTime running
@@ -987,6 +1017,12 @@ typedef struct {
   int16_t prohibitPHR_SF;
   ///DL Pathloss Change in db
   uint16_t PathlossChange_db;
+
+  /// default value is false
+  uint16_t extendedBSR_Sizes_r10;
+  /// default value is false
+  uint16_t extendedPHR_r10;
+
   //Bj bucket usage per  lcid
   int16_t Bj[MAX_NUM_LCID];
   // Bucket size per lcid
@@ -995,10 +1031,14 @@ typedef struct {
 /*!\brief Top level UE MAC structure */
 typedef struct {
   uint16_t Node_id;
-  /// frame counter
-  frame_t     frame;
-  /// subframe counter
-  sub_frame_t subframe;
+  /// RX frame counter
+  frame_t     rxFrame;
+  /// RX subframe counter
+  sub_frame_t rxSubframe;
+  /// TX frame counter
+  frame_t     txFrame;
+  /// TX subframe counter
+  sub_frame_t txSubframe;
   /// C-RNTI of UE
   uint16_t crnti;
   /// C-RNTI of UE before HO
@@ -1074,6 +1114,13 @@ typedef struct {
   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
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index 373bfd05cb93095d637f5dc9fce36e65ba8a61b6..c5dc8c88b04465ab71f69033ae2cd83cdb753acb 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -52,12 +52,23 @@
 //#include "LAYER2/MAC/pre_processor.c"
 #include "pdcp.h"
 
+#if defined(FLEXRAN_AGENT_SB_IF)
+//Agent-related headers
+#include "flexran_agent_extern.h"
+#include "flexran_agent_mac.h"
+#include "flexran_agent_mac_proto.h"
+#endif
+
 #if defined(ENABLE_ITTI)
 # include "intertask_interface.h"
 #endif
 
 #define ENABLE_MAC_PAYLOAD_DEBUG
 #define DEBUG_eNB_SCHEDULER 1
+//efine ENABLE_ENB_AGENT_DL_SCHEDULER
+//#define DISABLE_SF_TRIGGER
+//#define DISABLE_CONT_STATS
+
 //#define DEBUG_HEADER_PARSING 1
 //#define DEBUG_PACKET_TRACE 1
 
@@ -94,6 +105,10 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
   void         *DLSCH_dci=NULL;
   int size_bits=0,size_bytes=0;
 
+#if defined(FLEXRAN_AGENT_SB_IF)
+  Protocol__FlexranMessage *msg;
+#endif
+
   LOG_D(MAC,"[eNB %d] Frame %d, Subframe %d, entering MAC scheduler (UE_list->head %d)\n",module_idP, frameP, subframeP,UE_list->head);
 
   start_meas(&eNB_mac_inst[module_idP].eNB_scheduler);
@@ -126,8 +141,17 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 
     eNB_mac_inst[module_idP].UE_list.UE_sched_ctrl[i].cqi_req_timer++;
     
+
     if (mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti)==NULL) {
-      //      mac_remove_ue(module_idP, i, frameP, subframeP);
+	//mac_remove_ue(module_idP, i, frameP, subframeP);
+      //Inform the controller about the UE deactivation. Should be moved to RRC agent in the future
+#if defined(FLEXRAN_AGENT_SB_IF)
+      if (mac_agent_registered[module_idP]) {
+	agent_mac_xface[module_idP]->flexran_agent_notify_ue_state_change(module_idP,
+									  rnti,
+									  PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED);
+      }
+#endif
     }
     else {
       // check uplink failure
@@ -309,7 +333,14 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 
 
   }
-
+  
+/* #ifndef DISABLE_SF_TRIGGER */
+/*   //Send subframe trigger to the controller */
+/*   if (mac_agent_registered[module_idP]) { */
+/*     agent_mac_xface[module_idP]->flexran_agent_send_sf_trigger(module_idP); */
+/*   } */
+/* #endif */
+  
   //if (subframeP%5 == 0)
   //#ifdef EXMIMO
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP,module_idP);
@@ -363,10 +394,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
                 (mac_xface->frame_parms->tdd_config == 6)) {
       //schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag);
     }
-
+#ifndef FLEXRAN_AGENT_SB_IF
     schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
     fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
-
+#else
+    if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
     break;
 
   case 1:
@@ -378,12 +425,16 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       case 0:
       case 1:
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7);
+#ifndef FLEXRAN_AGENT_SB_IF
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
         break;
 
       case 6:
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8);
+#ifndef FLEXRAN_AGENT_SB_IF
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
         break;
 
       default:
@@ -391,8 +442,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       }
     } else { //FDD
       schedule_ulsch(module_idP,frameP,cooperation_flag,1,5);
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+      if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
     }
 
     break;
@@ -403,8 +472,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
     // FDD, normal UL/DLSCH
     if (mac_xface->frame_parms->frame_type == FDD) {  //FDD
       schedule_ulsch(module_idP,frameP,cooperation_flag,2,6);
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+      if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
     }
 
     break;
@@ -421,8 +508,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 
         // no break here!
       case 5:
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       default:
@@ -431,8 +536,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
     } else { //FDD
 
       schedule_ulsch(module_idP,frameP,cooperation_flag,3,7);
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+      if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+      }
+#endif
     }
 
     break;
@@ -456,9 +579,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 
         // no break here!
       case 5:
-
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
-        fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+	fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+					       frameP,
+					       subframeP,
+					       mbsfn_status,
+					       msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif	
         break;
 
       default:
@@ -468,8 +608,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       if (mac_xface->frame_parms->frame_type == FDD) {  //FDD
 
 	schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8);
+#ifndef FLEXRAN_AGENT_SB_IF
 	schedule_ue_spec(module_idP, frameP, subframeP,  mbsfn_status);
         fill_DLSCH_dci(module_idP, frameP, subframeP,   mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}     
+#endif
       }
     }
 
@@ -486,15 +644,53 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
     if (mac_xface->frame_parms->frame_type == FDD) {
       schedule_RA(module_idP,frameP,subframeP,1);
       schedule_ulsch(module_idP,frameP,cooperation_flag,5,9);
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP, frameP, subframeP,  mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+      if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+					  frameP,
+					  subframeP,
+					  mbsfn_status,
+					  msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
     } else if ((mac_xface->frame_parms->tdd_config == 0) || // TDD Config 0
                (mac_xface->frame_parms->tdd_config == 6)) { // TDD Config 6
       //schedule_ulsch(module_idP,cooperation_flag,subframeP);
+#ifndef FLEXRAN_AGENT_SB_IF
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
     } else {
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+      if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
     }
 
     break;
@@ -512,25 +708,65 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       case 1:
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2);
         //  schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
+#ifndef FLEXRAN_AGENT_SB_IF
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
         break;
 
       case 6:
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
         //  schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
+#ifndef FLEXRAN_AGENT_SB_IF
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#endif
         break;
 
       case 5:
         schedule_RA(module_idP,frameP,subframeP,2);
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       case 3:
       case 4:
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       default:
@@ -538,8 +774,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       }
     } else { //FDD
       schedule_ulsch(module_idP,frameP,cooperation_flag,6,0);
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+      if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
     }
 
     break;
@@ -553,13 +807,49 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       case 3:
       case 4:
         schedule_RA(module_idP,frameP,subframeP,3);  // 3 = Msg3 subframeP, not
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       case 5:
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       default:
@@ -567,8 +857,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       }
     } else { //FDD
       schedule_ulsch(module_idP,frameP,cooperation_flag,7,1);
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+      if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
     }
 
     break;
@@ -587,8 +895,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 
         //  schedule_RA(module_idP,subframeP);
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2);
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       default:
@@ -596,8 +922,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       }
     } else { //FDD
       schedule_ulsch(module_idP,frameP,cooperation_flag,8,2);
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+      if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
     }
 
     break;
@@ -610,29 +954,101 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       case 1:
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
         schedule_RA(module_idP,frameP,subframeP,7);  // 7 = Msg3 subframeP, not
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       case 3:
       case 4:
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       case 6:
         schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);
         //schedule_RA(module_idP,frameP,subframeP);
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       case 2:
       case 5:
         //schedule_RA(module_idP,frameP,subframeP);
+#ifndef FLEXRAN_AGENT_SB_IF
         schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
         fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+	if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+	}
+#endif
         break;
 
       default:
@@ -640,8 +1056,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
       }
     } else { //FDD
       schedule_ulsch(module_idP,frameP,cooperation_flag,9,3);
+#ifndef FLEXRAN_AGENT_SB_IF
       schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
       fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
+#else
+      if (mac_agent_registered[module_idP]) {                                  
+	  agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
+								      module_idP,
+								      frameP,                  
+								      subframeP,
+								      mbsfn_status,
+								      &msg);
+	  
+	  flexran_apply_dl_scheduling_decisions(module_idP,
+						frameP,
+						subframeP,
+						mbsfn_status,
+						msg);
+	  flexran_agent_mac_destroy_dl_config(msg);
+      }
+#endif
     }
 
     break;
@@ -654,6 +1088,15 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
   for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++)
     allocate_CCEs(module_idP,CC_id,subframeP,0);
 
+#if defined(FLEXRAN_AGENT_SB_IF)
+#ifndef DISABLE_CONT_STATS
+  //Send subframe trigger to the controller
+  if (mac_agent_registered[module_idP]) {
+    agent_mac_xface[module_idP]->flexran_agent_send_update_mac_stats(module_idP);
+  }
+#endif
+#endif
+
   /*
   int dummy=0;
   for (i=0;
@@ -673,7 +1116,6 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
 	    DCI_pdu[CC_id]->dci_alloc[i].firstCCE,
 	    DCI_pdu[CC_id]->num_pdcch_symbols);
 
-
   LOG_D(MAC,"frameP %d, subframeP %d\n",frameP,subframeP);
   */
 
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
index 23ba001d4c3804a011fb4dd1c333686484e64be3..e24281b89aeb985a17310d33cb805df5fd20cb18 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
@@ -648,7 +648,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
 	      if (opt_enabled==1) {
 		trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0],
 			  rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id),
-			  eNB->subframe,0,0);
+			  eNB->frame, eNB->subframe,0,0);
 		LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n",
 		      module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length);
 	      }
@@ -664,7 +664,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
 	LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n",
 	      module_idP,CC_id,frameP,subframeP);
 	// Get candidate harq_pid from PHY
-	mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,0);
+	mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,openair_harq_RA);
 	
 	if (round>0) {
 	  //RA_template->wait_ack_Msg4++;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
index 312de660a46709eccf7507c3388e76092b27295c..fb015320683e343104bcb5750e9d94c136c98068 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
@@ -311,6 +311,7 @@ schedule_SI(
                   0xffff,
                   4,
                   0xffff,
+                  eNB->frame,
                   eNB->subframe,
                   0,
                   0);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
index 3e7f601ef86d03c730ac8213087382e31559609e..573a3401b0d57008c5876ad6961a990dc6ef19a3 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
@@ -641,6 +641,7 @@ schedule_ue_spec(
           switch (mac_xface->get_transmission_mode(module_idP,CC_id,rnti)) {
           case 1:
           case 2:
+          case 7:
           default:
             switch (frame_parms[CC_id]->N_RB_DL) {
             case 6:
@@ -725,7 +726,8 @@ schedule_ue_spec(
             }
 
             break;
-
+	    /* 
+	    // this code is disabled for now - needs to be done properly
           case 4:
             //    if (nb_rb>10) {
             ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 0;
@@ -763,6 +765,7 @@ schedule_ue_spec(
             ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
             ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dl_power_off = 1;//dl_pow_off[UE_id];
             break;
+	    */
           }
 
           add_ue_dlsch_info(module_idP,
@@ -811,15 +814,15 @@ schedule_ue_spec(
           if (rlc_status.bytes_in_buffer > 0) {  // There is DCCH to transmit
             LOG_D(MAC,"[eNB %d] Frame %d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
                   module_idP,frameP,CC_id,TBS-header_len_dcch);
-            sdu_lengths[0] += mac_rlc_data_req(
-                                module_idP,
-                                rnti,
-				module_idP,
-                                frameP,
-                                ENB_FLAG_YES,
-                                MBMS_FLAG_NO,
-                                DCCH,
-                                (char *)&dlsch_buffer[sdu_lengths[0]]);
+            sdu_lengths[0] = mac_rlc_data_req(
+					      module_idP,
+					      rnti,
+					      module_idP,
+					      frameP,
+					      ENB_FLAG_YES,
+					      MBMS_FLAG_NO,
+					      DCCH,
+					      (char *)&dlsch_buffer[0]);
 
             T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
               T_INT(harq_pid), T_INT(DCCH), T_INT(sdu_lengths[0]));
@@ -844,7 +847,7 @@ schedule_ue_spec(
             sdu_length_total = 0;
           }
         }
-
+	
         // check for DCCH1 and update header information (assume 2 byte sub-header)
         if (TBS-ta_len-header_len_dcch-sdu_length_total > 0 ) {
           rlc_status = mac_rlc_status_ind(
@@ -857,9 +860,10 @@ schedule_ue_spec(
                          DCCH+1,
                          (TBS-ta_len-header_len_dcch-sdu_length_total)); // transport block set size less allocations for timing advance and
           // DCCH SDU
+	  sdu_lengths[num_sdus] = 0;
 
           if (rlc_status.bytes_in_buffer > 0) {
-            LOG_D(MAC,"[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
+            LOG_I(MAC,"[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
                   module_idP,frameP,CC_id,TBS-header_len_dcch-sdu_length_total);
             sdu_lengths[num_sdus] += mac_rlc_data_req(
                                        module_idP,
@@ -869,7 +873,7 @@ schedule_ue_spec(
                                        ENB_FLAG_YES,
                                        MBMS_FLAG_NO,
                                        DCCH+1,
-                                       (char *)&dlsch_buffer[sdu_lengths[num_sdus]]);
+                                       (char *)&dlsch_buffer[sdu_length_total]);
 
             T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
               T_INT(harq_pid), T_INT(DCCH+1), T_INT(sdu_lengths[num_sdus]));
@@ -1106,7 +1110,7 @@ schedule_ue_spec(
           if (opt_enabled == 1) {
             trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
                       TBS, module_idP, 3, UE_RNTI(module_idP,UE_id),
-                      eNB->subframe,0,0);
+                      eNB->frame, eNB->subframe,0,0);
             LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d  rnti %x  with size %d\n",
                   module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), TBS);
           }
@@ -1417,8 +1421,9 @@ schedule_ue_spec(
 
             break;
 
+	    /*
+	    // disabled for now as this needs to be done properly
           case 4:
-            //  if (nb_rb>10) {
             ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->mcs1 = mcs;
             ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
             ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 1;
@@ -1426,15 +1431,6 @@ schedule_ue_spec(
             ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
 	    ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->TPC = tpc;
 
-            //}
-            /* else {
-               ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->mcs1 = eNB_UE_stats->DL_cqi[0];
-               ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
-               ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->ndi1 = 1;
-               ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->rv1 = round&3;
-               ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->tpmi = 5;
-               ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
-               }*/
             break;
 
           case 5:
@@ -1465,6 +1461,7 @@ schedule_ue_spec(
 	    ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->TPC = tpc;
 
             break;
+	    */
           }
 
           // Toggle NDI for next time
@@ -1560,6 +1557,8 @@ fill_DLSCH_dci(
         case 1:
 
         case 2:
+
+        case 7:
           LOG_D(MAC,"[eNB %d] CC_id %d Adding UE %d spec DCI for %d PRBS \n",module_idP, CC_id, UE_id, nb_rb);
 
           if (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.frame_type == TDD) {
@@ -1744,9 +1743,9 @@ fill_DLSCH_dci(
 
           break;
 
+	  /*
         case 4:
 
-          //if (nb_rb>10) {
           // DCI format 2_2A
           ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub);
           ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->rah = 0;
@@ -1758,17 +1757,6 @@ fill_DLSCH_dci(
                           sizeof_DCI2_5MHz_2A_TDD_t,
                           format2,
                           0);
-          /*}
-            else {
-            ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->rballoc = allocate_prbs_sub(nb_rb,rballoc_sub);
-            add_ue_spec_dci(DCI_pdu,
-            DLSCH_dci,
-            rnti,
-            sizeof(DCI2_5MHz_2A_L10PRB_TDD_t),
-            2,//aggregation,
-            sizeof_DCI2_5MHz_2A_L10PRB_TDD_t,
-            format2_2A_L10PRB);
-            }*/
           break;
 
         case 5:
@@ -1798,6 +1786,7 @@ fill_DLSCH_dci(
                           format1E_2A_M10PRB,
                           0);
           break;
+	  */
 
         }
       }
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
index 383c18f7369f2cdc00c7dfd16abca55619943fd5..1dac7af70480cf3729724eab6956b3d02a4104a5 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
@@ -621,7 +621,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra
     if (opt_enabled ==1 ) {
       trace_pdu(1, (uint8_t *)eNB_mac_inst[module_idP].common_channels[CC_id].MCH_pdu.payload,
                 TBS, module_idP, 6, 0xffff,  // M_RNTI = 6 in wirehsark
-                eNB_mac_inst[module_idP].subframe,0,0);
+                eNB_mac_inst[module_idP].frame, eNB_mac_inst[module_idP].subframe,0,0);
       LOG_D(OPT,"[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n",
             module_idP, CC_id, frameP, TBS);
     }
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
index 5d72f6fc9d8f7a01d5d7d5206cf6661491581e25..ffd9630648d1dd18811f67ee5da965cbd7d14931 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
@@ -146,7 +146,7 @@ rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP)
     return (rnti);
   }
 
-  LOG_E(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP);
+  LOG_D(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP);
   //display_backtrace();
   return(NOT_A_RNTI);
 }
@@ -1006,7 +1006,7 @@ void dump_CCE_table(int *CCE_table,const int nCCE,const unsigned short rnti,cons
   for (i=0;i<nCCE;i++) {
     printf("%1d.",CCE_table[i]);
     if ((i&7) == 7)
-      printf("\n CCE %d: ", i);
+      printf("\n CCE %d: ",i);
   }
 
   Yk = (unsigned int)rnti;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
index 671e95aec57d040a6bedbd5a9e9e03506cd32dd9..c37224fbfb8e54effc0811311719b1ec1e522c0a 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
@@ -93,7 +93,7 @@ void rx_sdu(const module_id_t enb_mod_idP,
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,1);
   if (opt_enabled == 1) {
-    trace_pdu(0, sduP,sdu_lenP, 0, 3, rntiP,subframeP, 0,0);
+    trace_pdu(0, sduP,sdu_lenP, 0, 3, rntiP, frameP, subframeP, 0,0);
     LOG_D(OPT,"[eNB %d][ULSCH] Frame %d  rnti %x  with size %d\n",
     		  enb_mod_idP, frameP, rntiP, sdu_lenP);
   }
@@ -781,7 +781,7 @@ void schedule_ulsch_rnti(module_id_t   module_idP,
         UE_template   = &UE_list->UE_template[CC_id][UE_id];
         UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
 
-        if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,1) == -1 ) {
+        if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL) == -1 ) {
           LOG_W(MAC,"[eNB %d] Scheduler Frame %d, subframeP %d: candidate harq_pid from PHY for UE %d CC %d RNTI %x\n",
                 module_idP,frameP,subframeP, UE_id, CC_id, rnti);
           continue;
diff --git a/openair2/LAYER2/MAC/extern.h b/openair2/LAYER2/MAC/extern.h
index 8726cb1349a30255dea182b349e311fad7963251..aed8424561c82690379945bab9309c786f475b3f 100644
--- a/openair2/LAYER2/MAC/extern.h
+++ b/openair2/LAYER2/MAC/extern.h
@@ -43,12 +43,18 @@
 //#include "SIMULATION/simulation_defs.h"
 #endif //PHY_EMUL
 #include "PHY_INTERFACE/defs.h"
+#include "RRC/LITE/defs.h"
 
 extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE];
 //extern uint32_t EBSR_Level[63];
+extern const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE];
+//extern uint32_t Extended_BSR_TABLE[63];  ----currently not used 
 
 extern UE_MAC_INST *UE_mac_inst;
 extern eNB_MAC_INST *eNB_mac_inst;
+extern eNB_RRC_INST *eNB_rrc_inst;
+extern UE_RRC_INST *UE_rrc_inst;
+extern UE_MAC_INST *ue_mac_inst;
 extern MAC_RLC_XFACE *Mac_rlc_xface;
 extern uint8_t Is_rrc_registered;
 
diff --git a/openair2/LAYER2/MAC/flexran_agent_mac_proto.h b/openair2/LAYER2/MAC/flexran_agent_mac_proto.h
new file mode 100644
index 0000000000000000000000000000000000000000..060e8ab6ca3f2114b4d98ace3b2cafcee58789e2
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_mac_proto.h
@@ -0,0 +1,62 @@
+/*
+ * 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.0  (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 flexran_agent_mac_proto.h
+ * \brief MAC functions for FlexRAN agent
+ * \author Xenofon Foukas
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#ifndef __LAYER2_MAC_FLEXRAN_AGENT_MAC_PROTO_H__
+#define __LAYER2_MAC_FLEXRAN_AGENT_MAC_PROTO_H__
+
+#include "flexran_agent_defs.h"
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+
+/*
+ * Default scheduler used by the eNB agent
+ */
+void flexran_schedule_ue_spec_default(mid_t mod_id, uint32_t frame, uint32_t subframe,
+				      int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
+
+/*
+ * Data plane function for applying the DL decisions of the scheduler
+ */
+void flexran_apply_dl_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag,
+					   const Protocol__FlexranMessage *dl_scheduling_info);
+
+/*
+ * Data plane function for applying the UE specific DL decisions of the scheduler
+ */
+void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag,
+						uint32_t n_dl_ue_data, const Protocol__FlexDlData **dl_ue_data);
+
+/*
+ * Data plane function for filling the DCI structure
+ */
+void flexran_fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti, const Protocol__FlexDlDci *dl_dci);
+
+#endif
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c
new file mode 100644
index 0000000000000000000000000000000000000000..ff3ef32bd6db47dca8b8e8d90ad0d3a8b1a199f3
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dataplane.c
@@ -0,0 +1,537 @@
+/*
+ * 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.0  (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 flexran_agent_scheduler_dataplane.c
+ * \brief data plane procedures related to eNB scheduling
+ * \author Xenofon Foukas
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#include "assertions.h"
+#include "PHY/defs.h"
+#include "PHY/extern.h"
+
+#include "SCHED/defs.h"
+#include "SCHED/extern.h"
+
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/proto.h"
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/MAC/flexran_dci_conversions.h"
+
+#include "UTIL/LOG/log.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+#include "OCG.h"
+#include "OCG_extern.h"
+
+#include "RRC/LITE/extern.h"
+#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
+
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+
+#include "SIMULATION/TOOLS/defs.h" // for taus
+
+
+void flexran_apply_dl_scheduling_decisions(mid_t mod_id,
+					   uint32_t frame,
+					   uint32_t subframe,
+					   int *mbsfn_flag,
+					   const Protocol__FlexranMessage *dl_scheduling_info) {
+
+  Protocol__FlexDlMacConfig *mac_config = dl_scheduling_info->dl_mac_config_msg;
+
+  // Check if there is anything to schedule for random access
+  if (mac_config->n_dl_rar > 0) {
+    /*TODO: call the random access data plane function*/
+  }
+
+  // Check if there is anything to schedule for paging/broadcast
+  if (mac_config->n_dl_broadcast > 0) {
+    /*TODO: call the broadcast/paging data plane function*/
+  }
+
+  // Check if there is anything to schedule for the UEs
+  if (mac_config->n_dl_ue_data > 0) {
+    flexran_apply_ue_spec_scheduling_decisions(mod_id, frame, subframe, mbsfn_flag,
+					       mac_config->n_dl_ue_data, mac_config->dl_ue_data);
+  }
+  
+}
+
+
+void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
+						uint32_t frame,
+						uint32_t subframe,
+						int *mbsfn_flag,
+						uint32_t n_dl_ue_data,
+						const Protocol__FlexDlData **dl_ue_data) {
+
+  uint8_t               CC_id;
+  int                   UE_id;
+  int                   N_RBG[MAX_NUM_CCs];
+  unsigned char         aggregation;
+  mac_rlc_status_resp_t rlc_status;
+  unsigned char         ta_len=0;
+  unsigned char         header_len = 0, header_len_tmp = 0;
+  unsigned char         sdu_lcids[11],offset,num_sdus=0;
+  uint16_t              nb_rb,nb_rb_temp,total_nb_available_rb[MAX_NUM_CCs],nb_available_rb;
+  uint16_t              TBS,j,sdu_lengths[11],rnti,padding=0,post_padding=0;
+  unsigned char         dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
+  unsigned char         round            = 0;
+  unsigned char         harq_pid         = 0;
+  
+  LTE_eNB_UE_stats     *eNB_UE_stats     = NULL;
+  uint16_t              sdu_length_total = 0;
+  int                   mcs;
+  uint16_t              min_rb_unit[MAX_NUM_CCs];
+  short                 ta_update        = 0;
+  eNB_MAC_INST         *eNB      = &eNB_mac_inst[mod_id];
+  UE_list_t            *UE_list  = &eNB->UE_list;
+  LTE_DL_FRAME_PARMS   *frame_parms[MAX_NUM_CCs];
+  int32_t                 normalized_rx_power, target_rx_power;
+  int32_t                 tpc=1;
+  static int32_t          tpc_accumulated=0;
+  UE_sched_ctrl           *ue_sched_ctl;
+
+  int last_sdu_header_len = 0;
+
+  int i;
+
+  Protocol__FlexDlData *dl_data;
+  Protocol__FlexDlDci *dl_dci;
+
+  uint32_t rlc_size, n_lc, lcid;
+  
+  
+  // For each UE-related command
+  for (i = 0; i < n_dl_ue_data; i++) {
+      
+    dl_data = dl_ue_data[i];
+    dl_dci = dl_data->dl_dci;
+
+    CC_id = dl_data->serv_cell_index;
+    frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+    
+    rnti = dl_data->rnti;
+    UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]);
+
+    ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+    eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
+    
+    round = dl_dci->rv[0];
+    harq_pid = dl_dci->harq_process;
+    
+    // If this is a new transmission
+    if (round == 0) {
+      // First we have to deal with the creation of the PDU based on the message instructions
+      rlc_status.bytes_in_buffer = 0;
+      
+      TBS = dl_dci->tbs_size[0];
+      
+      if (dl_data->n_ce_bitmap > 0) {
+	//Check if there is TA command and set the length appropriately
+	ta_len = (dl_data->ce_bitmap[0] & PROTOCOL__FLEX_CE_TYPE__FLPCET_TA) ? 1 : 0; 
+      }
+      
+      num_sdus = 0;
+      sdu_length_total = 0;
+
+      if (ta_len > 0) {
+	// Reset the measurement
+	ue_sched_ctl->ta_timer = 20;
+	eNB_UE_stats->timing_advance_update = 0;
+	header_len = ta_len;
+	last_sdu_header_len = ta_len;
+      }
+
+      n_lc = dl_data->n_rlc_pdu;
+      // Go through each one of the channel commands and create SDUs
+      for (i = 0; i < n_lc; i++) {
+	lcid = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->logical_channel_id;
+	rlc_size = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->size;
+	LOG_D(MAC,"[TEST] [eNB %d] Frame %d, LCID %d, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
+	      mod_id, frame, lcid, CC_id, rlc_size);
+	if (rlc_size > 0) {
+	  
+	  rlc_status = mac_rlc_status_ind(mod_id,
+	   				  rnti,
+	   				  mod_id,
+	   				  frame,
+	   				  ENB_FLAG_YES,
+	   				  MBMS_FLAG_NO,
+	   				  lcid,
+	   				  0);
+
+	  if (rlc_status.bytes_in_buffer > 0) {
+
+	    if (rlc_size <= 2) {
+	      rlc_size = 3;
+	    }
+
+	    rlc_status = mac_rlc_status_ind(mod_id,
+					    rnti,
+					    mod_id,
+					    frame,
+					    ENB_FLAG_YES,
+					    MBMS_FLAG_NO,
+					    lcid,
+					    rlc_size); // transport block set size
+	  
+	    sdu_lengths[i] = 0;
+	  
+	    LOG_D(MAC, "[TEST] RLC can give %d bytes for LCID %d during second call\n", rlc_status.bytes_in_buffer, lcid);
+	  
+	    if (rlc_status.bytes_in_buffer > 0) {
+	      
+	      sdu_lengths[i] += mac_rlc_data_req(mod_id,
+						 rnti,
+						 mod_id,
+						 frame,
+						 ENB_FLAG_YES,
+						 MBMS_FLAG_NO,
+						 lcid,
+						 (char *)&dlsch_buffer[sdu_length_total]);
+	      
+	      LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[i]);
+	      sdu_length_total += sdu_lengths[i];
+	      sdu_lcids[i] = lcid;
+	      
+	      UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1;
+	      UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[i];
+	      
+	      if (sdu_lengths[i] <= 128) {
+		header_len += 2;
+		last_sdu_header_len = 2;
+	      } else {
+		header_len += 3;
+		last_sdu_header_len = 3;
+	      }
+	      num_sdus++;
+	    }
+	  }
+	}
+      } // SDU creation end
+      
+      
+      if (((sdu_length_total + header_len) > 0)) {
+
+	//	header_len_tmp = header_len;
+	
+	// If we have only a single SDU, header length becomes 1
+	if ((num_sdus + ta_len) == 1) {
+	  //if (header_len == 2 || header_len == 3) {
+	  header_len = 1;
+	} else {
+	  header_len = (header_len - last_sdu_header_len) + 1;
+	}
+	
+	// there is a payload
+	if (((sdu_length_total + header_len) > 0)) {
+	  // If we need a 1 or 2 bit padding or no padding at all
+	  if ((TBS - header_len - sdu_length_total - ta_len) <= 2
+	      || (TBS - header_len - sdu_length_total - ta_len) > TBS) { //protect from overflow
+	    padding = (TBS - header_len - sdu_length_total - ta_len);
+	    post_padding = 0;
+	  } else { // The last sdu needs to have a length field, since we add padding
+	    padding = 0;
+	    header_len = header_len_tmp;	    
+	    post_padding = TBS - sdu_length_total - header_len - ta_len - 1; // 1 is for the postpadding header
+	  }
+	}
+	
+	ta_update = (ta_len > 0) ? ue_sched_ctl->ta_update : 0;
+
+	// If there is nothing to schedule, just leave
+	if ((sdu_length_total) <= 0) { 
+	  return;
+	}
+	
+	offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
+				       num_sdus,              //num_sdus
+				       sdu_lengths,  //
+				       sdu_lcids,
+				       255,                                   // no drx
+				       ta_update, // timing advance
+				       NULL,                                  // contention res id
+				       padding,
+				       post_padding);
+	
+#ifdef DEBUG_eNB_SCHEDULER
+	LOG_T(MAC,"[eNB %d] First 16 bytes of DLSCH : \n");
+	
+	for (i=0; i<16; i++) {
+	  LOG_T(MAC,"%x.",dlsch_buffer[i]);
+	}
+	
+	LOG_T(MAC,"\n");
+#endif
+	// cycle through SDUs and place in dlsch_buffer
+	memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total);
+	// memcpy(&eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]);
+	
+	// fill remainder of DLSCH with random data
+	for (j=0; j<(TBS-sdu_length_total-offset); j++) {
+	  UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff);
+          }
+	
+	//eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset+sdu_lengths[0]+j] = (char)(taus()&0xff);
+	if (opt_enabled == 1) {
+	  trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
+		    TBS, mod_id, 3, UE_RNTI(mod_id, UE_id),
+		    eNB->frame, eNB->subframe,0,0);
+	  LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d  rnti %x  with size %d\n",
+		mod_id, CC_id, frame, UE_RNTI(mod_id,UE_id), TBS);
+	}
+	
+	// store stats
+	eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total;
+	eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1;
+	UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->DL_cqi[0];
+	
+	UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti;
+	UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(mod_id, rnti);
+	UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; 
+	UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
+	
+	//nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
+	//Find the number of resource blocks and set them to the template for retransmissions
+	nb_rb = get_min_rb_unit(mod_id, CC_id);
+	uint16_t stats_tbs = mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb);
+
+	while (stats_tbs < TBS) {
+	  nb_rb += get_min_rb_unit(mod_id, CC_id);
+	  stats_tbs = mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb);
+	}
+	
+	UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb;
+	UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb;
+	UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=dl_dci->mcs[0];
+	UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=dl_dci->mcs[0];
+	UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS;
+	
+	UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS - sdu_length_total;
+	UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total;
+	UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS;
+	UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1;
+	
+	//eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]];
+	//eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
+      }
+    } else {
+      // No need to create anything apart of DCI in case of retransmission
+      
+      /*TODO: Must add these */
+      //      eNB_UE_stats->dlsch_trials[round]++;
+      //UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1;
+      //UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb;
+      //UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb;
+      //UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx=nCCECC_id];
+    }
+
+    UE_list->UE_template[CC_id][UE_id].oldNDI[dl_dci->harq_process] = dl_dci->ndi[0];
+    eNB_UE_stats->dlsch_mcs1 = dl_dci->mcs[0];
+
+    //Fill the proper DCI of OAI
+    fill_oai_dci(mod_id, CC_id, rnti, dl_dci);
+  }
+}
+
+void fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti,
+		  const Protocol__FlexDlDci *dl_dci) {
+
+  void         *DLSCH_dci        = NULL;
+  DCI_PDU      *DCI_pdu;
+
+  unsigned char         round            = 0;
+  unsigned char         harq_pid         = 0;
+  LTE_DL_FRAME_PARMS   *frame_parms[MAX_NUM_CCs];
+  int           size_bits, size_bytes;
+  eNB_MAC_INST         *eNB      = &eNB_mac_inst[mod_id];
+  UE_list_t            *UE_list  = &eNB->UE_list;
+  LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+
+  int UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]);
+
+  uint32_t format;
+
+  harq_pid = dl_dci->harq_process;
+  round = dl_dci->rv[0];
+  
+  // Note this code is for a specific DCI format
+  DLSCH_dci = (void *)UE_list->UE_template[CC_id][UE_id].DLSCH_DCI[harq_pid];
+  DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
+  
+  frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id);
+
+  if (dl_dci->has_tpc == 1) {
+    // Check if tpc has been set and reset measurement */
+    if ((dl_dci->tpc == 0) || (dl_dci->tpc == 2)) {
+      eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
+      eNB_UE_stats->Po_PUCCH_update = 0;
+    }
+  }
+  
+  
+  switch (frame_parms[CC_id]->N_RB_DL) {
+  case 6:
+    if (frame_parms[CC_id]->frame_type == TDD) {
+      if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+	FILL_DCI_TDD_1(DCI1_1_5MHz_TDD_t, DLSCH_dci, dl_dci);
+	size_bytes = sizeof(DCI1_1_5MHz_TDD_t);
+	size_bits  = sizeof_DCI1_1_5MHz_TDD_t;
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+	//TODO
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+	//TODO
+      }
+    } else {
+      if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+	FILL_DCI_FDD_1(DCI1_1_5MHz_FDD_t, DLSCH_dci, dl_dci);
+	size_bytes = sizeof(DCI1_1_5MHz_FDD_t);
+	size_bits  = sizeof_DCI1_1_5MHz_FDD_t;
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+	//TODO
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+	  //TODO
+      }
+    }
+    break;
+  case 25:
+    if (frame_parms[CC_id]->frame_type == TDD) {
+      if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+	FILL_DCI_TDD_1(DCI1_5MHz_TDD_t, DLSCH_dci, dl_dci);
+	size_bytes = sizeof(DCI1_5MHz_TDD_t);
+	size_bits  = sizeof_DCI1_5MHz_TDD_t;
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+	//TODO
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+	//TODO
+      }
+    } else {
+      if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+	FILL_DCI_FDD_1(DCI1_5MHz_FDD_t, DLSCH_dci, dl_dci);
+	size_bytes = sizeof(DCI1_5MHz_FDD_t);
+	size_bits  = sizeof_DCI1_5MHz_FDD_t;
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+	//TODO
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+	//TODO
+      }
+    }
+    break;
+  case 50:
+    if (frame_parms[CC_id]->frame_type == TDD) {
+      if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+	FILL_DCI_TDD_1(DCI1_10MHz_TDD_t, DLSCH_dci, dl_dci);
+	size_bytes = sizeof(DCI1_10MHz_TDD_t);
+	size_bits  = sizeof_DCI1_10MHz_TDD_t;
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+	//TODO
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+	//TODO
+      }
+    } else {
+      if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+	FILL_DCI_FDD_1(DCI1_10MHz_FDD_t, DLSCH_dci, dl_dci);
+	size_bytes = sizeof(DCI1_10MHz_FDD_t);
+	size_bits  = sizeof_DCI1_10MHz_FDD_t;
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+	//TODO
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+	//TODO
+      }
+    }
+    break;
+  case 100:
+    if (frame_parms[CC_id]->frame_type == TDD) {
+      if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+	FILL_DCI_TDD_1(DCI1_20MHz_TDD_t, DLSCH_dci, dl_dci);
+	size_bytes = sizeof(DCI1_20MHz_TDD_t);
+	size_bits  = sizeof_DCI1_20MHz_TDD_t;
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+	//TODO
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+	//TODO
+      }
+    } else {
+      if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
+	FILL_DCI_FDD_1(DCI1_20MHz_FDD_t, DLSCH_dci, dl_dci);
+	size_bytes = sizeof(DCI1_20MHz_FDD_t);
+	size_bits  = sizeof_DCI1_20MHz_FDD_t;
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
+	//TODO
+      } else if (dl_dci->format ==  PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
+	//TODO
+      }
+    }
+    break;
+  }
+
+  //Set format to the proper type
+  switch(dl_dci->format) {
+  case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1:
+    format = format1;
+    break;
+  case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1A:
+    format = format1A;
+    break;
+  case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1B:
+    format = format1B;
+    break;
+  case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1C:
+    format = format1C;
+    break;
+  case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D:
+    format = format1E_2A_M10PRB;
+    break;
+  case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2:
+    format  = format2;
+    break;
+  case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A:
+    format = format2A;
+    break;
+  case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2B:
+    format = format2B;
+    break;
+  case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_3:
+    format = 3;
+    break;
+  default:
+    /*TODO: Need to deal with unsupported DCI type*/
+    return;
+  }
+  
+  add_ue_spec_dci(DCI_pdu,
+		  DLSCH_dci,
+		  rnti,
+		  size_bytes,
+		  dl_dci->aggr_level,
+		  size_bits,
+		  format,
+		  0);
+}
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c
new file mode 100644
index 0000000000000000000000000000000000000000..8975465e77b11ade441f6da867c9621c4048cbe8
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c
@@ -0,0 +1,1391 @@
+/*
+ * 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.0  (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 flexran_agent_scheduler_dlsch_ue.c
+ * \brief procedures related to eNB for the DLSCH transport channel
+ * \author Xenofon Foukas, Navid Nikaein and Raymond Knopp
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#include "assertions.h"
+#include "PHY/defs.h"
+#include "PHY/extern.h"
+
+#include "SCHED/defs.h"
+#include "SCHED/extern.h"
+
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/proto.h"
+#include "LAYER2/MAC/extern.h"
+#include "UTIL/LOG/log.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+#include "OCG.h"
+#include "OCG_extern.h"
+
+#include "RRC/LITE/extern.h"
+#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
+
+#include "ENB_APP/flexran_agent_defs.h"
+
+#include "pdcp.h"
+
+#include "header.pb-c.h"
+#include "flexran.pb-c.h"
+#include "flexran_agent_mac.h"
+
+#include "SIMULATION/TOOLS/defs.h" // for taus
+
+#if defined(ENABLE_ITTI)
+# include "intertask_interface.h"
+#endif
+
+#define ENABLE_MAC_PAYLOAD_DEBUG
+
+
+//------------------------------------------------------------------------------
+void
+flexran_schedule_ue_spec_default(mid_t   mod_id,
+				 uint32_t      frame,
+				 uint32_t      subframe,
+				 int           *mbsfn_flag,
+				 Protocol__FlexranMessage **dl_info)
+//------------------------------------------------------------------------------
+{
+  uint8_t               CC_id;
+  int                   UE_id;
+  int                   N_RBG[MAX_NUM_CCs];
+  unsigned char         aggregation;
+  mac_rlc_status_resp_t rlc_status;
+  unsigned char         header_len = 0, header_len_tmp = 0, ta_len = 0;
+  uint16_t              nb_rb, nb_rb_temp, total_nb_available_rb[MAX_NUM_CCs], nb_available_rb;
+  uint16_t              TBS, j, rnti, padding=0, post_padding=0;
+  unsigned char         round            = 0;
+  unsigned char         harq_pid         = 0;
+  void                 *DLSCH_dci        = NULL;
+  uint16_t              sdu_length_total = 0;
+  int                   mcs, mcs_tmp;
+  uint16_t              min_rb_unit[MAX_NUM_CCs];
+  eNB_MAC_INST         *eNB      = &eNB_mac_inst[mod_id];
+  /* TODO: Must move the helper structs to scheduler implementation */
+  UE_list_t            *UE_list  = &eNB->UE_list;
+  int32_t                 normalized_rx_power, target_rx_power;
+  int32_t                 tpc = 1;
+  static int32_t          tpc_accumulated=0;
+  UE_sched_ctrl           *ue_sched_ctl;
+
+  Protocol__FlexDlData *dl_data[NUM_MAX_UE];
+  int num_ues_added = 0;
+  int channels_added = 0;
+
+  Protocol__FlexDlDci *dl_dci;
+  Protocol__FlexRlcPdu *rlc_pdus[11];
+  uint32_t *ce_bitmap;
+  Protocol__FlexRlcPdu **rlc_pdu;
+  int num_tb;
+  uint32_t ce_flags = 0;
+
+  uint8_t            rballoc_sub[25];
+  int i;
+  uint32_t data_to_request;
+  uint32_t dci_tbs;
+  uint8_t ue_has_transmission = 0;
+  uint32_t ndi;
+  
+  flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
+  
+  if (UE_list->head==-1) {
+    return;
+  }
+  
+  start_meas(&eNB->schedule_dlsch);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN);
+
+  //weight = get_ue_weight(module_idP,UE_id);
+  aggregation = 2; // set to the maximum aggregation level
+
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    min_rb_unit[CC_id] = get_min_rb_unit(mod_id, CC_id);
+    // get number of PRBs less those used by common channels
+    total_nb_available_rb[CC_id] = flexran_get_N_RB_DL(mod_id, CC_id);
+    for (i=0;i < flexran_get_N_RB_DL(mod_id, CC_id); i++)
+      if (eNB->common_channels[CC_id].vrb_map[i] != 0)
+	total_nb_available_rb[CC_id]--;
+    
+    N_RBG[CC_id] = flexran_get_N_RBG(mod_id, CC_id);
+
+    // store the global enb stats:
+    eNB->eNB_stats[CC_id].num_dlactive_UEs =  UE_list->num_UEs;
+    eNB->eNB_stats[CC_id].available_prbs =  total_nb_available_rb[CC_id];
+    eNB->eNB_stats[CC_id].total_available_prbs +=  total_nb_available_rb[CC_id];
+    eNB->eNB_stats[CC_id].dlsch_bytes_tx=0;
+    eNB->eNB_stats[CC_id].dlsch_pdus_tx=0;
+  }
+
+   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_IN);
+
+   start_meas(&eNB->schedule_dlsch_preprocessor);
+   _dlsch_scheduler_pre_processor(mod_id,
+				 frame,
+				 subframe,
+				 N_RBG,
+				 mbsfn_flag);
+   stop_meas(&eNB->schedule_dlsch_preprocessor);
+   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT);
+
+   for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n",CC_id);
+
+    if (mbsfn_flag[CC_id]>0)
+      continue;
+
+    for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
+      rnti = flexran_get_ue_crnti(mod_id, UE_id);
+      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+
+      if (rnti==NOT_A_RNTI) {
+        LOG_D(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n", UE_id,UE_list->num_UEs);
+        // mac_xface->macphy_exit("Cannot find rnti for UE_id");
+        continue;
+      }
+
+      if (flexran_get_ue_crnti(mod_id, UE_id) == NOT_A_RNTI) {
+        LOG_D(MAC,"[eNB] Cannot find UE\n");
+        //  mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n");
+        continue;
+      }
+
+      if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) ||  // no RBs allocated 
+	  CCE_allocation_infeasible(mod_id, CC_id, 0, subframe, aggregation, rnti)) {
+        LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n",
+              mod_id, frame, UE_id, CC_id);
+        //if(mac_xface->get_transmission_mode(module_idP,rnti)==5)
+        continue; //to next user (there might be rbs availiable for other UEs in TM5
+        // else
+        //  break;
+      }
+
+      if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD)  {
+        set_ue_dai (subframe,
+                    flexran_get_subframe_assignment(mod_id, CC_id),
+                    UE_id,
+                    CC_id,
+                    UE_list);
+        //TODO: update UL DAI after DLSCH scheduling
+        //set_ul_DAI(mod_id, UE_id, CC_id, frame, subframe,frame_parms);
+      }
+
+      channels_added = 0;
+
+      // After this point all the UEs will be scheduled
+      dl_data[num_ues_added] = (Protocol__FlexDlData *) malloc(sizeof(Protocol__FlexDlData));
+      protocol__flex_dl_data__init(dl_data[num_ues_added]);
+      dl_data[num_ues_added]->has_rnti = 1;
+      dl_data[num_ues_added]->rnti = rnti;
+      dl_data[num_ues_added]->n_rlc_pdu = 0;
+      dl_data[num_ues_added]->has_serv_cell_index = 1;
+      dl_data[num_ues_added]->serv_cell_index = CC_id;
+      
+      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
+      flexran_get_harq(mod_id, CC_id, UE_id, frame, subframe, &harq_pid, &round);
+      sdu_length_total=0;
+      mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)];
+
+#ifdef EXMIMO
+
+       if (mac_xface->get_transmission_mode(mod_id, CC_id, rnti) == 5) {
+	  mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)];
+	  mcs =  cmin(mcs,16);
+       }
+
+#endif
+
+      // initializing the rb allocation indicator for each UE
+       for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
+        UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
+	rballoc_sub[j] = 0;
+      }
+
+      /* LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", */
+      /*       mod_id, frame, UE_id, CC_id, rnti, harq_pid, round, nb_available_rb, */
+      /*       eNB_UE_stats->DL_cqi[0], mcs, */
+      /*       UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); */
+
+      dl_dci = (Protocol__FlexDlDci*) malloc(sizeof(Protocol__FlexDlDci));
+      protocol__flex_dl_dci__init(dl_dci);
+      dl_data[num_ues_added]->dl_dci = dl_dci;
+
+      
+      dl_dci->has_rnti = 1;
+      dl_dci->rnti = rnti;
+      dl_dci->has_harq_process = 1;
+      dl_dci->harq_process = harq_pid;
+      
+      /* process retransmission  */
+
+      if (round > 0) {
+
+	if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+	  UE_list->UE_template[CC_id][UE_id].DAI++;
+	  update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI);
+	  LOG_D(MAC,"DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n",
+		CC_id, subframe,UE_id,UE_list->UE_template[CC_id][UE_id].DAI);
+	}
+
+	mcs = UE_list->UE_template[CC_id][UE_id].mcs[harq_pid];
+
+	  // get freq_allocation
+	nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
+	  
+	/*TODO: Must add this to FlexRAN agent API */
+	dci_tbs = mac_xface->get_TBS_DL(mcs, nb_rb);
+
+	if (nb_rb <= nb_available_rb) {
+	  
+	  if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
+	    for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band
+	      UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+            }
+	  } else {
+	    nb_rb_temp = nb_rb;
+	    j = 0;
+
+	    while((nb_rb_temp > 0) && (j < flexran_get_N_RBG(mod_id, CC_id))) {
+	      if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
+		UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+		
+		if((j == flexran_get_N_RBG(mod_id, CC_id) - 1) &&
+		   ((flexran_get_N_RB_DL(mod_id, CC_id) == 25)||
+		    (flexran_get_N_RB_DL(mod_id, CC_id) == 50))) {
+		  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
+		} else {
+		  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
+		}
+	      }
+	      j = j + 1;
+	    }
+	  }
+
+	  nb_available_rb -= nb_rb;
+	  aggregation = process_ue_cqi(mod_id, UE_id);
+	  
+	  PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
+	  PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
+	  
+	  for(j=0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
+	    PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
+	    rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
+	  }
+
+	  // Keep the old NDI, do not toggle
+	  ndi = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
+	  tpc = UE_list->UE_template[CC_id][UE_id].oldTPC[harq_pid];
+	  UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs;
+
+	  ue_has_transmission = 1;
+	  num_ues_added++;
+	} else {
+	  LOG_D(MAC,"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n",
+                mod_id, frame, CC_id, UE_id);
+	  ue_has_transmission = 0;
+	}
+	//End of retransmission
+      } else { /* This is a potentially new SDU opportunity */
+	rlc_status.bytes_in_buffer = 0;
+        // Now check RLC information to compute number of required RBs
+        // get maximum TBS size for RLC request
+        //TBS = mac_xface->get_TBS(eNB_UE_stats->DL_cqi[0]<<1,nb_available_rb);
+        TBS = mac_xface->get_TBS_DL(mcs, nb_available_rb);
+	dci_tbs = TBS;
+
+        // check first for RLC data on DCCH
+        // add the length for  all the control elements (timing adv, drx, etc) : header + payload
+
+	ta_len = (ue_sched_ctl->ta_update!=0) ? 2 : 0;
+	
+	dl_data[num_ues_added]->n_ce_bitmap = 2;
+	dl_data[num_ues_added]->ce_bitmap = (uint32_t *) malloc(sizeof(uint32_t) * 2);
+	
+	if (ta_len > 0) {
+	  ce_flags |= PROTOCOL__FLEX_CE_TYPE__FLPCET_TA;
+	}
+
+	/*TODO: Add other flags if DRX and other CE are required*/
+	
+	// Add the control element flags to the flexran message
+	dl_data[num_ues_added]->ce_bitmap[0] = ce_flags;
+	dl_data[num_ues_added]->ce_bitmap[1] = ce_flags;
+
+	// TODO : Need to prioritize DRBs
+	// Loop through the UE logical channels (DCCH, DCCH1, DTCH for now)
+	for (j = 1; j < NB_RB_MAX; j++) {
+	  header_len+=3;
+
+	  // Need to see if we have space for data from this channel
+	  if (dci_tbs - ta_len - header_len - sdu_length_total > 0) {
+	     LOG_D(MAC, "[TEST]Requested %d bytes from RLC buffer on channel %d during first call\n", dci_tbs-ta_len-header_len);
+	     //If we have space, we need to see how much data we can request at most (if any available)
+	     rlc_status = mac_rlc_status_ind(mod_id,
+					     rnti,
+					     mod_id,
+					     frame,
+					     ENB_FLAG_YES,
+					     MBMS_FLAG_NO,
+					     j,
+					     (dci_tbs-ta_len-header_len)); // transport block set size
+
+	     //If data are available in channel j
+	     if (rlc_status.bytes_in_buffer > 0) {
+	       LOG_D(MAC, "[TEST]Have %d bytes in DCCH buffer during first call\n", rlc_status.bytes_in_buffer);
+	       //Fill in as much as possible
+	       data_to_request = cmin(dci_tbs-ta_len-header_len, rlc_status.bytes_in_buffer);
+	       if (data_to_request < 128) { //The header will be one byte less
+		 header_len--;
+	       }
+	       /* if (j == 1 || j == 2) { */
+	       /*  data_to_request+=0; 
+	       /* } */
+	       LOG_D(MAC, "[TEST]Will request %d from channel %d\n", data_to_request, j);
+	       rlc_pdus[channels_added] = (Protocol__FlexRlcPdu *) malloc(sizeof(Protocol__FlexRlcPdu));
+	       protocol__flex_rlc_pdu__init(rlc_pdus[channels_added]);
+	       rlc_pdus[channels_added]->n_rlc_pdu_tb = 2;
+	       rlc_pdus[channels_added]->rlc_pdu_tb = (Protocol__FlexRlcPduTb **) malloc(sizeof(Protocol__FlexRlcPduTb *) * 2);
+	       rlc_pdus[channels_added]->rlc_pdu_tb[0] = (Protocol__FlexRlcPduTb *) malloc(sizeof(Protocol__FlexRlcPduTb));
+	       protocol__flex_rlc_pdu_tb__init(rlc_pdus[channels_added]->rlc_pdu_tb[0]);
+	       rlc_pdus[channels_added]->rlc_pdu_tb[0]->has_logical_channel_id = 1;
+	       rlc_pdus[channels_added]->rlc_pdu_tb[0]->logical_channel_id = j;
+	       rlc_pdus[channels_added]->rlc_pdu_tb[0]->has_size = 1;
+	       rlc_pdus[channels_added]->rlc_pdu_tb[0]->size = data_to_request;
+	       rlc_pdus[channels_added]->rlc_pdu_tb[1] = (Protocol__FlexRlcPduTb *) malloc(sizeof(Protocol__FlexRlcPduTb));
+	       protocol__flex_rlc_pdu_tb__init(rlc_pdus[channels_added]->rlc_pdu_tb[1]);
+	       rlc_pdus[channels_added]->rlc_pdu_tb[1]->has_logical_channel_id = 1;
+	       rlc_pdus[channels_added]->rlc_pdu_tb[1]->logical_channel_id = j;
+	       rlc_pdus[channels_added]->rlc_pdu_tb[1]->has_size = 1;
+	       rlc_pdus[channels_added]->rlc_pdu_tb[1]->size = data_to_request;
+	       dl_data[num_ues_added]->n_rlc_pdu++;
+	       channels_added++;
+	       //Set this to the max value that we might request
+	       sdu_length_total += data_to_request;
+	     } else {
+	       //Take back the assumption of a header for this channel
+	       header_len -= 3;
+	     } //End rlc_status.bytes_in_buffer <= 0
+	  } //end of if dci_tbs - ta_len - header_len > 0
+	} // End of iterating the logical channels
+	
+	// Add rlc_pdus to the dl_data message
+	dl_data[num_ues_added]->rlc_pdu = (Protocol__FlexRlcPdu **) malloc(sizeof(Protocol__FlexRlcPdu *) *
+									  dl_data[num_ues_added]->n_rlc_pdu);
+	for (i = 0; i < dl_data[num_ues_added]->n_rlc_pdu; i++) {
+	  dl_data[num_ues_added]->rlc_pdu[i] = rlc_pdus[i];
+	}
+	
+	// there is a payload
+        if (( dl_data[num_ues_added]->n_rlc_pdu > 0)) {
+	  // Now compute number of required RBs for total sdu length
+          // Assume RAH format 2
+          // adjust  header lengths
+	  header_len_tmp = header_len;
+
+	  if (header_len == 2 || header_len == 3) { //Only one SDU, remove length field
+	    header_len = 1;
+	  } else { //Remove length field from the last SDU
+	    header_len--;
+	  }
+
+	  mcs_tmp = mcs;
+	  if (mcs_tmp == 0) {
+            nb_rb = 4;  // don't let the TBS get too small
+          } else {
+            nb_rb=min_rb_unit[CC_id];
+          }
+
+	  LOG_D(MAC,"[TEST]The initial number of resource blocks was %d\n", nb_rb);
+	  LOG_D(MAC,"[TEST] The initial mcs was %d\n", mcs_tmp);
+
+	  TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb);
+	  LOG_D(MAC,"[TEST]The TBS during rate matching was %d\n", TBS);
+
+	  while (TBS < (sdu_length_total + header_len + ta_len))  {
+            nb_rb += min_rb_unit[CC_id];  //
+	    LOG_D(MAC, "[TEST]Had to increase the number of RBs\n");
+            if (nb_rb > nb_available_rb) { // if we've gone beyond the maximum number of RBs
+              // (can happen if N_RB_DL is odd)
+              TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_available_rb);
+              nb_rb = nb_available_rb;
+              break;
+            }
+
+            TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb);
+          }
+
+	  if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
+	    LOG_D(MAC, "[TEST]We had the exact number of rbs. Time to fill the rballoc subband\n");
+            for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) { // for indicating the rballoc for each sub-band
+              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+            }
+          } else {
+	    nb_rb_temp = nb_rb;
+            j = 0;
+	    LOG_D(MAC, "[TEST]Will only partially fill the bitmap\n");
+	    while((nb_rb_temp > 0) && (j < flexran_get_N_RBG(mod_id, CC_id))) {
+              if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
+                UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
+                if ((j == flexran_get_N_RBG(mod_id, CC_id) - 1) &&
+                    ((flexran_get_N_RB_DL(mod_id, CC_id) == 25)||
+                     (flexran_get_N_RB_DL(mod_id, CC_id) == 50))) {
+                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id] + 1;
+                } else {
+                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
+                }
+              }
+              j = j+1;
+            }
+	  }
+	  
+	  PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
+          PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
+
+	  for(j = 0; j < flexran_get_N_RBG(mod_id, CC_id); j++) {
+            PHY_vars_eNB_g[mod_id][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
+          }
+
+	  // decrease mcs until TBS falls below required length
+          while ((TBS > (sdu_length_total + header_len + ta_len)) && (mcs_tmp > 0)) {
+            mcs_tmp--;
+            TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb);
+          }
+
+	  // if we have decreased too much or we don't have enough RBs, increase MCS
+          while ((TBS < (sdu_length_total + header_len + ta_len)) &&
+		 ((( ue_sched_ctl->dl_pow_off[CC_id] > 0) && (mcs_tmp < 28))											     || ( (ue_sched_ctl->dl_pow_off[CC_id]==0) && (mcs_tmp <= 15)))) {
+            mcs_tmp++;
+            TBS = mac_xface->get_TBS_DL(mcs_tmp, nb_rb);
+          }
+
+	  dci_tbs = TBS;
+	  mcs = mcs_tmp;
+
+	  aggregation = process_ue_cqi(mod_id,UE_id);
+	  dl_dci->has_aggr_level = 1;
+	  dl_dci->aggr_level = aggregation;
+	  
+          UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb;
+
+	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+            UE_list->UE_template[CC_id][UE_id].DAI++;
+            //  printf("DAI update: subframeP %d: UE %d, DAI %d\n",subframeP,UE_id,UE_list->UE_template[CC_id][UE_id].DAI);
+	    //#warning only for 5MHz channel
+            update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI);
+          }
+
+	  // do PUCCH power control
+          // this is the normalized RX power
+	  normalized_rx_power = flexran_get_p0_pucch_dbm(mod_id,UE_id, CC_id); //eNB_UE_stats->Po_PUCCH_dBm; 
+	  target_rx_power = flexran_get_p0_nominal_pucch(mod_id, CC_id) + 10; //mac_xface->get_target_pucch_rx_power(mod_id, CC_id) + 10;
+
+	  // this assumes accumulated tpc
+	  // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
+	  int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe;
+
+	  if (((framex10psubframe+10)<=(frame*10+subframe)) || //normal case
+	      ((framex10psubframe>(frame*10+subframe)) && (((10240-framex10psubframe+frame*10+subframe)>=10)))) //frame wrap-around
+	    if (flexran_get_p0_pucch_status(mod_id, UE_id, CC_id) == 1) {
+	      flexran_update_p0_pucch(mod_id, UE_id, CC_id);
+	      
+	      UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frame;
+	      UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframe;
+	      if (normalized_rx_power>(target_rx_power+1)) {
+		tpc = 0; //-1
+		tpc_accumulated--;
+	      } else if (normalized_rx_power<(target_rx_power-1)) {
+		tpc = 2; //+1
+		tpc_accumulated++;
+	      } else {
+		tpc = 1; //0
+	      }
+	      LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
+		    mod_id, frame, subframe, harq_pid, tpc,
+		    tpc_accumulated, normalized_rx_power, target_rx_power);
+	    } // Po_PUCCH has been updated 
+	    else {
+	      tpc = 1; //0
+	    } // time to do TPC update 
+	  else {
+	    tpc = 1; //0
+	  }
+
+	  for(i=0; i<PHY_vars_eNB_g[mod_id][CC_id]->frame_parms.N_RBG; i++) {
+	    rballoc_sub[i] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i];
+          }	
+
+	   // Toggle NDI
+          LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n",
+                CC_id, frame, subframe, UE_id,
+                UE_list->UE_template[CC_id][UE_id].rnti,harq_pid, UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]);
+          UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]= 1 - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
+	  ndi =  UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
+	  
+	  UE_list->UE_template[CC_id][UE_id].mcs[harq_pid] = mcs;
+	  UE_list->UE_template[CC_id][UE_id].oldTPC[harq_pid] = tpc;
+
+	  // Increase the pointer for the number of scheduled UEs
+	  num_ues_added++;
+	  ue_has_transmission = 1;
+	}  else { // There is no data from RLC or MAC header, so don't schedule
+	  ue_has_transmission = 0;
+	}
+      } // End of new scheduling
+      
+      // If we has transmission or retransmission
+      if (ue_has_transmission) {
+	switch (mac_xface->get_transmission_mode(mod_id, CC_id, rnti)) {
+	case 1:
+	case 2:
+	default:
+	  dl_dci->has_res_alloc = 1;
+	  dl_dci->res_alloc = 0;
+	  dl_dci->has_vrb_format = 1;
+	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+	  dl_dci->has_format = 1;
+	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1;
+	  dl_dci->has_rb_bitmap = 1;
+	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+	  dl_dci->has_rb_shift = 1;
+	  dl_dci->rb_shift = 0;
+	  dl_dci->n_ndi = 1;
+	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+	  dl_dci->ndi[0] = ndi;
+	  dl_dci->n_rv = 1;
+	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+	  dl_dci->rv[0] = round & 3;
+	  dl_dci->has_tpc = 1;
+	  dl_dci->tpc = tpc;
+	  dl_dci->n_mcs = 1;
+	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+	  dl_dci->mcs[0] = mcs;
+	  dl_dci->n_tbs_size = 1;
+	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+	  dl_dci->tbs_size[0] = dci_tbs;
+	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+	    dl_dci->has_dai = 1;
+	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+	  }
+	  break;
+	case 3:
+	  dl_dci->has_res_alloc = 1;
+	  dl_dci->res_alloc = 0;
+	  dl_dci->has_vrb_format = 1;
+	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+	  dl_dci->has_format = 1;
+	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A;
+	  dl_dci->has_rb_bitmap = 1;
+	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+	  dl_dci->has_rb_shift = 1;
+	  dl_dci->rb_shift = 0;
+	  dl_dci->n_ndi = 2;
+	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+	  dl_dci->ndi[0] = ndi;
+	  dl_dci->ndi[1] = ndi;
+	  dl_dci->n_rv = 2;
+	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+	  dl_dci->rv[0] = round & 3;
+	  dl_dci->rv[1] = round & 3;
+	  dl_dci->has_tpc = 1;
+	  dl_dci->tpc = tpc;
+	  dl_dci->n_mcs = 2;
+	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+	  dl_dci->mcs[0] = mcs;
+	  dl_dci->mcs[1] = mcs;
+	  dl_dci->n_tbs_size = 2;
+	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+	  dl_dci->tbs_size[0] = dci_tbs;
+	  dl_dci->tbs_size[1] = dci_tbs;
+	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+	    dl_dci->has_dai = 1;
+	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+	  }
+	  break;
+	case 4:
+	  dl_dci->has_res_alloc = 1;
+	  dl_dci->res_alloc = 0;
+	  dl_dci->has_vrb_format = 1;
+	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+	  dl_dci->has_format = 1;
+	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A;
+	  dl_dci->has_rb_bitmap = 1;
+	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+	  dl_dci->has_rb_shift = 1;
+	  dl_dci->rb_shift = 0;
+	  dl_dci->n_ndi = 2;
+	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+	  dl_dci->ndi[0] = ndi;
+	  dl_dci->ndi[1] = ndi;
+	  dl_dci->n_rv = 2;
+	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+	  dl_dci->rv[0] = round & 3;
+	  dl_dci->rv[1] = round & 3;
+	  dl_dci->has_tpc = 1;
+	  dl_dci->tpc = tpc;
+	  dl_dci->n_mcs = 2;
+	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+	  dl_dci->mcs[0] = mcs;
+	  dl_dci->mcs[1] = mcs;
+	  dl_dci->n_tbs_size = 2;
+	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+	  dl_dci->tbs_size[0] = dci_tbs;
+	  dl_dci->tbs_size[1] = dci_tbs;
+	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+	    dl_dci->has_dai = 1;
+	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+	  }
+	  break;
+	case 5:
+	  dl_dci->has_res_alloc = 1;
+	  dl_dci->res_alloc = 0;
+	  dl_dci->has_vrb_format = 1;
+	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+	  dl_dci->has_format = 1;
+	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D;
+	  dl_dci->has_rb_bitmap = 1;
+	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+	  dl_dci->has_rb_shift = 1;
+	  dl_dci->rb_shift = 0;
+	  dl_dci->n_ndi = 1;
+	  dl_dci->ndi = 1;
+	  dl_dci->ndi[0] = ndi;
+	  dl_dci->n_rv = 1;
+	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+	  dl_dci->rv[0] = round & 3;
+	  dl_dci->has_tpc = 1;
+	  dl_dci->tpc = tpc;
+	  dl_dci->n_mcs = 1;
+	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+	  dl_dci->mcs[0] = mcs;
+	  dl_dci->n_tbs_size = 1;
+	  dl_dci->tbs_size = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_tbs_size);
+	  dl_dci->tbs_size[0] = dci_tbs;
+	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+	    dl_dci->has_dai = 1;
+	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+	  }
+	  
+	  if(ue_sched_ctl->dl_pow_off[CC_id] == 2) {
+	    ue_sched_ctl->dl_pow_off[CC_id] = 1;
+	  }
+	  
+	  dl_dci->has_dl_power_offset = 1;
+	  dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id];
+	  dl_dci->has_precoding_info = 1;
+	  dl_dci->precoding_info = 5; // Is this right??
+	  
+	  break;
+	case 6:
+	  dl_dci->has_res_alloc = 1;
+	  dl_dci->res_alloc = 0;
+	  dl_dci->has_vrb_format = 1;
+	  dl_dci->vrb_format = PROTOCOL__FLEX_VRB_FORMAT__FLVRBF_LOCALIZED;
+	  dl_dci->has_format = 1;
+	  dl_dci->format = PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D;
+	  dl_dci->has_rb_bitmap = 1;
+	  dl_dci->rb_bitmap = allocate_prbs_sub(nb_rb, rballoc_sub);
+	  dl_dci->has_rb_shift = 1;
+	  dl_dci->rb_shift = 0;
+	  dl_dci->n_ndi = 1;
+	  dl_dci->ndi = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_ndi);
+	  dl_dci->ndi[0] = ndi;
+	  dl_dci->n_rv = 1;
+	  dl_dci->rv = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_rv);
+	  dl_dci->rv[0] = round & 3;
+	  dl_dci->has_tpc = 1;
+	  dl_dci->tpc = tpc;
+	  dl_dci->n_mcs = 1;
+	  dl_dci->mcs = (uint32_t *) malloc(sizeof(uint32_t) * dl_dci->n_mcs);
+	  dl_dci->mcs[0] = mcs;
+	  if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+	    dl_dci->has_dai = 1;
+	    dl_dci->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
+	  }
+
+	  dl_dci->has_dl_power_offset = 1;
+	  dl_dci->dl_power_offset = ue_sched_ctl->dl_pow_off[CC_id];
+	  dl_dci->has_precoding_info = 1;
+	  dl_dci->precoding_info = 5; // Is this right??
+	  break;
+	}
+      }
+      
+      if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
+        
+	/* TODO */
+	//set_ul_DAI(mod_id, UE_id, CC_id, frame, subframe, frame_parms);
+      }
+    } // UE_id loop
+   } // CC_id loop
+
+   // Add all the dl_data elements to the flexran message
+   (*dl_info)->dl_mac_config_msg->n_dl_ue_data = num_ues_added;
+   (*dl_info)->dl_mac_config_msg->dl_ue_data = (Protocol__FlexDlData **) malloc(sizeof(Protocol__FlexDlData *) * num_ues_added);
+   for (i = 0; i < num_ues_added; i++) {
+     (*dl_info)->dl_mac_config_msg->dl_ue_data[i] = dl_data[i];
+   }
+   
+   stop_meas(&eNB->schedule_dlsch);
+   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_OUT);
+}
+
+// This function stores the downlink buffer for all the logical channels
+void _store_dlsch_buffer (module_id_t Mod_id,
+			  frame_t     frameP,
+			  sub_frame_t subframeP)
+{
+
+  int                   UE_id,i;
+  rnti_t                rnti;
+  mac_rlc_status_resp_t rlc_status;
+  UE_list_t             *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+  UE_TEMPLATE           *UE_template;
+
+  for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
+
+    UE_template = &UE_list->UE_template[UE_PCCID(Mod_id,UE_id)][UE_id];
+
+    // clear logical channel interface variables
+    UE_template->dl_buffer_total = 0;
+    UE_template->dl_pdus_total = 0;
+
+    for(i=0; i< MAX_NUM_LCID; i++) {
+      UE_template->dl_buffer_info[i]=0;
+      UE_template->dl_pdus_in_buffer[i]=0;
+      UE_template->dl_buffer_head_sdu_creation_time[i]=0;
+      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,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
+      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] = rlc_status.head_sdu_creation_time ;
+      UE_template->dl_buffer_head_sdu_creation_time_max = cmax(UE_template->dl_buffer_head_sdu_creation_time_max,
+          rlc_status.head_sdu_creation_time );
+      UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = rlc_status.head_sdu_remaining_size_to_send;
+      UE_template->dl_buffer_head_sdu_is_segmented[i] = rlc_status.head_sdu_is_segmented;
+      UE_template->dl_buffer_total += UE_template->dl_buffer_info[i];//storing the total dlsch buffer
+      UE_template->dl_pdus_total   += UE_template->dl_pdus_in_buffer[i];
+
+#ifdef DEBUG_eNB_SCHEDULER
+
+      /* note for dl_buffer_head_sdu_remaining_size_to_send[i] :
+       * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent
+       */
+      if (UE_template->dl_buffer_info[i]>0)
+        LOG_D(MAC,
+              "[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n",
+              Mod_id, frameP, subframeP, UE_id,
+              i, UE_template->dl_pdus_in_buffer[i],UE_template->dl_buffer_info[i],
+              UE_template->dl_buffer_head_sdu_creation_time[i],
+              UE_template->dl_buffer_head_sdu_remaining_size_to_send[i],
+              UE_template->dl_buffer_head_sdu_is_segmented[i]
+             );
+
+#endif
+
+    }
+
+    //#ifdef DEBUG_eNB_SCHEDULER
+    if ( UE_template->dl_buffer_total>0)
+      LOG_D(MAC,"[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n",
+            Mod_id, frameP, subframeP, UE_id,
+            UE_template->dl_buffer_total,
+            UE_template->dl_pdus_total
+           );
+
+    //#endif
+  }
+}
+
+
+// This function returns the estimated number of RBs required by each UE for downlink scheduling
+void _assign_rbs_required (module_id_t Mod_id,
+                          frame_t     frameP,
+                          sub_frame_t subframe,
+                          uint16_t    nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+                          int         min_rb_unit[MAX_NUM_CCs])
+{
+
+
+  rnti_t           rnti;
+  uint16_t         TBS = 0;
+  LTE_eNB_UE_stats *eNB_UE_stats[MAX_NUM_CCs];
+  int              UE_id,n,i,j,CC_id,pCCid,tmp;
+  UE_list_t        *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+  //  UE_TEMPLATE           *UE_template;
+
+  // clear rb allocations across all CC_ids
+  for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
+    pCCid = UE_PCCID(Mod_id,UE_id);
+    rnti = UE_list->UE_template[pCCid][UE_id].rnti;
+
+    //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[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti);
+      eNB_UE_stats[CC_id]->dlsch_mcs1=cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)];
+    }
+
+    // provide the list of CCs sorted according to MCS
+    for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) {
+      for (j=i+1; j<UE_list->numactiveCCs[UE_id]; j++) {
+        DevAssert( j < MAX_NUM_CCs );
+
+        if (eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]]->dlsch_mcs1 >
+            eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]]->dlsch_mcs1) {
+          tmp = UE_list->ordered_CCids[i][UE_id];
+          UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id];
+          UE_list->ordered_CCids[j][UE_id] = tmp;
+        }
+      }
+    }
+
+    /* NN --> RK
+     * check the index of UE_template"
+     */
+    if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total> 0) {
+      LOG_D(MAC,"[preprocessor] assign RB for UE %d\n",UE_id);
+
+      for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) {
+        CC_id = UE_list->ordered_CCids[i][UE_id];
+	eNB_UE_stats[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti);
+
+        if (eNB_UE_stats[CC_id]->dlsch_mcs1==0) {
+          nb_rbs_required[CC_id][UE_id] = 4;  // don't let the TBS get too small
+        } else {
+          nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id];
+        }
+
+        TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
+
+        LOG_D(MAC,"[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n",
+              UE_id, CC_id, UE_list->UE_template[pCCid][UE_id].dl_buffer_total,
+              nb_rbs_required[CC_id][UE_id],eNB_UE_stats[CC_id]->dlsch_mcs1,TBS);
+
+        /* calculating required number of RBs for each UE */
+        while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total)  {
+          nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id];
+
+          if (nb_rbs_required[CC_id][UE_id] > flexran_get_N_RB_DL(Mod_id, CC_id)) {
+            TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1, flexran_get_N_RB_DL(Mod_id, CC_id));
+            nb_rbs_required[CC_id][UE_id] = flexran_get_N_RB_DL(Mod_id, CC_id);
+            break;
+          }
+
+          TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
+        } // end of while
+
+        LOG_D(MAC,"[eNB %d] Frame %d: UE %d on CC %d: RB unit %d,  nb_required RB %d (TBS %d, mcs %d)\n",
+              Mod_id, frameP,UE_id, CC_id,  min_rb_unit[CC_id], nb_rbs_required[CC_id][UE_id], TBS, eNB_UE_stats[CC_id]->dlsch_mcs1);
+      }
+    }
+  }
+}
+
+// This function scans all CC_ids for a particular UE to find the maximum round index of its HARQ processes
+int _maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uint8_t ul_flag )
+{
+
+  uint8_t round,round_max=0,UE_id;
+  int CC_id;
+  UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+
+    UE_id = find_UE_id(Mod_id,rnti);
+    round    = UE_list->UE_sched_ctrl[UE_id].round[CC_id];
+    if (round > round_max) {
+      round_max = round;
+    }
+  }
+
+  return round_max;
+}
+
+// This function scans all CC_ids for a particular UE to find the maximum DL CQI
+int _maxcqi(module_id_t Mod_id,int32_t UE_id)
+{
+
+  LTE_eNB_UE_stats *eNB_UE_stats = NULL;
+  UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+  int CC_id,n;
+  int CQI = 0;
+
+  for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) {
+    CC_id = UE_list->ordered_CCids[n][UE_id];
+    eNB_UE_stats = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,UE_RNTI(Mod_id,UE_id));
+
+    if (eNB_UE_stats==NULL) {
+      mac_xface->macphy_exit("maxcqi: could not get eNB_UE_stats\n");
+      return 0; // not reached
+    }
+
+    if (eNB_UE_stats->DL_cqi[0] > CQI) {
+      CQI = eNB_UE_stats->DL_cqi[0];
+    }
+  }
+
+  return(CQI);
+}
+
+
+// This fuction sorts the UE in order their dlsch buffer and CQI
+void _sort_UEs (module_id_t Mod_idP,
+               int         frameP,
+               sub_frame_t subframeP)
+{
+
+
+  int               UE_id1,UE_id2;
+  int               pCC_id1,pCC_id2;
+  int               cqi1,cqi2,round1,round2;
+  int               i=0,ii=0;//,j=0;
+  rnti_t            rnti1,rnti2;
+
+  UE_list_t *UE_list = &eNB_mac_inst[Mod_idP].UE_list;
+
+  for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
+
+    for(ii=UE_list->next[i]; ii>=0; ii=UE_list->next[ii]) {
+
+      UE_id1  = i;
+      rnti1 = UE_RNTI(Mod_idP,UE_id1);
+      if(rnti1 == NOT_A_RNTI)
+	continue;
+      if (UE_list->UE_sched_ctrl[UE_id1].ul_out_of_sync == 1)
+	continue;
+      pCC_id1 = UE_PCCID(Mod_idP,UE_id1);
+      cqi1    = _maxcqi(Mod_idP,UE_id1); //
+      round1  = _maxround(Mod_idP,rnti1,frameP,subframeP,0);
+
+      UE_id2 = ii;
+      rnti2 = UE_RNTI(Mod_idP,UE_id2);
+      if(rnti2 == NOT_A_RNTI)
+        continue;
+      if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1)
+	continue;
+      cqi2    = _maxcqi(Mod_idP,UE_id2);
+      round2  = _maxround(Mod_idP,rnti2,frameP,subframeP,0);  //mac_xface->get_ue_active_harq_pid(Mod_id,rnti2,subframe,&harq_pid2,&round2,0);
+      pCC_id2 = UE_PCCID(Mod_idP,UE_id2);
+
+      if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order
+        swap_UEs(UE_list,UE_id1,UE_id2,0);
+      } else if (round2 == round1) {
+        // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels.  This should be done on the sum of all information that has to be sent.  And still it wouldn't ensure fairness.  It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service.
+
+        // first check the buffer status for SRB1 and SRB2
+        if ( (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2]) <
+             (UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2])   ) {
+          swap_UEs(UE_list,UE_id1,UE_id2,0);
+        } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max <
+                   UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max   ) {
+          swap_UEs(UE_list,UE_id1,UE_id2,0);
+        } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total <
+                   UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total   ) {
+          swap_UEs(UE_list,UE_id1,UE_id2,0);
+        } else if (cqi1 < cqi2) {
+          swap_UEs(UE_list,UE_id1,UE_id2,0);
+        }
+      }
+    }
+  }
+}
+
+// This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
+void _dlsch_scheduler_pre_processor (module_id_t   Mod_id,
+                                    frame_t       frameP,
+                                    sub_frame_t   subframeP,
+                                    int           N_RBG[MAX_NUM_CCs],
+                                    int           *mbsfn_flag)
+{
+
+  unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], harq_pid=0, total_ue_count;
+  unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
+  int                     UE_id, i;
+  unsigned char round = 0;
+  uint16_t                ii,j;
+  uint16_t                nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
+  uint16_t                nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
+  uint16_t                nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
+  uint16_t                average_rbs_per_user[MAX_NUM_CCs] = {0};
+  rnti_t             rnti;
+  int                min_rb_unit[MAX_NUM_CCs];
+  uint16_t r1=0;
+  uint8_t CC_id;
+  UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
+  LTE_DL_FRAME_PARMS   *frame_parms[MAX_NUM_CCs] = {0};
+
+  int transmission_mode = 0;
+  UE_sched_ctrl *ue_sched_ctl;
+
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+    
+    if (mbsfn_flag[CC_id]>0)  // If this CC is allocated for MBSFN skip it here
+      continue;
+    
+    frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);
+    
+    
+    min_rb_unit[CC_id]=get_min_rb_unit(Mod_id,CC_id);
+    
+    for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
+      UE_id = i;
+      // Initialize scheduling information for all active UEs
+      
+      
+      _dlsch_scheduler_pre_processor_reset(Mod_id,
+					   UE_id,
+					   CC_id,
+					   frameP,
+					   subframeP,
+					   N_RBG[CC_id],
+					   nb_rbs_required,
+					   nb_rbs_required_remaining,
+					   rballoc_sub,
+					   MIMO_mode_indicator);
+
+    }
+  }
+  
+  // Store the DLSCH buffer for each logical channel
+  _store_dlsch_buffer (Mod_id,frameP,subframeP);
+
+  // Calculate the number of RBs required by each UE on the basis of logical channel's buffer
+  _assign_rbs_required (Mod_id,frameP,subframeP,nb_rbs_required,min_rb_unit);
+
+  // Sorts the user on the basis of dlsch logical channel buffer and CQI
+  _sort_UEs (Mod_id,frameP,subframeP);
+
+  total_ue_count = 0;
+
+  // loop over all active UEs
+  for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
+    rnti = flexran_get_ue_crnti(Mod_id, i);
+    if(rnti == NOT_A_RNTI)
+      continue;
+    if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
+      continue;
+    UE_id = i;
+
+    // if there is no available harq_process, skip the UE
+    if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id]<0)
+      continue;
+
+    for (ii=0; ii < UE_num_active_CC(UE_list,UE_id); ii++) {
+      CC_id = UE_list->ordered_CCids[ii][UE_id];
+      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+      flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round);
+
+      average_rbs_per_user[CC_id]=0;
+
+      frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);
+
+      //      mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0);
+
+      if(round>0) {
+        nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
+      }
+
+      //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id];
+      if (nb_rbs_required[CC_id][UE_id] > 0) {
+        total_ue_count = total_ue_count + 1;
+      }
+
+
+      // hypotetical assignement
+      /*
+       * If schedule is enabled and if the priority of the UEs is modified
+       * The average rbs per logical channel per user will depend on the level of
+       * priority. Concerning the hypothetical assignement, we should assign more
+       * rbs to prioritized users. Maybe, we can do a mapping between the
+       * average rbs per user and the level of priority or multiply the average rbs
+       * per user by a coefficient which represents the degree of priority.
+       */
+
+      if (total_ue_count == 0) {
+        average_rbs_per_user[CC_id] = 0;
+      } else if( (min_rb_unit[CC_id] * total_ue_count) <= (frame_parms[CC_id]->N_RB_DL) ) {
+        average_rbs_per_user[CC_id] = (uint16_t) floor(frame_parms[CC_id]->N_RB_DL/total_ue_count);
+      } else {
+        average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE
+      }
+    }
+  }
+
+  // note: nb_rbs_required is assigned according to total_buffer_dl
+  // extend nb_rbs_required to capture per LCID RB required
+  for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
+    rnti = UE_RNTI(Mod_id,i);
+
+    for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) {
+      CC_id = UE_list->ordered_CCids[ii][i];
+
+      // control channel
+      if (mac_eNB_get_rrc_status(Mod_id,rnti) < RRC_RECONFIGURED) {
+        nb_rbs_required_remaining_1[CC_id][i] = nb_rbs_required[CC_id][i];
+      } else {
+        nb_rbs_required_remaining_1[CC_id][i] = cmin(average_rbs_per_user[CC_id],nb_rbs_required[CC_id][i]);
+
+      }
+    }
+  }
+
+  //Allocation to UEs is done in 2 rounds,
+  // 1st stage: average number of RBs allocated to each UE
+  // 2nd stage: remaining RBs are allocated to high priority UEs
+  for(r1=0; r1<2; r1++) {
+
+    for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
+      for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) {
+        CC_id = UE_list->ordered_CCids[ii][i];
+
+        if(r1 == 0) {
+          nb_rbs_required_remaining[CC_id][i] = nb_rbs_required_remaining_1[CC_id][i];
+        } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round
+          nb_rbs_required_remaining[CC_id][i] = nb_rbs_required[CC_id][i]-nb_rbs_required_remaining_1[CC_id][i]+nb_rbs_required_remaining[CC_id][i];
+        }
+
+        if (nb_rbs_required[CC_id][i]> 0 )
+          LOG_D(MAC,"round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d,  pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n",
+                r1, CC_id, i,
+                nb_rbs_required_remaining[CC_id][i],
+                nb_rbs_required_remaining_1[CC_id][i],
+                nb_rbs_required[CC_id][i],
+                UE_list->UE_sched_ctrl[i].pre_nb_available_rbs[CC_id],
+                N_RBG[CC_id],
+                min_rb_unit[CC_id]);
+
+      }
+    }
+
+    if (total_ue_count > 0 ) {
+      for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
+        UE_id = i;
+
+        for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
+          CC_id = UE_list->ordered_CCids[ii][UE_id];
+	  ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+	  flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round);	  
+          rnti = UE_RNTI(Mod_id,UE_id);
+
+          // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
+          if(rnti == NOT_A_RNTI)
+            continue;
+	  if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
+	    continue;
+
+          transmission_mode = mac_xface->get_transmission_mode(Mod_id,CC_id,rnti);
+          //rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti);
+          /* 1st allocate for the retx */
+
+          // retransmission in data channels
+          // control channel in the 1st transmission
+          // data channel for all TM
+          LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n ");
+          _dlsch_scheduler_pre_processor_allocate (Mod_id,
+						   UE_id,
+						   CC_id,
+						   N_RBG[CC_id],
+						   transmission_mode,
+						   min_rb_unit[CC_id],
+						   frame_parms[CC_id]->N_RB_DL,
+						   nb_rbs_required,
+						   nb_rbs_required_remaining,
+						   rballoc_sub,
+						   MIMO_mode_indicator);
+        }
+      }
+    } // total_ue_count
+  } // end of for for r1 and r2
+
+  for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
+    UE_id = i;
+    ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+
+    for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
+      CC_id = UE_list->ordered_CCids[ii][UE_id];
+      //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];
+
+      if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0 ) {
+        LOG_D(MAC,"******************DL Scheduling Information for UE%d ************************\n",UE_id);
+        LOG_D(MAC,"dl power offset UE%d = %d \n",UE_id,ue_sched_ctl->dl_pow_off[CC_id]);
+        LOG_D(MAC,"***********RB Alloc for every subband for UE%d ***********\n",UE_id);
+
+        for(j=0; j<N_RBG[CC_id]; j++) {
+          //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[i] = rballoc_sub_UE[CC_id][UE_id][i];
+          LOG_D(MAC,"RB Alloc for UE%d and Subband%d = %d\n",UE_id,j,ue_sched_ctl->rballoc_sub_UE[CC_id][j]);
+        }
+
+        //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id];
+        LOG_D(MAC,"Total RBs allocated for UE%d = %d\n",UE_id,ue_sched_ctl->pre_nb_available_rbs[CC_id]);
+      }
+    }
+  }
+}
+
+#define SF05_LIMIT 1
+
+void _dlsch_scheduler_pre_processor_reset (int module_idP,
+					   int UE_id,
+					   uint8_t  CC_id,
+					   int frameP,
+					   int subframeP,					  
+					   int N_RBG,
+					   uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+					   uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+					   unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
+					   unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]) {
+  int i,j;
+  UE_list_t *UE_list=&eNB_mac_inst[module_idP].UE_list;
+  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+  rnti_t rnti = UE_RNTI(module_idP,UE_id);
+  uint8_t *vrb_map = eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map;
+  int RBGsize = PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL/N_RBG;
+#ifdef SF05_LIMIT
+  //int subframe05_limit=0;
+  int sf05_upper=-1,sf05_lower=-1;
+#endif
+  LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
+  
+  flexran_update_TA(module_idP, UE_id, CC_id);
+
+  if (UE_id==0) {
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update);
+  }
+  nb_rbs_required[CC_id][UE_id]=0;
+  ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0;
+  ue_sched_ctl->dl_pow_off[CC_id] = 2;
+  nb_rbs_required_remaining[CC_id][UE_id] = 0;
+
+#ifdef SF05_LIMIT  
+  switch (N_RBG) {
+  case 6:
+    sf05_lower=0;
+    sf05_upper=5;
+    break;
+  case 8:
+    sf05_lower=2;
+    sf05_upper=5;
+    break;
+  case 13:
+    sf05_lower=4;
+    sf05_upper=7;
+    break;
+  case 17:
+    sf05_lower=7;
+    sf05_upper=9;
+    break;
+  case 25:
+    sf05_lower=11;
+    sf05_upper=13;
+    break;
+  }
+#endif
+  // Initialize Subbands according to VRB map
+  for (i=0; i<N_RBG; i++) {
+    ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0;
+    rballoc_sub[CC_id][i] = 0;
+#ifdef SF05_LIMIT
+    // for avoiding 6+ PRBs around DC in subframe 0-5 (avoid excessive errors)
+
+    if ((subframeP==0 || subframeP==5) && 
+	(i>=sf05_lower && i<=sf05_upper))
+      rballoc_sub[CC_id][i]=1;
+#endif
+    // for SI-RNTI,RA-RNTI and P-RNTI allocations
+    for (j=0;j<RBGsize;j++) {
+      if (vrb_map[j+(i*RBGsize)]!=0)  {
+	rballoc_sub[CC_id][i] = 1;
+	LOG_D(MAC,"Frame %d, subframe %d : vrb %d allocated\n",frameP,subframeP,j+(i*RBGsize));
+	break;
+      }
+    }
+    LOG_D(MAC,"Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n",frameP,subframeP,CC_id,i,rballoc_sub[CC_id][i]);
+    MIMO_mode_indicator[CC_id][i] = 2;
+  }
+}
+
+
+void _dlsch_scheduler_pre_processor_allocate (module_id_t   Mod_id,
+					      int           UE_id,
+					      uint8_t       CC_id,
+					      int           N_RBG,
+					      int           transmission_mode,
+					      int           min_rb_unit,
+					      uint8_t       N_RB_DL,
+					      uint16_t      nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+					      uint16_t      nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+					      unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],
+					      unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]) {
+  int i;
+  UE_list_t *UE_list=&eNB_mac_inst[Mod_id].UE_list;
+  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
+
+  for(i=0; i<N_RBG; i++) {
+
+    if((rballoc_sub[CC_id][i] == 0)           &&
+        (ue_sched_ctl->rballoc_sub_UE[CC_id][i] == 0) &&
+        (nb_rbs_required_remaining[CC_id][UE_id]>0)   &&
+        (ue_sched_ctl->pre_nb_available_rbs[CC_id] < nb_rbs_required[CC_id][UE_id])) {
+
+      // if this UE is not scheduled for TM5
+      if (ue_sched_ctl->dl_pow_off[CC_id] != 0 )  {
+
+	if ((i == N_RBG-1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) {
+	  rballoc_sub[CC_id][i] = 1;
+	  ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
+	  MIMO_mode_indicator[CC_id][i] = 1;
+	  if (transmission_mode == 5 ) {
+	    ue_sched_ctl->dl_pow_off[CC_id] = 1;
+	  }   
+	  nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit+1;
+          ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
+        } else {
+	  if (nb_rbs_required_remaining[CC_id][UE_id] >=  min_rb_unit){
+	    rballoc_sub[CC_id][i] = 1;
+	    ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
+	    MIMO_mode_indicator[CC_id][i] = 1;
+	    if (transmission_mode == 5 ) {
+	      ue_sched_ctl->dl_pow_off[CC_id] = 1;
+	    }
+	    nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit;
+	    ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit;
+	  }
+	}
+      } // dl_pow_off[CC_id][UE_id] ! = 0
+    }
+  }
+}
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c
new file mode 100644
index 0000000000000000000000000000000000000000..7dec8d0c563169a0bb9136ce3fd30521166b5634
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.c
@@ -0,0 +1,180 @@
+/*
+ * 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.0  (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 flexran_agent_scheduler_dlsch_ue_remote.c
+ * \brief procedures related to remote scheduling in the DLSCH transport channel
+ * \author Xenofon Foukas
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#include "flexran_agent_common_internal.h"
+
+#include "flexran_agent_scheduler_dlsch_ue_remote.h"
+
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/extern.h"
+
+struct DlMacConfigHead queue_head;
+
+int queue_initialized = 0;
+
+//uint32_t skip_subframe = 1;
+//uint32_t period = 10;
+//uint32_t sched [] = {1, 2, 3};
+
+void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe,
+				     int *mbsfn_flag, Protocol__FlexranMessage **dl_info) {
+
+  
+  //if ((subframe == skip_subframe) && (frame % period == 0)) {
+  //  LOG_I(MAC, "Will skip subframe %d %d\n", subframe, frame);
+  //  for (int i = 0; i < 3; i++) {
+  //    LOG_I(MAC, "%d\n", sched[i]);
+  //  }
+  //}
+
+  /* if (frame == 500 && subframe == 1) { */
+  /*   char policy[] = "rrc: \n - ul_scheduler: \n    behavior : tester_function\n    parameters:\n      period: !!int 3\nmac: \n - dl_scheduler: \n    parameters: \n      period : !!int 40\n      skip_subframe : !!int 3\n      sched : [!!int 4, !!int 5, !!int 6]"; */
+  /*   apply_reconfiguration_policy(mod_id, policy, strlen(policy)); */
+  /* } */
+
+  eNB_MAC_INST *eNB;
+
+  if (!queue_initialized) {
+    TAILQ_INIT(&queue_head);
+    queue_initialized = 1;
+  }
+
+  eNB = &eNB_mac_inst[mod_id]; 
+  
+  dl_mac_config_element_t *dl_config_elem;
+
+  int diff;
+  LOG_D(MAC, "[TEST] Current frame and subframe %d, %d\n", frame, subframe);
+  // First we check to see if we have a scheduling decision for this sfn_sf already in our queue
+  while(queue_head.tqh_first != NULL) {
+    dl_config_elem = queue_head.tqh_first;
+  
+    diff = get_sf_difference(mod_id, dl_config_elem->dl_info->dl_mac_config_msg->sfn_sf);
+    // Check if this decision is for now, for a later or a previous subframe
+    if ( diff == 0) { // Now
+      LOG_D(MAC, "Found a decision for this subframe in the queue. Let's use it!\n");
+      TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs);
+      *dl_info = dl_config_elem->dl_info;
+      free(dl_config_elem);
+      eNB->eNB_stats[mod_id].sched_decisions++;
+      return;
+    } else if (diff < 0) { //previous subframe , delete message and free memory
+      LOG_D(MAC, "Found a decision for a previous subframe in the queue. Let's get rid of it\n");
+      TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs);
+      flexran_agent_mac_destroy_dl_config(dl_config_elem->dl_info);
+      free(dl_config_elem);
+      eNB->eNB_stats[mod_id].sched_decisions++;
+      eNB->eNB_stats[mod_id].missed_deadlines++;
+    } else { // next subframe, nothing to do now
+      LOG_D(MAC, "Found a decision for a future subframe in the queue. Nothing to do now\n");
+      flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
+      return;
+    }
+  }
+
+  //Done with the local cache. Now we need to check if something new arrived
+  flexran_agent_get_pending_dl_mac_config(mod_id, dl_info);
+  while (*dl_info != NULL) {
+
+    diff = get_sf_difference(mod_id, (*dl_info)->dl_mac_config_msg->sfn_sf);
+    if (diff == 0) { // Got a command for this sfn_sf
+      LOG_D(MAC, "Found a decision for this subframe pending. Let's use it\n");
+      eNB->eNB_stats[mod_id].sched_decisions++;
+      return;
+    } else if (diff < 0) {
+      LOG_D(MAC, "Found a decision for a previous subframe. Let's get rid of it\n");
+      flexran_agent_mac_destroy_dl_config(*dl_info);
+      *dl_info = NULL;
+      flexran_agent_get_pending_dl_mac_config(mod_id, dl_info);
+      eNB->eNB_stats[mod_id].sched_decisions++;
+      eNB->eNB_stats[mod_id].missed_deadlines++;
+    } else { // Intended for future subframe. Store it in local cache
+      LOG_D(MAC, "Found a decision for a future subframe in the queue. Let's store it in the cache\n");
+      dl_mac_config_element_t *e = malloc(sizeof(dl_mac_config_element_t));
+      e->dl_info = *dl_info;
+      TAILQ_INSERT_TAIL(&queue_head, e, configs);
+      flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
+      // No need to look for another. Messages arrive ordered
+      return;
+    }
+  }
+  
+  // We found no pending command, so we will simply pass an empty one
+  flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
+}
+
+int get_sf_difference(mid_t mod_id, uint32_t sfn_sf) {
+  int diff_in_subframes;
+  
+  uint16_t current_frame = flexran_get_current_system_frame_num(mod_id);
+  uint16_t current_subframe = flexran_get_current_subframe(mod_id);
+  uint32_t current_sfn_sf = flexran_get_sfn_sf(mod_id);
+  
+  if (sfn_sf == current_sfn_sf) {
+    return 0;
+  }
+  
+  uint16_t frame_mask = ((1<<12) - 1);
+  uint16_t frame = (sfn_sf & (frame_mask << 4)) >> 4;
+  
+  uint16_t sf_mask = ((1<<4) - 1);
+  uint16_t subframe = (sfn_sf & sf_mask);
+
+ LOG_D(MAC, "[TEST] Target frame and subframe %d, %d\n", frame, subframe);
+  
+  if (frame == current_frame) {
+    return subframe - current_subframe;
+  } else if (frame > current_frame) {
+    diff_in_subframes = ((frame*10)+subframe) - ((current_frame*10)+current_subframe);
+    
+    //    diff_in_subframes = 9 - current_subframe;
+    //diff_in_subframes += (subframe + 1);
+    //diff_in_subframes += (frame-2) * 10;
+    if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) {
+      return -1;
+    } else {
+      return 1;
+    }
+  } else { //frame < current_frame
+    //diff_in_subframes = 9 - current_subframe;
+    //diff_in_subframes += (subframe + 1);
+    //if (frame > 0) {
+    //  diff_in_subframes += (frame - 1) * 10;
+    //}
+    //diff_in_subframes += (1023 - current_frame) * 10;
+    diff_in_subframes = 10240 - ((current_frame*10)+current_subframe) + ((frame*10)+subframe);
+    if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) {
+      return -1;
+    } else {
+      return 1;
+    }
+  }
+}
diff --git a/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a02ff2f1db6d278247bba94ec4481821916c6be
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue_remote.h
@@ -0,0 +1,69 @@
+/*
+ * 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.0  (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 flexran_agent_scheduler_dlsch_ue_remote.h
+ * \brief Local stub for remote scheduler used by the controller
+ * \author Xenofon Foukas
+ * \date 2016
+ * \email: x.foukas@sms.ed.ac.uk
+ * \version 0.1
+ * @ingroup _mac
+
+ */
+
+#ifndef __LAYER2_MAC_FLEXRAN_AGENT_SCHEDULER_DLSCH_UE_REMOTE_H__
+#define __LAYER2_MAC_FLEXRAN_AGENT_SCHEDULER_DLSCH_UE_REMOTE_H___
+
+#include "flexran.pb-c.h"
+#include "header.pb-c.h"
+
+#include "ENB_APP/flexran_agent_defs.h"
+#include "flexran_agent_mac.h"
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+
+#include <sys/queue.h>
+
+// Maximum value of schedule ahead of time
+// Required to identify if a dl_command is for the future or not
+#define SCHED_AHEAD_SUBFRAMES 20
+
+typedef struct dl_mac_config_element_s {
+  Protocol__FlexranMessage *dl_info;
+  TAILQ_ENTRY(dl_mac_config_element_s) configs;
+} dl_mac_config_element_t;
+
+TAILQ_HEAD(DlMacConfigHead, dl_mac_config_element_s);
+
+/*
+ * Default scheduler used by the eNB agent
+ */
+void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe,
+			     int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
+
+
+// Find the difference in subframes from the given subframe
+// negative for older value
+// 0 for equal
+// positive for future value
+// Based on  
+int get_sf_difference(mid_t mod_id, uint32_t sfn_sf);
+
+#endif
diff --git a/openair2/LAYER2/MAC/flexran_dci_conversions.h b/openair2/LAYER2/MAC/flexran_dci_conversions.h
new file mode 100644
index 0000000000000000000000000000000000000000..a417c39d208f853cafedb8c70974cee502c2d971
--- /dev/null
+++ b/openair2/LAYER2/MAC/flexran_dci_conversions.h
@@ -0,0 +1,51 @@
+/*
+ * 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.0  (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 flexran_dci_conversions.h
+ * \brief Conversion helpers from flexran messages to OAI formats DCI  
+ * \author Xenofon Foukas
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef LAYER2_MAC_FLEXRAN_DCI_CONVERISIONS_H__
+#define LAYER2_MAC_DCI_FLEXRAN_CONVERISIONS_H__
+
+#define FILL_DCI_FDD_1(TYPE, DCI, FLEXRAN_DCI) \
+  ((TYPE*)DCI)->harq_pid = FLEXRAN_DCI->harq_process; \
+  ((TYPE*)DCI)->rv = FLEXRAN_DCI->rv[0]; \
+  ((TYPE*)DCI)->rballoc = FLEXRAN_DCI->rb_bitmap; \
+  ((TYPE*)DCI)->rah = FLEXRAN_DCI->res_alloc; \
+  ((TYPE*)DCI)->mcs = FLEXRAN_DCI->mcs[0]; \
+  ((TYPE*)DCI)->TPC = FLEXRAN_DCI->tpc; \
+  ((TYPE*)DCI)->ndi = FLEXRAN_DCI->ndi[0];
+
+#define FILL_DCI_TDD_1(TYPE, DCI, FLEXRAN_DCI) \
+  ((TYPE*)DCI)->harq_pid = FLEXRAN_DCI->harq_process; \
+  ((TYPE*)DCI)->rv = FLEXRAN_DCI->rv[0]; \
+  ((TYPE*)DCI)->dai = FLEXRAN_DCI->dai; \
+  ((TYPE*)DCI)->rballoc = FLEXRAN_DCI->rb_bitmap; \
+  ((TYPE*)DCI)->rah = FLEXRAN_DCI->res_alloc; \
+  ((TYPE*)DCI)->mcs = FLEXRAN_DCI->mcs[0]; \
+  ((TYPE*)DCI)->TPC = FLEXRAN_DCI->tpc; \
+  ((TYPE*)DCI)->ndi = FLEXRAN_DCI->ndi[0];
+  
+#endif
diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c
index 0fe9d63b6ff26ba5d03ebe4bb95e004627f2875a..203bd3f36f8a9e24b75bce6627a33bc9ac63f436 100644
--- a/openair2/LAYER2/MAC/main.c
+++ b/openair2/LAYER2/MAC/main.c
@@ -527,6 +527,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui
 
   mac_xface->phy_config_dedicated_eNB    = phy_config_dedicated_eNB;
   mac_xface->phy_config_dedicated_ue     = phy_config_dedicated_ue;
+  mac_xface->phy_config_harq_ue          = phy_config_harq_ue;
 
   mac_xface->get_lte_frame_parms        = get_lte_frame_parms;
   mac_xface->get_mu_mimo_mode           = get_mu_mimo_mode;
diff --git a/openair2/LAYER2/MAC/openair2_proc.c b/openair2/LAYER2/MAC/openair2_proc.c
index 950713de5a0d6ddd1bbfd6d69828844a3368139b..4b635712778439a0fe4bdee87fed61b690f449ab 100644
--- a/openair2/LAYER2/MAC/openair2_proc.c
+++ b/openair2/LAYER2/MAC/openair2_proc.c
@@ -82,7 +82,7 @@ int openair2_stats_read(char *buffer, char **my_buffer, off_t off, int length)
     // mod_id used for PDCP and RLC
     Mod_id = NB_eNB_INST + ue_id ;
 
-    len+=sprintf(&buffer[len],"UE TTI: %d\n",UE_mac_inst[ue_id].frame);
+    len+=sprintf(&buffer[len],"UE RX TTI: %d\n",UE_mac_inst[ue_id].rxFrame);
 
     for (enb_id= 0; enb_id <NB_SIG_CNX_UE; enb_id++) {
 
diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c
index 4aea92c3e2993795e135614958dde973a3e63361..ed12d322c10d43a7a1cd7eb3b34288b401fdf979 100644
--- a/openair2/LAYER2/MAC/pre_processor.c
+++ b/openair2/LAYER2/MAC/pre_processor.c
@@ -763,7 +763,7 @@ void dlsch_scheduler_pre_processor_reset (int module_idP,
 				    frameP,subframeP,
 				    &ue_sched_ctl->harq_pid[CC_id],
 				    &ue_sched_ctl->round[CC_id],
-				    0);
+				    openair_harq_DL);
   if (ue_sched_ctl->ta_timer == 0) {
 
     // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...
@@ -1028,7 +1028,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP,
       // This is the actual CC_id in the list
       CC_id = UE_list->ordered_ULCCids[n][UE_id];
 
-      mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,1);
+      mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL);
 
       if(round>0) {
         nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid];
diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h
index 4df0c6fa459861f441404ebf4419f57a772a071e..9454f3da802d2a1d04b5054caf65e3d4522cb67d 100644
--- a/openair2/LAYER2/MAC/proto.h
+++ b/openair2/LAYER2/MAC/proto.h
@@ -28,6 +28,7 @@
  */
 #ifndef __LAYER2_MAC_PROTO_H__
 #define __LAYER2_MAC_PROTO_H__
+
 /** \addtogroup _mac
  *  @{
  */
@@ -121,6 +122,7 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i
 */
 void schedule_ue_spec(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag);
 
+
 /** \brief Function for UE/PHY to compute PUSCH transmit power in power-control procedure.
     @param Mod_id Module id of UE
     @returns Po_NOMINAL_PUSCH (PREAMBLE_RECEIVED_TARGET_POWER+DELTA_PREAMBLE
@@ -445,6 +447,9 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,u
 
 /* \brief Function called by PHY to process the received RAR.  It checks that the preamble matches what was sent by the eNB and provides the timing advance and t-CRNTI.
 @param Mod_id Index of UE instance
+@param CC_id Index to a component carrier
+@param frame Frame index
+@param ra_rnti RA_RNTI value
 @param dlsch_buffer  Pointer to dlsch_buffer containing RAR PDU
 @param t_crnti Pointer to PHY variable containing the T_CRNTI
 @param preamble_index Preamble Index used by PHY to transmit the PRACH.  This should match the received RAR to trigger the rest of
@@ -456,6 +461,7 @@ ue_process_rar(
   const module_id_t module_idP,
   const int CC_id,
   const frame_t frameP,
+  const rnti_t ra_rnti,
   uint8_t * const dlsch_buffer,
   rnti_t * const t_crnti,
   const uint8_t preamble_index
@@ -534,15 +540,20 @@ void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, UE_TEMPLATE *UE_templat
 /*! \fn  UE_L2_state_t ue_scheduler(const module_id_t module_idP,const frame_t frameP, const sub_frame_t subframe, const lte_subframe_t direction,const uint8_t eNB_index)
    \brief UE scheduler where all the ue background tasks are done.  This function performs the following:  1) Trigger PDCP every 5ms 2) Call RRC for link status return to PHY3) Perform SR/BSR procedures for scheduling feedback 4) Perform PHR procedures.
 \param[in] module_idP instance of the UE
-\param[in] subframe t the subframe number
+\param[in] rxFrame the RX frame number
+\param[in] rxSubframe the RX subframe number
+\param[in] txFrame the TX frame number
+\param[in] txSubframe the TX subframe number
 \param[in] direction  subframe direction
 \param[in] eNB_index  instance of eNB
 @returns L2 state (CONNETION_OK or CONNECTION_LOST or PHY_RESYNCH)
 */
 UE_L2_STATE_t ue_scheduler(
   const module_id_t module_idP,
-  const frame_t frameP,
-  const sub_frame_t subframe,
+  const frame_t rxFrameP,
+  const sub_frame_t rxSubframe,
+  const frame_t txFrameP,
+  const sub_frame_t txSubframe,
   const lte_subframe_t direction,
   const uint8_t eNB_index,
   const int CC_id);
@@ -557,21 +568,6 @@ UE_L2_STATE_t ue_scheduler(
 */
 int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen);
 
-/*! \fn  int get_bsr_lcgid (module_id_t module_idP);
-\brief determine the lcgid for the bsr
-\param[in] Mod_id instance of the UE
-\param[out] lcgid
-*/
-int get_bsr_lcgid (module_id_t module_idP);
-
-/*! \fn  uint8_t get_bsr_len (module_id_t module_idP,uint16_t bufflen);
-\brief determine whether the bsr is short or long assuming that the MAC pdu is built
-\param[in] Mod_id instance of the UE
-\param[in] bufflen size of phy transport block
-\param[out] bsr_len size of bsr control element
-*/
-uint8_t get_bsr_len (module_id_t module_idP, uint16_t buflen);
-
 /*! \fn  BSR_SHORT *  get_bsr_short(module_id_t module_idP, uint8_t bsr_len)
 \brief get short bsr level
 \param[in] Mod_id instance of the UE
@@ -588,22 +584,21 @@ BSR_SHORT *get_bsr_short(module_id_t module_idP, uint8_t bsr_len);
 */
 BSR_LONG * get_bsr_long(module_id_t module_idP, uint8_t bsr_len);
 
-/*! \fn  boolean_t update_bsr(module_id_t module_idP, frame_t frameP, uint8_t lcid)
+/*! \fn  boolean_t update_bsr(module_id_t module_idP, frame_t frameP,sub_frame_t subframeP)
    \brief get the rlc stats and update the bsr level for each lcid
 \param[in] Mod_id instance of the UE
 \param[in] frame Frame index
-\param[in] lcid logical channel identifier
 */
-boolean_t update_bsr(module_id_t module_idP, frame_t frameP, eNB_index_t eNB_index, uint8_t lcid, uint8_t lcgid);
+boolean_t update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP,eNB_index_t eNB_index);
 
-/*! \fn  locate (int *table, int size, int value)
+/*! \fn  locate_BsrIndexByBufferSize (int *table, int size, int value)
    \brief locate the BSR level in the table as defined in 36.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table.
 \param[in] *table Pointer to BSR table
 \param[in] size Size of the table
 \param[in] value Value of the buffer
 \return the index in the BSR_LEVEL table
 */
-uint8_t locate (const uint32_t *table, int size, int value);
+uint8_t locate_BsrIndexByBufferSize (const uint32_t *table, int size, int value);
 
 
 /*! \fn  int get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer)
diff --git a/openair2/LAYER2/MAC/ra_procedures.c b/openair2/LAYER2/MAC/ra_procedures.c
index ffc8df479213edd670a323c7c9b68cee519c6991..43bc1137985aedfb39e6e9a0f84e92f1e30ccca3 100644
--- a/openair2/LAYER2/MAC/ra_procedures.c
+++ b/openair2/LAYER2/MAC/ra_procedures.c
@@ -271,8 +271,8 @@ void Msg1_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id
   UE_mac_inst[module_idP].RA_attempt_number++;
 
   if (opt_enabled) {
-    trace_pdu(0, NULL, 0, module_idP, 2, UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex,
-              UE_mac_inst[module_idP].subframe, 0, UE_mac_inst[module_idP].RA_attempt_number);
+    trace_pdu(0, NULL, 0, module_idP, 0 , UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex,
+        UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, UE_mac_inst[module_idP].RA_attempt_number);
     LOG_D(OPT,"[UE %d][RAPROC] TX MSG1 Frame %d trace pdu for rnti %x  with size %d\n",
           module_idP, frameP, 1, UE_mac_inst[module_idP].RA_Msg3_size);
   }
@@ -296,7 +296,7 @@ void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id
 
   if (opt_enabled) { // msg3
     trace_pdu(0, &UE_mac_inst[module_idP].CCCH_pdu.payload[0], UE_mac_inst[module_idP].RA_Msg3_size,
-              module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].subframe, 0, 0);
+              module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0);
     LOG_D(OPT,"[UE %d][RAPROC] MSG3 Frame %d trace pdu Preamble %d   with size %d\n",
           module_idP, frameP, UE_mac_inst[module_idP].crnti /*UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex*/, UE_mac_inst[module_idP].RA_Msg3_size);
   }
@@ -391,7 +391,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
                                 1); //post_padding
           return(&UE_mac_inst[module_idP].RA_prach_resources);
 
-        } else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DCCH] > 0) {
+        } else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] > 0) {
           // This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example)
           dcch_header_len = 2 + 2;  /// SHORT Subheader + C-RNTI control element
           rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
@@ -412,7 +412,12 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
                                             (char *)&ulsch_buff[0]);
 
           LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
-          update_bsr(module_idP, frameP, eNB_indexP,DCCH,UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]);
+          update_bsr(module_idP, frameP, subframeP,eNB_indexP);
+	      UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] =
+	    		  locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]]);
+
+	      //TO DO: fill BSR infos in UL TBS
+
           //header_len +=2;
           UE_mac_inst[module_idP].RA_active                        = 1;
           UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
diff --git a/openair2/LAYER2/MAC/rar_tools.c b/openair2/LAYER2/MAC/rar_tools.c
index a637ddf18c436447dd8e76afef066cbb343ef01f..b453b5cca8529ed75aa50bbdbc1cd7cfa11b10d1 100644
--- a/openair2/LAYER2/MAC/rar_tools.c
+++ b/openair2/LAYER2/MAC/rar_tools.c
@@ -118,7 +118,7 @@ unsigned short fill_rar(
 
   if (opt_enabled) {
     trace_pdu(1, dlsch_buffer, input_buffer_length, module_idP, 2, 1,
-              eNB_mac_inst[module_idP].subframe, 0, 0);
+        eNB_mac_inst[module_idP].frame, eNB_mac_inst[module_idP].subframe, 0, 0);
     LOG_D(OPT,"[eNB %d][RAPROC] CC_id %d RAR Frame %d trace pdu for rnti %x and  rapid %d size %d\n",
           module_idP, CC_id, frameP, eNB_mac_inst[module_idP].common_channels[CC_id].RA_template[ra_idx].rnti,
           rarh->RAPID, input_buffer_length);
@@ -133,6 +133,7 @@ ue_process_rar(
   const module_id_t module_idP,
   const int CC_id,
   const frame_t frameP,
+  const rnti_t ra_rnti,
   uint8_t* const dlsch_buffer,
   rnti_t* const t_crnti,
   const uint8_t preamble_index
@@ -168,6 +169,12 @@ ue_process_rar(
   LOG_D(MAC,"[UE %d][RAPROC] rar->t_crnti %x\n",module_idP,(uint16_t)rar[5]+(rar[4]<<8));
 #endif
 
+  if (opt_enabled) {
+    LOG_D(OPT,"[UE %d][RAPROC] CC_id %d RAR Frame %d trace pdu for ra-RNTI %x\n",
+          module_idP, CC_id, frameP, ra_rnti);
+    trace_pdu(1, (uint8_t*)rarh, 7, module_idP, 2, ra_rnti,
+        UE_mac_inst[module_idP].rxFrame, UE_mac_inst[module_idP].rxSubframe, 0, 0);
+  }
 
   if (preamble_index == rarh->RAPID) {
     *t_crnti = (uint16_t)rar[5]+(rar[4]<<8);//rar->t_crnti;
diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c
index c91c977c3aabb7d961c4cbd95ef59964260ca440..cdac22c486a283af5514f9f55883c9c2fa3466de 100644
--- a/openair2/LAYER2/MAC/ue_procedures.c
+++ b/openair2/LAYER2/MAC/ue_procedures.c
@@ -70,6 +70,8 @@
 #define DEBUG_HEADER_PARSING 1
 #define ENABLE_MAC_PAYLOAD_DEBUG 1
 
+extern uint8_t usim_test;
+
 /*
 #ifndef USER_MODE
 #define msg debug_msg
@@ -91,7 +93,7 @@ void ue_init_mac(module_id_t module_idP)
   // default values as deined in 36.331 sec 9.2.2
   LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
   //UE_mac_inst[module_idP].scheduling_info.macConfig=NULL;
-  UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560;
+  UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf10240;
   UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity;
   UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20;
   UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20;
@@ -102,13 +104,19 @@ void ue_init_mac(module_id_t module_idP)
   UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
   UE_mac_inst[module_idP].scheduling_info.maxHARQ_Tx=MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
   UE_mac_inst[module_idP].scheduling_info.ttiBundling=0;
+  UE_mac_inst[module_idP].scheduling_info.extendedBSR_Sizes_r10=0;
+  UE_mac_inst[module_idP].scheduling_info.extendedPHR_r10=0;
   UE_mac_inst[module_idP].scheduling_info.drx_config=NULL;
   UE_mac_inst[module_idP].scheduling_info.phr_config=NULL;
-  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF  =  get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer);
-  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF     =  get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
+  // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value configured by the NW.
+  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF  =  MAC_UE_BSR_TIMER_NOT_RUNNING;
+  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF     =  MAC_UE_BSR_TIMER_NOT_RUNNING;
+  UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
+  
   UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF =  get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer);
   UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF =  get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer);
   UE_mac_inst[module_idP].scheduling_info.PathlossChange_db =  get_db_dl_PathlossChange(UE_mac_inst[module_idP].scheduling_info.PathlossChange);
+  UE_mac_inst[module_idP].PHR_reporting_active = 0;
 
   for (i=0; i < MAX_NUM_LCID; i++) {
     LOG_D(MAC,"[UE%d] Applying default logical channel config for LCGID %d\n",module_idP,i);
@@ -121,7 +129,8 @@ void ue_init_mac(module_id_t module_idP)
       UE_mac_inst[module_idP].scheduling_info.LCGID[i]=1;
     }
 
-    UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=0;
+    UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=LCID_EMPTY;
+    UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[i] = 0;
   }
 
 #ifdef CBA
@@ -143,7 +152,7 @@ unsigned char *parse_header(unsigned char *mac_header,
                             unsigned short tb_length)
 {
 
-  unsigned char not_done=1,num_ces=0,num_sdus=0,lcid, num_sdu_cnt;
+  unsigned char not_done=1,num_ces=0,num_cont_res = 0,num_padding = 0,num_sdus=0,lcid, num_sdu_cnt;
   unsigned char *mac_header_ptr = mac_header;
   unsigned short length,ce_len=0;
 
@@ -188,6 +197,7 @@ unsigned char *parse_header(unsigned char *mac_header,
       num_sdus++;
     } else { // This is a control element subheader
       if (lcid == SHORT_PADDING) {
+    	num_padding ++;
         mac_header_ptr++;
       } else {
         rx_ces[num_ces] = lcid;
@@ -197,6 +207,23 @@ unsigned char *parse_header(unsigned char *mac_header,
         if (lcid==TIMING_ADV_CMD) {
           ce_len++;
         } else if (lcid==UE_CONT_RES) {
+
+        	// FNA: check MAC Header is one of thoses defined in Annex B of 36.321
+        	// Check there is only 1 Contention Resolution
+        	if (num_cont_res) {
+        		LOG_W(MAC,"[UE] Msg4 Wrong received format: More than 1 Contention Resolution\n");
+        		// exit parsing
+        		return NULL;
+
+        	}
+
+        	// UE_CONT_RES shall never be the last subheader unless this is the only MAC subheader
+        	if ((not_done == 0) && ((num_sdus) || (num_ces > 1) || (num_padding))) {
+        		LOG_W(MAC,"[UE] Msg4 Wrong received format: Contention Resolution after num_ces=%d num_sdus=%d num_padding=%d\n",num_ces,num_sdus,num_padding);
+        		// exit parsing
+        		return NULL;
+        	}
+          num_cont_res ++;
           ce_len+=6;
         }
       }
@@ -286,6 +313,14 @@ uint32_t ue_get_SR(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t eNB_i
     // notify RRC to relase PUCCH/SRS
     // clear any configured dl/ul
     // initiate RA
+      if (UE_mac_inst[module_idP].scheduling_info.SR_pending){
+          // release all pucch resource
+          UE_mac_inst[module_idP].physicalConfigDedicated = NULL;
+          UE_mac_inst[module_idP].ul_active=0;
+          UE_mac_inst[module_idP].BSR_reporting_active=BSR_TRIGGER_NONE;
+
+          LOG_I(MAC,"[UE %d] Release all SRs \n", module_idP);
+      }
     UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
     UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
     return(0);
@@ -294,12 +329,16 @@ uint32_t ue_get_SR(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t eNB_i
 
 //------------------------------------------------------------------------------
 void
-ue_send_sdu(module_id_t module_idP,
+ue_send_sdu(
+  module_id_t module_idP,
 	    uint8_t CC_id,
 	    frame_t frameP,
 	    uint8_t* sdu,
 	    uint16_t sdu_len,
-	    uint8_t eNB_index) {
+  uint8_t eNB_index
+)
+//------------------------------------------------------------------------------
+{
 
   unsigned char rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr;
   unsigned char rx_lcids[NB_RB_MAX];
@@ -313,7 +352,7 @@ ue_send_sdu(module_id_t module_idP,
 
   if (opt_enabled) {
     trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti,
-              UE_mac_inst[module_idP].subframe, 0, 0); 
+        UE_mac_inst[module_idP].rxFrame, UE_mac_inst[module_idP].rxSubframe, 0, 0);
     LOG_D(OPT,"[UE %d][DLSCH] Frame %d trace pdu for rnti %x  with size %d\n",
           module_idP, frameP, UE_mac_inst[module_idP].crnti, sdu_len);
   }
@@ -335,6 +374,8 @@ ue_send_sdu(module_id_t module_idP,
   LOG_T(MAC,"\n");
 #endif
 
+  if (payload_ptr != NULL) {
+
   for (i=0; i<num_ce; i++) {
     //    printf("ce %d : %d\n",i,rx_ces[i]);
     switch (rx_ces[i]) {
@@ -459,6 +500,7 @@ ue_send_sdu(module_id_t module_idP,
     }
     payload_ptr+= rx_lengths[i];
   }
+  } // end if (payload_ptr != NULL)
   
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
   stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
@@ -491,7 +533,8 @@ void ue_decode_si(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_i
 	      module_idP,
 	      4,
 	      0xffff,
-	      UE_mac_inst[module_idP].subframe,
+	      UE_mac_inst[module_idP].rxFrame,
+	      UE_mac_inst[module_idP].rxSubframe,
 	      0,
 	      0);
     LOG_D(OPT,"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
@@ -526,7 +569,8 @@ void ue_decode_p(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_in
 	      module_idP,
 	      4,
 	      P_RNTI,
-	      UE_mac_inst[module_idP].subframe,
+	      UE_mac_inst[module_idP].rxFrame,
+	      UE_mac_inst[module_idP].rxSubframe,
 	      0,
 	      0);
     LOG_D(OPT,"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
@@ -1108,8 +1152,6 @@ unsigned char generate_ulsch_header(uint8_t *mac_header,
     *(ce_ptr)     = (long_bsr->Buffer_size0 << 2) | ((long_bsr->Buffer_size1 & 0x30) >> 4);
     *(ce_ptr + 1) = ((long_bsr->Buffer_size1 & 0x0F) << 4) | ((long_bsr->Buffer_size2 & 0x3C) >> 2);
     *(ce_ptr + 2) = ((long_bsr->Buffer_size2 & 0x03) << 2) | (long_bsr->Buffer_size3 & 0x3F);
-    /* Padding */
-    *(ce_ptr + 3) = 0;
     ce_ptr += BSR_LONG_SIZE;
 
     //    printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
@@ -1122,50 +1164,67 @@ unsigned char generate_ulsch_header(uint8_t *mac_header,
     LOG_T(MAC,"[UE] sdu subheader %d (lcid %d, %d bytes)\n",i,sdu_lcids[i],sdu_lengths[i]);
 #endif
 
-    if ((first_element>0)) {
-      mac_header_ptr->E = 1;
-#ifdef DEBUG_HEADER_PARSING
-      LOG_D(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
-            ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
-            ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
-            ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
-#endif
-      mac_header_ptr+=last_size;
-      //      printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
-    } else {
-      first_element=1;
-
+    if ((i == (num_sdus - 1)) && ((short_padding) || (post_padding == 0))) {
+        if (first_element>0) {
+            mac_header_ptr->E = 1;
+      #ifdef DEBUG_HEADER_PARSING
+            LOG_D(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
+                  ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
+                  ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
+                  ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
+      #endif
+            mac_header_ptr+=last_size;
+        }
+        mac_header_ptr->R    = 0;
+        mac_header_ptr->E    = 0;
+        mac_header_ptr->LCID = sdu_lcids[i];
     }
+    else {
+        if ((first_element>0)) {
+          mac_header_ptr->E = 1;
+    #ifdef DEBUG_HEADER_PARSING
+          LOG_D(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
+                ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
+                ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
+                ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
+    #endif
+          mac_header_ptr+=last_size;
+          //      printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
+        } else {
+          first_element=1;
 
-    if (sdu_lengths[i] < 128) {
-      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R    = 0; // 3
-      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E    = 0;
-      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F    = 0;
-      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = sdu_lcids[i];
-      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L    = (unsigned char)sdu_lengths[i];
-      last_size=2;
-#ifdef DEBUG_HEADER_PARSING
-      LOG_D(MAC,"[UE] short sdu\n");
-      LOG_T(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d,F%d,L%d)\n",
-            ((uint16_t*)mac_header_ptr)[0],
-            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R,
-            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E,
-            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID,
-            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F,
-            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L);
-#endif
-    } else {
-      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R    = 0;
-      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E    = 0;
-      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F    = 1;
-      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i];
-      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB    = ((unsigned short) sdu_lengths[i]>>8)&0x7f;
-      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB    = (unsigned short) sdu_lengths[i]&0xff;
-      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->padding  = 0x00;
-      last_size=3;
-#ifdef DEBUG_HEADER_PARSING
-      LOG_D(MAC,"[UE] long sdu\n");
-#endif
+        }
+
+        if (sdu_lengths[i] < 128) {
+          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R    = 0; // 3
+          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E    = 0;
+          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F    = 0;
+          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = sdu_lcids[i];
+          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L    = (unsigned char)sdu_lengths[i];
+          last_size=2;
+    #ifdef DEBUG_HEADER_PARSING
+          LOG_D(MAC,"[UE] short sdu\n");
+          LOG_T(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d,F%d,L%d)\n",
+                ((uint16_t*)mac_header_ptr)[0],
+                ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R,
+                ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E,
+                ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID,
+                ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F,
+                ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L);
+    #endif
+        } else {
+          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R    = 0;
+          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E    = 0;
+          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F    = 1;
+          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i];
+          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB    = ((unsigned short) sdu_lengths[i]>>8)&0x7f;
+          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB    = (unsigned short) sdu_lengths[i]&0xff;
+          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->padding  = 0x00;
+          last_size=3;
+    #ifdef DEBUG_HEADER_PARSING
+          LOG_D(MAC,"[UE] long sdu\n");
+    #endif
+        }
     }
   }
 
@@ -1183,6 +1242,7 @@ unsigned char generate_ulsch_header(uint8_t *mac_header,
     //mac_header_ptr=last_size; // FIXME: should be ++
   }
 
+
   if ((ce_ptr-mac_header_control_elements) > 0) {
     memcpy((void*)mac_header_ptr,mac_header_control_elements,ce_ptr-mac_header_control_elements);
     mac_header_ptr+=(unsigned char)(ce_ptr-mac_header_control_elements);
@@ -1205,27 +1265,36 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
 {
 
   mac_rlc_status_resp_t rlc_status;
-  uint8_t dcch_header_len=0,dcch1_header_len=0,dtch_header_len=0,dtch_header_len_last=0;
-  uint8_t dcch_header_len_tmp=0, dtch_header_len_tmp=0;
-  uint8_t bsr_header_len=0, bsr_ce_len=0, bsr_len=0;
+  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;
   uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0;
-  uint8_t lcid=0;
+  uint8_t lcid=0,lcid_rlc_pdu_count=0;
+  boolean_t is_lcid_processed = FALSE;
   uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
   uint8_t sdu_lcids[8]    = { 0, 0, 0, 0, 0, 0, 0, 0 };
   uint8_t payload_offset=0,num_sdus=0;
   uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES];
   uint16_t sdu_length_total=0;
-  BSR_SHORT bsr_short;
+  BSR_SHORT bsr_short,bsr_truncated;
   BSR_LONG bsr_long;
   BSR_SHORT *bsr_s=&bsr_short;
   BSR_LONG  *bsr_l=&bsr_long;
+  BSR_SHORT *bsr_t=&bsr_truncated;
   POWER_HEADROOM_CMD phr;
   POWER_HEADROOM_CMD *phr_p=&phr;
-  unsigned short short_padding=0, post_padding=0;
-  int lcgid;
+  unsigned short short_padding=0, post_padding=0, padding_len=0;
   int j; // used for padding
   // Compute header length
+  int lcg_id = 0;
+  int lcg_id_bsr_trunc = 0;
+  int highest_priority = 16;
+  int num_lcg_id_with_data = 0;
+  
+  LOG_D(MAC,"[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n",
+                        module_idP, frameP, subframe, buflen);
 
+  
   if (CC_id>0) {
     LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
     mac_xface->macphy_exit("MAC FATAL  CC_id>0");
@@ -1253,33 +1322,76 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
   }
 
 #endif
-  dcch_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
-  dcch1_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
-  // hypo length,in case of long header skip the padding byte
-  dtch_header_len=(buflen > 128 ) ? 3 : 2 ; //sizeof(SCH_SUBHEADER_LONG)-1 : sizeof(SCH_SUBHEADER_SHORT);
-  bsr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
+  bsr_header_len = 0;
   phr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
-  phr_ce_len = (UE_mac_inst[module_idP].PHR_reporting_active == 1) ? 1 /* sizeof(POWER_HEADROOM_CMD)*/: 0;
 
-  if (phr_ce_len > 0) {
+  while (lcg_id < MAX_NUM_LCGID) {
+     if  (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]){
+         num_lcg_id_with_data ++;
+     }
+     lcg_id ++;
+  }
+
+  if (num_lcg_id_with_data){
+      LOG_D(MAC,"[UE %d] MAC Tx data pending at frame%d subframe %d nb LCG =%d Bytes for LCG0=%d LCG1=%d LCG2=%d LCG3=%d BSR Trigger status =%d TBS=%d\n",
+                            module_idP,
+                            frameP,
+                            subframe,
+                            num_lcg_id_with_data,
+                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[0],
+                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[1],
+                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[2],
+                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[3],
+                            UE_mac_inst[module_idP].BSR_reporting_active, buflen);
+
+  }
+  //Restart ReTxBSR Timer at new grant indication (36.321)
+  if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING){
+      UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
+  }
+
+  // periodicBSR-Timer expires, trigger BSR
+  if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity)
+            && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF == 0)){
+        // Trigger BSR Periodic
+      UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PERIODIC;
+
+      LOG_D(MAC,"[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n",
+                       module_idP, frameP, subframe, buflen);
+
+    }
+
+  //Compute BSR Length if Regular or Periodic BSR is triggered
+  //WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing if there remains less than 1 LCGROUP with data after Tx
+  if (UE_mac_inst[module_idP].BSR_reporting_active){
+
+	  AssertFatal ((UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_PADDING) == 0 , "Inconsistent BSR Trigger=%d !\n",
+			  UE_mac_inst[module_idP].BSR_reporting_active);
+
+      if (buflen >= 4){
+    	  //A Regular or Periodic BSR can only be sent if TBS >= 4 as transmitting only a BSR is not allowed if UE has data to transmit
+    	  bsr_header_len = 1;
+
+          if (num_lcg_id_with_data <= 1){
+              bsr_ce_len = sizeof(BSR_SHORT); //1 byte
+          }
+          else{
+              bsr_ce_len = BSR_LONG_SIZE; //3 bytes
+          }
+      }
+  }
+
+  bsr_len = bsr_ce_len + bsr_header_len;
+
+  phr_ce_len = (UE_mac_inst[module_idP].PHR_reporting_active == 1) ? 1 /* sizeof(POWER_HEADROOM_CMD)*/: 0;
+  if ((phr_ce_len > 0) && ((phr_ce_len + phr_header_len + bsr_len) <= buflen)){
     phr_len = phr_ce_len + phr_header_len;
     LOG_D(MAC,"[UE %d] header size info: PHR len %d (ce%d,hdr%d) buff_len %d\n",
           module_idP, phr_len, phr_ce_len, phr_header_len, buflen);
   } else {
     phr_len=0;
-  }
-
-  bsr_ce_len = get_bsr_len (module_idP, buflen-phr_len);
-
-  if (bsr_ce_len > 0 ) {
-    bsr_len = bsr_ce_len + bsr_header_len;
-    LOG_D(MAC,"[UE %d] header size info: dcch %d, dcch1 %d, dtch %d, bsr (ce%d,hdr%d) buff_len %d\n",
-          module_idP, dcch_header_len,dcch1_header_len,dtch_header_len, bsr_ce_len, bsr_header_len, buflen);
-  } else {
-    bsr_len=0;
-    //LOG_D(MAC,"[UE %d] Empty buffers, send a long BSR to reset the bsr at eNB \n ",Mod_id);
-    //    bsr_ce_len = sizeof(BSR_LONG);
-    //bsr_len = bsr_ce_len + bsr_header_len;
+    phr_header_len = 0;
+    phr_ce_len = 0;
   }
 
   // check for UL bandwidth requests and add SR control element
@@ -1287,164 +1399,308 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
   // check for UL bandwidth requests and add SR control element
 
   // Check for DCCH first
+// TO DO: Unrool the loop to do it at least once to avoid the if num_sdu
+for (lcid=DCCH; lcid < DTCH ; lcid++) {
+  if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) {
 
-  if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH] == LCID_NOT_EMPTY) {
-
-    rlc_status = mac_rlc_status_ind(module_idP, 
-				    UE_mac_inst[module_idP].crnti, 
-				    eNB_index, 
-				    frameP,
-				    ENB_FLAG_NO,
-				    MBMS_FLAG_NO, // eNB_index
-                                    DCCH,
-                                    (buflen-dcch_header_len-bsr_len-phr_len));
-    LOG_D(MAC, "[UE %d] Frame %d : UL-DCCH -> ULSCH, RRC message has %d bytes to "
-          "send (Transport Block size %d, mac header len %d)\n",
-          module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dcch_header_len);
-
-    sdu_lengths[0] += mac_rlc_data_req(module_idP, 
-				       UE_mac_inst[module_idP].crnti,
-				       eNB_index,
-				       frameP,
-				       ENB_FLAG_NO, 
-				       MBMS_FLAG_NO,
-                                       DCCH,
-                                       (char *)&ulsch_buff[sdu_lengths[0]]);
-
-    sdu_length_total += sdu_lengths[0];
-    sdu_lcids[0] = DCCH;
-    LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
-    num_sdus = 1;
-    update_bsr(module_idP, frameP, eNB_index, DCCH, UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]);
-    //header_len +=2;
-  } else {
-    dcch_header_len=0;
-    num_sdus = 0;
-  }
-
-  // if the RLC AM is used, then RLC will only provide 2 bytes for ACK
-  // in this case, we sould add bsr
-
-  // DCCH1
-  if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH1] == LCID_NOT_EMPTY) {
-
-    rlc_status = mac_rlc_status_ind(module_idP, 
-				    UE_mac_inst[module_idP].crnti, 
-				    eNB_index,
-				    frameP,
-				    ENB_FLAG_NO,
-				    MBMS_FLAG_NO, // eNB_index
-                                    DCCH1,
-                                    (buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-sdu_length_total));
-
-    LOG_D(MAC,"[UE %d] Frame %d : UL-DCCH1 -> ULSCH, RRC message has %d bytes to"
-          " send (Transport Block size %d, mac header len %d)\n",
-          module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dcch1_header_len);
-
-    sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 
-					     UE_mac_inst[module_idP].crnti,
-					     eNB_index,
-					     frameP,
-					     ENB_FLAG_NO,
-					     MBMS_FLAG_NO,
-					     DCCH1,
-					     (char *)&ulsch_buff[sdu_lengths[num_sdus]]);
-    sdu_length_total += sdu_lengths[num_sdus];
-    sdu_lcids[num_sdus] = DCCH1;
-    LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH1\n",module_idP,sdu_lengths[num_sdus]);
-    num_sdus++;
-    //update_bsr(module_idP, frameP, DCCH1);
-    //dcch_header_len +=2; // include dcch1
-  } else {
-    dcch1_header_len =0;
-  }
+      is_lcid_processed = FALSE;
+      lcid_rlc_pdu_count = 0;
 
-  dtch_header_len=0;
-  dtch_header_len_last=0;
-  for (lcid=NB_RB_MAX-1; lcid>=DTCH ; lcid--){
-    dtch_header_len+=3; 
-    dtch_header_len_last=3;
-    
-    if ((UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) &&
-	((bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len+sdu_length_total) <= buflen)) {
-
-    // optimize the dtch header lenght
-    //if ((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH] > 128) &&
-    /*   if (((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH] >= 128) &&
-    ((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH]+bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len) > buflen)&&
-    buflen >=128 ))
-    dtch_header_len = 3;//sizeof(SCH_SUBHEADER_LONG);
-    else
-    dtch_header_len = 2;//sizeof(SCH_SUBHEADER_SHORT);
-     */
-      rlc_status = mac_rlc_status_ind(module_idP, 
-				      UE_mac_inst[module_idP].crnti, 
-				      eNB_index,
-				      frameP,
-				      ENB_FLAG_NO,
-				      MBMS_FLAG_NO, // eNB_index
-				      lcid,
-				      buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total);
-
-      LOG_D(MAC,"[UE %d] Frame %d : UL-DTCH -> ULSCH%d, %d bytes to send (Transport Block size %d, mac header len %d, BSR byte[%d] %d)\n",
-	    module_idP,frameP, lcid, rlc_status.bytes_in_buffer,buflen,dtch_header_len,
-	    lcid, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcid]);
-      
-       if (rlc_status.bytes_in_buffer > 0) {
-	 sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
-						  UE_mac_inst[module_idP].crnti,
-						  eNB_index,
-						  frameP, 
-						  ENB_FLAG_NO, 
-						  MBMS_FLAG_NO, // eNB_index
-						  lcid,
-						  (char *)&ulsch_buff[sdu_length_total]);
-	 
-	 //adjust dtch header
-	 LOG_D(MAC,"[UE %d] TX Got %d bytes for DTCH\n",module_idP,sdu_lengths[num_sdus]);
-	 sdu_lcids[num_sdus] = lcid;
-	 sdu_length_total += sdu_lengths[num_sdus];
-	 if (sdu_lengths[num_sdus] < 128) {
-	   dtch_header_len --;
-	   dtch_header_len_last --;
-	 }
-	 num_sdus++;
-	 UE_mac_inst[module_idP].ul_active = update_bsr(module_idP, frameP, eNB_index,lcid, UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]);
-       } else {
-	 dtch_header_len -= 3;
-       }
-    } else { // no rlc pdu : generate the dummy header
-      dtch_header_len -= 3;
-    }
+      //Multiplex all available DCCH RLC PDUs considering to multiplex the last PDU each time for maximize the data
+      //Adjust at the end of the loop
+      while ((!is_lcid_processed) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
+
+    	  // Workaround for issue in OAI eNB or EPC which are not able to process SRB2 message multiplexed with SRB1 on the same MAC PDU
+    	  if ((usim_test == 0) && (lcid == DCCH1) && (lcid_rlc_pdu_count == 0) && (num_sdus)) {
+
+    		  // Skip SRB2 multiplex if at least one SRB1 SDU is already multiplexed
+    		  break;
+    	  }
+
+          buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
+
+          rlc_status = mac_rlc_status_ind(module_idP,
+                          UE_mac_inst[module_idP].crnti,
+                          eNB_index,
+                          frameP,
+                          ENB_FLAG_NO,
+                          MBMS_FLAG_NO, // eNB_index
+                                          lcid,
+                                          buflen_remain);
+
+          // Workaround for BO issue in RLC AM ReTx : RLC BO can not be bigger than stored MAC BO
+          if (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] <  rlc_status.bytes_in_buffer) {
+
+        	  LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d\n",
+        	                          module_idP,frameP,subframe,
+									  lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count);
+
+        	  // Skip multiplexing for the LCID
+        	  break;
+          }
+
+          /*
+          AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >=  rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d Frame %d Subrame %d\n",
+                  lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count,frameP,subframe);
+                  */
+
+          if (rlc_status.bytes_in_buffer > 0) {
+
+
+          LOG_D(MAC, "[UE %d] Frame %d : UL-DCCH -> ULSCH, RLC SRB%d has %d bytes to "
+                "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n",
+                module_idP,frameP, lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
+
+
+          sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
+                             UE_mac_inst[module_idP].crnti,
+                             eNB_index,
+                             frameP,
+                             ENB_FLAG_NO,
+                             MBMS_FLAG_NO,
+                                             lcid,
+                                             (char *)&ulsch_buff[sdu_length_total]);
+
+
+            AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n",
+                    lcid,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]);
+
+
+
+          sdu_length_total += sdu_lengths[num_sdus];
+          sdu_lcids[num_sdus] = lcid;
+          LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for SRB%d\n",module_idP,sdu_lengths[num_sdus],lcid);
+          //header_len +=2;
+          // update LCID remain buffer
+          UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] -= sdu_lengths[num_sdus];
+          /* Update BSR : substract transmitted data */
+          if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] >= sdu_lengths[num_sdus]){
+              UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ;
+          }
+          else {
+              LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n",
+                        module_idP,frameP,subframe,
+                        UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
+                        UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],
+                        sdu_lengths[num_sdus],lcid);
+              UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] = 0;
+          }
+
+          //Update the number of LCGID with data as BSR shall reflect status after BSR transmission
+          if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0))
+          {
+              num_lcg_id_with_data --;
+              // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1
+              if ((bsr_len) && (num_lcg_id_with_data == 1))
+              {
+                  bsr_ce_len = sizeof(BSR_SHORT);
+                  bsr_len = bsr_ce_len + bsr_header_len;
+              }
+
+          }
+
+          if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) {
+              //No more remaining TBS after this PDU
+              //exit the function
+              rlc_pdu_header_len_last = 1;
+              is_lcid_processed = TRUE;
+          }
+          else {
+              rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ;
+
+              //Change to 1 byte if it does not fit in the TBS, ie last PDU
+              if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) {
+                  rlc_pdu_header_len_last = 1;
+                  is_lcid_processed = TRUE;
+              }
+          }
+
+          //Update number of SDU
+          num_sdus ++;
+
+          //Update total MAC Header size for RLC PDUs and save last one
+          total_rlc_pdu_header_len += rlc_pdu_header_len_last;
+
+          } //end if (rlc_status.bytes_in_buffer > 0)
+          else {
+              // Switch to next LCID or exit the whole loop
+              is_lcid_processed = TRUE;
+          }
+          lcid_rlc_pdu_count ++;
+   }
+
+    UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
+   }
+}
+
+
+// Now Check for DTCH first
+// TO DO: do it according to Logical Channel Prioritization if at least 2 DTCH
+for (lcid=DTCH; lcid < MAX_NUM_LCID ; lcid++) {
+if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) {
+
+    is_lcid_processed = FALSE;
+    lcid_rlc_pdu_count = 0;
+
+    //Multiplex all available DTCH RLC PDUs considering to multiplex the last PDU each time for maximize the data
+    //Adjust at the end of the loop
+    while ((!is_lcid_processed) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
+
+        buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
+
+        rlc_status = mac_rlc_status_ind(module_idP,
+                        UE_mac_inst[module_idP].crnti,
+                        eNB_index,
+                        frameP,
+                        ENB_FLAG_NO,
+                        MBMS_FLAG_NO, // eNB_index
+                                        lcid,
+                                        buflen_remain);
+
+        // Workaround for BO issue in RLC AM ReTx : RLC BO can not be bigger than stored MAC BO
+        if (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] <  rlc_status.bytes_in_buffer) {
+
+      	  LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d\n",
+      	                          module_idP,frameP,subframe,
+									  lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count);
+
+      	  // Skip multiplexing for the LCID
+      	  break;
+        }
+
+        /*
+        AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >=  rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d Frame %d Subrame %d\n",
+                  lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count,frameP,subframe);
+        */
+
+        if (rlc_status.bytes_in_buffer > 0) {
+
+
+        LOG_D(MAC, "[UE %d] Frame %d : UL-DTCH -> ULSCH, RLC LCID%d has %d bytes to "
+              "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n",
+              module_idP,frameP, lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
+
+
+        sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
+                           UE_mac_inst[module_idP].crnti,
+                           eNB_index,
+                           frameP,
+                           ENB_FLAG_NO,
+                           MBMS_FLAG_NO,
+                                           lcid,
+                                           (char *)&ulsch_buff[sdu_length_total]);
+
+        AssertFatal (sdu_lengths[num_sdus] < MAX_ULSCH_PAYLOAD_BYTES, "LCID=%d RLC PDU size = %d is too big\n",
+                lcid,sdu_lengths[num_sdus]);
+
+
+          AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n",
+                  lcid,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]);
+
+
+
+        sdu_length_total += sdu_lengths[num_sdus];
+        sdu_lcids[num_sdus] = lcid;
+        LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LCID%d\n",module_idP,sdu_lengths[num_sdus],lcid);
+        //header_len +=2;
+        // update LCID remain buffer
+        UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] -= sdu_lengths[num_sdus];
+        /* Update BSR : substract transmitted data */
+        if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] >= sdu_lengths[num_sdus]){
+            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ;
+        }
+        else {
+            LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n",
+                      module_idP,frameP,subframe,
+                      UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
+                      UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],
+                      sdu_lengths[num_sdus],lcid);
+            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] = 0;
+        }
+
+        //Update the number of LCGID with data as BSR shall reflect status after BSR transmission
+        if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0))
+        {
+            num_lcg_id_with_data --;
+            // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1
+            if ((bsr_len) && (num_lcg_id_with_data == 1))
+            {
+                bsr_ce_len = sizeof(BSR_SHORT);
+                bsr_len = bsr_ce_len + bsr_header_len;
+            }
+
+        }
+
+        if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) {
+            //No more remaining TBS after this PDU
+            //exit the function
+            rlc_pdu_header_len_last = 1;
+            is_lcid_processed = TRUE;
+        }
+        else {
+            rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ;
+
+            //Change to 1 byte if it does not fit in the TBS, ie last PDU
+            if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) {
+                rlc_pdu_header_len_last = 1;
+                is_lcid_processed = TRUE;
+            }
+        }
+
+        //Update number of SDU
+        num_sdus ++;
+
+        //Update total MAC Header size for RLC PDUs and save last one
+        total_rlc_pdu_header_len += rlc_pdu_header_len_last;
+
+        } //end if (rlc_status.bytes_in_buffer > 0)
+        else {
+            // Switch to next LCID or exit the whole loop
+            is_lcid_processed = TRUE;
+        }
+        lcid_rlc_pdu_count ++;
+ }
+
+  UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
+ }
+}
+
+  //lcgid= get_bsr_lcgid(module_idP);
+
+  // Compute BSR Values and update Nb LCGID with data after multiplexing
+  num_lcg_id_with_data = 0;
+  lcg_id_bsr_trunc = 0;
+  for (lcg_id=0;lcg_id<MAX_NUM_LCGID;lcg_id++){
+      UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id] = locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]);
+
+      if  (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]){
+          num_lcg_id_with_data ++;
+          lcg_id_bsr_trunc = lcg_id;
+      }
   }
-  
-  lcgid= get_bsr_lcgid(module_idP);
-
-  if (lcgid < 0 ) {
-    bsr_s = NULL;
-    bsr_l = NULL ;
-  } else if ((lcgid ==MAX_NUM_LCGID) && (bsr_ce_len == sizeof(BSR_LONG))) {
-    bsr_s = NULL;
-    bsr_l->Buffer_size0 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0];
-    bsr_l->Buffer_size1 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1];
-    bsr_l->Buffer_size2 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2];
-    bsr_l->Buffer_size3 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3];
-    LOG_D(MAC, "[UE %d] Frame %d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", module_idP,frameP,
-          UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0],
-          UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1],
-          UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2],
-          UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]);
-  } else if (bsr_ce_len == sizeof(BSR_SHORT)) {
-    bsr_l = NULL;
-    bsr_s->LCGID = lcgid;
-    bsr_s->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcgid];
-    LOG_D(MAC,"[UE %d] Frame %d report SHORT BSR with level %d for LCGID %d\n",
-          module_idP, frameP, UE_mac_inst[module_idP].scheduling_info.BSR[lcgid],lcgid);
-  } else {
-    bsr_s = NULL;
-    bsr_l = NULL;
+
+
+  if (bsr_ce_len) {
+      //Print updated BSR when sent
+      LOG_D(MAC,"[UE %d] Remaining Buffer after Tx frame%d subframe %d nb LCG =%d Bytes for LCG0=%d LCG1=%d LCG2=%d LCG3=%d BSR Trigger status =%d TBS=%d\n",
+                            module_idP,
+                            frameP,
+                            subframe,
+                            num_lcg_id_with_data,
+                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[0],
+                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[1],
+                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[2],
+                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[3],
+                            UE_mac_inst[module_idP].BSR_reporting_active, buflen);
+
+      LOG_D(MAC,"[UE %d] Frame %d Subframe %d TX BSR Regular or Periodic size=%d BSR0=%d BSR1=%d BSR2=%d BSR3=%d\n",module_idP,frameP,subframe,bsr_ce_len,
+              UE_mac_inst[module_idP].scheduling_info.BSR[0],
+              UE_mac_inst[module_idP].scheduling_info.BSR[1],
+              UE_mac_inst[module_idP].scheduling_info.BSR[2],
+              UE_mac_inst[module_idP].scheduling_info.BSR[3]);
   }
 
+
   // 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);
@@ -1458,37 +1714,146 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
 
   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);
 
-  if (dtch_header_len == 0 )
-    dtch_header_len_last =0;
-
-  // adjust the header length
-  dcch_header_len_tmp = dcch_header_len;
-  dtch_header_len_tmp = dtch_header_len;
 
-  if (dtch_header_len==0) {
-    dcch_header_len = (dcch_header_len>0)? 1: dcch_header_len;
-  } else {
-    dtch_header_len_last-=1; 
-    dtch_header_len= (dtch_header_len >0)? dtch_header_len - dtch_header_len_last : dtch_header_len;   
-  }
-
-  if ((buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total) <= 2) {
-    short_padding = buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total;
+  // 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:
+     -	if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller than the size of the Long BSR plus its subheader:
+         -	if more than one LCG has data available for transmission in the TTI where the BSR is transmitted: report Truncated BSR of the LCG with the highest priority logical channel with data available for transmission;
+         -	else report Short BSR.
+     -	else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR.
+   */
+  if (sdu_length_total) {
+      padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - rlc_pdu_header_len_last + sdu_length_total + 1);
+  }
+  else {
+      padding_len = buflen - (bsr_len + phr_len);
+  }
+
+
+   if ((padding_len) && (bsr_len == 0))
+   {
+	   /* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR*/
+     if (padding_len >= (1+BSR_LONG_SIZE))
+     {
+    	 bsr_ce_len = BSR_LONG_SIZE;
+    	 bsr_header_len = 1;
+         // Trigger BSR Padding
+       UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PADDING;
+
+
+     } else if (padding_len >= (1+sizeof(BSR_SHORT))) {
+    	 bsr_ce_len = sizeof(BSR_SHORT);
+    	 bsr_header_len = 1;
+
+    	 if (num_lcg_id_with_data > 1)
+    	 {
+    	  // REPORT TRUNCATED BSR
+       	  //Get LCGID of highest priority LCID with data
+    		 for (lcid=DCCH; lcid < MAX_NUM_LCID ; lcid++) {
+    			 if (UE_mac_inst[module_idP].logicalChannelConfig[lcid] != NULL) {
+        			 lcg_id = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid];
+
+        			 if ((lcg_id < MAX_NUM_LCGID) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id])
+        					 && (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority)) {
+        				 highest_priority = UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority;
+        				 lcg_id_bsr_trunc = lcg_id;
+        			 }
+    			 }
+    		 }
+    	 }
+    	 else
+    	 {
+    		 //Report SHORT BSR, clear bsr_t
+    		 bsr_t = NULL;
+    	 }
+
+       // Trigger BSR Padding
+       UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PADDING;
+     }
+ 	 bsr_len = bsr_header_len + bsr_ce_len;
+   }
+
+   //Fill BSR Infos
+   if (bsr_ce_len == 0 ) {
+     bsr_s = NULL;
+     bsr_l = NULL;
+     bsr_t = NULL;
+   } else if (bsr_ce_len == BSR_LONG_SIZE) {
+     bsr_s = NULL;
+     bsr_t = NULL;
+     bsr_l->Buffer_size0 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0];
+     bsr_l->Buffer_size1 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1];
+     bsr_l->Buffer_size2 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2];
+     bsr_l->Buffer_size3 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3];
+
+     LOG_D(MAC, "[UE %d] Frame %d subframe %d BSR Trig=%d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", module_idP,frameP,subframe,
+    	   UE_mac_inst[module_idP].BSR_reporting_active,
+           UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0],
+           UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1],
+           UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2],
+           UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]);
+
+   } else if (bsr_ce_len == sizeof(BSR_SHORT)) {
+     bsr_l = NULL;
+     if ((bsr_t != NULL) && (UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_PADDING)) {
+    	 //Truncated BSR
+    	 bsr_s = NULL;
+    	 bsr_t->LCGID = lcg_id_bsr_trunc;
+    	 bsr_t->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc];
+
+         LOG_D(MAC,"[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n",
+               module_idP, frameP, subframe, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc);
+
+     }
+     else
+     {
+    	 bsr_t = NULL;
+         bsr_s->LCGID = lcg_id_bsr_trunc;
+         bsr_s->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc];
+
+         LOG_D(MAC,"[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n",
+               module_idP, frameP, subframe, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc);
+     }
+   }
+
+// 1-bit padding or 2-bit padding  special padding subheader
+// Check for max padding size, ie MAC Hdr for last RLC PDU = 1
+   if (sdu_length_total) {
+       padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - rlc_pdu_header_len_last + sdu_length_total + 1);
+   }
+   else {
+       padding_len = buflen - (bsr_len + phr_len);
+   }
+
+  if (padding_len <= 2) {
+    short_padding = padding_len;
+    // only add padding header
     post_padding = 0;
-  } else {
-    if ((buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total) == buflen) {
+    //update total MAC Hdr size for RLC data
+    if (sdu_length_total) {
+        total_rlc_pdu_header_len = total_rlc_pdu_header_len - rlc_pdu_header_len_last + 1;
+        rlc_pdu_header_len_last = 1;
+   }
+  }
+  else if (sdu_length_total) {
+      post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
+      // If by adding MAC Hdr for last RLC PDU the padding is 0 then set MAC Hdr for last RLC PDU = 1 and compute 1 or 2 byte padding
+      if (post_padding == 0) {
+          total_rlc_pdu_header_len -= rlc_pdu_header_len_last;
+          padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
+          short_padding = padding_len;
+          total_rlc_pdu_header_len ++;
+      }
+  }
+  else {
+    if (padding_len == buflen) {// nona mac pdu
       *access_mode=CANCELED_ACCESS;
     }
 
     short_padding = 0;
 
-    if (dtch_header_len==0) {
-      dcch_header_len = dcch_header_len_tmp;
-    } else {
-      dtch_header_len= dtch_header_len_tmp;
-    }
-
-    post_padding = buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total -1 ;
+    post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
   }
 
   // Generate header
@@ -1501,33 +1866,64 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
                                          sdu_lcids,    // sdu lcid
                                          phr_p,  // power headroom
                                          NULL,  // crnti
-                                         NULL,  // truncated bsr
+                                         bsr_t,  // truncated bsr
                                          bsr_s, // short bsr
                                          bsr_l,
                                          post_padding); // long_bsr
 
   LOG_D(MAC,
-        "[UE %d] Generate header :bufflen %d  sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,  dcch_header_len %d, dtch_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n",
-        module_idP,buflen, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],payload_offset, dcch_header_len,  dtch_header_len,
+        "[UE %d] Generate header :bufflen %d  sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,  total_rlc_pdu_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n",
+        module_idP,buflen, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],payload_offset, total_rlc_pdu_header_len,
         short_padding,post_padding, bsr_len, phr_len,buflen-sdu_length_total-payload_offset);
   // cycle through SDUs and place in ulsch_buffer
-  memcpy(&ulsch_buffer[payload_offset],ulsch_buff,sdu_length_total);
+  if (sdu_length_total) {
+      memcpy(&ulsch_buffer[payload_offset],ulsch_buff,sdu_length_total);
+  }
 
   // fill remainder of DLSCH with random data
-  for (j=0; j<(buflen-sdu_length_total-payload_offset); j++) {
-    ulsch_buffer[payload_offset+sdu_length_total+j] = (char)(taus()&0xff);
+  if (post_padding) {
+      for (j=0; j<(buflen-sdu_length_total-payload_offset); j++) {
+        ulsch_buffer[payload_offset+sdu_length_total+j] = (char)(taus()&0xff);
+      }
   }
   LOG_D(MAC,"[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n",
         module_idP,payload_offset, sdu_length_total);
   UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
   UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
+
+  /* Actions when a BSR is sent */
+  if (bsr_ce_len)
+  {
+      LOG_D(MAC,"[UE %d] MAC BSR Sent !! bsr (ce%d,hdr%d) buff_len %d\n",
+              module_idP, bsr_ce_len, bsr_header_len, buflen);
+
+	  // Reset ReTx BSR Timer
+	  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
+
+	  LOG_D(MAC,"[UE %d] MAC ReTx BSR Timer Reset =%d\n",
+			  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF);
+
+	  // Reset Periodic Timer except when BSR is truncated
+	  if ((bsr_t == NULL) && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity))
+	  {
+		  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer);
+
+		  LOG_D(MAC,"[UE %d] MAC Periodic BSR Timer Reset =%d\n",
+				  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF);
+
+	  }
+
+	  // Reset BSR Trigger flags
+	  UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
+  }
+
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT);
   stop_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu);
   
   if (opt_enabled) {
-    trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].subframe, 0, 0);
+    trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0);
     LOG_D(OPT,"[UE %d][ULSCH] Frame %d trace pdu for rnti %x  with size %d\n",
-          module_idP, UE_mac_inst[module_idP].subframe, UE_mac_inst[module_idP].crnti, buflen);
+          module_idP, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, UE_mac_inst[module_idP].crnti, buflen);
   }
 }
 
@@ -1542,14 +1938,15 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
 UE_L2_STATE_t
 ue_scheduler(
   const module_id_t    module_idP,
-  const frame_t        frameP,
-  const sub_frame_t    subframeP,
+  const frame_t        rxFrameP,
+  const sub_frame_t    rxSubframeP,
+  const frame_t        txFrameP,
+  const sub_frame_t    txSubframeP,
   const lte_subframe_t directionP,
   const uint8_t        eNB_indexP,
   const int            CC_id)
 //------------------------------------------------------------------------------
 {
-
   int lcid; // lcid index
   int TTI= 1;
   int bucketsizeduration = -1;
@@ -1558,6 +1955,7 @@ ue_scheduler(
   // int8_t lcg_id;
   struct RACH_ConfigCommon *rach_ConfigCommon = (struct RACH_ConfigCommon *)NULL;
   protocol_ctxt_t   ctxt;
+
 #if defined(ENABLE_ITTI)
   MessageDef   *msg_p;
   const char   *msg_name;
@@ -1567,7 +1965,7 @@ ue_scheduler(
   start_meas(&UE_mac_inst[module_idP].ue_scheduler);
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_IN);
 
-  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_NO, UE_mac_inst[module_idP].crnti, frameP, subframeP,eNB_indexP);
+  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_NO, UE_mac_inst[module_idP].crnti, txFrameP, txSubframeP,eNB_indexP);
 #if defined(ENABLE_ITTI)
 
   do {
@@ -1606,11 +2004,13 @@ ue_scheduler(
   //LG#ifdef EXMIMO
   pdcp_run(&ctxt);
   //#endif
-  UE_mac_inst[module_idP].frame = frameP;
-  UE_mac_inst[module_idP].subframe = subframeP;
+  UE_mac_inst[module_idP].txFrame    = txFrameP;
+  UE_mac_inst[module_idP].txSubframe = txSubframeP;
+  UE_mac_inst[module_idP].rxFrame    = rxFrameP;
+  UE_mac_inst[module_idP].rxSubframe = rxSubframeP;
 
 #ifdef CELLULAR
-  rrc_rx_tx(module_idP, frameP, 0, eNB_indexP);
+  rrc_rx_tx(module_idP, txFrameP, 0, eNB_indexP);
 #else
 
   switch (rrc_rx_tx(&ctxt,
@@ -1664,7 +2064,7 @@ ue_scheduler(
       //return(RRC_OK);
     }
 
-    LOG_I(MAC,"Frame %d: Contention resolution timer %d/%d\n",frameP,UE_mac_inst[module_idP].RA_contention_resolution_cnt,
+    LOG_I(MAC,"Frame %d: Contention resolution timer %d/%d\n",txFrameP,UE_mac_inst[module_idP].RA_contention_resolution_cnt,
           ((1+rach_ConfigCommon->ra_SupervisionInfo.mac_ContentionResolutionTimer)<<3));
 
     UE_mac_inst[module_idP].RA_contention_resolution_cnt++;
@@ -1680,13 +2080,9 @@ ue_scheduler(
   }
 
 
-  // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp.  This should implement the procedures
-  // outlined in Sections 5.4.4 an 5.4.5 of 36.321
-  // Put this in another function
-
   // Get RLC status info and update Bj for all lcids that are active
-  for (lcid=DCCH; lcid <= DTCH; lcid++ ) {
-    if ((lcid == 0) ||(UE_mac_inst[module_idP].logicalChannelConfig[lcid])) {
+  for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++ ) {
+    if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]) {
       // meausre the Bj
       if ((directionP == SF_UL)&& (UE_mac_inst[module_idP].scheduling_info.Bj[lcid] >= 0)) {
         if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters) {
@@ -1704,14 +2100,41 @@ ue_scheduler(
         }
       }
 
-      if (update_bsr(module_idP,frameP, eNB_indexP, lcid, UE_mac_inst[module_idP].scheduling_info.LCGID[lcid])) {
-        UE_mac_inst[module_idP].scheduling_info.SR_pending= 1;
-        LOG_D(MAC,"[UE %d][SR] Frame %d subframe %d SR for PUSCH is pending for LCGID %d with BSR level %d (%d bytes in RLC)\n",
-              module_idP, frameP,subframeP,UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],
-              UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
-              UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
+
+      /*
+      if (lcid == DCCH) {    
+        LOG_D(MAC,"[UE %d][SR] Frame %d subframe %d Pending data for SRB1=%d for LCGID %d \n",                  
+        module_idP, frameP,subframeP,UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],                  
+//         UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]);
       }
+      */
+    }
+  }
+
+  // Call BSR procedure as described in Section 5.4.5 in 36.321
+
+  // First check ReTxBSR Timer because it is always configured
+  // Decrement ReTxBSR Timer if it is running and not null
+  if ((UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING)
+          && (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != 0)){
+      UE_mac_inst[module_idP].scheduling_info.retxBSR_SF --;
+  }
+
+  // Decrement Periodic Timer if it is running and not null
+  if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING)
+            && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != 0)){
+        UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF--;
     }
+
+  //Check whether Regular BSR is triggered
+  if (update_bsr(module_idP,txFrameP, txSubframeP,eNB_indexP) == TRUE) {
+  // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp.  This should implement the procedures
+  // outlined in Sections 5.4.4 an 5.4.5 of 36.321
+    UE_mac_inst[module_idP].scheduling_info.SR_pending= 1;
+    // Regular BSR trigger
+    UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_REGULAR;
+    LOG_D(MAC,"[UE %d][BSR] Regular BSR Triggered Frame %d subframe %d SR for PUSCH is pending\n",
+          module_idP, txFrameP,txSubframeP);
   }
 
   // UE has no valid phy config dedicated ||  no valid/released  SR
@@ -1926,103 +2349,147 @@ int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8
 }
 #endif
 
-int get_bsr_lcgid (module_id_t module_idP)
-{
-  int lcgid, lcgid_tmp=-1;
-  int num_active_lcgid = 0;
-
-  for (lcgid = 0 ; lcgid < MAX_NUM_LCGID; lcgid++) {
-    if (UE_mac_inst[module_idP].scheduling_info.BSR[lcgid] > 0 ) {
-      lcgid_tmp = lcgid;
-      num_active_lcgid+=1;
-    }
-  }
-
-  if (num_active_lcgid == 0) {
-    return -1;
-  } else if (num_active_lcgid == 1) {
-    return lcgid_tmp;
-  } else {
-    return MAX_NUM_LCGID;
-  }
-}
 
-uint8_t get_bsr_len (module_id_t module_idP, uint16_t buflen)
-{
-
-  int lcgid=0;
-  uint8_t bsr_len=0,  num_lcgid=0;
-  int pdu = 0;
-
-
-  for (lcgid=0; lcgid < MAX_NUM_LCGID; lcgid++ ) {
-    if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] > 0 ) {
-      pdu += (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] +  bsr_len + 2); //2 = sizeof(SCH_SUBHEADER_SHORT)
-    }
-
-    if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] > 128 ) { // long header size: adjust the header size
-      pdu += 1;
-    }
-
-    // current phy buff can not transport all sdu for this lcgid -> transmit a bsr for this lcgid
-
-    if ( (pdu > buflen) &&  (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] > 0 ) ) {
-      num_lcgid +=1;
-      bsr_len = (num_lcgid >= 2 ) ? sizeof(BSR_LONG) :  sizeof(BSR_SHORT) ;
-    }
-
-    LOG_D(MAC,"BSR Bytes %d for lcgid %d bsr len %d num lcgid %d\n", UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid], lcgid, bsr_len, num_lcgid);
-  }
-
-  if ( bsr_len > 0 )
-    LOG_D(MAC,"[UE %d] Prepare a %s (Transport Block Size %d, MAC pdu Size %d) \n",
-          module_idP, map_int_to_str(BSR_names, bsr_len), buflen, pdu);
-
-  return bsr_len;
-}
-
-
-boolean_t  update_bsr(module_id_t module_idP, frame_t frameP, eNB_index_t eNB_index, uint8_t lcid, uint8_t lcg_id)
+boolean_t  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 sr_pending = FALSE;
-
-
-  if ((lcg_id < 0) || (lcg_id >= MAX_NUM_LCGID) ) {
-    return sr_pending;
-  }
-
-  // fixme: need a better way to reset
-  if ((lcid == DCCH) || (lcid == DTCH)) {
-    UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id]=0;
-    UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]=0;
-  }
-
-  //  for (lcid =0 ; lcid < MAX_NUM_LCID; lcid++) {
-  if (UE_mac_inst[module_idP].scheduling_info.LCGID[lcid] == lcg_id) {
-    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
-                                    lcid,
-                                    0);
-
-    if (rlc_status.bytes_in_buffer > 0 ) {
-      sr_pending = TRUE;
-      UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_NOT_EMPTY;
-      UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id] += locate (BSR_TABLE,BSR_TABLE_SIZE, rlc_status.bytes_in_buffer);
-      UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id] += rlc_status.bytes_in_buffer;
-      // UE_mac_inst[module_idP].scheduling_info.BSR_short_lcid = lcid; // only applicable to short bsr
-      LOG_D(MAC,"[UE %d] BSR level %d (LCGID %d, rlc buffer %d byte)\n",
-            module_idP, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id],lcg_id,  UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]);
-    } else {
-      UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid]=LCID_EMPTY;
-    }
-  }
-
-  //}
-  return sr_pending;
+  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,ENB_FLAG_NO,MBMS_FLAG_NO,
+		                                    lcid,
+		                                    0);
+
+		    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));
+		         }
+		    }
+	  }
+
+  }
+
+  // Check whether a regular BSR can be triggered according to the first cases in 36.321
+  if (num_lcid_with_data)
+  {
+          LOG_D(MAC,"[UE %d] PDCCH Tick at frame %d subframe %d: NumLCID with data=%d Reordered LCID0=%d LCID1=%d LCID2=%d\n",
+                            module_idP, frameP, subframeP,num_lcid_with_data,lcid_reordered_array[0],lcid_reordered_array[1],lcid_reordered_array[2]);
+
+	  for (array_index=0; array_index < num_lcid_with_data; array_index++)
+	  {
+		  lcid = lcid_reordered_array[array_index];
+	      /* UL data, for a logical channel which belongs to a LCG, becomes available for transmission in the RLC entity
+	         either the data belongs to a logical channel with higher priority than the priorities of the logical channels
+	         which belong to any LCG and for which data is already available for transmission
+	      */
+		  if ((UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] == 0)
+			/* or there is no data available for any of the logical channels which belong to a LCG */
+			||(lcgid_buffer_remain[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0)
+			)
+		  {
+			  bsr_regular_triggered = TRUE;
+
+		      LOG_D(MAC,"[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d subframe %d\n",
+		                      module_idP, lcid,UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],frameP, subframeP);
+
+			  break;
+		  }
+	  }
+
+	  // Trigger Regular BSR if ReTxBSR Timer has expired and UE has data for transmission
+	  if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF == 0)
+	  {
+		  bsr_regular_triggered = TRUE;
+
+		  if ((UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_REGULAR) == 0) {
+		        LOG_I(MAC,"[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d subframe %d\n",
+		                          module_idP, frameP, subframeP);
+		  }
+
+	  }
+  }
+
+  //Store Buffer Occupancy in remain buffers for next TTI
+  for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++)
+  {
+	  UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = lcid_bytes_in_buffer[lcid];
+  }
+
+  return bsr_regular_triggered;
 }
 
-uint8_t locate (const uint32_t *table, int size, int value)
+uint8_t locate_BsrIndexByBufferSize (const uint32_t *table, int size, int value)
 {
 
   uint8_t ju, jm, jl;
@@ -2121,7 +2588,7 @@ int get_sf_periodicBSRTimer(uint8_t sf_offset)
 
   case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity:
   default:
-    return -1;
+    return 0xFFFF;
     break;
   }
 }
diff --git a/openair2/LAYER2/MAC/vars.h b/openair2/LAYER2/MAC/vars.h
index 83d159f910a8521e7ebcf1a73692dbeddcd5d670..236439c6e5b732fff57292c5f3e71326974c0ed8 100644
--- a/openair2/LAYER2/MAC/vars.h
+++ b/openair2/LAYER2/MAC/vars.h
@@ -45,6 +45,15 @@ const uint32_t BSR_TABLE[BSR_TABLE_SIZE]= {0,10,12,14,17,19,22,26,31,36,42,49,57
                                            1326,1552,1817,2127,2490,2915,3413,3995,4677,5467,6411,7505,8787,10287,12043,14099,
                                            16507,19325,22624,26487,31009,36304,42502,49759,58255,68201,79846,93479,109439, 128125,150000, 300000
                                           };
+// extended bsr table--currently not used										  
+const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE] = {0,10,13,16,19,23,29,35,43,53,65,80,98,120,147,
+                                                     181,223,274,337,414,509,625,769,945,1162,1429,
+                                                     1757,2161,2657,3267,4017,4940,6074,7469,9185,
+                                                     11294,13888,17077,20999,25822,31752,39045,48012,
+                                                     59039,72598,89272,109774,134986,165989,204111,
+                                                     250990,308634,379519,466683,573866,705666,867737,
+                                                     1067031,1312097,1613447,1984009,2439678,3000000,
+                                                     6000000};
 
 //uint32_t EBSR_Level[63]={0,10,13,16,19,23,29,35,43,53,65,80,98,120,147,181};
 
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index fe85c81de02d93028a1e8f03dce2ce21d6004b50..2ff2d90de96660627be67b0c79711cfc5e4635bf 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -1057,6 +1057,7 @@ rrc_pdcp_config_asn1_req (
 #ifdef Rel10
   ,PMCH_InfoList_r9_t*  const pmch_InfoList_r9_pP
 #endif
+  ,rb_id_t                 *const defaultDRB 
 )
 //-----------------------------------------------------------------------------
 {
@@ -1078,6 +1079,8 @@ rrc_pdcp_config_asn1_req (
 
   hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
   hashtable_rc_t  h_rc;
+  hash_key_t      key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE;
+  hashtable_rc_t  h_defaultDRB_rc;
 #ifdef Rel10
   int i,j;
   MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
@@ -1098,7 +1101,7 @@ rrc_pdcp_config_asn1_req (
       srb_id = srb2add_list_pP->list.array[cnt]->srb_Identity;
       srb_toaddmod_p = srb2add_list_pP->list.array[cnt];
       rlc_type = RLC_MODE_AM;
-      lc_id = srb_id;// + 2;
+      lc_id = srb_id;
       key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_YES);
       h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
 
@@ -1194,8 +1197,19 @@ rrc_pdcp_config_asn1_req (
       drb_toaddmod_p = drb2add_list_pP->list.array[cnt];
 
       drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
+      if (drb_toaddmod_p->logicalChannelIdentity) {
+        lc_id = *(drb_toaddmod_p->logicalChannelIdentity);
+      } else {
+        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" logicalChannelIdentity is missing in DRB-ToAddMod information element!\n",
+              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
+        continue;
+      }
+
+      if (lc_id == 1 || lc_id == 2) {
+        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %d is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
+        continue;
+      }
 
-      lc_id = drb_id + 2;
       DevCheck4(drb_id < maxDRB, drb_id, maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
       key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO);
       h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
@@ -1211,7 +1225,21 @@ rrc_pdcp_config_asn1_req (
         pdcp_p = calloc(1, sizeof(pdcp_t));
         h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
 
-        if (h_rc != HASH_TABLE_OK) {
+        // save the first configured DRB-ID as the default DRB-ID
+        if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
+          key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
+          h_defaultDRB_rc = hashtable_insert(pdcp_coll_p, key_defaultDRB, pdcp_p);
+        } else {
+          h_defaultDRB_rc = HASH_TABLE_OK; // do not trigger any error handling if this is not a default DRB
+        }
+
+        if (h_defaultDRB_rc != HASH_TABLE_OK) {
+          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD default DRB key 0x%"PRIx64" FAILED\n",
+                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
+                key_defaultDRB);
+          free(pdcp_p);
+          return TRUE;
+        } else if (h_rc != HASH_TABLE_OK) {
           LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD key 0x%"PRIx64" FAILED\n",
                 PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                 key);
@@ -1305,7 +1333,6 @@ rrc_pdcp_config_asn1_req (
     for (cnt=0; cnt<drb2release_list_pP->list.count; cnt++) {
       pdrb_id_p = drb2release_list_pP->list.array[cnt];
       drb_id =  *pdrb_id_p;
-      lc_id = drb_id + 2;
       key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_NO);
       h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
 
@@ -1315,6 +1342,7 @@ rrc_pdcp_config_asn1_req (
               drb_id);
         continue;
       }
+      lc_id = pdcp_p->lcid;
 
       action = CONFIG_ACTION_REMOVE;
       pdcp_config_req_asn1 (
@@ -1334,6 +1362,20 @@ rrc_pdcp_config_asn1_req (
         kRRCint_pP,
         kUPenc_pP);
       h_rc = hashtable_remove(pdcp_coll_p, key);
+
+      if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
+        // default DRB being removed. nevertheless this shouldn't happen as removing default DRB is not allowed in standard
+        key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
+        h_defaultDRB_rc = hashtable_get(pdcp_coll_p, key_defaultDRB, (void**)&pdcp_p);
+
+        if (h_defaultDRB_rc == HASH_TABLE_OK) {
+          h_defaultDRB_rc = hashtable_remove(pdcp_coll_p, key_defaultDRB);
+        } else {
+          LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED default DRB\n", PROTOCOL_CTXT_ARGS(ctxt_pP));
+        }
+      } else {
+        key_defaultDRB = HASH_TABLE_OK; // do not trigger any error handling if this is not a default DRB
+      }
     }
   }
 
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
index 5bff425abebf488d8926815a81e753f9649202cb..366f79dc9db9a7bf2ca68aa5907781c642c939f6 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
@@ -271,6 +271,7 @@ public_pdcp(void rrc_pdcp_config_req (
 * \param[in]  kRRCenc           RRC encryption key
 * \param[in]  kRRCint           RRC integrity key
 * \param[in]  kUPenc            User-Plane encryption key
+* \param[in]  defaultDRB        Default DRB ID
 * \return     A status about the processing, OK or error code.
 */
 public_pdcp(
@@ -286,6 +287,7 @@ public_pdcp(
 #ifdef Rel10
     ,PMCH_InfoList_r9_t  *pmch_InfoList_r9
 #endif
+    ,rb_id_t                 *const defaultDRB 
   ));
 
 /*! \fn boolean_t pdcp_config_req_asn1 (const protocol_ctxt_t* const ctxt_pP, srb_flag_t srb_flagP, uint32_t  action, rb_id_t rb_id, uint8_t rb_sn, uint8_t rb_report, uint16_t header_compression_profile, uint8_t security_mode)
@@ -459,12 +461,25 @@ protected_pdcp(unsigned char          pdcp_input_sdu_buffer[MAX_IP_PACKET_SIZE];
 protected_pdcp(sdu_size_t             pdcp_input_index_header;)
 protected_pdcp(sdu_size_t             pdcp_input_sdu_size_read;)
 protected_pdcp(sdu_size_t             pdcp_input_sdu_remaining_size_to_read;)
+
 #define PDCP_COLL_KEY_VALUE(mODULE_iD, rNTI, iS_eNB, rB_iD, iS_sRB) \
    ((hash_key_t)mODULE_iD          | \
     (((hash_key_t)(rNTI))   << 8)  | \
     (((hash_key_t)(iS_eNB)) << 24) | \
     (((hash_key_t)(rB_iD))  << 25) | \
-    (((hash_key_t)(iS_sRB)) << 33))
+    (((hash_key_t)(iS_sRB)) << 33) | \
+    (((hash_key_t)(0x55))   << 34))
+
+// hash key to the same PDCP as indexed by PDCP_COLL_KEY_VALUE(... rB_iD, iS_sRB=0) where rB_iD
+// is the default DRB ID. The hidden code 0x55 indicates the key is indexed by (rB_iD,is_sRB)
+// whereas the hidden code 0xaa indicates the key is for default DRB only
+#define PDCP_COLL_KEY_DEFAULT_DRB_VALUE(mODULE_iD, rNTI, iS_eNB) \
+    ((hash_key_t)mODULE_iD          | \
+     (((hash_key_t)(rNTI))   << 8)  | \
+     (((hash_key_t)(iS_eNB)) << 24) | \
+     (((hash_key_t)(0xff))   << 25) | \
+     (((hash_key_t)(0x00))   << 33) | \
+     (((hash_key_t)(0xaa))   << 34))
 
 // service id max val is maxServiceCount = 16 (asn1_constants.h)
 
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
index 8f5d0635f04a01f8dac27d86190a4f74d4b3ba3b..eb78a4ca7c493c9e354fc174b41005d464d8ae3a 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
@@ -67,6 +67,7 @@ extern int otg_enabled;
 #ifdef PDCP_USE_NETLINK
 #include <sys/socket.h>
 #include <linux/netlink.h>
+#include "NETWORK_DRIVER/UE_IP/constant.h"
 
 extern char nl_rx_buf[NL_MAX_PAYLOAD];
 extern struct sockaddr_nl nas_src_addr, nas_dest_addr;
@@ -186,7 +187,7 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const  ctxt_pP)
           ret = sendmsg(nas_sock_fd,&nas_msg_tx,0);
 
           if (ret<0) {
-            LOG_D(PDCP, "[PDCP_FIFOS] sendmsg returns %d (errno: %d)\n", ret, errno);
+            LOG_E(PDCP, "[PDCP_FIFOS] sendmsg returns %d (errno: %d)\n", ret, errno);
       	    MSC_LOG_TX_MESSAGE_FAILED(
       	      (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
       	      (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
@@ -423,18 +424,22 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
   return 0;
 # else /* PDCP_USE_NETLINK_QUEUES*/
   int              len = 1;
+  int  msg_len;
   rb_id_t          rab_id  = 0;
-
-  while (len > 0) {
+  int rlc_data_req_flag = 3;
+ 
+  while ((len > 0) && (rlc_data_req_flag !=0))  {
     len = recvmsg(nas_sock_fd, &nas_msg_rx, 0);
 
     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, len);
-           nas_nlh_rx = NLMSG_NEXT (nas_nlh_rx, len)) {
+           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");
@@ -491,6 +496,10 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
           ctxt.frame         = ctxt_cpy.frame;
           ctxt.enb_flag      = ctxt_cpy.enb_flag;
 
+#ifdef PDCP_DEBUG
+          LOG_I(PDCP, "[PDCP][NETLINK] pdcp_read_header_g.rb_id = %d\n", pdcp_read_header_g.rb_id);
+#endif
+
           if (ctxt_cpy.enb_flag) {
             ctxt.module_id = 0;
             rab_id      = pdcp_read_header_g.rb_id % maxDRB;
@@ -586,11 +595,21 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
             }
           } else { // 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 (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;
 #ifdef PDCP_DEBUG
                 LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n",
                       ctxt.frame,
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
index 2ff1a6c4b689a44fd8d441225212b473a1ef9011..ded7dc078393adc116d0c0e1ddf5861da94872b9 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
@@ -53,6 +53,7 @@ rlc_am_get_buffer_occupancy_in_bytes (
   uint32_t header_overhead;
 
   // priority of control trafic
+  rlc_pP->status_buffer_occupancy = 0;
   if (rlc_pP->status_requested) {
     if (rlc_pP->t_status_prohibit.running == 0) {
 #if TRACE_RLC_AM_BO
@@ -64,7 +65,7 @@ rlc_am_get_buffer_occupancy_in_bytes (
       }
 
 #endif
-      return ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
+      rlc_pP->status_buffer_occupancy = ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
     }
   }
 
@@ -113,7 +114,8 @@ config_req_rlc_am (
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t             srb_flagP,
   rlc_am_info_t  * const       config_am_pP,
-  const rb_id_t                rb_idP
+  const rb_id_t                rb_idP,
+  const logical_chan_id_t      chan_idP 
 )
 {
   rlc_union_t       *rlc_union_p = NULL;
@@ -135,7 +137,7 @@ config_req_rlc_am (
           config_am_pP->t_reordering,
           config_am_pP->t_status_prohibit);
     rlc_am_init(ctxt_pP, l_rlc_p);
-    rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP);
+    rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
     rlc_am_configure(ctxt_pP, l_rlc_p,
                      config_am_pP->max_retx_threshold,
                      config_am_pP->poll_pdu,
@@ -160,7 +162,8 @@ void config_req_rlc_am_asn1 (
   const protocol_ctxt_t* const         ctxt_pP,
   const srb_flag_t                     srb_flagP,
   const struct RLC_Config__am  * const config_am_pP,
-  const rb_id_t                        rb_idP)
+  const rb_id_t                        rb_idP,
+  const logical_chan_id_t              chan_idP)
 {
   rlc_union_t     *rlc_union_p   = NULL;
   rlc_am_entity_t *l_rlc_p         = NULL;
@@ -201,7 +204,7 @@ void config_req_rlc_am_asn1 (
             t_StatusProhibit_tab[config_am_pP->dl_AM_RLC.t_StatusProhibit]);
 
       rlc_am_init(ctxt_pP, l_rlc_p);
-      rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP);
+      rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
       rlc_am_configure(ctxt_pP, l_rlc_p,
                        maxRetxThreshold_tab[config_am_pP->ul_AM_RLC.maxRetxThreshold],
                        pollPDU_tab[config_am_pP->ul_AM_RLC.pollPDU],
@@ -338,6 +341,7 @@ rlc_am_get_pdus (
         if (pdu) {
           list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
           rlc_pP->status_requested = 0;
+          rlc_pP->status_buffer_occupancy = 0;
           rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP);
           return;
         }
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h
index 5d038dfdbc1ea5eba8f45364f896ecabcbd0052e..61c6a043cc0ba424571e2cba9d662461802563b6 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h
@@ -128,31 +128,35 @@ public_rlc_am(void     rlc_am_release (
 * @{
 */
 
-/*! \fn void config_req_rlc_am (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, rlc_am_info_t * config_amP, rb_id_t rb_idP)
+/*! \fn void config_req_rlc_am (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, rlc_am_info_t * config_amP, rb_id_t rb_idP, logical_chan_id_t chan_idP)
 * \brief    Configure the UL and DL parameters of the RLC AM
 * \param[in]  ctxt_pP                   Running context.
 * \param[in]  srb_flagP                 Flag to indicate signalling radio bearer (1) or data radio bearer (0).
 * \param[in]  config_amP                Configuration parameters for RLC AM instance.
 * \param[in]  rb_idP                    Radio bearer identifier.
+* \param[in]  chan_idP                  Transport channel identifier.
 */
 public_rlc_am(void     config_req_rlc_am (
                 const protocol_ctxt_t* const ctxtP,
                 const srb_flag_t  srb_flagP,
                 const rlc_am_info_t * const config_amP,
-                const rb_id_t      rb_idP);)
+                const rb_id_t      rb_idP,
+                const logical_chan_id_t chan_idP);) 
 
-/*! \fn void config_req_rlc_am_asn1 (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, struct RLC_Config__am * config_amP, rb_id_t rb_idP)
+/*! \fn void config_req_rlc_am_asn1 (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, struct RLC_Config__am * config_amP, rb_id_t rb_idP, logical_chan_id_t chan_idP)
 * \brief    Configure the UL and DL parameters of the RLC AM with the asn1c autogenerated pameters structs
 * \param[in]  ctxt_pP                   Running context.
 * \param[in]  srb_flagP                 Flag to indicate signalling radio bearer (1) or data radio bearer (0).
 * \param[in]  config_amP                Configuration parameters for RLC AM instance.
 * \param[in]  rb_idP                    Radio bearer identifier.
+* \param[in]  chan_idP                  Transport channel identifier.
 */
 public_rlc_am(void config_req_rlc_am_asn1 (
                 const protocol_ctxt_t* const ctxtP,
                 const srb_flag_t srb_flagP,
                 const struct RLC_Config__am * const config_amP,
-                const rb_id_t rb_idP);)
+                const rb_id_t rb_idP,
+                const logical_chan_id_t chan_idP);)
 
 /** @} */
 
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c
index d1c3d68c522855a1d75d7ae7bc9efe12dd404778..a7cf302d06758ee5f41f6631c817960ba8b4759c 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c
@@ -246,10 +246,11 @@ rlc_am_set_debug_infos(
   const protocol_ctxt_t* const  ctxt_pP,
   rlc_am_entity_t *const        rlc_pP,
   const srb_flag_t              srb_flagP,
-  const rb_id_t                 rb_idP)
+  const rb_id_t                 rb_idP,
+  const logical_chan_id_t       chan_idP) 
 {
-
   rlc_pP->rb_id         = rb_idP;
+  rlc_pP->channel_id    = chan_idP;
 
   if (srb_flagP) {
     rlc_pP->is_data_plane = 0;
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h
index 52034b7c773da2601d498ed6f9ef9f69bfaa2703..d088f9f0116430ef137d8307bc815e5671c178ad 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h
@@ -105,13 +105,15 @@ public_rlc_am_init( void rlc_am_configure(const protocol_ctxt_t* const ctxtP,
                     const uint32_t t_reorderingP,
                     const uint32_t t_status_prohibitP);)
 
+
 /*! \fn void rlc_am_set_debug_infos(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP)
 * \brief    Set informations that will be displayed in traces, helping the debug process.
 * \param[in]  ctxtP                     Running context.
 * \param[in]  rlc_pP                    RLC AM protocol instance pointer.
 * \param[in]  srb_flagP                 Flag to indicate signalling radio bearer (1) or data radio bearer (0).
 * \param[in]  rb_idP                    Radio bearer identifier.
+* \param[in]  chan_idP                  Transport channel identifier.
 */
-public_rlc_am_init( void rlc_am_set_debug_infos(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP);)
+public_rlc_am_init( void rlc_am_set_debug_infos(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP, const logical_chan_id_t chan_idP);)
 /** @} */
 #endif
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c
index 4bdb3ca00052cbc3bdf0bf2f9cb6ee5001400a97..d0b023833ad24b7fa9fe877d41b6cf446c7740bf 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c
@@ -413,8 +413,9 @@ rlc_am_receive_process_data_pdu (
           rlc_am_rx_list_reassemble_rlc_sdus(ctxt_pP, rlc_pP);
         }
 
+        //FNA: fix check VrX out of receiving window
         if (rlc_pP->t_reordering.running) {
-          if ((rlc_pP->vr_x == rlc_pP->vr_r) || ((rlc_am_in_rx_window(ctxt_pP, rlc_pP, pdu_info_p->sn) == 0) && (rlc_pP->vr_x != rlc_pP->vr_mr))) {
+          if ((rlc_pP->vr_x == rlc_pP->vr_r) || ((rlc_am_in_rx_window(ctxt_pP, rlc_pP, rlc_pP->vr_x) == 0) && (rlc_pP->vr_x != rlc_pP->vr_mr))) {
             rlc_am_stop_and_reset_timer_reordering(ctxt_pP, rlc_pP);
           }
         }
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c
index 100802e28c68a629712d0c3ce5f24e3590ea7cdc..e03741707e838a4bf74c796d949d29f24d6495b1 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c
@@ -698,8 +698,8 @@ void rlc_am_v9_3_0_test_tx_rx()
 
   rlc_am_init(&g_am_tx, g_frame);
   rlc_am_init(&g_am_rx, g_frame);
-  rlc_am_set_debug_infos(&g_am_tx, g_frame, 0, 0, 0, 1);
-  rlc_am_set_debug_infos(&g_am_rx, g_frame, 1, 1, 1, 1);
+  rlc_am_set_debug_infos(&g_am_tx, g_frame, 0, 0, 0, 1, 1 /* LC-id = DRB-id */);
+  rlc_am_set_debug_infos(&g_am_rx, g_frame, 1, 1, 1, 1, 1 /* LC-id = DRB-id */);
 
   rlc_am_configure(&g_am_tx, g_frame, max_retx_threshold, poll_pdu, poll_byte, t_poll_retransmit, t_reordering, t_status_prohibit);
   rlc_am_configure(&g_am_rx, g_frame, max_retx_threshold, poll_pdu, poll_byte, t_poll_retransmit, t_reordering, t_status_prohibit);
diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c
index 90fc084e845069c60a6b388edab1ab0e8b4e2382..4d75f3ee30cbd24b086d9728715f886945bb35eb 100644
--- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c
+++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c
@@ -29,7 +29,8 @@ void config_req_rlc_tm (
   const protocol_ctxt_t* const  ctxt_pP,
   const srb_flag_t  srb_flagP,
   const rlc_tm_info_t * const config_tmP,
-  const rb_id_t     rb_idP
+  const rb_id_t rb_idP,
+  const logical_chan_id_t chan_idP
 )
 {
   rlc_union_t     *rlc_union_p  = NULL;
@@ -48,7 +49,7 @@ void config_req_rlc_tm (
 
     rlc_tm_init(ctxt_pP, rlc_p);
     rlc_p->protocol_state = RLC_DATA_TRANSFER_READY_STATE;
-    rlc_tm_set_debug_infos(ctxt_pP, rlc_p, rb_idP, srb_flagP);
+    rlc_tm_set_debug_infos(ctxt_pP, rlc_p, srb_flagP, rb_idP, chan_idP);
     rlc_tm_configure(ctxt_pP, rlc_p, config_tmP->is_uplink_downlink);
   } else {
     LOG_E(RLC, PROTOCOL_RLC_TM_CTXT_FMT" CONFIG_REQ RB %u RLC NOT FOUND\n",
@@ -144,9 +145,11 @@ void rlc_tm_set_debug_infos(
   const protocol_ctxt_t* const  ctxt_pP,
   rlc_tm_entity_t * const rlcP,
   const srb_flag_t  srb_flagP,
-  const rb_id_t     rb_idP)
+  const rb_id_t     rb_idP,
+  const logical_chan_id_t chan_idP) 
 {
-  rlcP->rb_id     = rb_idP;
+  rlcP->rb_id      = rb_idP;
+  rlcP->channel_id = chan_idP;
 
   if (srb_flagP) {
     rlcP->is_data_plane = 0;
diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h
index f577db47d7ad86ac586830e77855a5bc0b5742f4..0e400a48adc6172633c6cfc4ec6acd2be5045344 100644
--- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h
+++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h
@@ -73,13 +73,14 @@ typedef volatile struct rlc_tm_info_s {
 * \param[in]  srb_flagP                 Flag to indicate SRB (1) or DRB (0)
 * \param[in]  config_tmP                Configuration parameters for RLC TM instance.
 * \param[in]  rb_idP                    Radio bearer identifier.
-* \param[in]  srb_flagP                 Flag to indicate signalling radio bearer (1) or data radio bearer (0).
+* \param[in]  chan_idP                  Transport channel identifier.
 */
 public_rlc_tm_init(   void config_req_rlc_tm (
                         const protocol_ctxt_t* const  ctxt_pP,
                         const srb_flag_t  srb_flagP,
                         const rlc_tm_info_t * const config_tmP,
-                        const rb_id_t     rb_idP);)
+                        const rb_id_t     rb_idP,
+                        const logical_chan_id_t chan_idP);) 
 
 /*! \fn void rlc_tm_init (const protocol_ctxt_t* const  ctxt_pP, rlc_tm_entity_t * const rlcP)
 * \brief    Initialize a RLC TM 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 TM protocol instance will be in RLC_NULL_STATE state.
@@ -120,11 +121,14 @@ protected_rlc_tm_init(void rlc_tm_configure(
 * \param[in]  rlcP                      RLC TM protocol instance pointer.
 * \param[in]  srb_flagP                 Flag to indicate signalling radio bearer (1) or data radio bearer (0).
 * \param[in]  rb_idP                    Radio bearer identifier.
+* \param[in]  chan_idP                  Transport channel identifier
 */
 protected_rlc_tm_init(void rlc_tm_set_debug_infos(
                         const protocol_ctxt_t* const  ctxt_pP,
                         rlc_tm_entity_t * const       rlcP,
                         const srb_flag_t              srb_flagP,
-                        const rb_id_t                 rb_idP);)
+                        const rb_id_t                 rb_idP,
+                        const logical_chan_id_t chan_idP);)
+
 /** @} */
 #    endif
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
index 3232399d105bd9936862fd7964f53ea3142d7b32..51440d0bfa33bbd6688374173bb5e2d9ad630f28 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
@@ -426,7 +426,7 @@ rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, void *argP, struct mac_data_ind
 
 //-----------------------------------------------------------------------------
 struct mac_status_resp
-rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP)
+rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP)
 {
   struct mac_status_resp status_resp;
   uint16_t  sdu_size = 0;
@@ -434,6 +434,7 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP
   int32_t diff_time=0;
   rlc_um_entity_t   *rlc_p = NULL;
   mem_block_t       *mb_p = NULL;
+  unsigned int       max_li_overhead = 0;
 
   status_resp.buffer_occupancy_in_pdus         = 0;
   status_resp.buffer_occupancy_in_bytes        = 0;
@@ -453,7 +454,20 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP
 
     if ((status_resp.buffer_occupancy_in_bytes > 0) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) {
 
-      status_resp.buffer_occupancy_in_bytes += rlc_p->tx_header_min_length_in_bytes;
+        //Fix on full Header size
+        if (enb_flagP == ENB_FLAG_NO)
+        {
+            // compute Length Indicator overhead to inform MAC of maximum full RLC PDU size according to stored SDUs
+            // For UE scheduler
+            // Could be useful for eNB: to be checked
+            if (rlc_p->input_sdus.nb_elements <= 1) {
+                max_li_overhead = 0;
+            } else {
+                unsigned int       num_li = rlc_p->input_sdus.nb_elements - 1;
+                max_li_overhead = num_li + (num_li >> 1) + (num_li & 1);
+            }
+        }
+      status_resp.buffer_occupancy_in_bytes += (rlc_p->tx_header_min_length_in_bytes + max_li_overhead);
       status_resp.buffer_occupancy_in_pdus = rlc_p->input_sdus.nb_elements;
 
       diff_time =   ctxt_pP->frame - ((struct rlc_um_tx_sdu_management *)mb_p->data)->sdu_creation_time;
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
index d87f1e29d03f18e9fcd8fc0d180059e1bc0dbd1e..5951eaf1490c58f9b62cc4fca0aabeb4875ce163 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
@@ -186,7 +186,7 @@ protected_rlc_um( void     rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, rlc_
 * \param[in]  tx_statusP                Transmission status given by MAC on previous MAC transmission of the PDU.
 * \return     The maximum number of bytes that can be served by RLC instance to MAC.
 */
-public_rlc_um(    struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP);)
+public_rlc_um(    struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP, const eNB_flag_t enb_flagP);)
 
 /*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
 * \brief    Gives PDUs to lower layer MAC.
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 688c8f646dc48d5c741e1346730fb764a4096f19..057be0000d45125d1cb9c454d98df2ae2de92b39 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
@@ -40,7 +40,8 @@ void config_req_rlc_um (
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t      srb_flagP,
   const rlc_um_info_t  * const config_um_pP,
-  const rb_id_t         rb_idP)
+  const rb_id_t           rb_idP,
+  const logical_chan_id_t chan_idP)
 {
   rlc_union_t     *rlc_union_p  = NULL;
   rlc_um_entity_t *rlc_p        = NULL;
@@ -61,7 +62,7 @@ void config_req_rlc_um (
     rlc_um_init(ctxt_pP, rlc_p);
 
     if (rlc_um_fsm_notify_event (ctxt_pP, rlc_p, RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT)) {
-      rlc_um_set_debug_infos(ctxt_pP, rlc_p, srb_flagP, rb_idP);
+      rlc_um_set_debug_infos(ctxt_pP, rlc_p, srb_flagP, rb_idP, chan_idP);
       rlc_um_configure(
         ctxt_pP,
         rlc_p,
@@ -87,7 +88,8 @@ void config_req_rlc_um_asn1 (
   const mbms_service_id_t   mbms_service_idP,
   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 rb_id_t             rb_idP,
+  const logical_chan_id_t   chan_idP)
 {
   uint32_t         ul_sn_FieldLength   = 0;
   uint32_t         dl_sn_FieldLength   = 0;
@@ -135,7 +137,7 @@ void config_req_rlc_um_asn1 (
 
 
   if (rlc_um_fsm_notify_event (ctxt_pP, rlc_p, RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT)) {
-    rlc_um_set_debug_infos(ctxt_pP,rlc_p, srb_flagP, rb_idP);
+    rlc_um_set_debug_infos(ctxt_pP,rlc_p, srb_flagP, rb_idP, chan_idP);
 
     if (ul_rlc_pP != NULL) {
       switch (ul_rlc_pP->sn_FieldLength) {
@@ -416,14 +418,16 @@ void rlc_um_configure(
 void rlc_um_set_debug_infos(
   const protocol_ctxt_t* const ctxt_pP,
   rlc_um_entity_t * const rlc_pP,
-  const srb_flag_t       srb_flagP,
-  const rb_id_t          rb_idP)
+  const srb_flag_t        srb_flagP,
+  const rb_id_t           rb_idP,
+  const logical_chan_id_t chan_idP) 
 {
   LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [SET DEBUG INFOS] rb_id %d srb_flag %d\n",
         PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
         rb_idP,
         srb_flagP);
-  rlc_pP->rb_id         = rb_idP;
+  rlc_pP->rb_id      = rb_idP;
+  rlc_pP->channel_id = chan_idP;
 
   if (srb_flagP) {
     rlc_pP->is_data_plane = 0;
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 97af1cfafa54692d8b02181f8238322d490d3aeb..b6964f9f129f0ad1911fc39891d9a9208e13affd 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
@@ -77,12 +77,14 @@ typedef volatile struct {
 * \param[in]  srb_flagP                 Flag to indicate signalling radio bearer (1) or data radio bearer (0).
 * \param[in]  config_umP                Configuration parameters for RLC UM instance.
 * \param[in]  rb_idP                    Radio bearer identifier.
+* \param[in]  chan_idP                  Transport channel identifier.
 */
 public_rlc_um_control_primitives(   void config_req_rlc_um (
                                       const protocol_ctxt_t* const ctxt_pP,
                                       const srb_flag_t srb_flagP,
                                       const rlc_um_info_t * const config_umP,
-                                      const rb_id_t rb_idP);)
+                                      const rb_id_t rb_idP,
+                                      const logical_chan_id_t chan_idP);) 
 
 /*! \fn void config_req_rlc_um_asn1 (
  *     const protocol_ctxt_t* const ctxt_pP,
@@ -102,6 +104,7 @@ public_rlc_um_control_primitives(   void config_req_rlc_um (
 * \param[in]  ul_rlc_pP                 Configuration parameters for RLC UM UL instance.
 * \param[in]  dl_rlc_pP                 Configuration parameters for RLC UM DL instance.
 * \param[in]  rb_idP                    Radio bearer identifier.
+* \param[in]  chan_idP                  Transport channel identifier.
 */
 public_rlc_um_control_primitives(   void config_req_rlc_um_asn1 (
                                       const protocol_ctxt_t* const ctxt_pP,
@@ -111,7 +114,8 @@ public_rlc_um_control_primitives(   void config_req_rlc_um_asn1 (
                                       const mbms_service_id_t  mbms_service_idP,
                                       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 rb_id_t            rb_idP,
+                                      const logical_chan_id_t  chan_idP);)
 
 /*! \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.
@@ -169,13 +173,15 @@ protected_rlc_um_control_primitives(void rlc_um_configure(
 * \brief    Set debug informations for a RLC UM protocol instance, these informations are only for trace purpose.
 * \param[in]  ctxtP                     Running context.
 * \param[in]  rlc_pP                    RLC UM protocol instance pointer.
-* \param[in]  rb_idP                    Radio bearer identifier.
 * \param[in]  srb_flagP                 Flag to indicate signalling radio bearer (1) or data radio bearer (0).
+* \param[in]  rb_idP                    Radio bearer identifier.
+* \param[in]  chan_idP                  Transport channel identifier.
 */
 protected_rlc_um_control_primitives(void rlc_um_set_debug_infos(
                                       const protocol_ctxt_t* const ctxt_pP,
                                       rlc_um_entity_t * const rlc_pP,
                                       const srb_flag_t srb_flagP,
-                                      const rb_id_t rb_idP);)
+                                      const rb_id_t rb_idP,
+                                      const logical_chan_id_t chan_idP);) 
 /** @} */
 #    endif
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c
index c01e709b415e50f102894f3e7d944cbf2c022f37..92f18e72d7629e228aa4627dc850b3493d7888d5 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c
@@ -188,8 +188,8 @@ void rlc_um_v9_3_0_test_windows_10()
   rlc_um_init(&um1);
   rlc_um_init(&um2);
 
-  rlc_um_set_debug_infos(&um1, g_frame, 0, 0, 0, 1);
-  rlc_um_set_debug_infos(&um2, g_frame, 1, 1, 1, 1);
+  rlc_um_set_debug_infos(&um1, g_frame, 0, 0, 0, 1, 1 /*LC-id = RAB-id*/);
+  rlc_um_set_debug_infos(&um2, g_frame, 1, 1, 1, 1, 1 /*LC-id = RAB-id*/);
 
   rlc_um_configure(&um1, g_frame, timer_reordering, sn_field_length, sn_field_length, is_mXch);
   rlc_um_configure(&um2, g_frame, timer_reordering, sn_field_length, sn_field_length, is_mXch);
@@ -242,8 +242,8 @@ void rlc_um_v9_3_0_test_windows_5()
   rlc_um_init(&um1);
   rlc_um_init(&um2);
 
-  rlc_um_set_debug_infos(&um1, g_frame, 0, 0, 0, 1);
-  rlc_um_set_debug_infos(&um2, g_frame, 1, 1, 1, 1);
+  rlc_um_set_debug_infos(&um1, g_frame, 0, 0, 0, 1, 1 /* LC-id = DRB-id */);
+  rlc_um_set_debug_infos(&um2, g_frame, 1, 1, 1, 1, 1 /* LC-id = DRB-id */);
 
   rlc_um_configure(&um1, g_frame, timer_reordering, sn_field_length, sn_field_length, is_mXch);
   rlc_um_configure(&um2, g_frame, timer_reordering, sn_field_length, sn_field_length, is_mXch);
@@ -471,9 +471,9 @@ void rlc_um_v9_3_0_test_exchange_pdus(rlc_um_entity_t *um_txP,
   memset(&mac_rlc_status_resp_tx, 0, sizeof(struct mac_status_resp));
   memset(&mac_rlc_status_resp_rx, 0, sizeof(struct mac_status_resp));
 
-  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status);
+  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status,ENB_FLAG_YES);
   data_request_tx        = rlc_um_mac_data_request(um_txP, g_frame);
-  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status);
+  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status,ENB_FLAG_YES);
   data_request_rx        = rlc_um_mac_data_request(um_rxP, g_frame);
 
 
@@ -517,9 +517,9 @@ void rlc_um_v9_3_0_test_exchange_delayed_pdus(rlc_um_entity_t *um_txP,
   memset(&mac_rlc_status_resp_tx, 0, sizeof(struct mac_status_resp));
   memset(&mac_rlc_status_resp_rx, 0, sizeof(struct mac_status_resp));
 
-  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status);
+  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status,ENB_FLAG_YES);
   data_request_tx        = rlc_um_mac_data_request(um_txP, g_frame);
-  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status);
+  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status,ENB_FLAG_YES);
   data_request_rx        = rlc_um_mac_data_request(um_rxP, g_frame);
 
 
@@ -614,8 +614,8 @@ void rlc_um_v9_3_0_test_reordering(uint32_t sn_field_lengthP)
   um_info.is_mXch          = 0;
 
   srand (0);
-  config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER);
-  config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER);
+  config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
+  config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
 
   rlc_um_display_rx_window(&um_tx);
 
@@ -736,8 +736,8 @@ void rlc_um_v9_3_0_test_tx_rx_10(void)
   um_info.is_mXch          = 0;
 
   srand (0);
-  config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER);
-  config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER);
+  config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
+  config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
 
   rlc_um_display_rx_window(&um_tx);
 
@@ -1065,8 +1065,8 @@ void rlc_um_v9_3_0_test_tx_rx_5(void)
   um_info.is_mXch          = 0;
 
   srand (0);
-  config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER);
-  config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER);
+  config_req_rlc_um (&um_tx, 0,0,0, &um_info, 0, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
+  config_req_rlc_um (&um_rx, 0,1,1, &um_info, 1, SIGNALLING_RADIO_BEARER, SIGNALLING_RADIO_BEARER /*LC-id = DRB-id*/);
 
   rlc_um_display_rx_window(&um_tx);
 
diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h
index ec5ee629b168ee572aec7b34d94b5c632af5d2cd..3fd5b8c3bcfef9cb0f016b1e8db3b00a17102950 100644
--- a/openair2/LAYER2/RLC/rlc.h
+++ b/openair2/LAYER2/RLC/rlc.h
@@ -262,7 +262,18 @@ public_rlc(logical_chan_id_t    rlc_mbms_rbid2lcid_eNB[NUMBER_OF_eNB_MAX][NB_RB_
     (((hash_key_t)(rNTI))   << 8)  | \
     (((hash_key_t)(iS_eNB)) << 24) | \
     (((hash_key_t)(rB_iD))  << 25) | \
-    (((hash_key_t)(iS_sRB)) << 33))
+    (((hash_key_t)(iS_sRB)) << 33) | \
+    (((hash_key_t)(0x05))   << 34))
+
+// index to the same RLC entity as RLC_COLL_KEY_VALUE(), but using LC_id instead
+// the hidden last key indicates if this is a hash-key with RB_id (0x05) or LC_id (0x0a)
+#define RLC_COLL_KEY_LCID_VALUE(eNB_iD, rNTI, iS_eNB, lC_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)(iS_sRB)) << 33) | \
+    (((hash_key_t)(0x0a))   << 34))
 
 // service id max val is maxServiceCount = 16 (asn1_constants.h)
 
diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c
index cb7357b5e7826ea57587fba43a8acb770b60ddf5..d59b187dc763ea19dca362597393309fb1e03969 100644
--- a/openair2/LAYER2/RLC/rlc_mac.c
+++ b/openair2/LAYER2/RLC/rlc_mac.c
@@ -129,7 +129,6 @@ tbs_size_t mac_rlc_data_req(
 {
   //-----------------------------------------------------------------------------
   struct mac_data_req    data_request;
-  rb_id_t                rb_id           = 0;
   rlc_mode_t             rlc_mode        = RLC_MODE_NONE;
   rlc_mbms_id_t         *mbms_id_p       = NULL;
   rlc_union_t           *rlc_union_p     = NULL;
@@ -172,13 +171,7 @@ tbs_size_t mac_rlc_data_req(
       return (tbs_size_t)0;
     }
   } else {
-    if (channel_idP > 2) {
-      rb_id = channel_idP - 2;
-    } else {
-      rb_id = channel_idP;
-    }
-
-    key = RLC_COLL_KEY_VALUE(module_idP, rntiP, enb_flagP, rb_id, srb_flag);
+    key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag);
   }
 
   h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
@@ -187,7 +180,7 @@ tbs_size_t mac_rlc_data_req(
     rlc_mode = rlc_union_p->mode;
   } else {
     rlc_mode = RLC_MODE_NONE;
-    AssertFatal (0 , "RLC not configured rb id %u lcid %u RNTI %x!\n", rb_id, channel_idP, rntiP);
+    AssertFatal (0 , "RLC not configured lcid %u RNTI %x!\n", channel_idP, rntiP);
   }
 
   switch (rlc_mode) {
@@ -237,7 +230,6 @@ void mac_rlc_data_ind     (
   crc_t                    *crcs_pP)
 {
   //-----------------------------------------------------------------------------
-  rb_id_t                rb_id      = 0;
   rlc_mode_t             rlc_mode   = RLC_MODE_NONE;
   rlc_mbms_id_t         *mbms_id_p  = NULL;
   rlc_union_t           *rlc_union_p     = NULL;
@@ -287,13 +279,7 @@ void mac_rlc_data_ind     (
       return;
     }
   } else {
-    if (channel_idP > 2) {
-      rb_id = channel_idP - 2;
-    } else {
-      rb_id = channel_idP;
-    }
-
-    key = RLC_COLL_KEY_VALUE(module_idP, rntiP, enb_flagP, rb_id, srb_flag);
+    key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag);
   }
 
   h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
@@ -343,7 +329,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
   mac_rlc_status_resp_t  mac_rlc_status_resp;
   struct mac_status_ind  tx_status;
   struct mac_status_resp status_resp;
-  rb_id_t                rb_id       = 0;
   rlc_mode_t             rlc_mode    = RLC_MODE_NONE;
   rlc_mbms_id_t         *mbms_id_p   = NULL;
   rlc_union_t           *rlc_union_p = NULL;
@@ -392,13 +377,7 @@ 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 {
-    if (channel_idP > 2) {
-      rb_id = channel_idP - 2;
-    } else {
-      rb_id = channel_idP;
-    }
-
-    key = RLC_COLL_KEY_VALUE(module_idP, rntiP, enb_flagP, rb_id, srb_flag);
+    key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag);
   }
 
   h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
@@ -427,7 +406,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
     break;
 
   case RLC_MODE_UM:
-    status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tb_sizeP, tx_status);
+    status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tb_sizeP, tx_status, enb_flagP);
     mac_rlc_status_resp.bytes_in_buffer                 = status_resp.buffer_occupancy_in_bytes;
     mac_rlc_status_resp.pdus_in_buffer                  = status_resp.buffer_occupancy_in_pdus;
     mac_rlc_status_resp.head_sdu_creation_time          = status_resp.head_sdu_creation_time;
diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c
index c78a3fa144615dfe73c1da8ec773df2a75c40939..9ef8bd87005280f712203fb4ac8ce9780ade675a 100644
--- a/openair2/LAYER2/RLC/rlc_rrc.c
+++ b/openair2/LAYER2/RLC/rlc_rrc.c
@@ -97,7 +97,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
   if (srb2add_listP != NULL) {
     for (cnt=0; cnt<srb2add_listP->list.count; cnt++) {
       rb_id = srb2add_listP->list.array[cnt]->srb_Identity;
-      lc_id  = rb_id + 2;
+      lc_id = rb_id;
 
       LOG_D(RLC, "Adding SRB %d, rb_id %d\n",srb2add_listP->list.array[cnt]->srb_Identity,rb_id);
       srb_toaddmod_p = srb2add_listP->list.array[cnt];
@@ -118,7 +118,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
                 ctxt_pP,
                 SRB_FLAG_YES,
                 &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.am,
-                rb_id);
+                rb_id, lc_id);
             } else {
               LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                     PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -137,7 +137,7 @@ 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);
+                rb_id, lc_id);
             } else {
               LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                     PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -156,7 +156,7 @@ 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);
+                rb_id, lc_id);
             } else {
               LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                     PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -175,7 +175,7 @@ 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);
+                rb_id, lc_id);
             } else {
               LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                     PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -209,7 +209,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
               ctxt_pP,
               SRB_FLAG_YES,
               &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.am,
-              rb_id);
+              rb_id,lc_id);
           } else {
             LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                   PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -225,7 +225,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
               UNUSED_PARAM_MBMS_SERVICE_ID,
               NULL, // TO DO DEFAULT CONFIG
               NULL, // TO DO DEFAULT CONFIG
-              rb_id);
+              rb_id, lc_id);
           } else {
             LOG_D(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                   PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -247,9 +247,19 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
       drb_toaddmod_p = drb2add_listP->list.array[cnt];
 
       drb_id = drb_toaddmod_p->drb_Identity;
-      lc_id  = drb_id + 2;
+      if (drb_toaddmod_p->logicalChannelIdentity) {
+        lc_id = *drb_toaddmod_p->logicalChannelIdentity;
+      } else {
+        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity is missing from drb-ToAddMod information element!\n", PROTOCOL_CTXT_ARGS(ctxt_pP));
+        continue;
+      }
+
+      if (lc_id == 1 || lc_id == 2) {
+        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %d is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
+        continue;
+      }
 
-      LOG_I(RLC, "Adding DRB %d, lc_id %d\n",drb_id,lc_id);
+      LOG_D(RLC, "Adding DRB %d, lc_id %d\n",drb_id,lc_id);
 
 
       if (drb_toaddmod_p->rlc_Config) {
@@ -264,7 +274,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP
               ctxt_pP,
               SRB_FLAG_NO,
               &drb_toaddmod_p->rlc_Config->choice.am,
-              drb_id);
+              drb_id, lc_id);
           }
 
           break;
@@ -279,7 +289,7 @@ 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);
+              drb_id, lc_id);
           }
 
           break;
@@ -294,7 +304,7 @@ 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);
+              drb_id, lc_id);
           }
 
           break;
@@ -309,7 +319,7 @@ 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);
+              drb_id, lc_id);
           }
 
           break;
@@ -393,7 +403,7 @@ 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);
+          rb_id, lc_id);
       }
     }
   }
@@ -474,6 +484,8 @@ rlc_op_status_t rrc_rlc_remove_rlc   (
   logical_chan_id_t      lcid            = 0;
   hash_key_t             key             = HASHTABLE_NOT_A_KEY_VALUE;
   hashtable_rc_t         h_rc;
+  hash_key_t             key_lcid        = HASHTABLE_NOT_A_KEY_VALUE;
+  hashtable_rc_t         h_lcid_rc;
   rlc_union_t           *rlc_union_p = NULL;
 #ifdef Rel10
   rlc_mbms_id_t         *mbms_id_p  = NULL;
@@ -517,23 +529,49 @@ rlc_op_status_t rrc_rlc_remove_rlc   (
   h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
 
   if (h_rc == HASH_TABLE_OK) {
+    // also remove the hash-key created by LC-id
+    switch (rlc_union_p->mode) {
+    case RLC_MODE_AM:
+      lcid = rlc_union_p->rlc.am.channel_id;
+      break;
+    case RLC_MODE_UM:
+      lcid = rlc_union_p->rlc.um.channel_id;
+      break;
+    case RLC_MODE_TM:
+      lcid = rlc_union_p->rlc.tm.channel_id;
+      break;
+    default:
+      LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] RLC mode is unknown!\n",
+            PROTOCOL_CTXT_ARGS(ctxt_pP),
+            (srb_flagP) ? "SRB" : "DRB",
+            rb_idP);
+    }
+    key_lcid = RLC_COLL_KEY_LCID_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, lcid, srb_flagP);
+    h_lcid_rc = hashtable_get(rlc_coll_p, key_lcid, (void**)&rlc_union_p);
+  } else {
+    h_lcid_rc = HASH_TABLE_KEY_NOT_EXISTS;
+  }
+
+  if ((h_rc == HASH_TABLE_OK) && (h_lcid_rc == HASH_TABLE_OK)) {
+    h_lcid_rc = hashtable_remove(rlc_coll_p, key_lcid);
     h_rc = hashtable_remove(rlc_coll_p, key);
-    LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u] RELEASED %s\n",
+    LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u LCID %d] RELEASED %s\n",
           PROTOCOL_CTXT_ARGS(ctxt_pP),
           (srb_flagP) ? "SRB" : "DRB",
-          rb_idP,
+          rb_idP, lcid,
           (srb_flagP) ? "SRB" : "DRB");
-  } else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
-    LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u] RELEASE : RLC NOT FOUND %s\n",
+  } else if ((h_rc == HASH_TABLE_KEY_NOT_EXISTS) || (h_lcid_rc == HASH_TABLE_KEY_NOT_EXISTS)) {
+    LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u LCID %d] RELEASE : RLC NOT FOUND %s, by RB-ID=%d, by LC-ID=%d\n",
           PROTOCOL_CTXT_ARGS(ctxt_pP),
           (srb_flagP) ? "SRB" : "DRB",
-          rb_idP,
-          (srb_flagP) ? "SRB" : "DRB");
+          rb_idP, lcid,
+          (srb_flagP) ? "SRB" : "DRB",
+          h_rc, h_lcid_rc);
   } else {
-    LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] RELEASE : INTERNAL ERROR %s\n",
+    LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u LCID %d] RELEASE : INTERNAL ERROR %s\n",
           PROTOCOL_CTXT_ARGS(ctxt_pP),
           (srb_flagP) ? "SRB" : "DRB",
-          rb_idP,
+          rb_idP, lcid,
           (srb_flagP) ? "SRB" : "DRB");
   }
 
@@ -551,6 +589,8 @@ rlc_union_t* rrc_rlc_add_rlc   (
   //-----------------------------------------------------------------------------
   hash_key_t             key         = HASHTABLE_NOT_A_KEY_VALUE;
   hashtable_rc_t         h_rc;
+  hash_key_t             key_lcid    = HASHTABLE_NOT_A_KEY_VALUE;
+  hashtable_rc_t         h_lcid_rc;
   rlc_union_t           *rlc_union_p = NULL;
 #ifdef Rel10
   rlc_mbms_id_t         *mbms_id_p  = NULL;
@@ -591,6 +631,7 @@ rlc_union_t* rrc_rlc_add_rlc   (
 #endif
   {
     key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
+    key_lcid = RLC_COLL_KEY_LCID_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, srb_flagP);
   }
 
   h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
@@ -606,8 +647,9 @@ rlc_union_t* rrc_rlc_add_rlc   (
   } else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
     rlc_union_p = calloc(1, sizeof(rlc_union_t));
     h_rc = hashtable_insert(rlc_coll_p, key, rlc_union_p);
+    h_lcid_rc = hashtable_insert(rlc_coll_p, key_lcid, rlc_union_p);
 
-    if (h_rc == HASH_TABLE_OK) {
+    if ((h_rc == HASH_TABLE_OK) && (h_lcid_rc == HASH_TABLE_OK)) {
 #ifdef Rel10
 
       if (MBMS_flagP == TRUE) {
@@ -628,11 +670,12 @@ rlc_union_t* rrc_rlc_add_rlc   (
       rlc_union_p->mode = rlc_modeP;
       return rlc_union_p;
     } else {
-      LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_add_rlc  FAILED %s\n",
+      LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_add_rlc FAILED %s (add by RB_id=%d; add by LC_id=%d)\n",
             PROTOCOL_CTXT_ARGS(ctxt_pP),
             (srb_flagP) ? "SRB" : "DRB",
             rb_idP,
-            (srb_flagP) ? "SRB" : "DRB");
+            (srb_flagP) ? "SRB" : "DRB",
+            h_rc, h_lcid_rc);
       free(rlc_union_p);
       rlc_union_p = NULL;
       return NULL;
@@ -689,7 +732,7 @@ rlc_op_status_t rrc_rlc_config_req   (
         ctxt_pP,
         srb_flagP,
         &rlc_infoP.rlc.rlc_am_info,
-        rb_idP);
+        rb_idP, rb_idP);
       break;
 
     case RLC_MODE_UM:
@@ -700,7 +743,7 @@ rlc_op_status_t rrc_rlc_config_req   (
         ctxt_pP,
         srb_flagP,
         &rlc_infoP.rlc.rlc_um_info,
-        rb_idP);
+        rb_idP, rb_idP);
       break;
 
     case RLC_MODE_TM:
@@ -711,7 +754,7 @@ rlc_op_status_t rrc_rlc_config_req   (
         ctxt_pP,
         srb_flagP,
         &rlc_infoP.rlc.rlc_tm_info,
-        rb_idP);
+        rb_idP, rb_idP);
       break;
 
     default:
diff --git a/openair2/LAYER2/openair2_proc.c b/openair2/LAYER2/openair2_proc.c
index 702ddde45b2fbdae1ed240deffa6b30513f93993..677d49bb65b48ed6fd4339bd8db6930396a6a4e7 100644
--- a/openair2/LAYER2/openair2_proc.c
+++ b/openair2/LAYER2/openair2_proc.c
@@ -115,11 +115,13 @@ int dump_eNB_l2_stats(char *buffer, int length)
     for (CC_id=0 ; CC_id < MAX_NUM_CCs; CC_id++) {
       eNB->eNB_stats[CC_id].dlsch_bitrate= 0;
 
-      len += sprintf(&buffer[len],"eNB %d CC %d Frame %d: Active UEs %d, Available PRBs %d, nCCE %d \n",
+      len += sprintf(&buffer[len],"eNB %d CC %d Frame %d: Active UEs %d, Available PRBs %d, nCCE %d, Scheduling decisions %d, Missed Deadlines %d \n",
                      eNB_id, CC_id, eNB->frame,
                      eNB->eNB_stats[CC_id].num_dlactive_UEs,
                      eNB->eNB_stats[CC_id].available_prbs,
-                     eNB->eNB_stats[CC_id].available_ncces);
+                     eNB->eNB_stats[CC_id].available_ncces,
+		     eNB->eNB_stats[CC_id].sched_decisions,
+		     eNB->eNB_stats[CC_id].missed_deadlines);
       
       len += sprintf(&buffer[len],"BCCH , NB_TX_MAC = %d, transmitted bytes (TTI %d, total %d) MCS (TTI %d)\n",
 		     eNB->eNB_stats[CC_id].total_num_bcch_pdu,
diff --git a/openair2/NETWORK_DRIVER/UE_IP/common.c b/openair2/NETWORK_DRIVER/UE_IP/common.c
index 6bef269de874ce0e60805d6e9c1f1c5ebf82e282..86968015975e09e05e37a6639bdcf6eee3cd6cff 100644
--- a/openair2/NETWORK_DRIVER/UE_IP/common.c
+++ b/openair2/NETWORK_DRIVER/UE_IP/common.c
@@ -99,7 +99,8 @@ ue_ip_common_class_wireless2ip(
   hard_header_len = ue_ip_dev[instP]->hard_header_len;
 
   skb_set_mac_header(skb_p, 0);
-
+  skb_set_network_header(skb_p, hard_header_len);
+skb_p->mark = rb_idP;
   //printk("[NAC_COMMIN_RECEIVE]: Packet Type %d (%d,%d)",skb_p->pkt_type,PACKET_HOST,PACKET_BROADCAST);
   skb_p->pkt_type = PACKET_HOST;
 
@@ -344,7 +345,7 @@ void ue_ip_common_wireless2ip(struct nlmsghdr *nlh_pP)
 
   ue_ip_common_class_wireless2ip(pdcph_p->data_size,
                                  (unsigned char *)NLMSG_DATA(nlh_pP) + UE_IP_PDCPH_SIZE,
-                                 pdcph_p->inst,
+                                 1, //pdcph_p->inst,
                                  pdcph_p->rb_id);
 
 }
diff --git a/openair2/PHY_INTERFACE/defs.h b/openair2/PHY_INTERFACE/defs.h
index 8c711e971de8d7fe0a955bcad5ca09904ad63b92..156b9091b7f82d7e9ccda1a490b995599e02574c 100644
--- a/openair2/PHY_INTERFACE/defs.h
+++ b/openair2/PHY_INTERFACE/defs.h
@@ -170,7 +170,7 @@ typedef struct {
   PRACH_RESOURCES_t* (*ue_get_rach)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t Msg3_flag,sub_frame_t subframe);
 
   /// Process Random-Access Response
-  uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t *dlsch_buffer,uint16_t *t_crnti,uint8_t preamble_index);
+  uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP, uint16_t ra_rnti, uint8_t *dlsch_buffer, uint16_t *t_crnti,uint8_t preamble_index);
 
   /// Get SR payload (0,1) from UE MAC
   uint32_t (*ue_get_SR)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t eNB_id,rnti_t rnti,sub_frame_t subframe);
@@ -179,12 +179,15 @@ typedef struct {
   void (*dl_phy_sync_success) (module_id_t Mod_id,frame_t frameP, uint8_t CH_index,uint8_t first_sync);
 
   /// Only calls the PDCP for now
-  UE_L2_STATE_t (*ue_scheduler)(module_id_t Mod_id, frame_t frameP,sub_frame_t subframe, lte_subframe_t direction, uint8_t eNB_id, int CC_id);
+  UE_L2_STATE_t (*ue_scheduler)(module_id_t Mod_id, frame_t rxFrameP,sub_frame_t rxSubframe, frame_t txFrameP,sub_frame_t txSubframe, lte_subframe_t direction, uint8_t eNB_id, int CC_id);
 
   /// PHY-Config-Dedicated UE
   void (*phy_config_dedicated_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
                                   struct PhysicalConfigDedicated *physicalConfigDedicated);
 
+  /// PHY-Config-harq UE
+  void (*phy_config_harq_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
+                             uint16_t max_harq_tx);
   /// Configure Common PHY parameters from SIB1
   void (*phy_config_sib1_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
                              TDD_Config_t *tdd_config,
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.c b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
index 51136dee195bd91cca2cf9fe8bcf229a9f5f4b93..5f9a8e0e2a735284cf8b0616ef4f512429a71405 100644
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.c
@@ -99,7 +99,7 @@ int errno;
 # endif
 #endif
 
-//#define XER_PRINT
+#define XER_PRINT
 
 extern Enb_properties_array_t enb_properties;
 typedef struct xer_sprint_string_s {
@@ -109,6 +109,7 @@ typedef struct xer_sprint_string_s {
 } xer_sprint_string_t;
 
 extern unsigned char NB_eNB_INST;
+extern uint8_t usim_test;
 
 uint16_t two_tier_hexagonal_cellIds[7] = {0,1,2,4,5,7,8};
 uint16_t two_tier_hexagonal_adjacent_cellIds[7][6] = {{1,2,4,5,7,8},    // CellId 0
@@ -1260,7 +1261,10 @@ uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uin
   rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension=CALLOC(1,
       sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension));
 
-  rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity=2;
+  if(usim_test == 0)
+      rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 2;
+  else
+      rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 1;
 
   rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME =
     NULL;//calloc(1,sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME));
@@ -1384,6 +1388,7 @@ uint8_t
 do_RRCConnectionSetup(
   const protocol_ctxt_t*     const ctxt_pP,
   rrc_eNB_ue_context_t*      const ue_context_pP,
+  int                              CC_id,
   uint8_t*                   const buffer,
   const uint8_t                    transmission_mode,
   const uint8_t                    Transaction_id,
@@ -1488,7 +1493,10 @@ do_RRCConnectionSetup(
   physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH         = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH));
   physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH         = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
   physicalConfigDedicated2->cqi_ReportConfig              = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig));
-  physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = NULL;//CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+  if (enb_properties.properties[ctxt_pP->module_id]->srs_enable[CC_id])
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+  else
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = NULL;
   physicalConfigDedicated2->antennaInfo                   = CALLOC(1,sizeof(*physicalConfigDedicated2->antennaInfo));
   physicalConfigDedicated2->schedulingRequestConfig       = CALLOC(1,sizeof(*physicalConfigDedicated2->schedulingRequestConfig));
 #ifdef CBA
@@ -1574,19 +1582,19 @@ do_RRCConnectionSetup(
     */
 
   //soundingRS-UL-ConfigDedicated
-  /*
-  physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->present = SoundingRS_UL_ConfigDedicated_PR_setup;
-  assign_enum(&physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth,
-        SoundingRS_UL_ConfigDedicated__setup__srs_Bandwidth_bw0);
-  assign_enum(&physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth,
-        SoundingRS_UL_ConfigDedicated__setup__srs_HoppingBandwidth_hbw0);
-  physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition=0;
-  physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.duration=1;
-  physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex=1;
-  physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb=0;
-  assign_enum(&physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift,
-        SoundingRS_UL_ConfigDedicated__setup__cyclicShift_cs0);
-  */
+  if (enb_properties.properties[ctxt_pP->module_id]->srs_enable[CC_id]) {
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->present = SoundingRS_UL_ConfigDedicated_PR_setup;
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth =
+                                                             SoundingRS_UL_ConfigDedicated__setup__srs_Bandwidth_bw0;
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth =
+          SoundingRS_UL_ConfigDedicated__setup__srs_HoppingBandwidth_hbw0;
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition=0;
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.duration=1;
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex=45;
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.transmissionComb=0;
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated->choice.setup.cyclicShift=
+          SoundingRS_UL_ConfigDedicated__setup__cyclicShift_cs0;
+  }
 
 
   //AntennaInfoDedicated
@@ -2661,6 +2669,21 @@ OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname)
 
     // UE_EUTRA_Capability->measParameters.bandListEUTRA.list.count                         = 0;  // no measurements on other bands
     // UE_EUTRA_Capability->featureGroupIndicators  // null
+
+    // featureGroup is mandatory for CMW tests
+    // featureGroup is filled only for usim-test mode
+    BIT_STRING_t *bit_string;
+    uint32_t     featrG;
+    bit_string = CALLOC(1, sizeof(*bit_string));
+    featrG     = 0x04000800;
+    if(usim_test == 1)
+    {
+        bit_string->buf         = &featrG;
+        bit_string->size        = 4;
+        bit_string->bits_unused = 0;
+        UE_EUTRA_Capability->featureGroupIndicators = bit_string;
+    }
+
     // UE_EUTRA_Capability->interRAT_Parameters     // null
   } else {
 
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.h b/openair2/RRC/LITE/MESSAGES/asn1_msg.h
index 661914ea6ec730f2dc824ec8080d7a1799509e89..881a778030294a2d1e9262c57fedd43dd6576f64 100644
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg.h
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.h
@@ -133,6 +133,7 @@ do_RRCConnectionReconfigurationComplete(
 PhysicalConfigDedicated IEs.  The latter does not enable periodic CQI reporting (PUCCH format 2/2a/2b) or SRS.
 @param ctxt_pP Running context
 @param ue_context_pP UE context
+@param CC_id         Component Carrier ID
 @param buffer Pointer to PER-encoded ASN.1 description of DL-CCCH-Message PDU
 @param transmission_mode Transmission mode for UE (1-9)
 @param UE_id UE index for this message
@@ -144,6 +145,7 @@ uint8_t
 do_RRCConnectionSetup(
   const protocol_ctxt_t*     const ctxt_pP,
   rrc_eNB_ue_context_t*      const ue_context_pP,
+  int                              CC_id,
   uint8_t*                   const buffer,
   const uint8_t                    transmission_mode,
   const uint8_t                    Transaction_id,
diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h
index f99b07e89360e13165d52f9853463a96024e9b87..0b0fd6b73fa73097e1fd3e385d1d015254986aa3 100644
--- a/openair2/RRC/LITE/defs.h
+++ b/openair2/RRC/LITE/defs.h
@@ -173,7 +173,7 @@ typedef enum HO_STATE_e {
 #define PAYLOAD_SIZE_MAX 1024
 #define RRC_BUF_SIZE 255
 #define UNDEF_SECURITY_MODE 0xff
-#define NO_SECURITY_MODE 0x33
+#define NO_SECURITY_MODE 0x20
 
 #define CBA_OFFSET        0xfff4
 // #define NUM_MAX_CBA_GROUP 4 // in the platform_constants
@@ -498,6 +498,7 @@ typedef struct UE_RRC_INST_s {
   struct SRB_ToAddMod             *SRB1_config[NB_CNX_UE];
   struct SRB_ToAddMod             *SRB2_config[NB_CNX_UE];
   struct DRB_ToAddMod             *DRB_config[NB_CNX_UE][8];
+  rb_id_t                         *defaultDRB; // remember the ID of the default DRB
   MeasObjectToAddMod_t            *MeasObj[NB_CNX_UE][MAX_MEAS_OBJ];
   struct ReportConfigToAddMod     *ReportConfig[NB_CNX_UE][MAX_MEAS_CONFIG];
   struct QuantityConfig           *QuantityConfig[NB_CNX_UE];
diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c
index 5d40872172597705c0b6d1f4bb9a637829d65d12..38d7121860b5c06c7bb8357623c1e8d769b4ea4e 100644
--- a/openair2/RRC/LITE/rrc_UE.c
+++ b/openair2/RRC/LITE/rrc_UE.c
@@ -32,6 +32,7 @@
 #define RRC_UE_C
 
 #include "assertions.h"
+#include "hashtable.h"
 #include "asn1_conversions.h"
 #include "defs.h"
 #include "PHY/TOOLS/dB_routines.h"
@@ -97,10 +98,19 @@ extern UE_MAC_INST *UE_mac_inst;
 extern void *bigphys_malloc(int);
 #endif
 
-//#define XER_PRINT
+#define XER_PRINT
 
 extern int8_t dB_fixed2(uint32_t x,uint32_t y);
 
+extern void pdcp_config_set_security(
+  const protocol_ctxt_t* const  ctxt_pP,
+  pdcp_t         * const pdcp_pP,
+  const rb_id_t         rb_idP,
+  const uint16_t        lc_idP,
+  const uint8_t         security_modeP,
+  uint8_t        * const kRRCenc,
+  uint8_t        * const kRRCint,
+  uint8_t        * const  kUPenc);
 
 // internal prototypes
 
@@ -807,6 +817,7 @@ rrc_ue_process_measConfig(
       }
     }
 
+    LOG_I(RRC,"call rrc_mac_config_req \n");
     rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
                        (RadioResourceConfigCommonSIB_t *)NULL,
                        (struct PhysicalConfigDedicated *)NULL,
@@ -953,6 +964,199 @@ rrc_ue_process_measConfig(
   }
 }
 
+
+void
+rrc_ue_update_radioResourceConfigDedicated(RadioResourceConfigDedicated_t* radioResourceConfigDedicated,
+        const protocol_ctxt_t* const ctxt_pP,
+        uint8_t eNB_index)
+{
+    PhysicalConfigDedicated_t* physicalConfigDedicated2 = NULL;
+
+    physicalConfigDedicated2 = CALLOC(1,sizeof(*physicalConfigDedicated2));
+    physicalConfigDedicated2->pdsch_ConfigDedicated         = CALLOC(1,sizeof(*physicalConfigDedicated2->pdsch_ConfigDedicated));
+    physicalConfigDedicated2->pusch_ConfigDedicated         = CALLOC(1,sizeof(*physicalConfigDedicated2->pusch_ConfigDedicated));
+    physicalConfigDedicated2->pucch_ConfigDedicated         = CALLOC(1,sizeof(*physicalConfigDedicated2->pucch_ConfigDedicated));
+    physicalConfigDedicated2->cqi_ReportConfig              = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig));
+    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+    physicalConfigDedicated2->schedulingRequestConfig       = CALLOC(1,sizeof(*physicalConfigDedicated2->schedulingRequestConfig));
+    physicalConfigDedicated2->antennaInfo                   = CALLOC(1,sizeof(*physicalConfigDedicated2->antennaInfo));
+
+    physicalConfigDedicated2->uplinkPowerControlDedicated   = CALLOC(1,sizeof(*physicalConfigDedicated2->uplinkPowerControlDedicated));
+    physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH         = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
+    physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH         = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH));
+
+    // Update pdsch_ConfigDedicated
+    if(radioResourceConfigDedicated->physicalConfigDedicated->pdsch_ConfigDedicated != NULL)
+    {
+        LOG_I(RRC,"Update pdsch_ConfigDedicated config \n");
+
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pdsch_ConfigDedicated == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pdsch_ConfigDedicated = CALLOC(1,sizeof(PDSCH_ConfigDedicated_t));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pdsch_ConfigDedicated,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->pdsch_ConfigDedicated,
+                sizeof(physicalConfigDedicated2->pdsch_ConfigDedicated));
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for pdsch_ConfigDedicated\n");
+    }
+
+    // Update pusch_ConfigDedicated
+    if(radioResourceConfigDedicated->physicalConfigDedicated->pusch_ConfigDedicated != NULL)
+    {
+        LOG_I(RRC,"Update pusch_ConfigDedicated config \n");
+
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pusch_ConfigDedicated == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pusch_ConfigDedicated = CALLOC(1,sizeof(PUSCH_ConfigDedicated_t));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pusch_ConfigDedicated,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->pusch_ConfigDedicated,
+                sizeof(physicalConfigDedicated2->pusch_ConfigDedicated));
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for pusch_ConfigDedicated\n");
+    }
+
+    // Update pucch_ConfigDedicated
+    if(radioResourceConfigDedicated->physicalConfigDedicated->pucch_ConfigDedicated != NULL)
+    {
+        LOG_I(RRC,"Update pucch_ConfigDedicated config \n");
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pucch_ConfigDedicated == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pucch_ConfigDedicated = CALLOC(1,sizeof(PUCCH_ConfigDedicated_t));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pucch_ConfigDedicated,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->pucch_ConfigDedicated,
+                sizeof(physicalConfigDedicated2->pucch_ConfigDedicated));
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for pucch_ConfigDedicated\n");
+    }
+
+    // Update cqi_ReportConfig
+    if(radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig != NULL)
+    {
+        LOG_I(RRC,"Update cqi_ReportConfig config \n");
+
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig = CALLOC(1,sizeof(CQI_ReportConfig_t));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig,
+                sizeof(physicalConfigDedicated2->cqi_ReportConfig));
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for cqi_ReportConfig\n");
+    }
+
+    // Update schedulingRequestConfig
+    if(radioResourceConfigDedicated->physicalConfigDedicated->schedulingRequestConfig != NULL)
+    {
+        LOG_I(RRC,"Update schedulingRequestConfig config \n");
+
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->schedulingRequestConfig == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->schedulingRequestConfig = CALLOC(1,sizeof(SchedulingRequestConfig_t));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->schedulingRequestConfig,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->schedulingRequestConfig,
+                sizeof(physicalConfigDedicated2->schedulingRequestConfig));
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for schedulingRequestConfig\n");
+    }
+
+    // Update soundingRS_UL_ConfigDedicated
+    if(radioResourceConfigDedicated->physicalConfigDedicated->soundingRS_UL_ConfigDedicated != NULL)
+    {
+        LOG_I(RRC,"Update soundingRS_UL_ConfigDedicated config \n");
+
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->soundingRS_UL_ConfigDedicated == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(SoundingRS_UL_ConfigDedicated_t));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->soundingRS_UL_ConfigDedicated,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->soundingRS_UL_ConfigDedicated,
+                sizeof(physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for soundingRS_UL_ConfigDedicated\n");
+    }
+
+    // Update antennaInfo
+    if(radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo != NULL)
+    {
+        LOG_I(RRC,"Update antennaInfo config \n");
+
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo = CALLOC(1,sizeof(struct PhysicalConfigDedicated__antennaInfo));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo,
+                sizeof(physicalConfigDedicated2->antennaInfo));
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for antennaInfo\n");
+    }
+
+
+    // Update uplinkPowerControlDedicated
+    if(radioResourceConfigDedicated->physicalConfigDedicated->uplinkPowerControlDedicated != NULL)
+    {
+        LOG_I(RRC,"Update uplinkPowerControlDedicated config \n");
+
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->uplinkPowerControlDedicated == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->uplinkPowerControlDedicated = CALLOC(1,sizeof(UplinkPowerControlDedicated_t));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->uplinkPowerControlDedicated,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->uplinkPowerControlDedicated,
+                sizeof(physicalConfigDedicated2->uplinkPowerControlDedicated));
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for uplinkPowerControlDedicated\n");
+    }
+
+    // Update tpc_PDCCH_ConfigPUCCH
+    if(radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUCCH != NULL)
+    {
+        LOG_I(RRC,"Update tpc_PDCCH_ConfigPUCCH config \n");
+
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUCCH == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUCCH = CALLOC(1,sizeof(TPC_PDCCH_Config_t));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUCCH,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUCCH,
+                sizeof(physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH));
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for tpc_PDCCH_ConfigPUCCH\n");
+    }
+
+    // Update tpc_PDCCH_ConfigPUSCH
+    if(radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUSCH != NULL)
+    {
+        LOG_I(RRC,"Update tpc_PDCCH_ConfigPUSCH config \n");
+
+        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUSCH == NULL)
+            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUSCH = CALLOC(1,sizeof(TPC_PDCCH_Config_t));
+
+        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUSCH,
+                (char*)radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUSCH,
+                sizeof(physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
+
+    }
+    else
+    {
+        LOG_I(RRC,"Keep old config for tpc_PDCCH_ConfigPUSCH\n");
+    }
+
+}
 //-----------------------------------------------------------------------------
 void
 rrc_ue_process_radioResourceConfigDedicated(
@@ -973,11 +1177,17 @@ rrc_ue_process_radioResourceConfigDedicated(
 
   // Save physicalConfigDedicated if present
   if (radioResourceConfigDedicated->physicalConfigDedicated) {
+    LOG_I(RRC,"Save physicalConfigDedicated if present \n");
+
     if (UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]) {
+#if 1
+        rrc_ue_update_radioResourceConfigDedicated(radioResourceConfigDedicated, ctxt_pP, eNB_index);
+#else
       memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index],(char*)radioResourceConfigDedicated->physicalConfigDedicated,
              sizeof(struct PhysicalConfigDedicated));
-
+#endif
     } else {
+      LOG_I(RRC,"Init physicalConfigDedicated UE_rrc_inst to radioResourceConfigDedicated->physicalConfigDedicated\n");
       UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index] = radioResourceConfigDedicated->physicalConfigDedicated;
     }
   }
@@ -1054,7 +1264,7 @@ rrc_ue_process_radioResourceConfigDedicated(
 #ifdef Rel10
                              ,(PMCH_InfoList_r9_t *)NULL
 #endif
-                            );
+                             ,NULL);
 
     // Refresh SRBs
     rrc_rlc_config_asn1_req(ctxt_pP,
@@ -1095,7 +1305,7 @@ rrc_ue_process_radioResourceConfigDedicated(
             SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
           }
 
-          LOG_D(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB1 eNB %d) --->][MAC_UE][MOD %02d][]\n",
+          LOG_I(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB1 eNB %d) --->][MAC_UE][MOD %02d][]\n",
                 ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
           rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
                              (RadioResourceConfigCommonSIB_t *)NULL,
@@ -1150,7 +1360,7 @@ rrc_ue_process_radioResourceConfigDedicated(
             SRB2_logicalChannelConfig = &SRB2_logicalChannelConfig_defaultValue;
           }
 
-          LOG_D(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
+          LOG_I(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
                 ctxt_pP->frame,
                 ctxt_pP->module_id,
                 eNB_index,
@@ -1194,6 +1404,15 @@ rrc_ue_process_radioResourceConfigDedicated(
 
   // Establish DRBs if present
   if (radioResourceConfigDedicated->drb_ToAddModList) {
+
+    if ( (UE_rrc_inst[ctxt_pP->module_id].defaultDRB == NULL) &&
+         (radioResourceConfigDedicated->drb_ToAddModList->list.count >= 1) ) {
+        // configure the first DRB ID as the default DRB ID
+        UE_rrc_inst[ctxt_pP->module_id].defaultDRB = malloc(sizeof(rb_id_t));
+        *UE_rrc_inst[ctxt_pP->module_id].defaultDRB = radioResourceConfigDedicated->drb_ToAddModList->list.array[0]->drb_Identity;
+        LOG_I(RRC,"[UE %d] default DRB = %d\n",ctxt_pP->module_id, *UE_rrc_inst[ctxt_pP->module_id].defaultDRB);
+      }
+
     uint8_t *kUPenc = NULL;
 
 #if defined(ENABLE_SECURITY)
@@ -1225,7 +1444,7 @@ rrc_ue_process_radioResourceConfigDedicated(
 #ifdef Rel10
                              ,(PMCH_InfoList_r9_t *)NULL
 #endif
-                            );
+                             , UE_rrc_inst[ctxt_pP->module_id].defaultDRB);
 
     // Refresh DRBs
     rrc_rlc_config_asn1_req(ctxt_pP,
@@ -1248,7 +1467,7 @@ rrc_ue_process_radioResourceConfigDedicated(
         UE_rrc_inst[ctxt_pP->module_id].DRB_config[eNB_index][DRB_id] = radioResourceConfigDedicated->drb_ToAddModList->list.array[i];
         rrc_ue_establish_drb(ctxt_pP->module_id,ctxt_pP->frame,eNB_index,radioResourceConfigDedicated->drb_ToAddModList->list.array[i]);
         // MAC/PHY Configuration
-        LOG_D(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (DRB %d eNB %d) --->][MAC_UE][MOD %02d][]\n",
+        LOG_I(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (DRB %d eNB %d) --->][MAC_UE][MOD %02d][]\n",
               ctxt_pP->frame, ctxt_pP->module_id,
               radioResourceConfigDedicated->drb_ToAddModList->list.array[i]->drb_Identity,
               eNB_index,
@@ -1386,6 +1605,62 @@ rrc_ue_process_securityModeCommand(
     ul_dcch_msg.message.choice.c1.present = UL_DCCH_MessageType__c1_PR_securityModeFailure;
   }
 
+
+#if defined(ENABLE_SECURITY)
+  uint8_t *kRRCenc = NULL;
+  uint8_t *kUPenc = NULL;
+  uint8_t *kRRCint = NULL;
+  pdcp_t *pdcp_p = NULL;
+  hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
+  hashtable_rc_t h_rc;
+
+  key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti,
+      ctxt_pP->enb_flag, DCCH, SRB_FLAG_YES);
+  h_rc = hashtable_get(pdcp_coll_p, key, (void**) &pdcp_p);
+
+  if (h_rc == HASH_TABLE_OK) {
+    LOG_D(RRC, "PDCP_COLL_KEY_VALUE() returns valid key = %d\n", key);
+
+    LOG_D(RRC, "driving kRRCenc, kRRCint and kUPenc from KeNB="
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x\n",
+        UE_rrc_inst[ctxt_pP->module_id].kenb[0],  UE_rrc_inst[ctxt_pP->module_id].kenb[1],  UE_rrc_inst[ctxt_pP->module_id].kenb[2],  UE_rrc_inst[ctxt_pP->module_id].kenb[3],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[4],  UE_rrc_inst[ctxt_pP->module_id].kenb[5],  UE_rrc_inst[ctxt_pP->module_id].kenb[6],  UE_rrc_inst[ctxt_pP->module_id].kenb[7],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[8],  UE_rrc_inst[ctxt_pP->module_id].kenb[9],  UE_rrc_inst[ctxt_pP->module_id].kenb[10], UE_rrc_inst[ctxt_pP->module_id].kenb[11],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[12], UE_rrc_inst[ctxt_pP->module_id].kenb[13], UE_rrc_inst[ctxt_pP->module_id].kenb[14], UE_rrc_inst[ctxt_pP->module_id].kenb[15],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[16], UE_rrc_inst[ctxt_pP->module_id].kenb[17], UE_rrc_inst[ctxt_pP->module_id].kenb[18], UE_rrc_inst[ctxt_pP->module_id].kenb[19],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[20], UE_rrc_inst[ctxt_pP->module_id].kenb[21], UE_rrc_inst[ctxt_pP->module_id].kenb[22], UE_rrc_inst[ctxt_pP->module_id].kenb[23],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[24], UE_rrc_inst[ctxt_pP->module_id].kenb[25], UE_rrc_inst[ctxt_pP->module_id].kenb[26], UE_rrc_inst[ctxt_pP->module_id].kenb[27],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[28], UE_rrc_inst[ctxt_pP->module_id].kenb[29], UE_rrc_inst[ctxt_pP->module_id].kenb[30], UE_rrc_inst[ctxt_pP->module_id].kenb[31]);
+
+    derive_key_rrc_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
+        UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCenc);
+    derive_key_rrc_int(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
+        UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCint);
+    derive_key_up_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
+        UE_rrc_inst[ctxt_pP->module_id].kenb, &kUPenc);
+
+    if (securityMode != 0xff) {
+      pdcp_config_set_security(ctxt_pP, pdcp_p, 0, 0,
+          UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm
+              | (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",
+          securityMode);
+    }
+  } else {
+    LOG_W(RRC, "Could not get PDCP instance where key=0x%\n", key);
+  }
+
+#endif //#if defined(ENABLE_SECURITY)
+
   if (securityModeCommand->criticalExtensions.present == SecurityModeCommand__criticalExtensions_PR_c1) {
     if (securityModeCommand->criticalExtensions.choice.c1.present == SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8) {
 
@@ -1719,7 +1994,7 @@ rrc_ue_process_mobilityControlInfo(
   #ifdef Rel10
          ,NULL
   #endif
-         );
+         ,NULL);
 
   rrc_rlc_config_asn1_req(NB_eNB_INST+ue_mod_idP, frameP,0,eNB_index,
         NULL,// SRB_ToAddModList
@@ -1728,7 +2003,7 @@ rrc_ue_process_mobilityControlInfo(
   #ifdef Rel10
         ,NULL
   #endif
-        );
+        ,NULL);
    */
 
 
@@ -1750,7 +2025,7 @@ rrc_ue_process_mobilityControlInfo(
   UE_rrc_inst[ue_mod_idP].DRB_config[eNB_index][0] = NULL;
    */
   //Synchronisation to DL of target cell
-  LOG_D(RRC,
+  LOG_I(RRC,
         "HO: Reset PDCP and RLC for configured RBs.. \n[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
         ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
 
@@ -2610,7 +2885,7 @@ static int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_
 
   UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIperiod     = siPeriod_int[sib1->schedulingInfoList.list.array[0]->si_Periodicity];
   UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIwindowsize = siWindowLength_int[sib1->si_WindowLength];
-  LOG_D( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
+  LOG_I( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
          ctxt_pP->module_id, eNB_index, ctxt_pP->module_id );
 
   rrc_mac_config_req(ctxt_pP->module_id, 0, ENB_FLAG_NO, 0, eNB_index,
@@ -3424,7 +3699,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
 	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] );
 	// adding here function to store necessary parameters for using in decode_MCCH_Message + maybe transfer to PHY layer
-	LOG_D( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB13 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
+	LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB13 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
 	       ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
 	rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
 			   (RadioResourceConfigCommonSIB_t *)NULL,
@@ -3881,7 +4156,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i
 {
   protocol_ctxt_t               ctxt;
 
-  LOG_D(RRC,"[UE %d] Frame %d : Number of MCH(s) in the MBSFN Sync Area %d  is %d\n",
+  LOG_I(RRC,"[UE %d] Frame %d : Number of MCH(s) in the MBSFN Sync Area %d  is %d\n",
         ue_mod_idP, frameP, mbsfn_sync_area, UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9.list.count);
   //  store to MAC/PHY necessary parameters for receiving MTCHs
   rrc_mac_config_req(ue_mod_idP,0,ENB_FLAG_NO,0,eNB_index,
@@ -3933,7 +4208,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i
 #ifdef Rel10
                            ,&(UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9)
 #endif
-                          );
+                           ,NULL);
 
   rrc_rlc_config_asn1_req(&ctxt,
                           NULL,// SRB_ToAddModList
@@ -4090,6 +4365,30 @@ void *rrc_ue_task( void *args_p )
 
 # if defined(ENABLE_USE_MME)
 
+    case NAS_KENB_REFRESH_REQ:
+        memcpy((void*)UE_rrc_inst[ue_mod_id].kenb, (void*)NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(UE_rrc_inst[ue_mod_id].kenb));
+
+        LOG_D(RRC, "[UE %d] Received %s: refreshed RRC::KeNB = "
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x\n",
+            ue_mod_id, msg_name,
+            UE_rrc_inst[ue_mod_id].kenb[0],  UE_rrc_inst[ue_mod_id].kenb[1],  UE_rrc_inst[ue_mod_id].kenb[2],  UE_rrc_inst[ue_mod_id].kenb[3],
+            UE_rrc_inst[ue_mod_id].kenb[4],  UE_rrc_inst[ue_mod_id].kenb[5],  UE_rrc_inst[ue_mod_id].kenb[6],  UE_rrc_inst[ue_mod_id].kenb[7],
+            UE_rrc_inst[ue_mod_id].kenb[8],  UE_rrc_inst[ue_mod_id].kenb[9],  UE_rrc_inst[ue_mod_id].kenb[10], UE_rrc_inst[ue_mod_id].kenb[11],
+            UE_rrc_inst[ue_mod_id].kenb[12], UE_rrc_inst[ue_mod_id].kenb[13], UE_rrc_inst[ue_mod_id].kenb[14], UE_rrc_inst[ue_mod_id].kenb[15],
+            UE_rrc_inst[ue_mod_id].kenb[16], UE_rrc_inst[ue_mod_id].kenb[17], UE_rrc_inst[ue_mod_id].kenb[18], UE_rrc_inst[ue_mod_id].kenb[19],
+            UE_rrc_inst[ue_mod_id].kenb[20], UE_rrc_inst[ue_mod_id].kenb[21], UE_rrc_inst[ue_mod_id].kenb[22], UE_rrc_inst[ue_mod_id].kenb[23],
+            UE_rrc_inst[ue_mod_id].kenb[24], UE_rrc_inst[ue_mod_id].kenb[25], UE_rrc_inst[ue_mod_id].kenb[26], UE_rrc_inst[ue_mod_id].kenb[27],
+            UE_rrc_inst[ue_mod_id].kenb[28], UE_rrc_inst[ue_mod_id].kenb[29], UE_rrc_inst[ue_mod_id].kenb[30], UE_rrc_inst[ue_mod_id].kenb[31]);
+
+      break;
+
       /* NAS messages */
     case NAS_CELL_SELECTION_REQ:
       ue_mod_id = 0; /* TODO force ue_mod_id to first UE, NAS UE not virtualized yet */
@@ -4202,12 +4501,26 @@ 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);
-      rrc_data_req (&ctxt,
-		    DCCH,
-		    rrc_mui++,
-		    SDU_CONFIRM_NO,
-		    length, buffer,
-		    PDCP_TRANSMISSION_MODE_CONTROL);
+
+      // 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 (&ctxt,
+                  DCCH,
+                  rrc_mui++,
+                  SDU_CONFIRM_NO,
+                  length, buffer,
+                  PDCP_TRANSMISSION_MODE_CONTROL);
+      }
+      else
+      {
+          rrc_data_req (&ctxt,
+                  DCCH1,
+                  rrc_mui++,
+                  SDU_CONFIRM_NO,
+                  length, buffer,
+                  PDCP_TRANSMISSION_MODE_CONTROL);
+      }
       break;
     }
       
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index 284c5fd2156de156fd48fcdad61ff36b7bd92423..d279764528de3cee992bad917a43bb3b1fdd9bb0 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -93,6 +93,9 @@
 
 #include "SIMULATION/TOOLS/defs.h" // for taus
 
+#if defined(FLEXRAN_AGENT_SB_IF)
+#include "flexran_agent_extern.h"
+#endif
 #define XER_PRINT
 
 #ifdef PHY_EMUL
@@ -473,7 +476,7 @@ static void init_MBMS(
 #   ifdef Rel10
                              , &(eNB_rrc_inst[enb_mod_idP].carrier[CC_id].mcch_message->pmch_InfoList_r9)
 #   endif
-                            );
+                             ,NULL);
 
     rrc_rlc_config_asn1_req(&ctxt,
                             NULL, // SRB_ToAddModList
@@ -644,6 +647,9 @@ void rrc_eNB_emulation_notify_ue_module_id(
 
   // find enb_module_id
   for (enb_module_id = 0; enb_module_id < NUMBER_OF_eNB_MAX; enb_module_id++) {
+    if(enb_module_id>0){ /*FIX LATER*/
+      return;
+    }
     for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
       if (eNB_rrc_inst[enb_module_id].carrier[CC_id].sib1 != NULL) {
         if (
@@ -652,7 +658,6 @@ void rrc_eNB_emulation_notify_ue_module_id(
           (eNB_rrc_inst[enb_module_id].carrier[CC_id].sib1->cellAccessRelatedInfo.cellIdentity.buf[2] == cell_identity_byte2P) &&
           (eNB_rrc_inst[enb_module_id].carrier[CC_id].sib1->cellAccessRelatedInfo.cellIdentity.buf[3] == cell_identity_byte3P)
         ) {
-          oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_id][ue_module_idP] = rntiP;
           ue_context_p = rrc_eNB_get_ue_context(
                            &eNB_rrc_inst[enb_module_id],
                            rntiP
@@ -662,10 +667,11 @@ void rrc_eNB_emulation_notify_ue_module_id(
             oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[enb_module_id][ue_context_p->local_uid] = ue_module_idP;
           }
 
-          return;
+          //return;
         }
       }
     }
+    oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_id][ue_module_idP] = rntiP;
   }
 
   AssertFatal(enb_module_id == NUMBER_OF_eNB_MAX,
@@ -2613,7 +2619,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
   physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH =
     CALLOC(1, sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
   physicalConfigDedicated2->cqi_ReportConfig = NULL;  //CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig));
-  physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = NULL; //CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+  physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
   physicalConfigDedicated2->antennaInfo = CALLOC(1, sizeof(*physicalConfigDedicated2->antennaInfo));
   physicalConfigDedicated2->schedulingRequestConfig =
     CALLOC(1, sizeof(*physicalConfigDedicated2->schedulingRequestConfig));
@@ -3275,7 +3281,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
 #ifdef Rel10
                            , (PMCH_InfoList_r9_t *) NULL
 #endif
-                          );
+                           ,NULL);
 
   rrc_rlc_config_asn1_req(&ctxt,
                           ue_context_pP->ue_context.SRB_configList,
@@ -3517,7 +3523,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
 #ifdef Rel10
     , (PMCH_InfoList_r9_t *) NULL
 #endif
-  );
+    ,NULL);
   // Refresh SRBs/DRBs
   rrc_rlc_config_asn1_req(
     ctxt_pP,
@@ -3737,8 +3743,9 @@ rrc_eNB_generate_RRCConnectionSetup(
   eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
     do_RRCConnectionSetup(ctxt_pP,
                           ue_context_pP,
+                          CC_id,
                           (uint8_t*) eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload,
-			  (fp->nb_antennas_tx_eNB==2)?2:1, //at this point we do not have the UE capability information, so it can only be TM1 or TM2
+			  (fp->nb_antenna_ports_eNB==2)?2:1, //at this point we do not have the UE capability information, so it can only be TM1 or TM2
                           rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id),
                           fp,
                           SRB_configList,
@@ -4342,7 +4349,7 @@ rrc_eNB_decode_ccch(
 #   ifdef Rel10
                                , (PMCH_InfoList_r9_t *) NULL
 #   endif
-                              );
+                               ,NULL);
 
       rrc_rlc_config_asn1_req(ctxt_pP,
                               ue_context_p->ue_context.SRB_configList,
@@ -4535,7 +4542,16 @@ rrc_eNB_decode_dcch(
 	rrc_eNB_process_RRCConnectionReconfigurationComplete(
           ctxt_pP,
           ue_context_p,
-          ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
+	  ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
+
+#if defined(FLEXRAN_AGENT_SB_IF)
+	//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
+	if (mac_agent_registered[ctxt_pP->module_id]) {
+	  agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
+										ue_context_p->ue_id_rnti,
+										PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED);
+	}
+#endif
       }
 #if defined(ENABLE_ITTI)
 #   if defined(ENABLE_USE_MME)
@@ -4631,6 +4647,15 @@ rrc_eNB_decode_dcch(
           ue_context_p->ue_context.Status = RRC_CONNECTED;
           LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_CONNECTED \n",
                 PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
+	  
+#if defined(FLEXRAN_AGENT_SB_IF)
+	  //WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
+	  if (mac_agent_registered[ctxt_pP->module_id]) {
+	    agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
+										  ue_context_p->ue_id_rnti,
+										  PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED);
+	  }
+#endif
         }
       }
 
diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c
index a3dc9f47a17ebfbd2313e25bc11f0f4ab919f9d5..8899c7d743bd9e024b18bea7985ce6206ff48d34 100644
--- a/openair2/RRC/LITE/rrc_eNB_S1AP.c
+++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c
@@ -774,8 +774,8 @@ rrc_eNB_process_S1AP_DOWNLINK_NAS(
   ue_initial_id = S1AP_DOWNLINK_NAS (msg_p).ue_initial_id;
   eNB_ue_s1ap_id = S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id;
   ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
-  srb_id = ue_context_p->ue_context.Srb2.Srb_info.Srb_id;
-  
+
+
   LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d\n",
         instance,
         msg_name,
@@ -822,6 +822,9 @@ rrc_eNB_process_S1AP_DOWNLINK_NAS(
   } else {
     PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
 
+    srb_id = ue_context_p->ue_context.Srb2.Srb_info.Srb_id;
+  
+
     /* Is it the first income from S1AP ? */
     if (ue_context_p->ue_context.eNB_ue_s1ap_id == 0) {
       ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_DOWNLINK_NAS (msg_p).eNB_ue_s1ap_id;
diff --git a/openair2/UTIL/ASYNC_IF/link_manager.c b/openair2/UTIL/ASYNC_IF/link_manager.c
new file mode 100644
index 0000000000000000000000000000000000000000..1c9fb72bfe3f79d9636fd2808799b09af85e51ab
--- /dev/null
+++ b/openair2/UTIL/ASYNC_IF/link_manager.c
@@ -0,0 +1,254 @@
+/*
+ * 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.0  (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 link_manager.c
+ * \brief this is the implementation of a link manager
+ * \author Cedric Roux
+ * \date November 2015
+ * \version 1.0
+ * \email: cedric.roux@eurecom.fr
+ * @ingroup _mac
+ */
+
+#include "link_manager.h"
+#include "log.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+/* that thread reads messages in the queue and sends them to the link */
+static void *link_manager_sender_thread(void *_manager)
+{
+  link_manager_t *manager = _manager;
+  void           *data;
+  int            size;
+  int            priority;
+
+  LOG_D(MAC, "starting link manager sender thread\n");
+
+  while (manager->run) {
+    while (message_get(manager->send_queue, &data, &size, &priority) == 0) {
+      link_send_packet(manager->socket_link, data, size);
+      free(data);
+    }
+    //    if (message_get(manager->send_queue, &data, &size, &priority))
+    //  goto error;
+    //if (link_send_packet(manager->socket_link, data, size))
+    //  goto error;
+    //free(data);
+  }
+
+  LOG_D(MAC, "link manager sender thread quits\n");
+
+  return NULL;
+
+error:
+  LOG_E(MAC, "%s: error\n", __FUNCTION__);
+  return NULL;
+}
+
+/* that thread receives messages from the link and puts them in the queue */
+static void *link_manager_receiver_thread(void *_manager)
+{
+  link_manager_t *manager = _manager;
+  void           *data;
+  int            size;
+
+  LOG_D(MAC, "starting link manager receiver thread\n");
+
+  while (manager->run) {
+    if (link_receive_packet(manager->socket_link, &data, &size))
+      goto error;
+    /* todo: priority */
+    if (message_put(manager->receive_queue, data, size, 0))
+      goto error;
+  }
+
+  LOG_D(MAC, "link manager receiver thread quits\n");
+
+  return NULL;
+
+error:
+  LOG_E(MAC, "%s: error\n", __FUNCTION__);
+  return NULL;
+}
+
+link_manager_t *create_link_manager(
+        message_queue_t *send_queue,
+        message_queue_t *receive_queue,
+        socket_link_t   *link)
+{
+  link_manager_t *ret = NULL;
+  pthread_attr_t attr;
+  pthread_t      t;
+
+  LOG_D(MAC, "create new link manager\n");
+
+  ret = calloc(1, sizeof(link_manager_t));
+  if (ret == NULL)
+    goto error;
+
+  ret->send_queue = send_queue;
+  ret->receive_queue = receive_queue;
+  ret->socket_link = link;
+  ret->run = 1;
+
+  if (pthread_attr_init(&attr))
+    goto error;
+
+  // Make the async interface threads real-time
+  //#ifndef LOWLATENCY
+  struct sched_param sched_param_recv_thread;
+  struct sched_param sched_param_send_thread;
+
+  sched_param_recv_thread.sched_priority = sched_get_priority_max(SCHED_RR) - 1;
+  pthread_attr_setschedparam(&attr, &sched_param_recv_thread);
+  pthread_attr_setschedpolicy(&attr, SCHED_RR);
+  //#endif
+
+  if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
+    goto error;
+
+  if (pthread_create(&t, &attr, link_manager_sender_thread, ret))
+    goto error;
+  ret->sender = t;
+
+  if (pthread_create(&t, &attr, link_manager_receiver_thread, ret))
+    /* we should destroy the other thread here */
+    goto error;
+  ret->receiver = t;
+
+  if (pthread_attr_destroy(&attr))
+    /* to be clean we should destroy the threads at this point,
+     * even if in practice we never reach it */
+    goto error;
+
+  return ret;
+
+error:
+  LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  free(ret);
+  return NULL;
+}
+
+void destroy_link_manager(link_manager_t *manager)
+{
+  LOG_D(MAC, "destroying link manager\n");
+  manager->run = 0;
+  /* todo: force threads to stop (using a dummy message?) */
+}
+
+#ifdef SERVER_TEST
+
+#include <string.h>
+
+int main(void)
+{
+  socket_link_t   *link;
+  message_queue_t *send_queue;
+  message_queue_t *receive_queue;
+  link_manager_t  *manager;
+  void            *data;
+  int             size;
+  int             priority;
+
+  printf("starting server\n");
+
+  link = new_link_server(2210);
+  if (link == NULL) goto error;
+
+  send_queue = new_message_queue();
+  if (send_queue == NULL) goto error;
+  receive_queue = new_message_queue();
+  if (receive_queue == NULL) goto error;
+
+  manager = create_link_manager(send_queue, receive_queue, link);
+  if (manager == NULL) goto error;
+
+  data = strdup("hello"); if (data == NULL) goto error;
+  if (message_put(send_queue, data, 6, 100)) goto error;
+
+  if (message_get(receive_queue, &data, &size, &priority)) goto error;
+  printf("received message:\n");
+  printf("    data: %s\n", (char *)data);
+  printf("    size: %d\n", size);
+  printf("    priority: %d\n", priority);
+
+  printf("server ends\n");
+  return 0;
+
+error:
+  printf("there was an error\n");
+  return 1;
+}
+
+#endif
+
+#ifdef CLIENT_TEST
+
+#include <string.h>
+#include <unistd.h>
+
+int main(void)
+{
+  socket_link_t   *link;
+  message_queue_t *send_queue;
+  message_queue_t *receive_queue;
+  link_manager_t  *manager;
+  void            *data;
+  int             size;
+  int             priority;
+
+  printf("starting client\n");
+
+  link = new_link_client("127.0.0.1", 2210);
+  if (link == NULL) goto error;
+
+  send_queue = new_message_queue();
+  if (send_queue == NULL) goto error;
+  receive_queue = new_message_queue();
+  if (receive_queue == NULL) goto error;
+
+  manager = create_link_manager(send_queue, receive_queue, link);
+  if (manager == NULL) goto error;
+
+  if (message_get(receive_queue, &data, &size, &priority)) goto error;
+  printf("received message:\n");
+  printf("    data: %s\n", (char *)data);
+  printf("    size: %d\n", size);
+  printf("    priority: %d\n", priority);
+
+  data = strdup("world"); if (data == NULL) goto error;
+  if (message_put(send_queue, data, 6, 200)) goto error;
+
+  /* let's wait for the message to be sent (unreliable sleep, but does it for the test) */
+  sleep(1);
+
+  printf("client ends\n");
+  return 0;
+
+error:
+  printf("there was an error\n");
+  return 1;
+}
+
+#endif
diff --git a/openair2/UTIL/ASYNC_IF/link_manager.h b/openair2/UTIL/ASYNC_IF/link_manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..a25c072b41245d17915b044dfde7e01c669452fd
--- /dev/null
+++ b/openair2/UTIL/ASYNC_IF/link_manager.h
@@ -0,0 +1,63 @@
+/*
+ * 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.0  (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 link_manager.h
+ * \brief this is the implementation of a link manager
+ * \author Cedric Roux
+ * \date November 2015
+ * \version 1.0
+ * \email: cedric.roux@eurecom.fr
+ * @ingroup _mac
+ */
+
+#ifndef LINK_MANAGER_H
+#define LINK_MANAGER_H
+
+//#include "message_queue.h"
+#include "ringbuffer_queue.h"
+#include "socket_link.h"
+
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+  message_queue_t *send_queue;
+  message_queue_t *receive_queue;
+  socket_link_t   *socket_link;
+  pthread_t       sender;
+  pthread_t       receiver;
+  volatile int    run;
+} link_manager_t;
+
+link_manager_t *create_link_manager(
+        message_queue_t *send_queue,
+        message_queue_t *receive_queue,
+        socket_link_t   *link);
+void destroy_link_manager(link_manager_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LINK_MANAGER_H */
diff --git a/openair2/UTIL/ASYNC_IF/message_queue.c b/openair2/UTIL/ASYNC_IF/message_queue.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee6c92d852a670d276720e7038f043a06eee8d94
--- /dev/null
+++ b/openair2/UTIL/ASYNC_IF/message_queue.c
@@ -0,0 +1,204 @@
+/*
+ * 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.0  (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 message_queue.c
+ * \brief this is the implementation of a message queue
+ * \author Cedric Roux
+ * \date November 2015
+ * \version 1.0
+ * \email: cedric.roux@eurecom.fr
+ * @ingroup _mac
+ */
+
+#include "message_queue.h"
+#include "log.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+message_queue_t *new_message_queue(void)
+{
+  message_queue_t *ret = NULL;
+
+  ret = calloc(1, sizeof(message_queue_t));
+  if (ret == NULL)
+    goto error;
+
+  ret->mutex = calloc(1, sizeof(pthread_mutex_t));
+  if (ret->mutex == NULL)
+    goto error;
+  if (pthread_mutex_init(ret->mutex, NULL))
+    goto error;
+
+  ret->cond = calloc(1, sizeof(pthread_cond_t));
+  if (ret->cond == NULL)
+    goto error;
+  if (pthread_cond_init(ret->cond, NULL))
+    goto error;
+
+  return ret;
+
+error:
+  LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  if (ret != NULL) {
+    free(ret->mutex);
+    free(ret->cond);
+    memset(ret, 0, sizeof(message_queue_t));
+    free(ret);
+  }
+  return NULL;
+}
+
+int message_put(message_queue_t *queue, void *data, int size, int priority)
+{
+  message_t *m = NULL;
+
+  m = calloc(1, sizeof(message_t));
+  if (m == NULL)
+    goto error;
+
+  m->data = data;
+  m->size = size;
+  m->priority = priority;
+  m->next = NULL;
+
+  if (pthread_mutex_lock(queue->mutex))
+    goto error;
+
+  if (queue->count == 0)
+    queue->head = m;
+  else
+    queue->tail->next = m;
+  queue->tail = m;
+
+  queue->count++;
+
+  if (pthread_cond_signal(queue->cond)) {
+    LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    pthread_mutex_unlock(queue->mutex);
+    exit(1);
+  }
+  if (pthread_mutex_unlock(queue->mutex)) {
+    LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  return 0;
+
+error:
+  free(m);
+  LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int message_get(message_queue_t *queue, void **data, int *size, int *priority)
+{
+  message_t *m;
+
+  if (pthread_mutex_lock(queue->mutex))
+    goto error;
+
+  while (queue->count == 0) {
+    if (pthread_cond_wait(queue->cond, queue->mutex)) {
+      pthread_mutex_unlock(queue->mutex);
+      goto error;
+    }
+  }
+
+  m = queue->head;
+  queue->head = queue->head->next;
+  if (queue->head == NULL)
+    queue->tail = NULL;
+
+  queue->count--;
+
+  if (pthread_mutex_unlock(queue->mutex))
+    goto error;
+
+  *data = m->data;
+  *size = m->size;
+  *priority = m->priority;
+  free(m);
+
+  return 0;
+
+error:
+  LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+/* when calling this function, the queue must not be used anymore (we don't lock it) */
+/* we suppose that the data pointer in messages was allocated by malloc/calloc/realloc */
+void destroy_message_queue(message_queue_t *queue)
+{
+  while (queue->head) {
+    message_t *m = queue->head;
+    queue->head = queue->head->next;
+    free(m->data);
+    memset(m, 0, sizeof(message_t));
+    free(m);
+  }
+  free(queue->mutex);
+  free(queue->cond);
+  memset(queue, 0, sizeof(message_queue_t));
+  free(queue);
+}
+
+#ifdef TEST
+
+/* some very basic tests */
+int main(void)
+{
+  void *data;
+  int size;
+  int priority;
+  message_queue_t *q;
+  char *s;
+
+  q = new_message_queue();
+  if (q == NULL) goto error;
+
+  if (message_put(q, "hello", 6, 0)) goto error;
+  if (message_put(q, "world", 6, 1)) goto error;
+
+  if (message_get(q, &data, &size, &priority)) goto error;
+  printf("message:\n  data: '%s'\n  size: %d\n  priority: %d\n",
+         (char *)data, size, priority);
+  if (message_get(q, &data, &size, &priority)) goto error;
+  printf("message:\n  data: '%s'\n  size: %d\n  priority: %d\n",
+         (char *)data, size, priority);
+
+  /* let's put a message before destroying the queue */
+  s = malloc(10); if (s == NULL) goto error;
+  sprintf(s, "hello");
+  if (message_put(q, s, 6, 0)) goto error;
+  destroy_message_queue(q);
+
+  return 0;
+
+error:
+  printf("error\n");
+  return 1;
+}
+
+#endif
diff --git a/openair2/UTIL/ASYNC_IF/message_queue.h b/openair2/UTIL/ASYNC_IF/message_queue.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e46ec08d673064702f025edd879405526b6fbe0
--- /dev/null
+++ b/openair2/UTIL/ASYNC_IF/message_queue.h
@@ -0,0 +1,64 @@
+/*
+ * 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.0  (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 message_queue.h
+ * \brief this is the implementation of a message queue
+ * \author Cedric Roux
+ * \date November 2015
+ * \version 1.0
+ * \email: cedric.roux@eurecom.fr
+ * @ingroup _mac
+ */
+
+#ifndef MESSAGE_QUEUE_H
+#define MESSAGE_QUEUE_H
+
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct message_t {
+  void *data;
+  int  size;
+  int  priority;
+  struct message_t *next;
+} message_t;
+
+typedef struct {
+  message_t       *head;
+  message_t       *tail;
+  volatile int    count;
+  pthread_mutex_t *mutex;
+  pthread_cond_t  *cond;
+} message_queue_t;
+
+message_queue_t *new_message_queue(void);
+int message_put(message_queue_t *queue, void *data, int size, int priority);
+int message_get(message_queue_t *queue, void **data, int *size, int *priority);
+void destroy_message_queue(message_queue_t *queue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MESSAGE_QUEUE_H */
diff --git a/openair2/UTIL/ASYNC_IF/ringbuffer_queue.c b/openair2/UTIL/ASYNC_IF/ringbuffer_queue.c
new file mode 100644
index 0000000000000000000000000000000000000000..047e3f716c67cba5558948356fdaa76518acf9db
--- /dev/null
+++ b/openair2/UTIL/ASYNC_IF/ringbuffer_queue.c
@@ -0,0 +1,136 @@
+/*
+ * 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.0  (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 ringbuffer_queue.c
+ * \brief Lock-free ringbuffer used for async message passing of agent
+ * \author Xenofon Foukas
+ * \date March 2016
+ * \version 1.0
+ * \email: x.foukas@sms.ed.ac.uk
+ * @ingroup _mac
+ */
+
+#include "ringbuffer_queue.h"
+#include "log.h"
+
+message_queue_t * new_message_queue(int size) {
+  
+  message_queue_t *ret = NULL;
+
+  ret = calloc(1, sizeof(message_queue_t));
+  if (ret == NULL)
+    goto error;
+
+  lfds700_misc_library_init_valid_on_current_logical_core();
+  lfds700_misc_prng_init(&(ret->ps));
+  ret->ringbuffer_array = malloc(sizeof(struct lfds700_ringbuffer_element) * size);
+  lfds700_ringbuffer_init_valid_on_current_logical_core(&(ret->ringbuffer_state),
+							ret->ringbuffer_array,
+							size,
+							&(ret->ps),
+							NULL);
+
+  return ret;
+  
+ error:
+  LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  if (ret != NULL) {
+    free(ret->ringbuffer_array);
+    memset(ret, 0, sizeof(message_queue_t));
+    free(ret);
+  }
+  return NULL;
+}
+
+int message_put(message_queue_t *queue, void *data, int size, int priority) {
+
+  struct lfds700_misc_prng_state ls;
+  enum lfds700_misc_flag overwrite_occurred_flag;
+  message_t *overwritten_msg;
+  message_t *m = NULL;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+  lfds700_misc_prng_init(&ls);
+  
+  m = calloc(1, sizeof(message_t));
+  if (m == NULL)
+    goto error;
+
+  m->data = data;
+  m->size = size;
+  m->priority = priority;
+
+  lfds700_ringbuffer_write(&(queue->ringbuffer_state),
+			   NULL,
+			   (void *) m,
+			   &overwrite_occurred_flag,
+			   NULL,
+			   (void **) &overwritten_msg,
+			   &ls);
+
+  if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
+    free(overwritten_msg->data);
+    free(overwritten_msg);
+  }
+
+  return 0;
+
+ error:
+  free(m);
+  LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+  return -1;
+}
+
+int message_get(message_queue_t *queue, void **data, int *size, int *priority) {
+  message_t *m;
+  struct lfds700_misc_prng_state ls;
+  
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+  lfds700_misc_prng_init(&ls);
+
+  if (lfds700_ringbuffer_read(&(queue->ringbuffer_state), NULL, (void **) &m, &ls) == 0) {
+    return -1;
+  }
+
+  *data = m->data;
+  *size = m->size;
+  *priority = m->priority;
+  free(m);
+  return 0;
+}
+
+message_queue_t destroy_message_queue(message_queue_t *queue) {
+  struct lfds700_misc_prng_state ls;
+
+  message_t *m;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+  lfds700_misc_prng_init(&ls);
+
+  while (lfds700_ringbuffer_read(&(queue->ringbuffer_state), NULL, (void **) &m, &ls) != 0) {
+    free(m->data);
+    memset(m, 0, sizeof(message_t));
+    free(m);
+  }
+  free(queue->ringbuffer_array);
+  memset(queue, 0, sizeof(message_queue_t));
+  free(queue);
+}
diff --git a/openair2/UTIL/ASYNC_IF/ringbuffer_queue.h b/openair2/UTIL/ASYNC_IF/ringbuffer_queue.h
new file mode 100644
index 0000000000000000000000000000000000000000..7dc4637404773c67457b8ec7680e5aedcbce167f
--- /dev/null
+++ b/openair2/UTIL/ASYNC_IF/ringbuffer_queue.h
@@ -0,0 +1,53 @@
+/*
+ * 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.0  (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 ringbuffer_queue.h
+ * \brief Lock-free ringbuffer used for async message passing of agent
+ * \author Xenofon Foukas
+ * \date March 2016
+ * \version 1.0
+ * \email: x.foukas@sms.ed.ac.uk
+ * @ingroup _mac
+ */
+
+#ifndef RINGBUFFER_QUEUE_H
+#define RINGBUFFER_QUEUE_H
+
+#include "liblfds700.h"
+
+typedef struct message_s {
+  void *data;
+  int size;
+  int priority;
+} message_t;
+
+typedef struct {
+  struct lfds700_misc_prng_state ps;
+  struct lfds700_ringbuffer_element *ringbuffer_array;
+  struct lfds700_ringbuffer_state ringbuffer_state;
+} message_queue_t;
+
+message_queue_t * new_message_queue(int size);
+int message_put(message_queue_t *queue, void *data, int size, int priority);
+int message_get(message_queue_t *queue, void **data, int *size, int *priority);
+message_queue_t destroy_message_queue(message_queue_t *queue);
+
+#endif /* RINGBUFFER_QUEUE_H */
diff --git a/openair2/UTIL/ASYNC_IF/socket_link.c b/openair2/UTIL/ASYNC_IF/socket_link.c
new file mode 100644
index 0000000000000000000000000000000000000000..720a55398c5b719510c0a1dea304cecf416afbd8
--- /dev/null
+++ b/openair2/UTIL/ASYNC_IF/socket_link.c
@@ -0,0 +1,357 @@
+/*
+ * 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.0  (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 socket_link.c
+ * \brief this is the implementation of a TCP socket ASYNC IF
+ * \author Cedric Roux
+ * \date November 2015
+ * \version 1.0
+ * \email: cedric.roux@eurecom.fr
+ * @ingroup _mac
+ */
+
+#include "socket_link.h"
+#include "log.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <stdint.h>
+
+socket_link_t *new_link_server(int port)
+{
+  socket_link_t      *ret = NULL;
+  int                reuse;
+  struct sockaddr_in addr;
+  socklen_t          addrlen;
+  int                socket_server = -1;
+  int no_delay;
+  
+  ret = calloc(1, sizeof(socket_link_t));
+  if (ret == NULL) {
+    LOG_E(MAC, "%s:%d: out of memory\n", __FILE__, __LINE__);
+    goto error;
+  }
+  ret->socket_fd = -1;
+
+  LOG_D(MAC, "create a new link server socket at port %d\n", port);
+
+  socket_server = socket(AF_INET, SOCK_STREAM, 0);
+  if (socket_server == -1) {
+    LOG_E(MAC, "%s:%d: socket: %s\n", __FILE__, __LINE__, strerror(errno));
+    goto error;
+  }
+
+  reuse = 1;
+  if (setsockopt(socket_server, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
+    LOG_E(MAC, "%s:%d: setsockopt: %s\n", __FILE__, __LINE__, strerror(errno));
+    goto error;
+  }
+
+  no_delay = 1;
+  if (setsockopt(socket_server, IPPROTO_TCP, TCP_NODELAY, &no_delay, sizeof(no_delay)) == -1) {
+    LOG_E(MAC, "%s:%d: setsockopt: %s\n", __FILE__, __LINE__, strerror(errno));
+    goto error;
+  }
+  
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(port);
+  addr.sin_addr.s_addr = INADDR_ANY;
+  if (bind(socket_server, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+    LOG_E(MAC, "%s:%d: bind: %s\n", __FILE__, __LINE__, strerror(errno));
+    goto error;
+  }
+
+  if (listen(socket_server, 5)) {
+    LOG_E(MAC, "%s:%d: listen: %s\n", __FILE__, __LINE__, strerror(errno));
+    goto error;
+  }
+
+  addrlen = sizeof(addr);
+  ret->socket_fd = accept(socket_server, (struct sockaddr *)&addr, &addrlen);
+  if (ret->socket_fd == -1) {
+    LOG_E(MAC, "%s:%d: accept: %s\n", __FILE__, __LINE__, strerror(errno));
+    goto error;
+  }
+
+  close(socket_server);
+
+  LOG_D(MAC, "connection from %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+  return ret;
+
+error:
+  close(socket_server);
+  if (ret != NULL) close(ret->socket_fd);
+  free(ret);
+  LOG_E(MAC, "ERROR in new_link_server (see above), returning NULL\n");
+  return NULL;
+}
+
+socket_link_t *new_link_client(char *server, int port)
+{
+  socket_link_t      *ret = NULL;
+  struct sockaddr_in addr;
+  int no_delay;
+
+  ret = calloc(1, sizeof(socket_link_t));
+  if (ret == NULL) {
+    LOG_E(MAC, "%s:%d: out of memory\n", __FILE__, __LINE__);
+    goto error;
+  }
+  ret->socket_fd = -1;
+
+  LOG_D(MAC, "create a new link client socket connecting to %s:%d\n", server, port);
+
+  ret->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
+  if (ret->socket_fd == -1) {
+    LOG_E(MAC, "%s:%d: socket: %s\n", __FILE__, __LINE__, strerror(errno));
+    goto error;
+  }
+
+  no_delay = 1;
+  if (setsockopt(ret->socket_fd, SOL_TCP, TCP_NODELAY, &no_delay, sizeof(no_delay)) == -1) {
+    LOG_E(MAC, "%s:%d: setsockopt: %s\n", __FILE__, __LINE__, strerror(errno));
+    goto error;
+  }
+  
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(port);
+  if (inet_aton(server, &addr.sin_addr) == 0) {
+    LOG_E(MAC, "invalid IP address '%s', use a.b.c.d notation\n", server);
+    goto error;
+  }
+  if (connect(ret->socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+    LOG_E(MAC, "%s:%d: connect: %s\n", __FILE__, __LINE__, strerror(errno));
+    goto error;
+  }
+
+  LOG_D(MAC, "connection to %s:%d established\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+  return ret;
+
+error:
+  if (ret != NULL) close(ret->socket_fd);
+  free(ret);
+  LOG_E(MAC, "ERROR in new_link_client (see above), returning NULL\n");
+  return NULL;
+}
+
+/*
+ * return -1 on error and 0 if the sending was fine
+ */
+static int socket_send(int socket_fd, void *buf, int size)
+{
+  char *s = buf;
+  int   l;
+
+  while (size) {
+    l = send(socket_fd, s, size, MSG_NOSIGNAL);
+    if (l == -1) goto error;
+    if (l == 0) { LOG_E(MAC, "%s:%d: this cannot happen, normally...\n", __FILE__, __LINE__); abort(); }
+    size -= l;
+    s += l;
+  }
+
+  return 0;
+
+error:
+  LOG_E(MAC, "socket_send: ERROR: %s\n", strerror(errno));
+  return -1;
+}
+
+/*
+ * return -1 on error and 0 if the receiving was fine
+ */
+static int socket_receive(int socket_fd, void *buf, int size)
+{
+  char *s = buf;
+  int   l;
+
+  while (size) {
+    l = read(socket_fd, s, size);
+    if (l == -1) goto error;
+    if (l == 0) goto socket_closed;
+    size -= l;
+    s += l;
+  }
+
+  return 0;
+
+error:
+  LOG_E(MAC, "socket_receive: ERROR: %s\n", strerror(errno));
+  return -1;
+
+socket_closed:
+  LOG_E(MAC, "socket_receive: socket closed\n");
+  return -1;
+}
+
+/*
+ * return -1 on error and 0 if the sending was fine
+ */
+int link_send_packet(socket_link_t *link, void *data, int size)
+{
+  char sizebuf[4];
+  int32_t s = size;
+
+  /* send the size first, maximum is 2^31 bytes */
+  sizebuf[0] = (s >> 24) & 255;
+  sizebuf[1] = (s >> 16) & 255;
+  sizebuf[2] = (s >> 8) & 255;
+  sizebuf[3] = s & 255;
+
+  if (socket_send(link->socket_fd, sizebuf, 4) == -1)
+    goto error;
+
+  link->bytes_sent += 4;
+
+  if (socket_send(link->socket_fd, data, size) == -1)
+    goto error;
+
+  link->bytes_sent += size;
+  link->packets_sent++;
+
+  return 0;
+
+error:
+  return -1;
+}
+
+/*
+ * return -1 on error and 0 if the sending was fine
+ */
+int link_receive_packet(socket_link_t *link, void **ret_data, int *ret_size)
+{
+  unsigned char sizebuf[4];
+  int32_t       size;
+  void          *data = NULL;
+
+  /* received the size first, maximum is 2^31 bytes */
+  if (socket_receive(link->socket_fd, sizebuf, 4) == -1)
+    goto error;
+
+  size = (sizebuf[0] << 24) |
+         (sizebuf[1] << 16) |
+         (sizebuf[2] << 8)  |
+          sizebuf[3];
+
+  link->bytes_received += 4;
+
+  data = malloc(size);
+  if (data == NULL) {
+    LOG_E(MAC, "%s:%d: out of memory\n", __FILE__, __LINE__);
+    goto error;
+  }
+
+  if (socket_receive(link->socket_fd, data, size) == -1)
+    goto error;
+
+  link->bytes_received += size;
+  link->packets_received++;
+
+  *ret_data = data;
+  *ret_size = size;
+  return 0;
+
+error:
+  free(data);
+  *ret_data = NULL;
+  *ret_size = 0;
+  return -1;
+}
+
+/*
+ * return -1 on error, 0 if all is fine
+ */
+int close_link(socket_link_t *link)
+{
+  close(link->socket_fd);
+  memset(link, 0, sizeof(socket_link_t));
+  free(link);
+  return 0;
+}
+
+#ifdef SERVER_TEST
+
+#include <inttypes.h>
+
+int main(void)
+{
+  void *data;
+  int size;
+  socket_link_t *l = new_link_server(2210);
+  if (l == NULL) { printf("no link created\n"); return 1; }
+  printf("link is up\n");
+  printf("server starts sleeping...\n");
+  /* this sleep is here to test for broken pipe. You can run "nc localhost 2210"
+   * and interrupt it quickly so that the server gets a 'broken' pipe on the
+   * following link_send_packet.
+   */
+  sleep(1);
+  printf("... done\n");
+  if (link_send_packet(l, "hello\n", 6+1) ||
+      link_send_packet(l, "world\n", 6+1)) return 1;
+  if (link_receive_packet(l, &data, &size)) return 1; printf("%s", (char *)data); free(data);
+  if (link_receive_packet(l, &data, &size)) return 1; printf("%s", (char *)data); free(data);
+  printf("stats:\n");
+  printf("    sent packets %"PRIu64"\n", l->packets_sent);
+  printf("    sent bytes %"PRIu64"\n", l->bytes_sent);
+  printf("    received packets %"PRIu64"\n", l->packets_received);
+  printf("    received bytes %"PRIu64"\n", l->bytes_received);
+  if (close_link(l)) return 1;
+  printf("link is down\n");
+  return 0;
+}
+
+#endif
+
+#ifdef CLIENT_TEST
+
+#include <inttypes.h>
+
+int main(void)
+{
+  void *data;
+  int size;
+  socket_link_t *l = new_link_client("127.0.0.1", 2210);
+  if (l == NULL) { printf("no link created\n"); return 1; }
+  printf("link is up\n");
+  if (link_receive_packet(l, &data, &size)) return 1; printf("%s", (char *)data); free(data);
+  if (link_receive_packet(l, &data, &size)) return 1; printf("%s", (char *)data); free(data);
+  if (link_send_packet(l, "bye\n", 4+1) ||
+      link_send_packet(l, "server\n", 7+1)) return 1;
+  printf("stats:\n");
+  printf("    sent packets %"PRIu64"\n", l->packets_sent);
+  printf("    sent bytes %"PRIu64"\n", l->bytes_sent);
+  printf("    received packets %"PRIu64"\n", l->packets_received);
+  printf("    received bytes %"PRIu64"\n", l->bytes_received);
+  if (close_link(l)) return 1;
+  printf("link is down\n");
+  return 0;
+}
+
+#endif
diff --git a/openair2/UTIL/ASYNC_IF/socket_link.h b/openair2/UTIL/ASYNC_IF/socket_link.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b9f438c8aa0747eecd759fb02939e701ddc004d
--- /dev/null
+++ b/openair2/UTIL/ASYNC_IF/socket_link.h
@@ -0,0 +1,58 @@
+/*
+ * 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.0  (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 socket_link.h
+ * \brief this is the implementation of a TCP socket ASYNC IF
+ * \author Cedric Roux
+ * \date November 2015
+ * \version 1.0
+ * \email: cedric.roux@eurecom.fr
+ * @ingroup _mac
+ */
+
+#ifndef SOCKET_LINK_H
+#define SOCKET_LINK_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+  int      socket_fd;
+  uint64_t bytes_sent;
+  uint64_t packets_sent;
+  uint64_t bytes_received;
+  uint64_t packets_received;
+} socket_link_t;
+
+socket_link_t *new_link_server(int port);
+socket_link_t *new_link_client(char *server, int port);
+int link_send_packet(socket_link_t *link, void *data, int size);
+int link_receive_packet(socket_link_t *link, void **data, int *size);
+int close_link(socket_link_t *link);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SOCKET_LINK_H */
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/gcc_and_gnumake/Makefile b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/gcc_and_gnumake/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..27e4d91df3c2f7a1dafd98aa6ac8b04441961194
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/gcc_and_gnumake/Makefile
@@ -0,0 +1,168 @@
+##### paths #####
+BINDIR    := ../../bin
+INCDIR    := ../../inc
+OBJDIR    := ../../obj
+SRCDIR    := ../../src
+
+##### misc #####
+QUIETLY        := 1>/dev/null 2>/dev/null
+VERSION_NUMBER := 1
+MINOR_NUMBER   := 0
+RELEASE_NUMBER := 0
+
+##### sources, objects and libraries #####
+BINNAME    := liblfds700
+ARFILENAME := $(BINNAME).a
+ARPATHNAME := $(BINDIR)/$(ARFILENAME)
+SOBASENAME := $(BINNAME).so
+SONAME     := $(SOBASENAME).$(VERSION_NUMBER)
+SOFILENAME := $(SONAME).$(MINOR_NUMBER).$(RELEASE_NUMBER)
+SOPATHNAME := $(BINDIR)/$(SOFILENAME)
+INCNAME    := $(INCDIR)/$(BINNAME).h
+SRCDIRS := lfds700_btree_addonly_unbalanced lfds700_freelist lfds700_hash_addonly lfds700_list_addonly_ordered_singlylinked lfds700_list_addonly_singlylinked_unordered lfds700_misc lfds700_queue lfds700_queue_bounded_singleconsumer_singleproducer lfds700_ringbuffer lfds700_stack
+SOURCES := lfds700_hash_addonly_cleanup.c lfds700_hash_addonly_get.c lfds700_hash_addonly_init.c lfds700_hash_addonly_insert.c lfds700_hash_addonly_iterate.c lfds700_hash_addonly_query.c \
+           lfds700_list_addonly_ordered_singlylinked_cleanup.c lfds700_list_addonly_ordered_singlylinked_get.c lfds700_list_addonly_ordered_singlylinked_init.c lfds700_list_addonly_ordered_singlylinked_insert.c lfds700_list_addonly_ordered_singlylinked_query.c \
+           lfds700_list_addonly_singlylinked_unordered_cleanup.c lfds700_list_addonly_singlylinked_unordered_get.c lfds700_list_addonly_singlylinked_unordered_init.c lfds700_list_addonly_singlylinked_unordered_insert.c lfds700_list_addonly_singlylinked_unordered_query.c \
+           lfds700_btree_addonly_unbalanced_cleanup.c lfds700_btree_addonly_unbalanced_get.c lfds700_btree_addonly_unbalanced_init.c lfds700_btree_addonly_unbalanced_insert.c lfds700_btree_addonly_unbalanced_query.c \
+           lfds700_freelist_cleanup.c lfds700_freelist_init.c lfds700_freelist_pop.c lfds700_freelist_push.c lfds700_freelist_query.c \
+           lfds700_misc_cleanup.c lfds700_misc_globals.c lfds700_misc_init.c lfds700_misc_prng.c lfds700_misc_query.c \
+           lfds700_queue_cleanup.c lfds700_queue_dequeue.c lfds700_queue_enqueue.c lfds700_queue_init.c lfds700_queue_query.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c lfds700_queue_bounded_singleconsumer_singleproducer_init.c lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
+           lfds700_ringbuffer_cleanup.c lfds700_ringbuffer_init.c lfds700_ringbuffer_query.c lfds700_ringbuffer_read.c lfds700_ringbuffer_write.c \
+           lfds700_stack_cleanup.c lfds700_stack_init.c lfds700_stack_pop.c lfds700_stack_push.c lfds700_stack_query.c
+OBJECTS := $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
+SYSLIBS := 
+
+##### default paths fix up #####
+CPATH   := $(subst : ,:,$(SRCDIR):$(INCDIR))
+
+##### tools #####
+MAKE    := make
+MFLAGS  := 
+
+DG      := gcc
+DGFLAGS := -MM -std=gnu89
+
+CC      := gcc
+CFBASE  := -c -fno-strict-aliasing -std=gnu89 -Wall -Werror -Wno-unknown-pragmas -Wno-unused-but-set-variable -Wno-unused-variable
+CFCOV   := -O0 -ggdb -DCOVERAGE -fprofile-arcs -ftest-coverage
+CFDBG   := -O0 -ggdb -D_DEBUG
+CFPROF  := -O0 -ggdb -DPROF     -pg
+CFREL   := -O2       -DNDEBUG   -finline-functions
+CFTSAN  := -O0 -ggdb -DTSAN     -fsanitize=thread -fPIC
+CFBARE  := -ffreestanding -nodefaultlibs -nostdinc -nostdlib
+
+AR      := ar
+AFLAGS  := -rcs
+
+LD      := gcc
+LFBASE  := -pthread -shared -std=gnu89 -Wl,-soname,$(SONAME) -o $(SOPATHNAME) -Wall -Werror
+LFCOV   := -O0 -fprofile-arcs -ftest-coverage
+LFDBG   := -O0 -ggdb
+LFPROF  := -O0 -pg
+LFREL   := -O2 -s -finline-functions
+LFTSAN  := -O0 -fsanitize=thread -fPIC
+LFBARE  := -ffreestanding -nodefaultlibs -nostdinc -nostdlib
+
+##### CPU variants #####
+GCCARCH := native
+CFBASE  += -march=$(GCCARCH)
+
+##### build variants #####
+ifeq ($(findstring so,$(MAKECMDGOALS)),so)
+  CFBASE += -fPIC
+endif
+
+CFLAGS += $(CFBASE)
+LFLAGS += $(LFBASE)
+
+ifeq ($(MAKECMDGOALS),)
+  CFLAGS += $(CFDBG)
+  LFLAGS += $(LFDBG)
+endif
+
+ifeq ($(findstring cov,$(MAKECMDGOALS)),cov)
+  CFLAGS  += $(CFCOV)
+  LFLAGS  += $(LFCOV)
+  SYSLIBS += -lgcov
+endif
+
+ifeq ($(findstring dbg,$(MAKECMDGOALS)),dbg)
+  CFLAGS += $(CFDBG)
+  LFLAGS += $(LFDBG)
+endif
+
+ifeq ($(findstring prof,$(MAKECMDGOALS)),prof)
+  CFLAGS += $(CFPROF)
+  LFLAGS += $(LFPROF)
+endif
+
+ifeq ($(findstring rel,$(MAKECMDGOALS)),rel)
+  CFLAGS += $(CFREL)
+  LFLAGS += $(LFREL)
+endif
+
+ifeq ($(findstring tsan,$(MAKECMDGOALS)),tsan)
+  CFLAGS += $(CFTSAN)
+  LFLAGS += $(LFTSAN)
+endif
+
+ifeq ($(findstring b_,$(MAKECMDGOALS)),b_)
+  CFLAGS += $(CFBARE)
+  LFLAGS += $(CFBARE)
+endif
+
+##### search paths #####
+vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
+
+##### implicit rules #####
+$(OBJDIR)/%.o : %.c
+	$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
+	$(CC) $(CFLAGS) -o $@ $<
+
+##### explicit rules #####
+$(ARPATHNAME) : $(OBJECTS)
+	$(AR) $(AFLAGS) $(ARPATHNAME) $(OBJECTS)
+
+$(SOPATHNAME) : $(OBJECTS)
+	$(LD) $(LFLAGS) $(OBJECTS) -o $(SOPATHNAME)
+	@ln -fs $(SOFILENAME) $(BINDIR)/$(SONAME)
+	@ln -fs $(SOFILENAME) $(BINDIR)/$(SOBASENAME)
+
+##### phony #####
+.PHONY : clean bare_ar_cov bare_ar_dbg bare_ar_prof bare_ar_rel bare_ar_tsan bare_so_cov bare_so_dbg bare_so_prof bare_so_rel bare_so_tsan hosted_ar_cov hosted_ar_dbg hosted_ar_prof hosted_ar_rel hosted_ar_tsan hosted_so_cov hosted_so_dbg hosted_so_prof hosted_so_rel hosted_so_tsan
+
+clean : 
+	@rm -f $(BINDIR)/* $(OBJDIR)/*
+
+bare_ar_cov   : $(ARPATHNAME) # bare, archive (.a), coverage
+bare_ar_dbg   : $(ARPATHNAME) # bare, archive (.a), debug
+bare_ar_prof  : $(ARPATHNAME) # bare, archive (.a), profiling
+bare_ar_rel   : $(ARPATHNAME) # bare, archive (.a), release
+bare_ar_tsan  : $(ARPATHNAME) # bare, archive (.a), thread sanitizer
+
+bare_so_cov   : $(SOPATHNAME) # bare, shared (.so), coverage
+bare_so_dbg   : $(SOPATHNAME) # bare, shared (.so), debug
+bare_so_prof  : $(SOPATHNAME) # bare, shared (.so), profiling
+bare_so_rel   : $(SOPATHNAME) # bare, shared (.so), release
+bare_so_tsan  : $(SOPATHNAME) # bare, shared (.so), thread sanitizer
+
+hosted_ar_cov  : $(ARPATHNAME) # hosted implementation, archive (.a), coverage
+hosted_ar_dbg  : $(ARPATHNAME) # hosted implementation, archive (.a), debug
+hosted_ar_prof : $(ARPATHNAME) # hosted implementation, archive (.a), profiling
+hosted_ar_rel  : $(ARPATHNAME) # hosted implementation, archive (.a), release
+hosted_ar_tsan : $(ARPATHNAME) # hosted implementation, archive (.a), thread sanitizer
+
+hosted_so_cov  : $(SOPATHNAME) # hosted implementation, shared (.so), coverage
+hosted_so_dbg  : $(SOPATHNAME) # hosted implementation, shared (.so), debug
+hosted_so_prof : $(SOPATHNAME) # hosted implementation, shared (.so), profiling
+hosted_so_rel  : $(SOPATHNAME) # hosted implementation, shared (.so), release
+hosted_so_tsan : $(SOPATHNAME) # hosted implementation, shared (.so), thread sanitizer
+
+##### dependencies #####
+-include $(DEPENDS)
+
+##### notes #####
+# TRD : we use -std=gnu89 for C++ style comments
+#       hosted implementation differs from bare simply in that <assert.h> ends up being included
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/gcc_kbuild_and_gnumake/Kbuild b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/gcc_kbuild_and_gnumake/Kbuild
new file mode 100644
index 0000000000000000000000000000000000000000..1ae6b362404b0755a923764ce82201c4fa82dd5c
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/gcc_kbuild_and_gnumake/Kbuild
@@ -0,0 +1,76 @@
+lib-y :=
+
+lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_cleanup.o
+lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_get.o
+lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_init.o
+lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_insert.o
+lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_query.o
+
+lib-y += ../../src/lfds700_freelist/lfds700_freelist_cleanup.o
+lib-y += ../../src/lfds700_freelist/lfds700_freelist_init.o
+lib-y += ../../src/lfds700_freelist/lfds700_freelist_pop.o
+lib-y += ../../src/lfds700_freelist/lfds700_freelist_push.o
+lib-y += ../../src/lfds700_freelist/lfds700_freelist_query.o
+
+lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.o
+lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_get.o
+lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_init.o
+lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_insert.o
+lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_iterate.o
+lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_query.o
+
+lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_cleanup.o
+lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_get.o
+lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_init.o
+lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_insert.o
+lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_query.o
+
+lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_cleanup.o
+lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_get.o
+lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_init.o
+lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.o
+lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_query.o
+
+lib-y += ../../src/lfds700_misc/lfds700_misc_cleanup.o
+lib-y += ../../src/lfds700_misc/lfds700_misc_globals.o
+lib-y += ../../src/lfds700_misc/lfds700_misc_init.o
+lib-y += ../../src/lfds700_misc/lfds700_misc_prng.o
+lib-y += ../../src/lfds700_misc/lfds700_misc_query.o
+
+lib-y += ../../src/lfds700_queue/lfds700_queue_cleanup.o
+lib-y += ../../src/lfds700_queue/lfds700_queue_dequeue.o
+lib-y += ../../src/lfds700_queue/lfds700_queue_enqueue.o
+lib-y += ../../src/lfds700_queue/lfds700_queue_init.o
+lib-y += ../../src/lfds700_queue/lfds700_queue_query.o
+
+lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.o
+lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.o
+lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.o
+lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_init.o
+lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_query.o
+
+lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_cleanup.o
+lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_init.o
+lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_query.o
+lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_read.o
+lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_write.o
+
+lib-y += ../../src/lfds700_stack/lfds700_stack_cleanup.o
+lib-y += ../../src/lfds700_stack/lfds700_stack_init.o
+lib-y += ../../src/lfds700_stack/lfds700_stack_pop.o
+lib-y += ../../src/lfds700_stack/lfds700_stack_push.o
+lib-y += ../../src/lfds700_stack/lfds700_stack_query.o
+
+libs-y := ../../bin/
+
+ccflags-y := -I$(src)/../../inc
+ccflags-y += -I$(src)/../../inc/liblfds700
+ccflags-y += -D_KERNEL_MODE
+ccflags-y += -fno-strict-aliasing
+ccflags-y += -std=gnu89
+ccflags-y += -Wall
+ccflags-y += -Werror
+ccflags-y += -Wno-unknown-pragmas
+ccflags-y += -Wno-unused-but-set-variable
+ccflags-y += -Wno-unused-variable
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/gcc_kbuild_and_gnumake/Makefile b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/gcc_kbuild_and_gnumake/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d6de5f4b5dbf897b5a74fcba0d28050cc6e0b53a
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/gcc_kbuild_and_gnumake/Makefile
@@ -0,0 +1,14 @@
+default:
+	$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD)
+
+clean:
+	$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
+	find ../../src/ -name "*.o" -type f -delete
+
+help:
+	$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) help
+
+modules:
+	$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
+
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/sdk_for_windows_7_and_gnumake/liblfds700.def b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/sdk_for_windows_7_and_gnumake/liblfds700.def
new file mode 100644
index 0000000000000000000000000000000000000000..583ce35dbdb08c553e2cb2a7f335f4bcaf9458da
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/sdk_for_windows_7_and_gnumake/liblfds700.def
@@ -0,0 +1,69 @@
+EXPORTS
+
+lfds700_btree_au_init_valid_on_current_logical_core                     = lfds700_btree_au_init_valid_on_current_logical_core
+lfds700_btree_au_cleanup                                                = lfds700_btree_au_cleanup
+lfds700_btree_au_insert                                                 = lfds700_btree_au_insert
+lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
+lfds700_btree_au_get_by_absolute_position                               = lfds700_btree_au_get_by_absolute_position
+lfds700_btree_au_get_by_relative_position                               = lfds700_btree_au_get_by_relative_position
+lfds700_btree_au_get_by_key                                             = lfds700_btree_au_get_by_key
+lfds700_btree_au_query                                                  = lfds700_btree_au_query
+
+lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
+lfds700_freelist_cleanup                            = lfds700_freelist_cleanup
+lfds700_freelist_push                               = lfds700_freelist_push
+lfds700_freelist_pop                                = lfds700_freelist_pop
+lfds700_freelist_query                              = lfds700_freelist_query
+
+lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
+lfds700_hash_a_cleanup                            = lfds700_hash_a_cleanup
+lfds700_hash_a_insert                             = lfds700_hash_a_insert
+lfds700_hash_a_get_by_key                         = lfds700_hash_a_get_by_key
+lfds700_hash_a_iterate_init                       = lfds700_hash_a_iterate_init
+lfds700_hash_a_iterate                            = lfds700_hash_a_iterate
+lfds700_hash_a_query                              = lfds700_hash_a_query
+
+lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
+lfds700_list_aos_cleanup                            = lfds700_list_aos_cleanup
+lfds700_list_aos_insert                             = lfds700_list_aos_insert
+lfds700_list_aos_get_by_key                         = lfds700_list_aos_get_by_key
+lfds700_list_aos_query                              = lfds700_list_aos_query
+
+lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
+lfds700_list_asu_cleanup                            = lfds700_list_asu_cleanup
+lfds700_list_asu_insert_at_position                 = lfds700_list_asu_insert_at_position
+lfds700_list_asu_insert_at_start                    = lfds700_list_asu_insert_at_start
+lfds700_list_asu_insert_at_end                      = lfds700_list_asu_insert_at_end
+lfds700_list_asu_insert_after_element               = lfds700_list_asu_insert_after_element
+lfds700_list_asu_get_by_key                         = lfds700_list_asu_get_by_key
+lfds700_list_asu_query                              = lfds700_list_asu_query
+
+lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
+lfds700_misc_library_cleanup                            = lfds700_misc_library_cleanup
+lfds700_misc_prng_init                                  = lfds700_misc_prng_init
+lfds700_misc_query                                      = lfds700_misc_query
+
+lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
+lfds700_queue_cleanup                            = lfds700_queue_cleanup
+lfds700_queue_enqueue                            = lfds700_queue_enqueue
+lfds700_queue_dequeue                            = lfds700_queue_dequeue
+lfds700_queue_query                              = lfds700_queue_query
+
+lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
+lfds700_queue_bss_cleanup                            = lfds700_queue_bss_cleanup
+lfds700_queue_bss_enqueue                            = lfds700_queue_bss_enqueue
+lfds700_queue_bss_dequeue                            = lfds700_queue_bss_dequeue
+lfds700_queue_bss_query                              = lfds700_queue_bss_query
+
+lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
+lfds700_ringbuffer_cleanup                            = lfds700_ringbuffer_cleanup
+lfds700_ringbuffer_read                               = lfds700_ringbuffer_read
+lfds700_ringbuffer_write                              = lfds700_ringbuffer_write
+lfds700_ringbuffer_query                              = lfds700_ringbuffer_query
+
+lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
+lfds700_stack_cleanup                            = lfds700_stack_cleanup
+lfds700_stack_push                               = lfds700_stack_push
+lfds700_stack_pop                                = lfds700_stack_pop
+lfds700_stack_query                              = lfds700_stack_query
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/sdk_for_windows_7_and_gnumake/makefile b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/sdk_for_windows_7_and_gnumake/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..7b257c92777703bc11c4c864f4cea3ddd5b10fa8
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/sdk_for_windows_7_and_gnumake/makefile
@@ -0,0 +1,114 @@
+##### paths #####
+BINDIR := ..\..\bin
+INCDIR := ..\..\inc
+OBJDIR := ..\..\obj
+SRCDIR := ..\..\src
+
+##### misc #####
+QUIETLY := 1>nul 2>nul
+NULL := 
+SPACE := $(NULL) # TRD : with a trailing space
+
+##### sources, objects and libraries #####
+BINNAME := liblfds700
+LIB_BINARY := $(BINDIR)\$(BINNAME).lib
+DLL_BINARY := $(BINDIR)\$(BINNAME).dll
+SRCDIRS := lfds700_btree_addonly_unbalanced lfds700_freelist lfds700_hash_addonly lfds700_list_addonly_ordered_singlylinked lfds700_list_addonly_singlylinked_unordered lfds700_misc lfds700_queue lfds700_queue_bounded_singleconsumer_singleproducer lfds700_ringbuffer lfds700_stack
+SOURCES := lfds700_hash_addonly_cleanup.c lfds700_hash_addonly_get.c lfds700_hash_addonly_init.c lfds700_hash_addonly_insert.c lfds700_hash_addonly_iterate.c lfds700_hash_addonly_query.c \
+           lfds700_list_addonly_ordered_singlylinked_cleanup.c lfds700_list_addonly_ordered_singlylinked_get.c lfds700_list_addonly_ordered_singlylinked_init.c lfds700_list_addonly_ordered_singlylinked_insert.c lfds700_list_addonly_ordered_singlylinked_query.c \
+           lfds700_list_addonly_singlylinked_unordered_cleanup.c lfds700_list_addonly_singlylinked_unordered_get.c lfds700_list_addonly_singlylinked_unordered_init.c lfds700_list_addonly_singlylinked_unordered_insert.c lfds700_list_addonly_singlylinked_unordered_query.c \
+           lfds700_btree_addonly_unbalanced_cleanup.c lfds700_btree_addonly_unbalanced_get.c lfds700_btree_addonly_unbalanced_init.c lfds700_btree_addonly_unbalanced_insert.c lfds700_btree_addonly_unbalanced_query.c \
+           lfds700_freelist_cleanup.c lfds700_freelist_init.c lfds700_freelist_pop.c lfds700_freelist_push.c lfds700_freelist_query.c \
+           lfds700_misc_cleanup.c lfds700_misc_globals.c lfds700_misc_init.c lfds700_misc_prng.c lfds700_misc_query.c \
+           lfds700_queue_cleanup.c lfds700_queue_dequeue.c lfds700_queue_enqueue.c lfds700_queue_init.c lfds700_queue_query.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c lfds700_queue_bounded_singleconsumer_singleproducer_init.c lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
+           lfds700_ringbuffer_cleanup.c lfds700_ringbuffer_init.c lfds700_ringbuffer_query.c lfds700_ringbuffer_read.c lfds700_ringbuffer_write.c \
+           lfds700_stack_cleanup.c lfds700_stack_init.c lfds700_stack_pop.c lfds700_stack_push.c lfds700_stack_query.c
+OBJECTS := $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
+SYSLIBS := kernel32.lib
+
+##### default paths fix up #####
+INCDIRS := $(patsubst %,%;,$(INCDIR))
+INCLUDE += $(subst $(SPACE),,$(INCDIRS))
+
+##### tools #####
+MAKE    := make
+MFLAGS  := 
+
+CC      := cl
+CBASE   := /c "-I$(SRCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN /DUNICODE /D_UNICODE /DUNICODE /nologo /W4 /wd 4068 /WX
+CFREL   := /DNDEBUG /Ox
+CFDBG   := /D_DEBUG /Gm /Od /Zi
+
+AR      := lib
+AFLAGS  := /nologo /subsystem:console /verbose /wx
+
+LD      := link
+LFBASE  := /def:$(BINNAME).def /dll /nodefaultlib /nologo /nxcompat /subsystem:console /wx
+LFREL   := /incremental:no
+LFDBG   := /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
+
+##### variants #####
+CFLAGS  := $(CBASE) $(CFDBG) /MTd
+ASFLAGS := $(ASBASE) $(ASDBG)
+LFLAGS  := $(LFBASE) $(LFDBG)
+CLIB    := libcmtd.lib
+
+ifeq ($(MAKECMDGOALS),librel)
+  CFLAGS  := $(CBASE) $(CFREL) /MT
+  ASFLAGS := $(ASBASE) $(ASREL)
+  LFLAGS  := $(LFBASE) $(LFREL)
+  CLIB    := libcmt.lib
+endif
+
+ifeq ($(MAKECMDGOALS),libdbg)
+  CFLAGS  := $(CBASE) $(CFDBG) /MTd
+  ASFLAGS := $(ASBASE) $(ASDBG)
+  LFLAGS  := $(LFBASE) $(LFDBG)
+  CLIB    := libcmtd.lib
+endif
+
+ifeq ($(MAKECMDGOALS),dllrel)
+  CFLAGS  := $(CBASE) $(CFREL) /MD
+  ASFLAGS := $(ASBASE) $(ASREL)
+  LFLAGS  := $(LFBASE) $(LFREL)
+  CLIB    := msvcrt.lib
+endif
+
+ifeq ($(MAKECMDGOALS),dlldbg)
+  CFLAGS  := $(CBASE) $(CFDBG) /MDd
+  ASFLAGS := $(ASBASE) $(ASDBG)
+  LFLAGS  := $(LFBASE) $(LFDBG)
+  CLIB    := msvcrtd.lib
+endif
+
+##### search paths #####
+vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS))
+
+##### implicit rules #####
+$(OBJDIR)/%.obj : %.c
+	$(CC) $(CFLAGS) "/Fo$@" $<
+
+##### explicit rules #####
+$(LIB_BINARY) : $(OBJECTS)
+	$(AR) $(AFLAGS) $(OBJECTS) /out:$(LIB_BINARY)
+
+$(DLL_BINARY) : $(OBJECTS)
+	$(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(OBJECTS) /out:$(DLL_BINARY)
+
+##### phony #####
+.PHONY : clean librel libdbg dllrel dlldbg
+
+clean : 
+	@erase /Q $(BINDIR)\$(BINNAME).* $(OBJDIR)\*.obj $(QUIETLY)
+
+dlldbg : $(DLL_BINARY)
+dllrel : $(DLL_BINARY)
+
+libdbg : $(LIB_BINARY)
+librel : $(LIB_BINARY)
+
+##### notes #####
+# /wd 4068 : turn off "unknown pragma" warning
+
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.def b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.def
new file mode 100644
index 0000000000000000000000000000000000000000..583ce35dbdb08c553e2cb2a7f335f4bcaf9458da
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.def
@@ -0,0 +1,69 @@
+EXPORTS
+
+lfds700_btree_au_init_valid_on_current_logical_core                     = lfds700_btree_au_init_valid_on_current_logical_core
+lfds700_btree_au_cleanup                                                = lfds700_btree_au_cleanup
+lfds700_btree_au_insert                                                 = lfds700_btree_au_insert
+lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
+lfds700_btree_au_get_by_absolute_position                               = lfds700_btree_au_get_by_absolute_position
+lfds700_btree_au_get_by_relative_position                               = lfds700_btree_au_get_by_relative_position
+lfds700_btree_au_get_by_key                                             = lfds700_btree_au_get_by_key
+lfds700_btree_au_query                                                  = lfds700_btree_au_query
+
+lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
+lfds700_freelist_cleanup                            = lfds700_freelist_cleanup
+lfds700_freelist_push                               = lfds700_freelist_push
+lfds700_freelist_pop                                = lfds700_freelist_pop
+lfds700_freelist_query                              = lfds700_freelist_query
+
+lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
+lfds700_hash_a_cleanup                            = lfds700_hash_a_cleanup
+lfds700_hash_a_insert                             = lfds700_hash_a_insert
+lfds700_hash_a_get_by_key                         = lfds700_hash_a_get_by_key
+lfds700_hash_a_iterate_init                       = lfds700_hash_a_iterate_init
+lfds700_hash_a_iterate                            = lfds700_hash_a_iterate
+lfds700_hash_a_query                              = lfds700_hash_a_query
+
+lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
+lfds700_list_aos_cleanup                            = lfds700_list_aos_cleanup
+lfds700_list_aos_insert                             = lfds700_list_aos_insert
+lfds700_list_aos_get_by_key                         = lfds700_list_aos_get_by_key
+lfds700_list_aos_query                              = lfds700_list_aos_query
+
+lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
+lfds700_list_asu_cleanup                            = lfds700_list_asu_cleanup
+lfds700_list_asu_insert_at_position                 = lfds700_list_asu_insert_at_position
+lfds700_list_asu_insert_at_start                    = lfds700_list_asu_insert_at_start
+lfds700_list_asu_insert_at_end                      = lfds700_list_asu_insert_at_end
+lfds700_list_asu_insert_after_element               = lfds700_list_asu_insert_after_element
+lfds700_list_asu_get_by_key                         = lfds700_list_asu_get_by_key
+lfds700_list_asu_query                              = lfds700_list_asu_query
+
+lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
+lfds700_misc_library_cleanup                            = lfds700_misc_library_cleanup
+lfds700_misc_prng_init                                  = lfds700_misc_prng_init
+lfds700_misc_query                                      = lfds700_misc_query
+
+lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
+lfds700_queue_cleanup                            = lfds700_queue_cleanup
+lfds700_queue_enqueue                            = lfds700_queue_enqueue
+lfds700_queue_dequeue                            = lfds700_queue_dequeue
+lfds700_queue_query                              = lfds700_queue_query
+
+lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
+lfds700_queue_bss_cleanup                            = lfds700_queue_bss_cleanup
+lfds700_queue_bss_enqueue                            = lfds700_queue_bss_enqueue
+lfds700_queue_bss_dequeue                            = lfds700_queue_bss_dequeue
+lfds700_queue_bss_query                              = lfds700_queue_bss_query
+
+lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
+lfds700_ringbuffer_cleanup                            = lfds700_ringbuffer_cleanup
+lfds700_ringbuffer_read                               = lfds700_ringbuffer_read
+lfds700_ringbuffer_write                              = lfds700_ringbuffer_write
+lfds700_ringbuffer_query                              = lfds700_ringbuffer_query
+
+lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
+lfds700_stack_cleanup                            = lfds700_stack_cleanup
+lfds700_stack_push                               = lfds700_stack_push
+lfds700_stack_pop                                = lfds700_stack_pop
+lfds700_stack_query                              = lfds700_stack_query
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.sln b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.sln
new file mode 100644
index 0000000000000000000000000000000000000000..b52c44e46f36cfc3de33a8a5663832062c6de1cf
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds700", "liblfds700.vcxproj", "{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug DLL|Win32 = Debug DLL|Win32
+		Debug DLL|x64 = Debug DLL|x64
+		Debug LIB|Win32 = Debug LIB|Win32
+		Debug LIB|x64 = Debug LIB|x64
+		Release DLL|Win32 = Release DLL|Win32
+		Release DLL|x64 = Release DLL|x64
+		Release LIB|Win32 = Release LIB|Win32
+		Release LIB|x64 = Release LIB|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Deploy.0 = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Build.0 = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Deploy.0 = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Deploy.0 = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Build.0 = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Deploy.0 = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Build.0 = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Deploy.0 = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.ActiveCfg = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Build.0 = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Deploy.0 = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Build.0 = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Deploy.0 = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.ActiveCfg = Release LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Build.0 = Release LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Deploy.0 = Release LIB|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..3d4bf6364f8d8d7f85cc85e8bdf812d5bfb6bb7f
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj
@@ -0,0 +1,705 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug DLL|Win32">
+      <Configuration>Debug DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug DLL|x64">
+      <Configuration>Debug DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug LIB|Win32">
+      <Configuration>Debug LIB</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug LIB|x64">
+      <Configuration>Debug LIB</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release DLL|Win32">
+      <Configuration>Release DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release DLL|x64">
+      <Configuration>Release DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release LIB|Win32">
+      <Configuration>Release LIB</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release LIB|x64">
+      <Configuration>Release LIB</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
+      <LinkStatus>
+      </LinkStatus>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <MapExports>true</MapExports>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <GenerateMapFile>true</GenerateMapFile>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+    <ProjectReference>
+      <LinkLibraryDependencies>true</LinkLibraryDependencies>
+    </ProjectReference>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <OmitFramePointers>false</OmitFramePointers>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <OmitFramePointers>false</OmitFramePointers>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <MapExports>true</MapExports>
+      <OptimizeReferences>false</OptimizeReferences>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
+      <GenerateMapFile>true</GenerateMapFile>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
+      <LinkStatus>
+      </LinkStatus>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+    <ProjectReference>
+      <LinkLibraryDependencies>true</LinkLibraryDependencies>
+    </ProjectReference>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\inc\liblfds700.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h" />
+    <ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj.filters b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..5ec0bea579b2125c7e4bfcc4e919e99e00b5e90f
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj.filters
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+    </Filter>
+    <Filter Include="Header Files\liblfds700">
+      <UniqueIdentifier>{258be429-7dac-4999-b995-753aa2f0c505}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_freelist">
+      <UniqueIdentifier>{469abf8e-47d8-4678-bd66-7c7e65c5f52e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_ringbuffer">
+      <UniqueIdentifier>{62ee141b-2acb-4555-b016-7be20a57f2bf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_stack">
+      <UniqueIdentifier>{19c73b0f-25e0-4166-9093-427f1dfb4f70}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_queue">
+      <UniqueIdentifier>{00eb30fe-e638-4c2b-8ca1-1f09c4a0ed45}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_misc">
+      <UniqueIdentifier>{400ae4e9-2281-4549-b918-59d1a27a2d07}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_btree_addonly_unbalanced">
+      <UniqueIdentifier>{0b1fafc3-817b-4c18-8eb1-121884e3a29b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_hash_addonly">
+      <UniqueIdentifier>{bcbadc74-1748-4696-aad7-7fdbe5614624}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_list_addonly_ordered_singlylinked">
+      <UniqueIdentifier>{c45194af-7b41-4c28-bc0e-1095ec347664}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_queue_bounded_singleconsumer_singleproducer">
+      <UniqueIdentifier>{6250c4d5-ac8e-4c28-93de-0954c5bed1cb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_list_addonly_singlylinked_unordered">
+      <UniqueIdentifier>{3ac93721-1d81-49e4-9581-dbc12ace5c0c}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\inc\liblfds700.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj.user b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj.user
new file mode 100644
index 0000000000000000000000000000000000000000..7cbb3216adb733fd25e1bd27d504ac8419b8c5bb
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012/liblfds700.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/driver_entry.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/driver_entry.c
new file mode 100644
index 0000000000000000000000000000000000000000..9ea5612e54cbfd9a804db99cea19270e596d3eef
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/driver_entry.c
@@ -0,0 +1 @@
+#include <wdf.h>
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.def b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.def
new file mode 100644
index 0000000000000000000000000000000000000000..583ce35dbdb08c553e2cb2a7f335f4bcaf9458da
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.def
@@ -0,0 +1,69 @@
+EXPORTS
+
+lfds700_btree_au_init_valid_on_current_logical_core                     = lfds700_btree_au_init_valid_on_current_logical_core
+lfds700_btree_au_cleanup                                                = lfds700_btree_au_cleanup
+lfds700_btree_au_insert                                                 = lfds700_btree_au_insert
+lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
+lfds700_btree_au_get_by_absolute_position                               = lfds700_btree_au_get_by_absolute_position
+lfds700_btree_au_get_by_relative_position                               = lfds700_btree_au_get_by_relative_position
+lfds700_btree_au_get_by_key                                             = lfds700_btree_au_get_by_key
+lfds700_btree_au_query                                                  = lfds700_btree_au_query
+
+lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
+lfds700_freelist_cleanup                            = lfds700_freelist_cleanup
+lfds700_freelist_push                               = lfds700_freelist_push
+lfds700_freelist_pop                                = lfds700_freelist_pop
+lfds700_freelist_query                              = lfds700_freelist_query
+
+lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
+lfds700_hash_a_cleanup                            = lfds700_hash_a_cleanup
+lfds700_hash_a_insert                             = lfds700_hash_a_insert
+lfds700_hash_a_get_by_key                         = lfds700_hash_a_get_by_key
+lfds700_hash_a_iterate_init                       = lfds700_hash_a_iterate_init
+lfds700_hash_a_iterate                            = lfds700_hash_a_iterate
+lfds700_hash_a_query                              = lfds700_hash_a_query
+
+lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
+lfds700_list_aos_cleanup                            = lfds700_list_aos_cleanup
+lfds700_list_aos_insert                             = lfds700_list_aos_insert
+lfds700_list_aos_get_by_key                         = lfds700_list_aos_get_by_key
+lfds700_list_aos_query                              = lfds700_list_aos_query
+
+lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
+lfds700_list_asu_cleanup                            = lfds700_list_asu_cleanup
+lfds700_list_asu_insert_at_position                 = lfds700_list_asu_insert_at_position
+lfds700_list_asu_insert_at_start                    = lfds700_list_asu_insert_at_start
+lfds700_list_asu_insert_at_end                      = lfds700_list_asu_insert_at_end
+lfds700_list_asu_insert_after_element               = lfds700_list_asu_insert_after_element
+lfds700_list_asu_get_by_key                         = lfds700_list_asu_get_by_key
+lfds700_list_asu_query                              = lfds700_list_asu_query
+
+lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
+lfds700_misc_library_cleanup                            = lfds700_misc_library_cleanup
+lfds700_misc_prng_init                                  = lfds700_misc_prng_init
+lfds700_misc_query                                      = lfds700_misc_query
+
+lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
+lfds700_queue_cleanup                            = lfds700_queue_cleanup
+lfds700_queue_enqueue                            = lfds700_queue_enqueue
+lfds700_queue_dequeue                            = lfds700_queue_dequeue
+lfds700_queue_query                              = lfds700_queue_query
+
+lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
+lfds700_queue_bss_cleanup                            = lfds700_queue_bss_cleanup
+lfds700_queue_bss_enqueue                            = lfds700_queue_bss_enqueue
+lfds700_queue_bss_dequeue                            = lfds700_queue_bss_dequeue
+lfds700_queue_bss_query                              = lfds700_queue_bss_query
+
+lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
+lfds700_ringbuffer_cleanup                            = lfds700_ringbuffer_cleanup
+lfds700_ringbuffer_read                               = lfds700_ringbuffer_read
+lfds700_ringbuffer_write                              = lfds700_ringbuffer_write
+lfds700_ringbuffer_query                              = lfds700_ringbuffer_query
+
+lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
+lfds700_stack_cleanup                            = lfds700_stack_cleanup
+lfds700_stack_push                               = lfds700_stack_push
+lfds700_stack_pop                                = lfds700_stack_pop
+lfds700_stack_query                              = lfds700_stack_query
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.sln b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.sln
new file mode 100644
index 0000000000000000000000000000000000000000..b52c44e46f36cfc3de33a8a5663832062c6de1cf
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds700", "liblfds700.vcxproj", "{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug DLL|Win32 = Debug DLL|Win32
+		Debug DLL|x64 = Debug DLL|x64
+		Debug LIB|Win32 = Debug LIB|Win32
+		Debug LIB|x64 = Debug LIB|x64
+		Release DLL|Win32 = Release DLL|Win32
+		Release DLL|x64 = Release DLL|x64
+		Release LIB|Win32 = Release LIB|Win32
+		Release LIB|x64 = Release LIB|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Deploy.0 = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Build.0 = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Deploy.0 = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Deploy.0 = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Build.0 = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Deploy.0 = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Build.0 = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Deploy.0 = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.ActiveCfg = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Build.0 = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Deploy.0 = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Build.0 = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Deploy.0 = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.ActiveCfg = Release LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Build.0 = Release LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Deploy.0 = Release LIB|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..f19ead0c18bbf81a532e866d71d98d4ca1c6726d
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj
@@ -0,0 +1,733 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug DLL|Win32">
+      <Configuration>Debug DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug DLL|x64">
+      <Configuration>Debug DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug LIB|Win32">
+      <Configuration>Debug LIB</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug LIB|x64">
+      <Configuration>Debug LIB</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release DLL|Win32">
+      <Configuration>Release DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release DLL|x64">
+      <Configuration>Release DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release LIB|Win32">
+      <Configuration>Release LIB</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release LIB|x64">
+      <Configuration>Release LIB</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath);</LibraryPath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
+      <LinkStatus>
+      </LinkStatus>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <MapExports>true</MapExports>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <GenerateMapFile>true</GenerateMapFile>
+      <Driver>WDM</Driver>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+    <ProjectReference>
+      <LinkLibraryDependencies>true</LinkLibraryDependencies>
+    </ProjectReference>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <OmitFramePointers>false</OmitFramePointers>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <OmitFramePointers>false</OmitFramePointers>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <MapExports>true</MapExports>
+      <OptimizeReferences>false</OptimizeReferences>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
+      <GenerateMapFile>true</GenerateMapFile>
+      <Driver>WDM</Driver>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
+      <LinkStatus>
+      </LinkStatus>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <Driver>WDM</Driver>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+    <ProjectReference>
+      <LinkLibraryDependencies>true</LinkLibraryDependencies>
+    </ProjectReference>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
+      <Driver>WDM</Driver>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\inc\liblfds700.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h" />
+    <ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj.filters b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..978f8ec1c98008cec77c0e4b7676a8cdcd1179c3
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj.filters
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+    </Filter>
+    <Filter Include="Header Files\liblfds700">
+      <UniqueIdentifier>{258be429-7dac-4999-b995-753aa2f0c505}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_freelist">
+      <UniqueIdentifier>{469abf8e-47d8-4678-bd66-7c7e65c5f52e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_ringbuffer">
+      <UniqueIdentifier>{62ee141b-2acb-4555-b016-7be20a57f2bf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_stack">
+      <UniqueIdentifier>{19c73b0f-25e0-4166-9093-427f1dfb4f70}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_queue">
+      <UniqueIdentifier>{00eb30fe-e638-4c2b-8ca1-1f09c4a0ed45}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_queue_bounded_singleconsumer_singleproducer">
+      <UniqueIdentifier>{6250c4d5-ac8e-4c28-93de-0954c5bed1cb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_misc">
+      <UniqueIdentifier>{400ae4e9-2281-4549-b918-59d1a27a2d07}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_list_addonly_ordered_singlylinked">
+      <UniqueIdentifier>{c45194af-7b41-4c28-bc0e-1095ec347664}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_list_addonly_singlylinked_unordered">
+      <UniqueIdentifier>{8b3cbb5c-7436-429f-9b72-bae1f4721746}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_hash_addonly">
+      <UniqueIdentifier>{bcbadc74-1748-4696-aad7-7fdbe5614624}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_btree_addonly_unbalanced">
+      <UniqueIdentifier>{0b1fafc3-817b-4c18-8eb1-121884e3a29b}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\inc\liblfds700.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj.user b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj.user
new file mode 100644
index 0000000000000000000000000000000000000000..7cbb3216adb733fd25e1bd27d504ac8419b8c5bb
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2012_and_wdk_8.0/liblfds700.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/driver_entry.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/driver_entry.c
new file mode 100644
index 0000000000000000000000000000000000000000..9ea5612e54cbfd9a804db99cea19270e596d3eef
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/driver_entry.c
@@ -0,0 +1 @@
+#include <wdf.h>
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.def b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.def
new file mode 100644
index 0000000000000000000000000000000000000000..583ce35dbdb08c553e2cb2a7f335f4bcaf9458da
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.def
@@ -0,0 +1,69 @@
+EXPORTS
+
+lfds700_btree_au_init_valid_on_current_logical_core                     = lfds700_btree_au_init_valid_on_current_logical_core
+lfds700_btree_au_cleanup                                                = lfds700_btree_au_cleanup
+lfds700_btree_au_insert                                                 = lfds700_btree_au_insert
+lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
+lfds700_btree_au_get_by_absolute_position                               = lfds700_btree_au_get_by_absolute_position
+lfds700_btree_au_get_by_relative_position                               = lfds700_btree_au_get_by_relative_position
+lfds700_btree_au_get_by_key                                             = lfds700_btree_au_get_by_key
+lfds700_btree_au_query                                                  = lfds700_btree_au_query
+
+lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
+lfds700_freelist_cleanup                            = lfds700_freelist_cleanup
+lfds700_freelist_push                               = lfds700_freelist_push
+lfds700_freelist_pop                                = lfds700_freelist_pop
+lfds700_freelist_query                              = lfds700_freelist_query
+
+lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
+lfds700_hash_a_cleanup                            = lfds700_hash_a_cleanup
+lfds700_hash_a_insert                             = lfds700_hash_a_insert
+lfds700_hash_a_get_by_key                         = lfds700_hash_a_get_by_key
+lfds700_hash_a_iterate_init                       = lfds700_hash_a_iterate_init
+lfds700_hash_a_iterate                            = lfds700_hash_a_iterate
+lfds700_hash_a_query                              = lfds700_hash_a_query
+
+lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
+lfds700_list_aos_cleanup                            = lfds700_list_aos_cleanup
+lfds700_list_aos_insert                             = lfds700_list_aos_insert
+lfds700_list_aos_get_by_key                         = lfds700_list_aos_get_by_key
+lfds700_list_aos_query                              = lfds700_list_aos_query
+
+lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
+lfds700_list_asu_cleanup                            = lfds700_list_asu_cleanup
+lfds700_list_asu_insert_at_position                 = lfds700_list_asu_insert_at_position
+lfds700_list_asu_insert_at_start                    = lfds700_list_asu_insert_at_start
+lfds700_list_asu_insert_at_end                      = lfds700_list_asu_insert_at_end
+lfds700_list_asu_insert_after_element               = lfds700_list_asu_insert_after_element
+lfds700_list_asu_get_by_key                         = lfds700_list_asu_get_by_key
+lfds700_list_asu_query                              = lfds700_list_asu_query
+
+lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
+lfds700_misc_library_cleanup                            = lfds700_misc_library_cleanup
+lfds700_misc_prng_init                                  = lfds700_misc_prng_init
+lfds700_misc_query                                      = lfds700_misc_query
+
+lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
+lfds700_queue_cleanup                            = lfds700_queue_cleanup
+lfds700_queue_enqueue                            = lfds700_queue_enqueue
+lfds700_queue_dequeue                            = lfds700_queue_dequeue
+lfds700_queue_query                              = lfds700_queue_query
+
+lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
+lfds700_queue_bss_cleanup                            = lfds700_queue_bss_cleanup
+lfds700_queue_bss_enqueue                            = lfds700_queue_bss_enqueue
+lfds700_queue_bss_dequeue                            = lfds700_queue_bss_dequeue
+lfds700_queue_bss_query                              = lfds700_queue_bss_query
+
+lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
+lfds700_ringbuffer_cleanup                            = lfds700_ringbuffer_cleanup
+lfds700_ringbuffer_read                               = lfds700_ringbuffer_read
+lfds700_ringbuffer_write                              = lfds700_ringbuffer_write
+lfds700_ringbuffer_query                              = lfds700_ringbuffer_query
+
+lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
+lfds700_stack_cleanup                            = lfds700_stack_cleanup
+lfds700_stack_push                               = lfds700_stack_push
+lfds700_stack_pop                                = lfds700_stack_pop
+lfds700_stack_query                              = lfds700_stack_query
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.sln b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.sln
new file mode 100644
index 0000000000000000000000000000000000000000..1cc19a8e23b313d31807285fd75813feb699abdb
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.sln
@@ -0,0 +1,59 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.40629.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds700", "liblfds700.vcxproj", "{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug DLL|ARM = Debug DLL|ARM
+		Debug DLL|Win32 = Debug DLL|Win32
+		Debug DLL|x64 = Debug DLL|x64
+		Debug LIB|ARM = Debug LIB|ARM
+		Debug LIB|Win32 = Debug LIB|Win32
+		Debug LIB|x64 = Debug LIB|x64
+		Release DLL|ARM = Release DLL|ARM
+		Release DLL|Win32 = Release DLL|Win32
+		Release DLL|x64 = Release DLL|x64
+		Release LIB|ARM = Release LIB|ARM
+		Release LIB|Win32 = Release LIB|Win32
+		Release LIB|x64 = Release LIB|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|ARM.ActiveCfg = Debug DLL|ARM
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|ARM.Build.0 = Debug DLL|ARM
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Deploy.0 = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Build.0 = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Deploy.0 = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|ARM.ActiveCfg = Debug LIB|ARM
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|ARM.Build.0 = Debug LIB|ARM
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Deploy.0 = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Build.0 = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Deploy.0 = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|ARM.ActiveCfg = Release DLL|ARM
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|ARM.Build.0 = Release DLL|ARM
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Build.0 = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Deploy.0 = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.ActiveCfg = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Build.0 = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Deploy.0 = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|ARM.ActiveCfg = Release LIB|ARM
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|ARM.Build.0 = Release LIB|ARM
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Build.0 = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Deploy.0 = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.ActiveCfg = Release LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Build.0 = Release LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Deploy.0 = Release LIB|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..e67a540e3703147000ca84131a519accc4ebe193
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj
@@ -0,0 +1,1054 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug DLL|ARM">
+      <Configuration>Debug DLL</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug DLL|Win32">
+      <Configuration>Debug DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug DLL|x64">
+      <Configuration>Debug DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug LIB|ARM">
+      <Configuration>Debug LIB</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug LIB|Win32">
+      <Configuration>Debug LIB</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug LIB|x64">
+      <Configuration>Debug LIB</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release DLL|ARM">
+      <Configuration>Release DLL</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release DLL|Win32">
+      <Configuration>Release DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release DLL|x64">
+      <Configuration>Release DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release LIB|ARM">
+      <Configuration>Release LIB</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release LIB|Win32">
+      <Configuration>Release LIB</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release LIB|x64">
+      <Configuration>Release LIB</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|ARM'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|ARM'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|ARM'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|ARM'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|ARM'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|ARM'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|ARM'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|ARM'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
+    <LibraryPath>$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(WDKContentRoot)lib\wdf\kmdf\x86\</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|ARM'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
+    <LibraryPath>$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(WDKContentRoot)lib\wdf\kmdf\x86\</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|ARM'">
+    <LinkIncremental />
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath)</LibraryPath>
+    <ExcludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(MSBuildToolsPath);$(MSBuildFrameworkToolsPath);$(MSBuild_ExecutablePath);$(VC_LibraryPath_ARM);</ExcludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
+    <LibraryPath>$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);;$(WDKContentRoot)lib\wdf\kmdf\x64\</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
+    <LibraryPath>$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);;$(WDKContentRoot)lib\wdf\kmdf\x64\</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
+    <LibraryPath>$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(WDKContentRoot)lib\wdf\kmdf\x86\</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|ARM'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
+    <LibraryPath>$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSDK_LibraryPath_x86);$(WDKContentRoot)lib\wdf\kmdf\x86\</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|ARM'">
+    <LinkIncremental />
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath)</IncludePath>
+    <LibraryPath>$(WDKContentRoot)lib\$(DDKSpec)\KM\$(DDKPlatform);$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
+    <LibraryPath>$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);;$(WDKContentRoot)lib\wdf\kmdf\x64\</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
+    <LinkIncremental>
+    </LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+    <IncludePath>$(ProjectDir);$(IncludePath);$(WDKContentRoot)include\km\;$(WDKContentRoot)include\wdf\kmdf\1.11\</IncludePath>
+    <LibraryPath>$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSDK_LibraryPath_x64);;$(WDKContentRoot)lib\wdf\kmdf\x64\</LibraryPath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|ARM'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineARM</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
+      <LinkStatus>
+      </LinkStatus>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <MapExports>true</MapExports>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <GenerateMapFile>true</GenerateMapFile>
+      <Driver>WDM</Driver>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+    <ProjectReference>
+      <LinkLibraryDependencies>true</LinkLibraryDependencies>
+    </ProjectReference>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|ARM'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
+      <LinkStatus>
+      </LinkStatus>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <MapExports>true</MapExports>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <GenerateMapFile>true</GenerateMapFile>
+      <Driver>WDM</Driver>
+      <IgnoreSpecificDefaultLibraries />
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+    <ProjectReference>
+      <LinkLibraryDependencies>true</LinkLibraryDependencies>
+    </ProjectReference>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <OmitFramePointers>false</OmitFramePointers>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>true</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <SDLCheck>true</SDLCheck>
+      <MinimalRebuild>false</MinimalRebuild>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <OmitFramePointers>false</OmitFramePointers>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <MapExports>true</MapExports>
+      <OptimizeReferences>false</OptimizeReferences>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;msvcrtd.lib</AdditionalDependencies>
+      <GenerateMapFile>true</GenerateMapFile>
+      <Driver>WDM</Driver>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+    </Lib>
+    <Lib>
+      <LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|ARM'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineARM</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
+      <LinkStatus>
+      </LinkStatus>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <Driver>WDM</Driver>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+    <ProjectReference>
+      <LinkLibraryDependencies>true</LinkLibraryDependencies>
+    </ProjectReference>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|ARM'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
+      <LinkStatus>
+      </LinkStatus>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <Driver>WDM</Driver>
+      <IgnoreSpecificDefaultLibraries />
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+    <ProjectReference>
+      <LinkLibraryDependencies>true</LinkLibraryDependencies>
+    </ProjectReference>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Native</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;LFDS700_BUILD_TYPE_STRING="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>
+      </AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>false</ExceptionHandling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>
+      </FunctionLevelLinking>
+      <EnableParallelCodeGeneration>
+      </EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>
+      </EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>
+      </CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <CompileAs>CompileAsC</CompileAs>
+      <UseFullPaths>true</UseFullPaths>
+      <ErrorReporting>None</ErrorReporting>
+      <OmitFramePointers>true</OmitFramePointers>
+      <DisableSpecificWarnings>4068</DisableSpecificWarnings>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <AdditionalOptions>/kernel %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Native</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+      <ModuleDefinitionFile>liblfds700.def</ModuleDefinitionFile>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;msvcrt.lib</AdditionalDependencies>
+      <Driver>WDM</Driver>
+    </Link>
+    <Lib>
+      <TreatLibWarningAsErrors>true</TreatLibWarningAsErrors>
+    </Lib>
+    <Lib>
+      <TargetMachine>MachineX64</TargetMachine>
+    </Lib>
+    <Lib>
+      <SubSystem>Console</SubSystem>
+      <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\inc\liblfds700.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h" />
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h" />
+    <ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h" />
+    <ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c" />
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c" />
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c" />
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c" />
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c" />
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c" />
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c" />
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c" />
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj.filters b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..978f8ec1c98008cec77c0e4b7676a8cdcd1179c3
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj.filters
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+    </Filter>
+    <Filter Include="Header Files\liblfds700">
+      <UniqueIdentifier>{258be429-7dac-4999-b995-753aa2f0c505}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_freelist">
+      <UniqueIdentifier>{469abf8e-47d8-4678-bd66-7c7e65c5f52e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_ringbuffer">
+      <UniqueIdentifier>{62ee141b-2acb-4555-b016-7be20a57f2bf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_stack">
+      <UniqueIdentifier>{19c73b0f-25e0-4166-9093-427f1dfb4f70}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_queue">
+      <UniqueIdentifier>{00eb30fe-e638-4c2b-8ca1-1f09c4a0ed45}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_queue_bounded_singleconsumer_singleproducer">
+      <UniqueIdentifier>{6250c4d5-ac8e-4c28-93de-0954c5bed1cb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_misc">
+      <UniqueIdentifier>{400ae4e9-2281-4549-b918-59d1a27a2d07}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_list_addonly_ordered_singlylinked">
+      <UniqueIdentifier>{c45194af-7b41-4c28-bc0e-1095ec347664}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_list_addonly_singlylinked_unordered">
+      <UniqueIdentifier>{8b3cbb5c-7436-429f-9b72-bae1f4721746}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_hash_addonly">
+      <UniqueIdentifier>{bcbadc74-1748-4696-aad7-7fdbe5614624}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\lfds700_btree_addonly_unbalanced">
+      <UniqueIdentifier>{0b1fafc3-817b-4c18-8eb1-121884e3a29b}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\inc\liblfds700.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_freelist\lfds700_freelist_internal.h">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_stack\lfds700_stack_internal.h">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_queue\lfds700_queue_internal.h">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_btree_addonly_unbalanced.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_freelist.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_hash_addonly.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_ordered_singlylinked.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_list_addonly_singlylinked_unordered.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_misc.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_compiler.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_operating_system.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_porting_abstraction_layer_processor.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_queue_bounded_singleconsumer_singleproducer.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_ringbuffer.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\inc\liblfds700\lfds700_stack.h">
+      <Filter>Header Files\liblfds700</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_internal.h">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_internal.h">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_internal.h">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_misc\lfds700_misc_internal.h">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_internal.h">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_internal.h">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_internal.h">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_cleanup.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_init.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_pop.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_push.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_freelist\lfds700_freelist_query.c">
+      <Filter>Source Files\lfds700_freelist</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_cleanup.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_init.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_pop.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_push.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_stack\lfds700_stack_query.c">
+      <Filter>Source Files\lfds700_stack</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_cleanup.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_dequeue.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_enqueue.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_init.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue\lfds700_queue_query.c">
+      <Filter>Source Files\lfds700_queue</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_cleanup.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_get.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_init.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_insert.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_iterate.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_hash_addonly\lfds700_hash_addonly_query.c">
+      <Filter>Source Files\lfds700_hash_addonly</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_cleanup.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_get.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_init.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_insert.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_ordered_singlylinked\lfds700_list_addonly_ordered_singlylinked_query.c">
+      <Filter>Source Files\lfds700_list_addonly_ordered_singlylinked</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_cleanup.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_get.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_init.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_insert.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_btree_addonly_unbalanced\lfds700_btree_addonly_unbalanced_query.c">
+      <Filter>Source Files\lfds700_btree_addonly_unbalanced</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_cleanup.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_globals.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_init.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_prng.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_misc\lfds700_misc_query.c">
+      <Filter>Source Files\lfds700_misc</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_init.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\lfds700_queue_bounded_singleconsumer_singleproducer_query.c">
+      <Filter>Source Files\lfds700_queue_bounded_singleconsumer_singleproducer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_cleanup.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_get.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_init.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_insert.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_list_addonly_singlylinked_unordered\lfds700_list_addonly_singlylinked_unordered_query.c">
+      <Filter>Source Files\lfds700_list_addonly_singlylinked_unordered</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_cleanup.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_init.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_query.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_read.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\lfds700_ringbuffer\lfds700_ringbuffer_write.c">
+      <Filter>Source Files\lfds700_ringbuffer</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj.user b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj.user
new file mode 100644
index 0000000000000000000000000000000000000000..7cbb3216adb733fd25e1bd27d504ac8419b8c5bb
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/visual_studio_professional_2013_and_wdk_8.1/liblfds700.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/dirs b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/dirs
new file mode 100644
index 0000000000000000000000000000000000000000..64e002cc57abf19f52e3d3c5dbc24a8629e36d1f
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/dirs
@@ -0,0 +1,3 @@
+DIRS = single_dir_for_windows_kernel
+
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/driver_entry_renamed_to_avoid_compiler_warning.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/driver_entry_renamed_to_avoid_compiler_warning.c
new file mode 100644
index 0000000000000000000000000000000000000000..09d7acb7fca0761205e16a3d470b224881cb5a5c
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/driver_entry_renamed_to_avoid_compiler_warning.c
@@ -0,0 +1,23 @@
+#include "liblfds700_internal.h"
+
+
+
+
+
+/****************************************************************************/
+DRIVER_INITIALIZE DriverEntry;
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+NTSTATUS DriverEntry( struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath )
+{
+	return( STATUS_SUCCESS );
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/liblfds700.def b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/liblfds700.def
new file mode 100644
index 0000000000000000000000000000000000000000..583ce35dbdb08c553e2cb2a7f335f4bcaf9458da
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/liblfds700.def
@@ -0,0 +1,69 @@
+EXPORTS
+
+lfds700_btree_au_init_valid_on_current_logical_core                     = lfds700_btree_au_init_valid_on_current_logical_core
+lfds700_btree_au_cleanup                                                = lfds700_btree_au_cleanup
+lfds700_btree_au_insert                                                 = lfds700_btree_au_insert
+lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
+lfds700_btree_au_get_by_absolute_position                               = lfds700_btree_au_get_by_absolute_position
+lfds700_btree_au_get_by_relative_position                               = lfds700_btree_au_get_by_relative_position
+lfds700_btree_au_get_by_key                                             = lfds700_btree_au_get_by_key
+lfds700_btree_au_query                                                  = lfds700_btree_au_query
+
+lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
+lfds700_freelist_cleanup                            = lfds700_freelist_cleanup
+lfds700_freelist_push                               = lfds700_freelist_push
+lfds700_freelist_pop                                = lfds700_freelist_pop
+lfds700_freelist_query                              = lfds700_freelist_query
+
+lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
+lfds700_hash_a_cleanup                            = lfds700_hash_a_cleanup
+lfds700_hash_a_insert                             = lfds700_hash_a_insert
+lfds700_hash_a_get_by_key                         = lfds700_hash_a_get_by_key
+lfds700_hash_a_iterate_init                       = lfds700_hash_a_iterate_init
+lfds700_hash_a_iterate                            = lfds700_hash_a_iterate
+lfds700_hash_a_query                              = lfds700_hash_a_query
+
+lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
+lfds700_list_aos_cleanup                            = lfds700_list_aos_cleanup
+lfds700_list_aos_insert                             = lfds700_list_aos_insert
+lfds700_list_aos_get_by_key                         = lfds700_list_aos_get_by_key
+lfds700_list_aos_query                              = lfds700_list_aos_query
+
+lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
+lfds700_list_asu_cleanup                            = lfds700_list_asu_cleanup
+lfds700_list_asu_insert_at_position                 = lfds700_list_asu_insert_at_position
+lfds700_list_asu_insert_at_start                    = lfds700_list_asu_insert_at_start
+lfds700_list_asu_insert_at_end                      = lfds700_list_asu_insert_at_end
+lfds700_list_asu_insert_after_element               = lfds700_list_asu_insert_after_element
+lfds700_list_asu_get_by_key                         = lfds700_list_asu_get_by_key
+lfds700_list_asu_query                              = lfds700_list_asu_query
+
+lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
+lfds700_misc_library_cleanup                            = lfds700_misc_library_cleanup
+lfds700_misc_prng_init                                  = lfds700_misc_prng_init
+lfds700_misc_query                                      = lfds700_misc_query
+
+lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
+lfds700_queue_cleanup                            = lfds700_queue_cleanup
+lfds700_queue_enqueue                            = lfds700_queue_enqueue
+lfds700_queue_dequeue                            = lfds700_queue_dequeue
+lfds700_queue_query                              = lfds700_queue_query
+
+lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
+lfds700_queue_bss_cleanup                            = lfds700_queue_bss_cleanup
+lfds700_queue_bss_enqueue                            = lfds700_queue_bss_enqueue
+lfds700_queue_bss_dequeue                            = lfds700_queue_bss_dequeue
+lfds700_queue_bss_query                              = lfds700_queue_bss_query
+
+lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
+lfds700_ringbuffer_cleanup                            = lfds700_ringbuffer_cleanup
+lfds700_ringbuffer_read                               = lfds700_ringbuffer_read
+lfds700_ringbuffer_write                              = lfds700_ringbuffer_write
+lfds700_ringbuffer_query                              = lfds700_ringbuffer_query
+
+lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
+lfds700_stack_cleanup                            = lfds700_stack_cleanup
+lfds700_stack_push                               = lfds700_stack_push
+lfds700_stack_pop                                = lfds700_stack_pop
+lfds700_stack_query                              = lfds700_stack_query
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/readme_before_win_kernel_build.txt b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/readme_before_win_kernel_build.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1481c8d08aa8fa829a554dfb3510c04eaa775baf
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/readme_before_win_kernel_build.txt
@@ -0,0 +1,32 @@
+The Windows kernel build environment is primitive and has a number
+of severe limitations; in particular, all source files must be in
+one directory and it is not possible to choose the output binary type
+(static or dynamic library) from the build command line; rather,
+a string has to be modified in a text file used by the build (!)
+
+To deal with these limitations, it is necessary for a Windows kernel
+build to run a batch file prior to building.
+
+There are two batch files, one for static library builds and the other
+for dynamic library builds.
+
+They are both idempotent; you can run them as often as you like and
+switch between them as often as you want.  It's all fine; whenever
+you run one of them, it will take you from whatever state you were
+previously in, into the state you want to be in.
+
+Both batch files copy all the sources file into a single directory,
+"/src/single_dir_for_windows_kernel/".
+
+The static library batch file will then copy "/sources.static" into
+"/src/single_dir_for_windows_kernel/", which will cause a static
+library to be built.
+
+The dynamic library batch file will then copy "/sources.dynamic" into
+"/src/single_dir_for_windows_kernel/", which will cause a dynamic
+library to be built.  It will also copy "src/driver_entry.c" into
+"/src/single_dir_for_windows_kernel/", since the linker requires
+the DriverEntry function to exist for dynamic libraries, even
+though it's not used.
+
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/runme_before_win_kernel_dynamic_lib_build.bat b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/runme_before_win_kernel_dynamic_lib_build.bat
new file mode 100644
index 0000000000000000000000000000000000000000..ff6fc8a1f36abbe2ba2fd4136abd983a7db35bed
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/runme_before_win_kernel_dynamic_lib_build.bat
@@ -0,0 +1,22 @@
+@echo off
+rmdir /q /s single_dir_for_windows_kernel                                                                              1>nul 2>nul
+mkdir single_dir_for_windows_kernel                                                                                    1>nul 2>nul
+
+copy /y ..\..\src\lfds700_btree_addonly_unbalanced\*                     single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_freelist\*                                     single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_hash_addonly\*                                 single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_list_addonly_ordered_singlylinked\*            single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_list_addonly_singlylinked_unordered\*          single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_misc\*                                         single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_queue\*                                        single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\*  single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_ringbuffer\*                                   single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_stack\*                                        single_dir_for_windows_kernel\                1>nul 2>nul
+
+copy /y ..\..\src\liblfds700_internal.h                                  single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y driver_entry_renamed_to_avoid_compiler_warning.c                 single_dir_for_windows_kernel\driver_entry.c  1>nul 2>nul
+copy /y sources.dynamic                                                  single_dir_for_windows_kernel\sources         1>nul 2>nul
+
+echo Windows kernel dynamic library build directory structure created.
+echo (Note the effects of this batch file are idempotent).
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/runme_before_win_kernel_static_lib_build.bat b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/runme_before_win_kernel_static_lib_build.bat
new file mode 100644
index 0000000000000000000000000000000000000000..81c35e99c8e56591d478b897c89d43bb6292bbe1
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/runme_before_win_kernel_static_lib_build.bat
@@ -0,0 +1,21 @@
+@echo off
+rmdir /q /s single_dir_for_windows_kernel                                                                              1>nul 2>nul
+mkdir single_dir_for_windows_kernel                                                                                    1>nul 2>nul
+
+copy /y ..\..\src\lfds700_btree_addonly_unbalanced\*                     single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_freelist\*                                     single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_hash_addonly\*                                 single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_list_addonly_ordered_singlylinked\*            single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_list_addonly_singlylinked_unordered\*          single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_misc\*                                         single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_queue\*                                        single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_queue_bounded_singleconsumer_singleproducer\*  single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_ringbuffer\*                                   single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y ..\..\src\lfds700_stack\*                                        single_dir_for_windows_kernel\                1>nul 2>nul
+
+copy /y ..\..\src\liblfds700_internal.h                                  single_dir_for_windows_kernel\                1>nul 2>nul
+copy /y sources.static                                                   single_dir_for_windows_kernel\sources         1>nul 2>nul
+
+echo Windows kernel static library build directory structure created.
+echo (Note the effects of this batch file are idempotent).
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/sources.dynamic b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/sources.dynamic
new file mode 100644
index 0000000000000000000000000000000000000000..b0d241f85f6885598b57d58e992224a658317ece
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/sources.dynamic
@@ -0,0 +1,62 @@
+MSC_WARNING_LEVEL = /WX /wd4127 /W4
+DLLDEF            = ../liblfds700.def
+TARGETNAME        = liblfds700
+TARGETPATH        = ../../../bin/
+TARGETTYPE        = EXPORT_DRIVER
+UMTYPE            = nt
+USER_C_FLAGS      = /D_KERNEL_MODE
+
+INCLUDES = ../../../inc/
+SOURCES  = lfds700_hash_addonly_cleanup.c \
+           lfds700_hash_addonly_get.c \
+           lfds700_hash_addonly_init.c \
+           lfds700_hash_addonly_insert.c \
+           lfds700_hash_addonly_iterate.c \
+           lfds700_hash_addonly_query.c \
+           lfds700_list_addonly_ordered_singlylinked_cleanup.c \
+           lfds700_list_addonly_ordered_singlylinked_get.c \
+           lfds700_list_addonly_ordered_singlylinked_init.c \
+           lfds700_list_addonly_ordered_singlylinked_insert.c \
+           lfds700_list_addonly_ordered_singlylinked_query.c \
+           lfds700_list_addonly_singlylinked_unordered_cleanup.c \
+           lfds700_list_addonly_singlylinked_unordered_get.c \
+           lfds700_list_addonly_singlylinked_unordered_init.c \
+           lfds700_list_addonly_singlylinked_unordered_insert.c \
+           lfds700_list_addonly_singlylinked_unordered_query.c \
+           lfds700_btree_addonly_unbalanced_cleanup.c \
+           lfds700_btree_addonly_unbalanced_get.c \
+           lfds700_btree_addonly_unbalanced_init.c \
+           lfds700_btree_addonly_unbalanced_insert.c \
+           lfds700_btree_addonly_unbalanced_query.c \
+           lfds700_freelist_cleanup.c \
+           lfds700_freelist_init.c \
+           lfds700_freelist_pop.c \
+           lfds700_freelist_push.c \
+           lfds700_freelist_query.c \
+           lfds700_misc_cleanup.c \
+           lfds700_misc_globals.c \
+           lfds700_misc_init.c \
+           lfds700_misc_prng.c \
+           lfds700_misc_query.c \
+           lfds700_queue_cleanup.c \
+           lfds700_queue_dequeue.c \
+           lfds700_queue_enqueue.c \
+           lfds700_queue_init.c \
+           lfds700_queue_query.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_init.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
+           lfds700_ringbuffer_cleanup.c \
+           lfds700_ringbuffer_init.c \
+           lfds700_ringbuffer_query.c \
+           lfds700_ringbuffer_read.c \
+           lfds700_ringbuffer_write.c \
+           lfds700_stack_cleanup.c \
+           lfds700_stack_init.c \
+           lfds700_stack_pop.c \
+           lfds700_stack_push.c \
+           lfds700_stack_query.c \
+           driver_entry.c
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/sources.static b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/sources.static
new file mode 100644
index 0000000000000000000000000000000000000000..401b381c7d0274b777edb7228edcd69a7d6e7909
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/build/wdk_7.1/sources.static
@@ -0,0 +1,60 @@
+MSC_WARNING_LEVEL = /WX /wd4127 /W4
+TARGETNAME        = liblfds700
+TARGETPATH        = ../../../bin/
+TARGETTYPE        = DRIVER_LIBRARY
+UMTYPE            = nt
+USER_C_FLAGS      = /D_KERNEL_MODE
+
+INCLUDES = ../../../inc/
+SOURCES  = lfds700_hash_addonly_cleanup.c \
+           lfds700_hash_addonly_get.c \
+           lfds700_hash_addonly_init.c \
+           lfds700_hash_addonly_insert.c \
+           lfds700_hash_addonly_iterate.c \
+           lfds700_hash_addonly_query.c \
+           lfds700_list_addonly_ordered_singlylinked_cleanup.c \
+           lfds700_list_addonly_ordered_singlylinked_get.c \
+           lfds700_list_addonly_ordered_singlylinked_init.c \
+           lfds700_list_addonly_ordered_singlylinked_insert.c \
+           lfds700_list_addonly_ordered_singlylinked_query.c \
+           lfds700_list_addonly_singlylinked_unordered_cleanup.c \
+           lfds700_list_addonly_singlylinked_unordered_get.c \
+           lfds700_list_addonly_singlylinked_unordered_init.c \
+           lfds700_list_addonly_singlylinked_unordered_insert.c \
+           lfds700_list_addonly_singlylinked_unordered_query.c \
+           lfds700_btree_addonly_unbalanced_cleanup.c \
+           lfds700_btree_addonly_unbalanced_get.c \
+           lfds700_btree_addonly_unbalanced_init.c \
+           lfds700_btree_addonly_unbalanced_insert.c \
+           lfds700_btree_addonly_unbalanced_query.c \
+           lfds700_freelist_cleanup.c \
+           lfds700_freelist_init.c \
+           lfds700_freelist_pop.c \
+           lfds700_freelist_push.c \
+           lfds700_freelist_query.c \
+           lfds700_misc_cleanup.c \
+           lfds700_misc_globals.c \
+           lfds700_misc_init.c \
+           lfds700_misc_prng.c \
+           lfds700_misc_query.c \
+           lfds700_queue_cleanup.c \
+           lfds700_queue_dequeue.c \
+           lfds700_queue_enqueue.c \
+           lfds700_queue_init.c \
+           lfds700_queue_query.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_init.c \
+           lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
+           lfds700_ringbuffer_cleanup.c \
+           lfds700_ringbuffer_init.c \
+           lfds700_ringbuffer_query.c \
+           lfds700_ringbuffer_read.c \
+           lfds700_ringbuffer_write.c \
+           lfds700_stack_cleanup.c \
+           lfds700_stack_init.c \
+           lfds700_stack_pop.c \
+           lfds700_stack_push.c \
+           lfds700_stack_query.c
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700.h
new file mode 100644
index 0000000000000000000000000000000000000000..fdda50cefba67824e61c23fd2229129637d324ff
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700.h
@@ -0,0 +1,31 @@
+#ifndef LIBLFDS700_H
+
+  /***** defines *****/
+  #define LIBLFDS700_H
+
+  /***** pragmas on *****/
+  #pragma warning( disable : 4324 )                                          // TRD : 4324 disables MSVC warnings for structure alignment padding due to alignment specifiers
+
+  #pragma prefast( disable : 28113 28182 28183, "blah" )
+
+  /***** includes *****/
+  #include "liblfds700/lfds700_porting_abstraction_layer_compiler.h"
+  #include "liblfds700/lfds700_porting_abstraction_layer_operating_system.h"
+  #include "liblfds700/lfds700_porting_abstraction_layer_processor.h"
+
+  #include "liblfds700/lfds700_misc.h"                                       // TRD : everything after depends on misc
+  #include "liblfds700/lfds700_btree_addonly_unbalanced.h"                   // TRD : hash_addonly depends on btree_addonly_unbalanced
+  #include "liblfds700/lfds700_freelist.h"
+  #include "liblfds700/lfds700_hash_addonly.h"
+  #include "liblfds700/lfds700_list_addonly_ordered_singlylinked.h"
+  #include "liblfds700/lfds700_list_addonly_singlylinked_unordered.h"
+  #include "liblfds700/lfds700_queue.h"
+  #include "liblfds700/lfds700_queue_bounded_singleconsumer_singleproducer.h"
+  #include "liblfds700/lfds700_ringbuffer.h"
+  #include "liblfds700/lfds700_stack.h"
+
+  /***** pragmas off *****/
+  #pragma warning( default : 4324 )
+
+#endif
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_btree_addonly_unbalanced.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_btree_addonly_unbalanced.h
new file mode 100644
index 0000000000000000000000000000000000000000..bdc63a4273b6976011403203177fa3160763513b
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_btree_addonly_unbalanced.h
@@ -0,0 +1,113 @@
+/***** defines *****/
+#define LFDS700_BTREE_AU_GET_KEY_FROM_ELEMENT( btree_au_element )             ( (btree_au_element).key )
+#define LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( btree_au_element, new_key )      ( (btree_au_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
+#define LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( btree_au_element )           ( LFDS700_MISC_BARRIER_LOAD, (btree_au_element).value )
+#define LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( btree_au_element, new_value )  { void *local_new_value = (void *) (lfds700_pal_uint_t) (new_value); LFDS700_PAL_ATOMIC_EXCHANGE( &(btree_au_element).value, &local_new_value ); }
+#define LFDS700_BTREE_AU_GET_USER_STATE_FROM_STATE( btree_au_state )          ( (btree_au_state).user_state )
+
+/***** enums *****/
+enum lfds700_btree_au_absolute_position
+{
+  LFDS700_BTREE_AU_ABSOLUTE_POSITION_ROOT,
+  LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE,
+  LFDS700_BTREE_AU_ABSOLUTE_POSITION_LARGEST_IN_TREE
+};
+
+enum lfds700_btree_au_existing_key
+{
+  LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE,
+  LFDS700_BTREE_AU_EXISTING_KEY_FAIL
+};
+
+enum lfds700_btree_au_insert_result
+{
+  LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY,
+  LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE,
+  LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS
+};
+
+enum lfds700_btree_au_relative_position
+{
+  LFDS700_BTREE_AU_RELATIVE_POSITION_UP,
+  LFDS700_BTREE_AU_RELATIVE_POSITION_LEFT,
+  LFDS700_BTREE_AU_RELATIVE_POSITION_RIGHT,
+  LFDS700_BTREE_AU_RELATIVE_POSITION_SMALLEST_ELEMENT_BELOW_CURRENT_ELEMENT,
+  LFDS700_BTREE_AU_RELATIVE_POSITION_LARGEST_ELEMENT_BELOW_CURRENT_ELEMENT,
+  LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_SMALLER_ELEMENT_IN_ENTIRE_TREE,
+  LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE
+};
+
+enum lfds700_btree_au_query
+{
+  LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
+  LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE
+};
+
+/***** structs *****/
+struct lfds700_btree_au_element
+{
+  struct lfds700_btree_au_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile left,
+    *volatile right,
+    *volatile up;
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile value;
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *key;
+};
+
+struct lfds700_btree_au_state
+{
+  struct lfds700_btree_au_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile root;
+
+  int LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    (*key_compare_function)( void const *new_key, void const *existing_key );
+
+  enum lfds700_btree_au_existing_key 
+    existing_key;
+
+  void
+    *user_state;
+};
+
+/***** public prototypes *****/
+void lfds700_btree_au_init_valid_on_current_logical_core( struct lfds700_btree_au_state *baus,
+                                                          int (*key_compare_function)(void const *new_key, void const *existing_key),
+                                                          enum lfds700_btree_au_existing_key existing_key,
+                                                          void *user_state );
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+
+void lfds700_btree_au_cleanup( struct lfds700_btree_au_state *baus,
+                               void (*element_cleanup_callback)(struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element *baue) );
+
+enum lfds700_btree_au_insert_result lfds700_btree_au_insert( struct lfds700_btree_au_state *baus,
+                                                             struct lfds700_btree_au_element *baue,
+                                                             struct lfds700_btree_au_element **existing_baue,
+                                                             struct lfds700_misc_prng_state *ps );
+  // TRD : if a link collides with an existing key and existing_baue is non-NULL, existing_baue is set to the existing element
+
+int lfds700_btree_au_get_by_key( struct lfds700_btree_au_state *baus, 
+                                 void *key,
+                                 struct lfds700_btree_au_element **baue );
+
+int lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position( struct lfds700_btree_au_state *baus,
+                                                                             struct lfds700_btree_au_element **baue,
+                                                                             enum lfds700_btree_au_absolute_position absolute_position,
+                                                                             enum lfds700_btree_au_relative_position relative_position );
+  // TRD : if *baue is NULL, we get the element at position, otherwise we move from *baue according to direction
+
+int lfds700_btree_au_get_by_absolute_position( struct lfds700_btree_au_state *baus,
+                                               struct lfds700_btree_au_element **baue,
+                                               enum lfds700_btree_au_absolute_position absolute_position );
+
+int lfds700_btree_au_get_by_relative_position( struct lfds700_btree_au_element **baue,
+                                               enum lfds700_btree_au_relative_position relative_position );
+
+void lfds700_btree_au_query( struct lfds700_btree_au_state *baus,
+                             enum lfds700_btree_au_query query_type,
+                             void *query_input,
+                             void *query_output );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_freelist.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_freelist.h
new file mode 100644
index 0000000000000000000000000000000000000000..6a89386c5d33316d7bc401b364078d112390393e
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_freelist.h
@@ -0,0 +1,54 @@
+/***** defines *****/
+#define LFDS700_FREELIST_GET_KEY_FROM_ELEMENT( freelist_element )             ( (freelist_element).key )
+#define LFDS700_FREELIST_SET_KEY_IN_ELEMENT( freelist_element, new_key )      ( (freelist_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
+#define LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( freelist_element )           ( (freelist_element).value )
+#define LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( freelist_element, new_value )  ( (freelist_element).value = (void *) (lfds700_pal_uint_t) (new_value) )
+#define LFDS700_FREELIST_GET_USER_STATE_FROM_STATE( freelist_state )          ( (freelist_state).user_state )
+
+/***** enums *****/
+enum lfds700_freelist_query
+{
+  LFDS700_FREELIST_QUERY_SINGLETHREADED_GET_COUNT,
+  LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE
+};
+
+/***** structures *****/
+struct lfds700_freelist_element
+{
+  struct lfds700_freelist_element
+    *volatile next;
+
+  void
+    *key,
+    *value;
+};
+
+struct lfds700_freelist_state
+{
+  struct lfds700_freelist_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile top[PAC_SIZE];
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *user_state;
+};
+
+/***** public prototypes *****/
+void lfds700_freelist_init_valid_on_current_logical_core( struct lfds700_freelist_state *fs, void *user_state );
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+
+void lfds700_freelist_cleanup( struct lfds700_freelist_state *fs,
+                               void (*element_cleanup_callback)(struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe) );
+
+void lfds700_freelist_push( struct lfds700_freelist_state *fs,
+                            struct lfds700_freelist_element *fe,
+                            struct lfds700_misc_prng_state *ps );
+
+int lfds700_freelist_pop( struct lfds700_freelist_state *fs,
+                          struct lfds700_freelist_element **fe,
+                          struct lfds700_misc_prng_state *ps );
+
+void lfds700_freelist_query( struct lfds700_freelist_state *fs,
+                             enum lfds700_freelist_query query_type,
+                             void *query_input,
+                             void *query_output );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_hash_addonly.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_hash_addonly.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7962db9e03680c33b5b163ac4526260819c53c1
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_hash_addonly.h
@@ -0,0 +1,127 @@
+/***** defines *****/
+#define LFDS700_HASH_A_GET_KEY_FROM_ELEMENT( hash_a_element )             ( (hash_a_element).key )
+#define LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hash_a_element, new_key )      ( (hash_a_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
+#define LFDS700_HASH_A_GET_VALUE_FROM_ELEMENT( hash_a_element )           ( LFDS700_MISC_BARRIER_LOAD, (hash_a_element).value )
+#define LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hash_a_element, new_value )  { void *local_new_value = (void *) (lfds700_pal_uint_t) (new_value); LFDS700_PAL_ATOMIC_EXCHANGE( &(hash_a_element).value, &local_new_value ); }
+#define LFDS700_HASH_A_GET_USER_STATE_FROM_STATE( hash_a_state )          ( (hash_a_state).user_state )
+
+#define LFDS700_HASH_A_32BIT_HASH_FUNCTION( data, data_length_in_bytes, hash )  {                                                           \
+                                                                                  lfds700_pal_uint_t                                        \
+                                                                                    loop;                                                   \
+                                                                                                                                            \
+                                                                                  for( loop = 0 ; loop < (data_length_in_bytes) ; loop++ )  \
+                                                                                  {                                                         \
+                                                                                    (hash) += *( (char unsigned *) (data) + loop );         \
+                                                                                    (hash) += ((hash) << 10);                               \
+                                                                                    (hash) ^= ((hash) >> 6);                                \
+                                                                                  }                                                         \
+                                                                                                                                            \
+                                                                                  (hash) += ((hash) << 3);                                  \
+                                                                                  (hash) ^= ((hash) >> 11);                                 \
+                                                                                  (hash) += ((hash) << 15);                                 \
+                                                                                }
+  /* TRD : this is the Jenkins one-at-a-time hash
+           it produces a 32 bit hash
+           http://en.wikipedia.org/wiki/Jenkins_hash_function
+
+           we ourselves do *not* initialize the value of *hash, so that
+           our caller has the option to call us multiple times, each
+           time with for example a different member of a struct, which is
+           then hashed into the existing, built-up-so-far hash value, and
+           so build up a quality hash
+  */
+
+/***** enums *****/
+enum lfds700_hash_a_existing_key
+{
+  LFDS700_HASH_A_EXISTING_KEY_OVERWRITE,
+  LFDS700_HASH_A_EXISTING_KEY_FAIL
+};
+
+enum lfds700_hash_a_insert_result
+{
+  LFDS700_HASH_A_PUT_RESULT_FAILURE_EXISTING_KEY,
+  LFDS700_HASH_A_PUT_RESULT_SUCCESS_OVERWRITE,
+  LFDS700_HASH_A_PUT_RESULT_SUCCESS
+};
+
+enum lfds700_hash_a_query
+{
+  LFDS700_HASH_A_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
+  LFDS700_HASH_A_QUERY_SINGLETHREADED_VALIDATE
+};
+
+/***** structs *****/
+struct lfds700_hash_a_element
+{
+  struct lfds700_btree_au_element
+    baue;
+
+  void
+    *key;
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile value;
+};
+
+struct lfds700_hash_a_iterate
+{
+  struct lfds700_btree_au_element
+    *baue;
+
+  struct lfds700_btree_au_state
+    *baus,
+    *baus_end;
+};
+
+struct lfds700_hash_a_state
+{
+  enum lfds700_hash_a_existing_key
+    existing_key;
+
+  int
+    (*key_compare_function)( void const *new_key, void const *existing_key );
+
+  lfds700_pal_uint_t
+    array_size;
+
+  struct lfds700_btree_au_state
+    *baus_array;
+
+  void
+    (*element_cleanup_callback)( struct lfds700_hash_a_state *has, struct lfds700_hash_a_element *hae ),
+    (*key_hash_function)( void const *key, lfds700_pal_uint_t *hash ),
+    *user_state;
+};
+
+/***** public prototypes *****/
+void lfds700_hash_a_init_valid_on_current_logical_core( struct lfds700_hash_a_state *has,
+                                                        struct lfds700_btree_au_state *baus_array,
+                                                        lfds700_pal_uint_t array_size,
+                                                        int (*key_compare_function)(void const *new_key, void const *existing_key),
+                                                        void (*key_hash_function)(void const *key, lfds700_pal_uint_t *hash),
+                                                        enum lfds700_hash_a_existing_key existing_key,
+                                                        void *user_state );
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+
+void lfds700_hash_a_cleanup( struct lfds700_hash_a_state *has,
+                             void (*element_cleanup_function)(struct lfds700_hash_a_state *has, struct lfds700_hash_a_element *hae) );
+
+enum lfds700_hash_a_insert_result lfds700_hash_a_insert( struct lfds700_hash_a_state *has,
+                                                         struct lfds700_hash_a_element *hae,
+                                                         struct lfds700_hash_a_element **existing_hae,
+                                                         struct lfds700_misc_prng_state *ps );
+  // TRD : if existing_value is not NULL and the key exists, existing_value is set to the value of the existing key
+
+int lfds700_hash_a_get_by_key( struct lfds700_hash_a_state *has,
+                               void *key,
+                               struct lfds700_hash_a_element **hae );
+
+void lfds700_hash_a_iterate_init( struct lfds700_hash_a_state *has, struct lfds700_hash_a_iterate *hai );
+int lfds700_hash_a_iterate( struct lfds700_hash_a_iterate *hai, struct lfds700_hash_a_element **hae );
+
+void lfds700_hash_a_query( struct lfds700_hash_a_state *has,
+                           enum lfds700_hash_a_query query_type,
+                           void *query_input,
+                           void *query_output );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_list_addonly_ordered_singlylinked.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_list_addonly_ordered_singlylinked.h
new file mode 100644
index 0000000000000000000000000000000000000000..dffab0aa6b1901e85008faf900a513e8ede980ed
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_list_addonly_ordered_singlylinked.h
@@ -0,0 +1,85 @@
+/***** defines *****/
+#define LFDS700_LIST_AOS_GET_START( list_aos_state )                                             ( LFDS700_MISC_BARRIER_LOAD, (list_aos_state).start->next )
+#define LFDS700_LIST_AOS_GET_NEXT( list_aos_element )                                            ( LFDS700_MISC_BARRIER_LOAD, (list_aos_element).next )
+#define LFDS700_LIST_AOS_GET_START_AND_THEN_NEXT( list_aos_state, pointer_to_list_aos_element )  ( (pointer_to_list_aos_element) == NULL ? ( (pointer_to_list_aos_element) = LFDS700_LIST_AOS_GET_START(list_aos_state) ) : ( (pointer_to_list_aos_element) = LFDS700_LIST_AOS_GET_NEXT(*(pointer_to_list_aos_element)) ) )
+#define LFDS700_LIST_AOS_GET_KEY_FROM_ELEMENT( list_aos_element )                                ( (list_aos_element).key )
+#define LFDS700_LIST_AOS_SET_KEY_IN_ELEMENT( list_aos_element, new_key )                         ( (list_aos_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
+#define LFDS700_LIST_AOS_GET_VALUE_FROM_ELEMENT( list_aos_element )                              ( LFDS700_MISC_BARRIER_LOAD, (list_aos_element).value )
+#define LFDS700_LIST_AOS_SET_VALUE_IN_ELEMENT( list_aos_element, new_value )                     { void *local_new_value = (void *) (lfds700_pal_uint_t) (new_value); LFDS700_PAL_ATOMIC_EXCHANGE( &(list_aos_element).value, &local_new_value ); }
+#define LFDS700_LIST_AOS_GET_USER_STATE_FROM_STATE( list_aos_state )                             ( (list_aos_state).user_state )
+
+/***** enums *****/
+enum lfds700_list_aos_existing_key
+{
+  LFDS700_LIST_AOS_EXISTING_KEY_OVERWRITE,
+  LFDS700_LIST_AOS_EXISTING_KEY_FAIL
+};
+
+enum lfds700_list_aos_insert_result
+{
+  LFDS700_LIST_AOS_INSERT_RESULT_FAILURE_EXISTING_KEY,
+  LFDS700_LIST_AOS_INSERT_RESULT_SUCCESS_OVERWRITE,
+  LFDS700_LIST_AOS_INSERT_RESULT_SUCCESS
+};
+
+enum lfds700_list_aos_query
+{
+  LFDS700_LIST_AOS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
+  LFDS700_LIST_AOS_QUERY_SINGLETHREADED_VALIDATE
+};
+
+/***** structures *****/
+struct lfds700_list_aos_element
+{
+  struct lfds700_list_aos_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile next;
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile value;
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *key;
+};
+
+struct lfds700_list_aos_state
+{
+  struct lfds700_list_aos_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile start;
+
+  struct lfds700_list_aos_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    dummy_element;
+
+  int LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    (*key_compare_function)( void const *new_key, void const *existing_key );
+
+  enum lfds700_list_aos_existing_key
+    existing_key;
+
+  void
+    *user_state;
+};
+
+/***** public prototypes *****/
+void lfds700_list_aos_init_valid_on_current_logical_core( struct lfds700_list_aos_state *laoss,
+                                                          int (*key_compare_function)(void const *new_key, void const *existing_key),
+                                                          enum lfds700_list_aos_existing_key existing_key,
+                                                          void *user_state );
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+
+void lfds700_list_aos_cleanup( struct lfds700_list_aos_state *laoss,
+                               void (*element_cleanup_callback)(struct lfds700_list_aos_state *laoss, struct lfds700_list_aos_element *laose) );
+
+enum lfds700_list_aos_insert_result lfds700_list_aos_insert( struct lfds700_list_aos_state *laoss,
+                                                             struct lfds700_list_aos_element *laose,
+                                                             struct lfds700_list_aos_element **existing_laose,
+                                                             struct lfds700_misc_prng_state *ps );
+
+int lfds700_list_aos_get_by_key( struct lfds700_list_aos_state *laoss,
+                                 void *key,
+                                 struct lfds700_list_aos_element **laose );
+
+void lfds700_list_aos_query( struct lfds700_list_aos_state *laoss,
+                             enum lfds700_list_aos_query query_type,
+                             void *query_input,
+                             void *query_output );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_list_addonly_singlylinked_unordered.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_list_addonly_singlylinked_unordered.h
new file mode 100644
index 0000000000000000000000000000000000000000..38d21511a1d9da781dc6a4f131374d02102f7e6e
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_list_addonly_singlylinked_unordered.h
@@ -0,0 +1,90 @@
+/***** defines *****/
+#define LFDS700_LIST_ASU_GET_START( list_asu_state )                                             ( LFDS700_MISC_BARRIER_LOAD, (list_asu_state).start->next )
+#define LFDS700_LIST_ASU_GET_NEXT( list_asu_element )                                            ( LFDS700_MISC_BARRIER_LOAD, (list_asu_element).next )
+#define LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT( list_asu_state, pointer_to_list_asu_element )  ( (pointer_to_list_asu_element) == NULL ? ( (pointer_to_list_asu_element) = LFDS700_LIST_ASU_GET_START(list_asu_state) ) : ( (pointer_to_list_asu_element) = LFDS700_LIST_ASU_GET_NEXT(*(pointer_to_list_asu_element)) ) )
+#define LFDS700_LIST_ASU_GET_KEY_FROM_ELEMENT( list_asu_element )                                ( (list_asu_element).key )
+#define LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( list_asu_element, new_key )                         ( (list_asu_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
+#define LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( list_asu_element )                              ( LFDS700_MISC_BARRIER_LOAD, (list_asu_element).value )
+#define LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( list_asu_element, new_value )                     { void *local_new_value = (void *) (lfds700_pal_uint_t) (new_value); LFDS700_PAL_ATOMIC_EXCHANGE( &(list_asu_element).value, &local_new_value ); }
+#define LFDS700_LIST_ASU_GET_USER_STATE_FROM_STATE( list_asu_state )                             ( (list_asu_state).user_state )
+
+/***** enums *****/
+enum lfds700_list_asu_position
+{
+  LFDS700_LIST_ASU_POSITION_START,
+  LFDS700_LIST_ASU_POSITION_END,
+  LFDS700_LIST_ASU_POSITION_AFTER
+};
+
+enum lfds700_list_asu_query
+{
+  LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
+  LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE
+};
+
+/***** structures *****/
+struct lfds700_list_asu_element
+{
+  struct lfds700_list_asu_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile next;
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile value;
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *key;
+};
+
+struct lfds700_list_asu_state
+{
+  struct lfds700_list_asu_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile end,
+    *volatile start;
+
+  struct lfds700_list_asu_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    dummy_element;
+
+  int LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    (*key_compare_function)( void const *new_key, void const *existing_key );
+
+  void
+    *user_state;
+};
+
+/***** public prototypes *****/
+void lfds700_list_asu_init_valid_on_current_logical_core( struct lfds700_list_asu_state *lasus,
+                                                          int (*key_compare_function)(void const *new_key, void const *existing_key),
+                                                          void *user_state );
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+
+void lfds700_list_asu_cleanup( struct lfds700_list_asu_state *lasus,
+                               void (*element_cleanup_callback)(struct lfds700_list_asu_state *lasus, struct lfds700_list_asu_element *lasue) );
+
+void lfds700_list_asu_insert_at_position( struct lfds700_list_asu_state *lasus,
+                                          struct lfds700_list_asu_element *lasue,
+                                          struct lfds700_list_asu_element *lasue_predecessor,
+                                          enum lfds700_list_asu_position position,
+                                          struct lfds700_misc_prng_state *ps );
+
+void lfds700_list_asu_insert_at_start( struct lfds700_list_asu_state *lasus,
+                                       struct lfds700_list_asu_element *lasue,
+                                       struct lfds700_misc_prng_state *ps );
+
+void lfds700_list_asu_insert_at_end( struct lfds700_list_asu_state *lasus,
+                                     struct lfds700_list_asu_element *lasue,
+                                     struct lfds700_misc_prng_state *ps );
+
+void lfds700_list_asu_insert_after_element( struct lfds700_list_asu_state *lasus,
+                                            struct lfds700_list_asu_element *lasue,
+                                            struct lfds700_list_asu_element *lasue_predecessor,
+                                            struct lfds700_misc_prng_state *ps );
+
+int lfds700_list_asu_get_by_key( struct lfds700_list_asu_state *lasus,
+                                 void *key,
+                                 struct lfds700_list_asu_element **lasue );
+
+void lfds700_list_asu_query( struct lfds700_list_asu_state *lasus,
+                             enum lfds700_list_asu_query query_type,
+                             void *query_input,
+                             void *query_output );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_misc.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_misc.h
new file mode 100644
index 0000000000000000000000000000000000000000..014f72dac533b8cdcf902ef69bae8adbca39a425
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_misc.h
@@ -0,0 +1,192 @@
+/***** defines *****/
+#define LFDS700_MISC_VERSION_STRING   "7.0.0"
+#define LFDS700_MISC_VERSION_INTEGER  700
+
+#ifndef NULL
+  #define NULL ( (void *) 0 )
+#endif
+
+#define POINTER   0
+#define COUNTER   1
+#define PAC_SIZE  2
+
+#define LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE  0
+#define LFDS700_MISC_PRNG_MAX                           ( (lfds700_pal_uint_t) -1 )
+#define LFDS700_MISC_DELIBERATELY_CRASH                 { char *c = 0; *c = 0; }
+#define LFDS700_MISC_PRNG_SEED                          0x0a34655d34c092feULL
+  /* TRD : from an on-line hardware RNG, using atmospheric noise
+           the URL eblow will generate another 16 random hex digits (e.g. a 64-bit number) and is
+           the RNG used to generate the number above (0x0a34655d34c092fe)
+           http://www.random.org/integers/?num=16&min=0&max=15&col=1&base=16&format=plain&rnd=new
+
+           this seed is a fixed seed which is used for the slow, high quality PRNG,
+           which in turn is used when thread start to generate a single high quality seed
+           for the fast, low quality PRNG used for the CAS exponential backoff
+  */
+
+#if( LFDS700_PAL_ALIGN_SINGLE_POINTER == 4 ) // TRD : any 32-bit platform
+  // TRD : PRNG is a 32-bit xorshift, numbers suggested by George Marsaglia, in his paper http://www.jstatsoft.org/v08/i14/paper
+  #define LFDS700_MISC_PRNG_GENERATE( pointer_to_lfds700_misc_prng_state )  ( (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 13, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state << 17, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 5 )
+#endif
+
+#if( LFDS700_PAL_ALIGN_SINGLE_POINTER == 8 ) // TRD : any 64-bit platform
+  // TRD : PRNG is 64-bit xorshift (xorshift64*), from Sebastiano Vigna (vigna at acm dot org), http://creativecommons.org/publicdomain/zero/1.0/
+  #define LFDS700_MISC_PRNG_GENERATE( pointer_to_lfds700_misc_prng_state )  ( (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 12, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state << 25, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 27, (pointer_to_lfds700_misc_prng_state)->prng_state *= 2685821657736338717LL )
+#endif
+
+#if( !defined LFDS700_PAL_ATOMIC_CAS )
+  #define LFDS700_PAL_NO_ATOMIC_CAS
+
+  // TRD : lfds700_pal_atom_t volatile *destination, lfds700_pal_atom_t *compare, lfds700_pal_atom_t new_destination, enum lfds700_misc_cas_strength cas_strength, char unsigned result
+
+  #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )  \
+  {                                                                                                                    \
+    LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_CAS not implemented for this platform." );                                \
+    LFDS700_MISC_DELIBERATELY_CRASH;                                                                                   \
+    (result) = (char unsigned) 1;                                                                                      \
+  }
+#endif
+
+#if( !defined LFDS700_PAL_ATOMIC_DWCAS )
+  #define LFDS700_PAL_NO_ATOMIC_DWCAS
+
+  // TRD : lfds700_pal_atom_t volatile (*destination)[2], lfds700_pal_atom_t (*compare)[2], lfds700_pal_atom_t (*new_destination)[2], enum lfds700_misc_cas_strength cas_strength, unsigned char result
+
+  #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )  \
+  {                                                                                                                                 \
+    LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_DWCAS not implemented for this platform." );                                           \
+    LFDS700_MISC_DELIBERATELY_CRASH;                                                                                                \
+    (result) = (char unsigned) 1;                                                                                                   \
+  }
+#endif
+
+#if( !defined LFDS700_PAL_ATOMIC_EXCHANGE )
+  #define LFDS700_PAL_NO_ATOMIC_EXCHANGE
+  // TRD : lfds700_pal_atom_t volatile *destination, lfds700_pal_atom_t *exchange
+  #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )          \
+  {                                                                                           \
+    LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_EXCHANGE not implemented for this platform." );  \
+    LFDS700_MISC_DELIBERATELY_CRASH;                                                          \
+  }
+#endif
+
+#if( defined LFDS700_PAL_NO_COMPILER_BARRIERS )
+  #define LFDS700_MISC_BARRIER_LOAD   ( LFDS700_PAL_BARRIER_PROCESSOR_LOAD  )
+  #define LFDS700_MISC_BARRIER_STORE  ( LFDS700_PAL_BARRIER_PROCESSOR_STORE )
+  #define LFDS700_MISC_BARRIER_FULL   ( LFDS700_PAL_BARRIER_PROCESSOR_FULL  )
+#else
+  #define LFDS700_MISC_BARRIER_LOAD   ( LFDS700_PAL_BARRIER_COMPILER_LOAD,  LFDS700_PAL_BARRIER_PROCESSOR_LOAD,  LFDS700_PAL_BARRIER_COMPILER_LOAD  )
+  #define LFDS700_MISC_BARRIER_STORE  ( LFDS700_PAL_BARRIER_COMPILER_STORE, LFDS700_PAL_BARRIER_PROCESSOR_STORE, LFDS700_PAL_BARRIER_COMPILER_STORE )
+  #define LFDS700_MISC_BARRIER_FULL   ( LFDS700_PAL_BARRIER_COMPILER_FULL,  LFDS700_PAL_BARRIER_PROCESSOR_FULL,  LFDS700_PAL_BARRIER_COMPILER_FULL  )
+#endif
+
+#define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE  LFDS700_MISC_BARRIER_LOAD
+
+#if( defined LFDS700_PAL_NO_ATOMIC_CAS )
+  #define LFDS700_MISC_ATOMIC_SUPPORT_CAS 0
+#else
+  #define LFDS700_MISC_ATOMIC_SUPPORT_CAS 1
+#endif
+
+#if( defined LFDS700_PAL_NO_ATOMIC_DWCAS )
+  #define LFDS700_MISC_ATOMIC_SUPPORT_DWCAS 0
+#else
+  #define LFDS700_MISC_ATOMIC_SUPPORT_DWCAS 1
+#endif
+
+#if( defined LFDS700_PAL_NO_ATOMIC_EXCHANGE )
+  #define LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE 0
+#else
+  #define LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE 1
+#endif
+
+/***** enums *****/
+enum lfds700_misc_cas_strength
+{
+  // TRD : yes, weak is 1 (one) - blame GCC!
+  LFDS700_MISC_CAS_STRENGTH_WEAK   = 1,
+  LFDS700_MISC_CAS_STRENGTH_STRONG = 0
+};
+
+enum lfds700_misc_validity
+{
+  LFDS700_MISC_VALIDITY_VALID,
+  LFDS700_MISC_VALIDITY_INVALID_LOOP,
+  LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS,
+  LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS,
+  LFDS700_MISC_VALIDITY_INVALID_TEST_DATA,
+  LFDS700_MISC_VALIDITY_INVALID_ORDER
+};
+
+enum lfds700_misc_flag
+{
+  LFDS700_MISC_FLAG_LOWERED,
+  LFDS700_MISC_FLAG_RAISED
+};
+
+enum lfds700_misc_query
+{
+  LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS,
+  LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS,
+  LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS,
+  LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS,
+  LFDS700_MISC_QUERY_GET_BUILD_AND_VERSION_STRING
+};
+
+/***** struct *****/
+struct lfds700_misc_globals
+{
+  lfds700_pal_atom_t
+    exponential_backoff_timeslot_length_in_loop_iterations_for_cas,
+    exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
+};
+
+struct lfds700_misc_prng_state
+{
+  lfds700_pal_uint_t
+    prng_state;
+
+  // TRD : here to be on the same cache-line as prng_state, and so all are obtained from one cache-line read
+  lfds700_pal_atom_t
+    local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_cas,
+    local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
+};
+
+struct lfds700_misc_validation_info
+{
+  lfds700_pal_uint_t
+    min_elements,
+    max_elements;
+};
+
+/***** externs *****/
+extern struct lfds700_misc_globals
+  lfds700_misc_globals;
+
+/***** public prototypes *****/
+void lfds700_misc_library_init_valid_on_current_logical_core( void );
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+void lfds700_misc_library_cleanup( void );
+
+static LFDS700_PAL_INLINE void lfds700_misc_force_store( void );
+
+void lfds700_misc_prng_init( struct lfds700_misc_prng_state *ps );
+
+void lfds700_misc_query( enum lfds700_misc_query query_type, void *query_input, void *query_output );
+
+/***** public in-line functions *****/
+#pragma prefast( disable : 28112, "blah" )
+
+static LFDS700_PAL_INLINE void lfds700_misc_force_store()
+{
+  lfds700_pal_uint_t
+    exchange = 0;
+
+  lfds700_pal_atom_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    destination;
+
+  LFDS700_PAL_ATOMIC_EXCHANGE( &destination, &exchange );
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_compiler.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_compiler.h
new file mode 100644
index 0000000000000000000000000000000000000000..c628ddd03af42949754008ec3c5be2b54e59a6a7
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_compiler.h
@@ -0,0 +1,478 @@
+/****************************************************************************/
+#if( defined __GNUC__ )
+  // TRD : makes checking GCC versions much tidier
+  #define LFDS700_PAL_GCC_VERSION ( __GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__ )
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined _MSC_VER && _MSC_VER >= 1400 )
+
+  /* TRD : MSVC 8.0 and greater
+
+           _MSC_VER  indicates Microsoft C compiler and version
+                       - __declspec(align)                  requires 7.1 (1310)
+                       - __nop                              requires 8.0 (1400)
+                       - _ReadBarrier                       requires 8.0 (1400)
+                       - _WriteBarrier                      requires 8.0 (1400)
+                       - _ReadWriteBarrier                  requires 7.1 (1310)
+                       - _InterlockedCompareExchangePointer requires 8.0 (1400)
+                       - _InterlockedExchange               requires 7.1 (1310)
+                       - _InterlockedExchangePointer        requires 8.0 (1400)
+                       - _InterlockedCompareExchange64      requires 8.0 (1400) (seems to, docs unclear)
+                       - _InterlockedCompareExchange128     requires 9.0 (1500)
+
+           load/store barriers are mandatory for liblfds, which means the earliest viable version of MSCV is 1400
+           strictly we could get away with 1310 and use _ReadWriteBarrier, but the difference between 1310 and 1400 is small, so WTH
+
+           _InterlockedCompareExchange128 is needed on 64-bit platforms to provide DWCAS, but DWCAS is not mandatory,
+           so we check against the compiler version - remember, any unimplemented atomic will be masked by its dummy define,
+           so everything will compile -  it just means you can't use data structures which require that atomic
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_compiler.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
+
+  #define LFDS700_PAL_COMPILER_STRING            "MSVC"
+
+  #define LFDS700_PAL_ALIGN(alignment)           __declspec( align(alignment) )
+  #define LFDS700_PAL_INLINE                     __forceinline
+
+  #define LFDS700_PAL_BARRIER_COMPILER_LOAD      _ReadBarrier()
+  #define LFDS700_PAL_BARRIER_COMPILER_STORE     _WriteBarrier()
+  #define LFDS700_PAL_BARRIER_COMPILER_FULL      _ReadWriteBarrier()
+
+  /* TRD : there are four processors to consider;
+
+           . ARM32    (32 bit, CAS, DWCAS) (defined _M_ARM)
+           . Itanium  (64 bit, CAS)        (defined _M_IA64)
+           . x64      (64 bit, CAS, DWCAS) (defined _M_X64 || defined _M_AMD64)
+           . x86      (32 bit, CAS, DWCAS) (defined _M_IX86)
+
+           can't find any indications of 64-bit ARM support yet
+
+           ARM has better intrinsics than the others, as there are no-fence variants
+
+           in theory we also have to deal with 32-bit Windows on a 64-bit platform,
+           and I presume we'd see the compiler properly indicate this in its macros,
+           but this would require that we use 32-bit atomics on the 64-bit platforms,
+           while keeping 64-bit cache line lengths and so on, and this is just so
+           wierd a thing to do these days that it's not supported
+
+           note that _InterlockedCompareExchangePointer performs CAS on all processors
+           however, it is documented as being available for x86 when in fact it is not
+           so we have to #if for processor type and use the length specific intrinsics
+  */
+
+  #if( defined _M_ARM )
+    #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD   __dmb( _ARM_BARRIER_ISH )
+    #define LFDS700_PAL_BARRIER_PROCESSOR_STORE  __dmb( _ARM_BARRIER_ISHST )
+    #define LFDS700_PAL_BARRIER_PROCESSOR_FULL   __dmb( _ARM_BARRIER_ISH )
+
+    #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                                          \
+    {                                                                                                                                                                                                            \
+      lfds700_pal_atom_t                                                                                                                                                                                         \
+        original_compare;                                                                                                                                                                                        \
+                                                                                                                                                                                                                 \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                                              \
+      /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                                                  \
+      /* TRD : new_destination can be any value in its range */                                                                                                                                                  \
+      /* TRD : cas_strength can be any value in its range */                                                                                                                                                     \
+      /* TRD : result can be any value in its range */                                                                                                                                                           \
+                                                                                                                                                                                                                 \
+      original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                                                                                                             \
+                                                                                                                                                                                                                 \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                         \
+      *(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange_nf( (long volatile *) (pointer_to_destination), (long) (new_destination), (long) *(pointer_to_compare) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                         \
+                                                                                                                                                                                                                 \
+      result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                                                                                                               \
+    }
+
+    #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )                                                                        \
+    {                                                                                                                                                                                                       \
+      __int64                                                                                                                                                                                               \
+        original_compare;                                                                                                                                                                                   \
+                                                                                                                                                                                                            \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                                         \
+      /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                                             \
+      /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */                                                                                                                                     \
+      /* TRD : cas_strength can be any value in its range */                                                                                                                                                \
+      /* TRD : result can be any value in its range */                                                                                                                                                      \
+                                                                                                                                                                                                            \
+      original_compare = *(__int64 *) (pointer_to_compare);                                                                                                                                                 \
+                                                                                                                                                                                                            \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                    \
+      *(__int64 *) (pointer_to_compare) = _InterlockedCompareExchange64_nf( (__int64 volatile *) (pointer_to_destination), *(__int64 *) (pointer_to_new_destination), *(__int64 *) (pointer_to_compare) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                    \
+                                                                                                                                                                                                            \
+      result = (char unsigned) ( *(__int64 *) (pointer_to_compare) == original_compare );                                                                                                                   \
+    }
+
+    #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                                                    \
+    {                                                                                                                                                                                     \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                       \
+      /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                                                          \
+                                                                                                                                                                                          \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                  \
+      *(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchange_nf( (int long volatile *) (pointer_to_destination), (int long) *(pointer_to_exchange) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                  \
+    }
+  #endif
+
+  #if( defined _M_IA64 )
+    #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD   __mf()
+    #define LFDS700_PAL_BARRIER_PROCESSOR_STORE  __mf()
+    #define LFDS700_PAL_BARRIER_PROCESSOR_FULL   __mf()
+
+    #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                                         \
+    {                                                                                                                                                                                                           \
+      lfds700_pal_atom_t                                                                                                                                                                                        \
+        original_compare;                                                                                                                                                                                       \
+                                                                                                                                                                                                                \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                                             \
+      /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                                                 \
+      /* TRD : new_destination can be any value in its range */                                                                                                                                                 \
+      /* TRD : cas_strength can be any value in its range */                                                                                                                                                    \
+      /* TRD : result can be any value in its range */                                                                                                                                                          \
+                                                                                                                                                                                                                \
+      original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                                                                                                            \
+                                                                                                                                                                                                                \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                        \
+      *(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange64_acq( (__int64 volatile *) (pointer_to_destination), (__int64) (new_destination), (__int64) *(pointer_to_compare) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                        \
+                                                                                                                                                                                                                \
+      result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                                                                                                              \
+    }
+
+    #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                                                     \
+    {                                                                                                                                                                                      \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                        \
+      /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                                                           \
+                                                                                                                                                                                           \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                   \
+      *(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchange64_acq( (__int64 volatile *) (pointer_to_destination), (__int64) *(pointer_to_exchange) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                   \
+    }
+  #endif
+
+  #if( defined _M_X64 || defined _M_AMD64 )
+    #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD   _mm_lfence()
+    #define LFDS700_PAL_BARRIER_PROCESSOR_STORE  _mm_sfence()
+    #define LFDS700_PAL_BARRIER_PROCESSOR_FULL   _mm_mfence()
+
+    #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                                         \
+    {                                                                                                                                                                                                           \
+      lfds700_pal_atom_t                                                                                                                                                                                        \
+        original_compare;                                                                                                                                                                                       \
+                                                                                                                                                                                                                \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                                             \
+      /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                                                 \
+      /* TRD : new_destination can be any value in its range */                                                                                                                                                 \
+      /* TRD : cas_strength can be any value in its range */                                                                                                                                                    \
+      /* TRD : result can be any value in its range */                                                                                                                                                          \
+                                                                                                                                                                                                                \
+      original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                                                                                                            \
+                                                                                                                                                                                                                \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                        \
+      *(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange64( (__int64 volatile *) (pointer_to_destination), (__int64) (new_destination), (__int64) *(pointer_to_compare) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                        \
+                                                                                                                                                                                                                \
+      result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                                                                                                              \
+    }
+
+    #if( _MSC_VER >= 1500 )
+      #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )                                                                                                     \
+      {                                                                                                                                                                                                                                    \
+        /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */                                                                                                                                                                  \
+        /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                                                                      \
+        /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                                                                          \
+        /* TRD : cas_strength can be any value in its range */                                                                                                                                                                             \
+        /* TRD : result can be any value in its range */                                                                                                                                                                                   \
+                                                                                                                                                                                                                                           \
+        LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                                                 \
+        result = (char unsigned) _InterlockedCompareExchange128( (__int64 volatile *) (pointer_to_destination), (__int64) (pointer_to_new_destination[1]), (__int64) (pointer_to_new_destination[0]), (__int64 *) (pointer_to_compare) );  \
+        LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                                                 \
+      }
+    #endif
+
+    #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                                                    \
+    {                                                                                                                                                                                     \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                       \
+      /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                                                          \
+                                                                                                                                                                                          \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                  \
+      *(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchangePointer( (void * volatile *) (pointer_to_destination), (void *) *(pointer_to_exchange) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                  \
+    }
+  #endif
+
+  #if( defined _M_IX86 )
+    #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD   lfds700_misc_force_store()
+    #define LFDS700_PAL_BARRIER_PROCESSOR_STORE  lfds700_misc_force_store()
+    #define LFDS700_PAL_BARRIER_PROCESSOR_FULL   lfds700_misc_force_store()
+
+    #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                                       \
+    {                                                                                                                                                                                                         \
+      lfds700_pal_atom_t                                                                                                                                                                                      \
+        original_compare;                                                                                                                                                                                     \
+                                                                                                                                                                                                              \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                                           \
+      /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                                               \
+      /* TRD : new_destination can be any value in its range */                                                                                                                                               \
+      /* TRD : cas_strength can be any value in its range */                                                                                                                                                  \
+      /* TRD : result can be any value in its range */                                                                                                                                                        \
+                                                                                                                                                                                                              \
+      original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                                                                                                          \
+                                                                                                                                                                                                              \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                      \
+      *(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange( (long volatile *) (pointer_to_destination), (long) (new_destination), (long) *(pointer_to_compare) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                      \
+                                                                                                                                                                                                              \
+      result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                                                                                                            \
+    }
+
+    #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )                                                                     \
+    {                                                                                                                                                                                                    \
+      __int64                                                                                                                                                                                            \
+        original_compare;                                                                                                                                                                                \
+                                                                                                                                                                                                         \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                                      \
+      /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                                          \
+      /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */                                                                                                                                  \
+      /* TRD : cas_strength can be any value in its range */                                                                                                                                             \
+      /* TRD : result can be any value in its range */                                                                                                                                                   \
+                                                                                                                                                                                                         \
+      original_compare = *(__int64 *) (pointer_to_compare);                                                                                                                                              \
+                                                                                                                                                                                                         \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                 \
+      *(__int64 *) (pointer_to_compare) = _InterlockedCompareExchange64( (__int64 volatile *) (pointer_to_destination), *(__int64 *) (pointer_to_new_destination), *(__int64 *) (pointer_to_compare) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                 \
+                                                                                                                                                                                                         \
+      result = (char unsigned) ( *(__int64 *) (pointer_to_compare) == original_compare );                                                                                                                \
+    }
+
+    #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                                                 \
+    {                                                                                                                                                                                  \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                    \
+      /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                                                       \
+                                                                                                                                                                                       \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                               \
+      *(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchange( (int long volatile *) (pointer_to_destination), (int long) *(pointer_to_exchange) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                               \
+    }
+  #endif
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && LFDS700_PAL_GCC_VERSION >= 412 && LFDS700_PAL_GCC_VERSION < 473 )
+
+  /* TRD : GCC 4.1.2 up to 4.7.3
+
+           __GNUC__                 indicates GCC
+           LFDS700_PAL_GCC_VERSION  indicates which version
+                                      - __sync_synchronize requires 4.1.2
+
+           GCC 4.1.2 introduced the __sync_*() atomic intrinsics
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_compiler.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
+
+  #define LFDS700_PAL_COMPILER_STRING          "GCC < 4.7.3"
+
+  #define LFDS700_PAL_ALIGN(alignment)         __attribute__( (aligned(alignment)) )
+  #define LFDS700_PAL_INLINE                   inline
+
+  static LFDS700_PAL_INLINE void lfds700_pal_barrier_compiler( void )
+  {
+    __asm__ __volatile__ ( "" : : : "memory" );
+  }
+
+  #define LFDS700_PAL_BARRIER_COMPILER_LOAD    lfds700_pal_barrier_compiler()
+  #define LFDS700_PAL_BARRIER_COMPILER_STORE   lfds700_pal_barrier_compiler()
+  #define LFDS700_PAL_BARRIER_COMPILER_FULL    lfds700_pal_barrier_compiler()
+
+  #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD   __sync_synchronize()
+  #define LFDS700_PAL_BARRIER_PROCESSOR_STORE  __sync_synchronize()
+  #define LFDS700_PAL_BARRIER_PROCESSOR_FULL   __sync_synchronize()
+
+  #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )       \
+  {                                                                                                                         \
+    lfds700_pal_atom_t                                                                                                      \
+      original_compare;                                                                                                     \
+                                                                                                                            \
+    /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                           \
+    /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                               \
+    /* TRD : new_destination can be any value in its range */                                                               \
+    /* TRD : cas_strength can be any value in its range */                                                                  \
+    /* TRD : result can be any value in its range */                                                                        \
+                                                                                                                            \
+    original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                          \
+                                                                                                                            \
+    LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                      \
+    *(pointer_to_compare) = __sync_val_compare_and_swap( pointer_to_destination, *(pointer_to_compare), new_destination );  \
+    LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                      \
+                                                                                                                            \
+    result = (unsigned char) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                            \
+  }
+
+  // TRD : ARM and x86 have DWCAS which we can get via GCC intrinsics
+  #if( defined __arm__ || defined __i686__ || defined __i586__ || defined __i486__ )
+    #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )                                                                                                   \
+    {                                                                                                                                                                                                                                  \
+      int long long unsigned                                                                                                                                                                                                           \
+        original_destination;                                                                                                                                                                                                          \
+                                                                                                                                                                                                                                       \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                                                                    \
+      /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                                                                        \
+      /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */                                                                                                                                                                \
+      /* TRD : cas_strength can be any value in its range */                                                                                                                                                                           \
+      /* TRD : result can be any value in its range */                                                                                                                                                                                 \
+                                                                                                                                                                                                                                       \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                                               \
+      original_destination = __sync_val_compare_and_swap( (int long long unsigned volatile *) (pointer_to_destination), *(int long long unsigned *) (pointer_to_compare), *(int long long unsigned *) (pointer_to_new_destination) );  \
+      LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                                                                                               \
+                                                                                                                                                                                                                                       \
+      result = (char unsigned) ( original_destination == *(int long long unsigned *) (pointer_to_compare) );                                                                                                                           \
+                                                                                                                                                                                                                                       \
+      *(int long long unsigned *) (pointer_to_compare) = original_destination;                                                                                                                                                         \
+    }
+  #endif
+
+  #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                   \
+  {                                                                                                                                                    \
+    /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                      \
+    /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                         \
+                                                                                                                                                       \
+    LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                 \
+    *( (lfds700_pal_atom_t *) pointer_to_exchange) = (lfds700_pal_atom_t) __sync_lock_test_and_set( pointer_to_destination, *(pointer_to_exchange) );  \
+    LFDS700_PAL_BARRIER_COMPILER_FULL;                                                                                                                 \
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && LFDS700_PAL_GCC_VERSION >= 473 )
+
+  /* TRD : GCC 4.7.3 and greater
+
+           __GNUC__                 indicates GCC
+           LFDS700_PAL_GCC_VERSION  indicates which version
+                                      - __atomic_thread_fence requires 4.7.3
+
+           GCC 4.7.3 introduced the better __atomic*() atomic intrinsics
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_compiler.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
+
+  #define LFDS700_PAL_COMPILER_STRING          "GCC >= 4.7.3"
+
+  #define LFDS700_PAL_ALIGN(alignment)         __attribute__( (aligned(alignment)) )
+  #define LFDS700_PAL_INLINE                   inline
+
+  // TRD : GCC >= 4.7.3 compiler barriers are built into the intrinsics
+  #define LFDS700_PAL_NO_COMPILER_BARRIERS
+
+  #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD   __atomic_thread_fence( __ATOMIC_ACQUIRE )
+  #define LFDS700_PAL_BARRIER_PROCESSOR_STORE  __atomic_thread_fence( __ATOMIC_RELEASE )
+  #define LFDS700_PAL_BARRIER_PROCESSOR_FULL   __atomic_thread_fence( __ATOMIC_ACQ_REL )
+
+  #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                      \
+  {                                                                                                                                                                                        \
+    /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                          \
+    /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                              \
+    /* TRD : new_destination can be any value in its range */                                                                                                                              \
+    /* TRD : cas_strength can be any value in its range */                                                                                                                                 \
+    /* TRD : result can be any value in its range */                                                                                                                                       \
+                                                                                                                                                                                           \
+    result = (char unsigned) __atomic_compare_exchange_n( pointer_to_destination, (void *) (pointer_to_compare), (new_destination), (cas_strength), __ATOMIC_RELAXED, __ATOMIC_RELAXED );  \
+  }
+
+  // TRD : ARM and x86 have DWCAS which we can get via GCC intrinsics
+  #if( defined __arm__ || defined __i686__ || defined __i586__ || defined __i486__ )
+    #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )                                                                                                                                                          \
+    {                                                                                                                                                                                                                                                                                         \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                                                                                                                           \
+      /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                                                                                                                                                                               \
+      /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */                                                                                                                                                                                                                       \
+      /* TRD : cas_strength can be any value in its range */                                                                                                                                                                                                                                  \
+      /* TRD : result can be any value in its range */                                                                                                                                                                                                                                        \
+                                                                                                                                                                                                                                                                                              \
+      (result) = (char unsigned) __atomic_compare_exchange_n( (int long long unsigned volatile *) (pointer_to_destination), (int long long unsigned *) (pointer_to_compare), *(int long long unsigned *) (pointer_to_new_destination), (cas_strength), __ATOMIC_RELAXED, __ATOMIC_RELAXED );  \
+    }
+  #endif
+
+  #if( defined __x86_64__ )
+    /* TRD : __GNUC__    indicates GCC
+                           - __asm__ requires GCC
+                           - __volatile__ requires GCC
+             __x86_64__  indicates x64
+                           - cmpxchg16b requires x64
+
+             On 64 bit platforms, unsigned long long int is 64 bit, so we must manually use cmpxchg16b, 
+             as __sync_val_compare_and_swap() will only emit cmpxchg8b
+    */
+
+    // TRD : lfds700_pal_atom_t volatile (*destination)[2], lfds700_pal_atom_t (*compare)[2], lfds700_pal_atom_t (*new_destination)[2], enum lfds700_misc_cas_strength cas_strength, char unsigned result
+
+    #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )  \
+    {                                                                                                                                 \
+      /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                   \
+      /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */                                                                       \
+      /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */                                                               \
+      /* TRD : cas_strength can be any value in its range */                                                                          \
+      /* TRD : result can be any value in its range */                                                                                \
+                                                                                                                                      \
+      (result) = 0;                                                                                                                   \
+                                                                                                                                      \
+      __asm__ __volatile__                                                                                                            \
+      (                                                                                                                               \
+        "lock;"           /* make cmpxchg16b atomic        */                                                                         \
+        "cmpxchg16b %0;"  /* cmpxchg16b sets ZF on success */                                                                         \
+        "setz       %3;"  /* if ZF set, set result to 1    */                                                                         \
+                                                                                                                                      \
+        /* output */                                                                                                                  \
+        : "+m" (*pointer_to_destination), "+a" ((pointer_to_compare)[0]), "+d" ((pointer_to_compare)[1]), "=q" (result)               \
+                                                                                                                                      \
+        /* input */                                                                                                                   \
+        : "b" ((pointer_to_new_destination)[0]), "c" ((pointer_to_new_destination)[1])                                                \
+                                                                                                                                      \
+        /* clobbered */                                                                                                               \
+        : "cc", "memory"                                                                                                              \
+      );                                                                                                                              \
+    }
+  #endif
+
+  #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                     \
+  {                                                                                                                      \
+    /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                        \
+    /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                           \
+                                                                                                                         \
+    *(pointer_to_exchange) = __atomic_exchange_n( (pointer_to_destination), *(pointer_to_exchange), __ATOMIC_RELAXED );  \
+  }
+
+#endif
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_operating_system.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_operating_system.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c1eba628a5a33553240c645810687114871a746
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_operating_system.h
@@ -0,0 +1,133 @@
+/****************************************************************************/
+#if( defined _MSC_VER )
+  /* TRD : MSVC compiler
+
+           an unfortunately necessary hack for MSVC
+           MSVC only defines __STDC__ if /Za is given, where /Za turns off MSVC C extensions - 
+           which prevents Windows header files from compiling.
+  */
+
+  #define __STDC__         1
+  #define __STDC_HOSTED__  1
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined _MSC_VER && _MSC_VER >= 1400 && __STDC_HOSTED__ == 1 && !defined _KERNEL_MODE )
+
+  // TRD : MSVC
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+
+  #include <assert.h>
+
+  #define LFDS700_PAL_OS_STRING             "Windows"
+  #define LFDS700_PAL_ASSERT( expression )  assert( expression )
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined _MSC_VER && _MSC_VER >= 1400 && defined __STDC_HOSTED__ && __STDC_HOSTED__ == 1 && defined _WIN32 && defined _KERNEL_MODE )
+
+  // TRD : MSVC, Windows kernel-mode
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+
+  #include <assert.h>
+  #include <intrin.h>
+
+  #define LFDS700_PAL_OS_STRING             "Windows"
+  #define LFDS700_PAL_ASSERT( expression )  assert( expression )
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && __STDC_HOSTED__ == 1 && !(defined __linux__ && defined _KERNEL_MODE) )
+
+  // TRD : GCC, hosted implementation (except for Linux kernel mode)
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+
+  #include <assert.h>
+
+  #define LFDS700_PAL_OS_STRING             "Embedded (hosted)"
+  #define LFDS700_PAL_ASSERT( expression )  assert( expression )
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && __STDC_HOSTED__ == 0 )
+
+  // TRD : GCC, freestanding or bare implementation
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+
+  #define LFDS700_PAL_OS_STRING             "Embedded (freestanding/bare)"
+  #define LFDS700_PAL_ASSERT( expression )
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __linux__ && defined _KERNEL_MODE )
+
+  // TRD : GCC, Linux kernel-mode
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_operating_system.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM
+
+  #include <linux/module.h>
+
+  #define LFDS700_PAL_OS_STRING             "Linux"
+  #define LFDS700_PAL_ASSERT( expression )  BUG_ON( expression )
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( !defined LFDS700_PAL_PORTING_ABSTRACTION_LAYER_OPERATING_SYSTEM )
+
+  #error No matching porting abstraction layer in lfds700_porting_abstraction_layer_operating_system.h
+
+#endif
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_processor.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_processor.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e81c0eae27234127e6dffabeb8ac8fa7cfda941
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_processor.h
@@ -0,0 +1,544 @@
+/****************************************************************************/
+#if( defined _MSC_VER && _MSC_VER >= 1400 && defined _M_IX86 )
+
+  /* TRD : MSVC, x86
+           x86 is CAS, so isolation is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long unsigned lfds700_pal_atom_t;
+  typedef int long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "x86"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        4
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        8
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  32
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   32
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined _MSC_VER && _MSC_VER >= 1400 && (defined _M_X64 || defined _M_AMD64) )
+
+  /* TRD : MSVC, x64
+           x64 is CAS, so isolation is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long long unsigned lfds700_pal_atom_t;
+  typedef int long long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "x64"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        8
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        16
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  64
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   64
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined _MSC_VER && _MSC_VER >= 1400 && defined _M_IA64 )
+
+  /* TRD : MSVC, Itanium
+           IA64 is CAS, so isolation is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long long unsigned lfds700_pal_atom_t;
+  typedef int long long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "IA64"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        8
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        16
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  64
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   64
+
+#endif
+
+
+
+
+
+  /****************************************************************************/
+#if( defined _MSC_VER && _MSC_VER >= 1400 && defined _M_ARM )
+
+  /* TRD : MSVC, 32-bit ARM
+
+  ARM is LL/SC and uses a reservation granule of 8 to 2048 bytes
+  so the isolation value used here is worst-case - be sure to set
+  this correctly, otherwise structures are painfully large
+  */
+
+#ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+#error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+#endif
+
+#define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long unsigned lfds700_pal_atom_t;
+  typedef int long unsigned lfds700_pal_uint_t;
+
+#define LFDS700_PAL_PROCESSOR_STRING            "ARM (32-bit)"
+
+#define LFDS700_PAL_ALIGN_SINGLE_POINTER        4
+#define LFDS700_PAL_ALIGN_DOUBLE_POINTER        8
+
+#define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  32
+#define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   2048
+
+#endif
+  
+  
+  
+  
+  
+/****************************************************************************/
+#if( defined __GNUC__ && defined __arm__ )
+
+  /* TRD : GCC, 32-bit ARM
+
+           ARM is LL/SC and uses a reservation granule of 8 to 2048 bytes
+           so the isolation value used here is worst-case - be sure to set
+           this correctly, otherwise structures are painfully large
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long unsigned lfds700_pal_atom_t;
+  typedef int long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "ARM (32-bit)"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        4
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        8
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  32
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   2048
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __aarch64__ )
+
+  /* TRD : GCC, 64-bit ARM
+
+           ARM is LL/SC and uses a reservation granule of 8 to 2048 bytes
+           so the isolation value used here is worst-case - be sure to set
+           this correctly, otherwise structures are painfully large
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long long unsigned lfds700_pal_atom_t;
+  typedef int long long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "ARM (64-bit)"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        8
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        16
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  64
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   2048
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && (defined __i686__ || defined __i586__ || defined __i486__) )
+
+  /* TRD : GCC, x86
+
+           x86 is CAS, so isolation is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long unsigned lfds700_pal_atom_t;
+  typedef int long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "x86"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        4
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        8
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  32
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   32
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __x86_64__ )
+
+  /* TRD : GCC, x86
+
+           x64 is CAS, so isolation is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long long unsigned lfds700_pal_atom_t;
+  typedef int long long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "x64"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        8
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        16
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  64
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   64
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __alpha__ )
+
+  /* TRD : GCC, alpha
+
+           alpha is LL/SC, but there is only one reservation per processor,
+           so the isolation value used here is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long unsigned lfds700_pal_atom_t;
+  typedef int long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "alpha"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        8
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        16
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  32
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   64
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __ia64__ )
+
+  /* TRD : GCC, Itanium
+
+           Itanium is CAS, so isolation is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long long unsigned lfds700_pal_atom_t;
+  typedef int long long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "IA64"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        8
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        16
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  64
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   64
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __mips__ )
+
+  /* TRD : GCC, MIPS (32-bit)
+
+           MIPS is LL/SC, but there is only one reservation per processor,
+           so the isolation value used here is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long unsigned lfds700_pal_atom_t;
+  typedef int long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "MIPS (32-bit)"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        4
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        8
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  32
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   32
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __mips64 )
+
+  /* TRD : GCC, MIPS (64-bit)
+
+           MIPS is LL/SC, but there is only one reservation per processor,
+           so the isolation value used here is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long long unsigned lfds700_pal_atom_t;
+  typedef int long long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "MIPS (64-bit)"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        8
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        16
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  64
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   64
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __ppc__ )
+
+  /* TRD : GCC, POWERPC (32-bit)
+
+           POWERPC is LL/SC and uses a reservation granule but I can't find
+           canonical documentation for its size - 128 bytes seems to be the
+           largest value I've found
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long unsigned lfds700_pal_atom_t;
+  typedef int long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "POWERPC (32-bit)"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        4
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        8
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  32
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   128
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __ppc64__ )
+
+  /* TRD : GCC, POWERPC (64-bit)
+
+           POWERPC is LL/SC and uses a reservation granule but I can't find
+           canonical documentation for its size - 128 bytes seems to be the
+           largest value I've found
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long long unsigned lfds700_pal_atom_t;
+  typedef int long long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "POWERPC (64-bit)"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        8
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        16
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  64
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   128
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __sparc__ && !defined __sparc_v9__ )
+
+  /* TRD : GCC, SPARC (32-bit)
+
+           SPARC is CAS, so isolation is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long unsigned lfds700_pal_atom_t;
+  typedef int long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "SPARC (32-bit)"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        4
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        8
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  32
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   32
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __sparc__ && defined __sparc_v9__ )
+
+  /* TRD : GCC, SPARC (64-bit)
+
+           SPARC is CAS, so isolation is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long long unsigned lfds700_pal_atom_t;
+  typedef int long long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "SPARC (64-bit)"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        8
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        16
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  64
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   64
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __m68k__ )
+
+  /* TRD : GCC, 680x0
+
+           680x0 is CAS, so isolation is cache-line length
+  */
+
+  #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+    #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_processor.h
+  #endif
+
+  #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR
+
+  typedef int long unsigned lfds700_pal_atom_t;
+  typedef int long unsigned lfds700_pal_uint_t;
+
+  #define LFDS700_PAL_PROCESSOR_STRING            "680x0"
+
+  #define LFDS700_PAL_ALIGN_SINGLE_POINTER        4
+  #define LFDS700_PAL_ALIGN_DOUBLE_POINTER        8
+
+  #define LFDS700_PAL_CACHE_LINE_LENGTH_IN_BYTES  32
+  #define LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES   32
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( !defined LFDS700_PAL_PORTING_ABSTRACTION_LAYER_PROCESSOR )
+
+  #error No matching porting abstraction layer in lfds700_porting_abstraction_layer_processor.h
+
+#endif
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_queue.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_queue.h
new file mode 100644
index 0000000000000000000000000000000000000000..025b0673e991852ab8476d5376a37ede95e11228
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_queue.h
@@ -0,0 +1,60 @@
+/***** defines *****/
+#define LFDS700_QUEUE_GET_KEY_FROM_ELEMENT( queue_element )             ( (queue_element).key )
+#define LFDS700_QUEUE_SET_KEY_IN_ELEMENT( queue_element, new_key )      ( (queue_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
+#define LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( queue_element )           ( (queue_element).value )
+#define LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( queue_element, new_value )  ( (queue_element).value = (void *) (lfds700_pal_uint_t) (new_value) )
+#define LFDS700_QUEUE_GET_USER_STATE_FROM_STATE( queue_state )          ( (queue_state).user_state )
+
+/***** enums *****/
+enum lfds700_queue_query
+{
+  LFDS700_QUEUE_QUERY_SINGLETHREADED_GET_COUNT,
+  LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE
+};
+
+/***** structures *****/
+struct lfds700_queue_element
+{
+  struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile next[PAC_SIZE];
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *key;
+
+  void
+    *value;
+};
+
+struct lfds700_queue_state
+{
+  struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile enqueue[PAC_SIZE],
+    *volatile dequeue[PAC_SIZE];
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *user_state;
+};
+
+/***** public prototypes *****/
+void lfds700_queue_init_valid_on_current_logical_core( struct lfds700_queue_state *qs,
+                                                       struct lfds700_queue_element *qe_dummy,
+                                                       struct lfds700_misc_prng_state *ps,
+                                                       void *user_state );
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+
+void lfds700_queue_cleanup( struct lfds700_queue_state *qs,
+                            void (*element_cleanup_callback)(struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag) );
+
+void lfds700_queue_enqueue( struct lfds700_queue_state *qs,
+                            struct lfds700_queue_element *qe,
+                            struct lfds700_misc_prng_state *ps );
+
+int lfds700_queue_dequeue( struct lfds700_queue_state *qs,
+                           struct lfds700_queue_element **qe,
+                           struct lfds700_misc_prng_state *ps );
+
+void lfds700_queue_query( struct lfds700_queue_state *qs,
+                          enum lfds700_queue_query query_type,
+                          void *query_input,
+                          void *query_output );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_queue_bounded_singleconsumer_singleproducer.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_queue_bounded_singleconsumer_singleproducer.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b090e1d450dad72281a2d11175bbbdd306c27ad
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_queue_bounded_singleconsumer_singleproducer.h
@@ -0,0 +1,59 @@
+/***** defines *****/
+#define LFDS700_QUEUE_BSS_GET_USER_STATE_FROM_STATE( queue_bss_state )  ( (queue_bss_state).user_state )
+
+/***** enums *****/
+enum lfds700_queue_bss_query
+{
+  LFDS700_QUEUE_BSS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT,
+  LFDS700_QUEUE_BSS_QUERY_VALIDATE
+};
+
+/***** structures *****/
+struct lfds700_queue_bss_element
+{
+  void
+    *volatile key,
+    *volatile value;
+};
+
+struct lfds700_queue_bss_state
+{
+  lfds700_pal_uint_t
+    number_elements,
+    mask;
+
+  lfds700_pal_uint_t volatile
+    read_index,
+    write_index;
+
+  struct lfds700_queue_bss_element
+    *element_array;
+
+  void
+    *user_state;
+};
+
+/***** public prototypes *****/
+void lfds700_queue_bss_init_valid_on_current_logical_core( struct lfds700_queue_bss_state *qbsss, 
+                                                           struct lfds700_queue_bss_element *element_array,
+                                                           lfds700_pal_uint_t number_elements,
+                                                           void *user_state );
+  // TRD : number_elements must be a positive integer power of 2
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+
+void lfds700_queue_bss_cleanup( struct lfds700_queue_bss_state *qbsss,
+                                void (*element_cleanup_callback)(struct lfds700_queue_bss_state *qbsss, void *key, void *value) );
+
+int lfds700_queue_bss_enqueue( struct lfds700_queue_bss_state *qbsss,
+                               void *key,
+                               void *value );
+
+int lfds700_queue_bss_dequeue( struct lfds700_queue_bss_state *qbsss,
+                               void **key,
+                               void **value );
+
+void lfds700_queue_bss_query( struct lfds700_queue_bss_state *qbsss,
+                              enum lfds700_queue_bss_query query_type,
+                              void *query_input,
+                              void *query_output );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_ringbuffer.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_ringbuffer.h
new file mode 100644
index 0000000000000000000000000000000000000000..fbb21d2be4d4cba782e9c9c7cb7468d1220cba69
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_ringbuffer.h
@@ -0,0 +1,69 @@
+/***** enums *****/
+#define LFDS700_RINGBUFFER_GET_USER_STATE_FROM_STATE( ringbuffer_state )  ( (ringbuffer_state).user_state )
+
+/***** enums *****/
+enum lfds700_ringbuffer_query
+{
+  LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_GET_COUNT,
+  LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE
+};
+
+/***** structures *****/
+struct lfds700_ringbuffer_element
+{
+  struct lfds700_freelist_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    fe;
+
+  struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    qe;
+
+  struct lfds700_queue_element
+    *qe_use; // TRD : hack for 7.0.0; we need a new queue with no dummy element
+
+  void
+    *key,
+    *value;
+};
+
+struct lfds700_ringbuffer_state
+{
+  struct lfds700_freelist_state LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    fs;
+
+  struct lfds700_queue_state LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    qs;
+
+  void
+    (*element_cleanup_callback)( struct lfds700_ringbuffer_state *rs, void *key, void *value, enum lfds700_misc_flag unread_flag ),
+    *user_state;
+};
+
+/***** public prototypes *****/
+void lfds700_ringbuffer_init_valid_on_current_logical_core( struct lfds700_ringbuffer_state *rs,
+                                                            struct lfds700_ringbuffer_element *re_array_inc_dummy,
+                                                            lfds700_pal_uint_t number_elements,
+                                                            struct lfds700_misc_prng_state *ps,
+                                                            void *user_state );
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+
+void lfds700_ringbuffer_cleanup( struct lfds700_ringbuffer_state *rs,
+                                 void (*element_cleanup_callback)(struct lfds700_ringbuffer_state *rs, void *key, void *value, enum lfds700_misc_flag unread_flag) );
+
+int lfds700_ringbuffer_read( struct lfds700_ringbuffer_state *rs,
+                             void **key,
+                             void **value,
+                             struct lfds700_misc_prng_state *ps );
+
+void lfds700_ringbuffer_write( struct lfds700_ringbuffer_state *rs,
+                               void *key,
+                               void *value,
+                               enum lfds700_misc_flag *overwrite_occurred_flag,
+                               void **overwritten_key,
+                               void **overwritten_value,
+                               struct lfds700_misc_prng_state *ps );
+
+void lfds700_ringbuffer_query( struct lfds700_ringbuffer_state *rs,
+                               enum lfds700_ringbuffer_query query_type,
+                               void *query_input,
+                               void *query_output );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_stack.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_stack.h
new file mode 100644
index 0000000000000000000000000000000000000000..3faed80308a41bb5d2072a9b5f0f9df4f584fc15
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_stack.h
@@ -0,0 +1,55 @@
+/***** defines *****/
+#define LFDS700_STACK_GET_KEY_FROM_ELEMENT( stack_element )             ( (stack_element).key )
+#define LFDS700_STACK_SET_KEY_IN_ELEMENT( stack_element, new_key )      ( (stack_element).key = (void *) (lfds700_pal_uint_t) (new_key) )
+#define LFDS700_STACK_GET_VALUE_FROM_ELEMENT( stack_element )           ( (stack_element).value )
+#define LFDS700_STACK_SET_VALUE_IN_ELEMENT( stack_element, new_value )  ( (stack_element).value = (void *) (lfds700_pal_uint_t) (new_value) )
+#define LFDS700_STACK_GET_USER_STATE_FROM_STATE( stack_state )          ( (stack_state).user_state )
+
+/***** enums *****/
+enum lfds700_stack_query
+{
+  LFDS700_STACK_QUERY_SINGLETHREADED_GET_COUNT,
+  LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE
+};
+
+/***** structures *****/
+struct lfds700_stack_element
+{
+  struct lfds700_stack_element
+    *volatile next;
+
+  void
+    *key,
+    *value;
+};
+
+struct lfds700_stack_state
+{
+  struct lfds700_stack_element LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *volatile top[PAC_SIZE];
+
+  void LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    *user_state;
+};
+
+/***** public prototypes *****/
+void lfds700_stack_init_valid_on_current_logical_core( struct lfds700_stack_state *ss, void *user_state );
+  // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
+
+void lfds700_stack_cleanup( struct lfds700_stack_state *ss,
+                            void (*element_cleanup_callback)(struct lfds700_stack_state *ss, struct lfds700_stack_element *se) );
+
+void lfds700_stack_push( struct lfds700_stack_state *ss,
+                         struct lfds700_stack_element *se,
+                         struct lfds700_misc_prng_state *ps );
+
+int lfds700_stack_pop( struct lfds700_stack_state *ss,
+                       struct lfds700_stack_element **se,
+                       struct lfds700_misc_prng_state *ps );
+
+void lfds700_stack_query( struct lfds700_stack_state *ss,
+                          enum lfds700_stack_query query_type,
+                          void *query_input,
+                          void *query_output );
+
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..2927c98628453417fd5c3e1443f54709e73df6b6
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_cleanup.c
@@ -0,0 +1,117 @@
+/***** includes *****/
+#include "lfds700_btree_addonly_unbalanced_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_btree_au_cleanup( struct lfds700_btree_au_state *baus,
+                               void (*element_cleanup_callback)(struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element *baue) )
+{
+  enum lfds700_btree_au_delete_action
+    delete_action = LFDS700_BTREE_AU_DELETE_SELF; // TRD : to remove compiler warning
+
+  struct lfds700_btree_au_element
+    *baue;
+
+  struct lfds700_btree_au_element
+    *temp;
+
+  LFDS700_PAL_ASSERT( baus != NULL );
+  // TRD : element_delete_function can be NULL
+
+  /* TRD : we're not lock-free now, so delete at will
+           but be iterative, so can be used in kernels (where there's little stack)
+           and be performant, since the user may be
+           creating/destroying many of these trees
+           also remember the user may be deallocating user data
+           so we cannot visit an element twice
+
+           we start at the root and iterate till we go to NULL
+           if the element has zero children, we delete it and move up to its parent
+           if the element has one child, we delete it, move its child into its place, and continue from its child
+           if the element has two children, we move left
+
+           the purpose of this is to minimize walking around the tree
+           to prevent visiting an element twice
+           while also minimizing code complexity
+  */
+
+  if( element_cleanup_callback == NULL )
+    return;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  lfds700_btree_au_get_by_absolute_position( baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_ROOT );
+
+  while( baue != NULL )
+  {
+    if( baue->left == NULL and baue->right == NULL )
+      delete_action = LFDS700_BTREE_AU_DELETE_SELF;
+
+    if( baue->left != NULL and baue->right == NULL )
+      delete_action = LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_LEFT_CHILD;
+
+    if( baue->left == NULL and baue->right != NULL )
+      delete_action = LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_RIGHT_CHILD;
+
+    if( baue->left != NULL and baue->right != NULL )
+      delete_action = LFDS700_BTREE_AU_DELETE_MOVE_LEFT;
+
+    switch( delete_action )
+    {
+      case LFDS700_BTREE_AU_DELETE_SELF:
+        // TRD : if we have a parent (we could be root) set his point to us to NULL
+        if( baue->up != NULL )
+        {
+          if( baue->up->left == baue )
+            baue->up->left = NULL;
+          if( baue->up->right == baue )
+            baue->up->right = NULL;
+        }
+
+        temp = baue;
+        lfds700_btree_au_get_by_relative_position( &baue, LFDS700_BTREE_AU_RELATIVE_POSITION_UP );
+        element_cleanup_callback( baus, temp );
+      break;
+
+      case LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_LEFT_CHILD:
+        baue->left->up = baue->up;
+        if( baue->up != NULL )
+        {
+          if( baue->up->left == baue )
+            baue->up->left = baue->left;
+          if( baue->up->right == baue )
+            baue->up->right = baue->left;
+        }
+
+        temp = baue;
+        lfds700_btree_au_get_by_relative_position( &baue, LFDS700_BTREE_AU_RELATIVE_POSITION_LEFT );
+        element_cleanup_callback( baus, temp );
+      break;
+
+      case LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_RIGHT_CHILD:
+        baue->right->up = baue->up;
+        if( baue->up != NULL )
+        {
+          if( baue->up->left == baue )
+            baue->up->left = baue->right;
+          if( baue->up->right == baue )
+            baue->up->right = baue->right;
+        }
+
+        temp = baue;
+        lfds700_btree_au_get_by_relative_position( &baue, LFDS700_BTREE_AU_RELATIVE_POSITION_RIGHT );
+        element_cleanup_callback( baus, temp );
+      break;
+
+      case LFDS700_BTREE_AU_DELETE_MOVE_LEFT:
+        lfds700_btree_au_get_by_relative_position( &baue, LFDS700_BTREE_AU_RELATIVE_POSITION_LEFT );
+      break;
+    }
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_get.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_get.c
new file mode 100644
index 0000000000000000000000000000000000000000..8a2cdf93e81198a77018fcd0ee69ccfd973b89da
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_get.c
@@ -0,0 +1,467 @@
+/***** includes *****/
+#include "lfds700_btree_addonly_unbalanced_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_btree_au_internal_inorder_walk_from_largest_get_next_smallest_element( struct lfds700_btree_au_element **baue );
+static void lfds700_btree_au_internal_inorder_walk_from_smallest_get_next_largest_element( struct lfds700_btree_au_element **baue );
+
+
+
+
+
+/****************************************************************************/
+int lfds700_btree_au_get_by_key( struct lfds700_btree_au_state *baus,
+                                 void *key,
+                                 struct lfds700_btree_au_element **baue )
+{
+  int
+    compare_result = !0,
+    rv = 1;
+
+  LFDS700_PAL_ASSERT( baus != NULL );
+  // TRD : key can be NULL
+  LFDS700_PAL_ASSERT( baue != NULL );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  *baue = baus->root;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  while( *baue != NULL and compare_result != 0 )
+  {
+    compare_result = baus->key_compare_function( key, (*baue)->key );
+
+    if( compare_result < 0 )
+    {
+      *baue = (*baue)->left;
+      LFDS700_MISC_BARRIER_LOAD;
+    }
+
+    if( compare_result > 0 )
+    {
+      *baue = (*baue)->right;
+      LFDS700_MISC_BARRIER_LOAD;
+    }
+  }
+
+  if( *baue == NULL )
+    rv = 0;
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+int lfds700_btree_au_get_by_absolute_position( struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element **baue, enum lfds700_btree_au_absolute_position absolute_position )
+{
+  int
+    rv = 1;
+
+  LFDS700_PAL_ASSERT( baus != NULL );
+  LFDS700_PAL_ASSERT( baue != NULL );
+  // TRD : absolute_position can be any value in its range
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  *baue = baus->root;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  switch( absolute_position )
+  {
+    case LFDS700_BTREE_AU_ABSOLUTE_POSITION_ROOT:
+    break;
+
+    case LFDS700_BTREE_AU_ABSOLUTE_POSITION_LARGEST_IN_TREE:
+      if( *baue != NULL )
+        while( (*baue)->right != NULL )
+        {
+          *baue = (*baue)->right;
+          LFDS700_MISC_BARRIER_LOAD;
+        }
+    break;
+
+    case LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE:
+      if( *baue != NULL )
+        while( (*baue)->left != NULL )
+        {
+          *baue = (*baue)->left;
+          LFDS700_MISC_BARRIER_LOAD;
+        }
+    break;
+  }
+
+  if( *baue == NULL )
+    rv = 0;
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+int lfds700_btree_au_get_by_relative_position( struct lfds700_btree_au_element **baue, enum lfds700_btree_au_relative_position relative_position )
+{
+  int
+    rv = 1;
+
+  LFDS700_PAL_ASSERT( baue != NULL );
+  // TRD : relative_position can baue any value in its range
+
+  if( *baue == NULL )
+    return( 0 );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  switch( relative_position )
+  {
+    case LFDS700_BTREE_AU_RELATIVE_POSITION_UP:
+      *baue = (*baue)->up;
+      // TRD : no load barrier - up already existed, so is known to be safely propagated
+    break;
+
+    case LFDS700_BTREE_AU_RELATIVE_POSITION_LEFT:
+      *baue = (*baue)->left;
+      LFDS700_MISC_BARRIER_LOAD;
+    break;
+
+    case LFDS700_BTREE_AU_RELATIVE_POSITION_RIGHT:
+      *baue = (*baue)->right;
+      LFDS700_MISC_BARRIER_LOAD;
+    break;
+
+    case LFDS700_BTREE_AU_RELATIVE_POSITION_SMALLEST_ELEMENT_BELOW_CURRENT_ELEMENT:
+      *baue = (*baue)->left;
+      if( *baue != NULL )
+      {
+        LFDS700_MISC_BARRIER_LOAD;
+        while( (*baue)->right != NULL )
+        {
+          *baue = (*baue)->right;
+          LFDS700_MISC_BARRIER_LOAD;
+        }
+      }
+    break;
+
+    case LFDS700_BTREE_AU_RELATIVE_POSITION_LARGEST_ELEMENT_BELOW_CURRENT_ELEMENT:
+      *baue = (*baue)->right;
+      if( *baue != NULL )
+      {
+        LFDS700_MISC_BARRIER_LOAD;
+        while( (*baue)->left != NULL )
+        {
+          *baue = (*baue)->left;
+          LFDS700_MISC_BARRIER_LOAD;
+        }
+      }
+    break;
+
+    case LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_SMALLER_ELEMENT_IN_ENTIRE_TREE:
+      lfds700_btree_au_internal_inorder_walk_from_largest_get_next_smallest_element( baue );
+    break;
+
+    case LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE:
+      lfds700_btree_au_internal_inorder_walk_from_smallest_get_next_largest_element( baue );
+    break;
+  }
+
+  if( *baue == NULL )
+    rv = 0;
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_btree_au_internal_inorder_walk_from_largest_get_next_smallest_element( struct lfds700_btree_au_element **baue )
+{
+  enum lfds700_btree_au_move
+    action = LFDS700_BTREE_AU_MOVE_INVALID;
+
+  enum lfds700_misc_flag
+    finished_flag = LFDS700_MISC_FLAG_LOWERED,
+    load_finished_flag = LFDS700_MISC_FLAG_LOWERED;
+
+  struct lfds700_btree_au_element
+    *left = NULL,
+    *right = NULL,
+    *up = NULL,
+    *up_left = NULL,
+    *up_right = NULL;
+
+  LFDS700_PAL_ASSERT( baue != NULL );
+
+  /* TRD : from any given element, the next smallest element is;
+           1. if we have a left, it's the largest element on the right branch of our left child
+           2. if we don't have a left, and we're on the right of our parent, then it's our parent
+           3. if we don't have a left, and we're on the left of our parent or we have no parent,
+              iterative up the tree until we find the first child who is on the right of its parent; then it's the parent
+  */
+
+  /* TRD : we need to ensure the variables we use to decide our action are self-consistent
+           to do this, we make local copies of them all
+           then, if they are all not NULL, we can know they cannot change and we can continue
+           if however any of them are NULL, they could have changed while we were reading
+           and so our variables could be non-self-consistent
+           to check for this, we issue another processor read barrier
+           and then compare our local variables with the values in the tree
+           if they all match, then we know our variable set is self-consistent
+           (even though it may now be wrong - but we will discover this when we try the atomic operation)
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  while( load_finished_flag == LFDS700_MISC_FLAG_LOWERED )
+  {
+    left = (*baue)->left;
+    right = (*baue)->right;
+    up = (*baue)->up;
+    if( up != NULL )
+    {
+      up_left = (*baue)->up->left;
+      up_right = (*baue)->up->right;
+    }
+
+    if( left != NULL and right != NULL and (up == NULL or (up != NULL and up_left != NULL and up_right != NULL)) )
+      break;
+
+    LFDS700_MISC_BARRIER_LOAD;
+
+    if( left == (*baue)->left and right == (*baue)->right and (up == NULL or (up != NULL and up == (*baue)->up and up_left == (*baue)->up->left and up_right == (*baue)->up->right)) )
+      load_finished_flag = LFDS700_MISC_FLAG_RAISED;
+  }
+
+  if( left != NULL )
+    action = LFDS700_BTREE_AU_MOVE_LARGEST_FROM_LEFT_CHILD;
+
+  if( left == NULL and up != NULL and up_right == *baue )
+    action = LFDS700_BTREE_AU_MOVE_GET_PARENT;
+
+  if( (left == NULL and up == NULL) or (up != NULL and up_left == *baue and left == NULL) )
+    action = LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE;
+
+  switch( action )
+  {
+    case LFDS700_BTREE_AU_MOVE_INVALID:
+    case LFDS700_BTREE_AU_MOVE_SMALLEST_FROM_RIGHT_CHILD:
+      // TRD : eliminates a compiler warning
+    break;
+
+    case LFDS700_BTREE_AU_MOVE_LARGEST_FROM_LEFT_CHILD:
+      *baue = left;
+      if( *baue != NULL )
+      {
+        LFDS700_MISC_BARRIER_LOAD;
+        while( (*baue)->right != NULL )
+        {
+          *baue = (*baue)->right;
+          LFDS700_MISC_BARRIER_LOAD;
+        }
+      }
+    break;
+
+    case LFDS700_BTREE_AU_MOVE_GET_PARENT:
+      *baue = up;
+    break;
+
+    case LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE:
+      while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
+      {
+        load_finished_flag = LFDS700_MISC_FLAG_LOWERED;
+
+        while( load_finished_flag == LFDS700_MISC_FLAG_LOWERED )
+        {
+          up = (*baue)->up;
+          if( up != NULL )
+            up_left = (*baue)->up->left;
+
+          if( up == NULL or (up != NULL and up_left != NULL) )
+            break;
+
+          LFDS700_MISC_BARRIER_LOAD;
+
+          if( up == (*baue)->up and up_left == (*baue)->up->left )
+            load_finished_flag = LFDS700_MISC_FLAG_RAISED;
+        }
+
+        if( *baue != NULL and up != NULL and *baue == up_left )
+          *baue = up;
+        else
+          finished_flag = LFDS700_MISC_FLAG_RAISED;
+      }
+
+      *baue = up;
+
+      /*
+
+      while( *baue != NULL and (*baue)->up != NULL and *baue == (*baue)->up->left )
+        *baue = (*baue)->up;
+
+      *baue = (*baue)->up;
+
+      */
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_btree_au_internal_inorder_walk_from_smallest_get_next_largest_element( struct lfds700_btree_au_element **baue )
+{
+  enum lfds700_btree_au_move
+    action = LFDS700_BTREE_AU_MOVE_INVALID;
+
+  enum lfds700_misc_flag
+    finished_flag = LFDS700_MISC_FLAG_LOWERED,
+    load_finished_flag = LFDS700_MISC_FLAG_LOWERED;
+
+  struct lfds700_btree_au_element
+    *left = NULL,
+    *right = NULL,
+    *up = NULL,
+    *up_left = NULL,
+    *up_right = NULL;
+
+  LFDS700_PAL_ASSERT( baue != NULL );
+
+  /* TRD : from any given element, the next largest element is;
+           1. if we have a right, it's the smallest element on the left branch of our right child
+           2. if we don't have a right, and we're on the left of our parent, then it's our parent
+           3. if we don't have a right, and we're on the right of our parent or we have no parent,
+              iterate up the tree until we find the first child who is on the left of its parent; then it's the parent
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  while( load_finished_flag == LFDS700_MISC_FLAG_LOWERED )
+  {
+    left = (*baue)->left;
+    right = (*baue)->right;
+    up = (*baue)->up;
+    if( up != NULL )
+    {
+      up_left = (*baue)->up->left;
+      up_right = (*baue)->up->right;
+    }
+
+    if( left != NULL and right != NULL and (up == NULL or (up != NULL and up_left != NULL and up_right != NULL)) )
+      break;
+
+    LFDS700_MISC_BARRIER_LOAD;
+
+    if( left == (*baue)->left and right == (*baue)->right and (up == NULL or (up != NULL and up == (*baue)->up and up_left == (*baue)->up->left and up_right == (*baue)->up->right)) )
+      load_finished_flag = LFDS700_MISC_FLAG_RAISED;
+  }
+
+  if( right != NULL )
+    action = LFDS700_BTREE_AU_MOVE_SMALLEST_FROM_RIGHT_CHILD;
+
+  if( right == NULL and up != NULL and up_left == *baue )
+    action = LFDS700_BTREE_AU_MOVE_GET_PARENT;
+
+  if( (right == NULL and up == NULL) or (up != NULL and up_right == *baue and right == NULL) )
+    action = LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE;
+
+  switch( action )
+  {
+    case LFDS700_BTREE_AU_MOVE_INVALID:
+    case LFDS700_BTREE_AU_MOVE_LARGEST_FROM_LEFT_CHILD:
+      // TRD : remove compiler warning
+    break;
+
+    case LFDS700_BTREE_AU_MOVE_SMALLEST_FROM_RIGHT_CHILD:
+      *baue = right;
+      if( *baue != NULL )
+      {
+        LFDS700_MISC_BARRIER_LOAD;
+        while( (*baue)->left != NULL )
+        {
+          *baue = (*baue)->left;
+          LFDS700_MISC_BARRIER_LOAD;
+        }
+      }
+    break;
+
+    case LFDS700_BTREE_AU_MOVE_GET_PARENT:
+      *baue = up;
+    break;
+
+    case LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE:
+      while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
+      {
+        load_finished_flag = LFDS700_MISC_FLAG_LOWERED;
+
+        while( load_finished_flag == LFDS700_MISC_FLAG_LOWERED )
+        {
+          up = (*baue)->up;
+          if( up != NULL )
+            up_right = (*baue)->up->right;
+
+          if( up == NULL or (up != NULL and up_right != NULL) )
+            break;
+
+          LFDS700_MISC_BARRIER_LOAD;
+
+          if( up == (*baue)->up and up_right == (*baue)->up->right )
+            load_finished_flag = LFDS700_MISC_FLAG_RAISED;
+        }
+
+        if( *baue != NULL and up != NULL and *baue == up_right )
+          *baue = up;
+        else
+          finished_flag = LFDS700_MISC_FLAG_RAISED;
+      }
+
+      *baue = up;
+
+      /*
+
+      while( *baue != NULL and (*baue)->up != NULL and *baue == (*baue)->up->right )
+        *baue = (*baue)->up;
+
+      *baue = (*baue)->up;
+
+      */
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+int lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position( struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element **baue, enum lfds700_btree_au_absolute_position absolute_position, enum lfds700_btree_au_relative_position relative_position )
+{
+  int
+    rv;
+
+  LFDS700_PAL_ASSERT( baus != NULL );
+  LFDS700_PAL_ASSERT( baue != NULL );
+  // TRD: absolute_position can be any value in its range
+  // TRD: relative_position can be any value in its range
+
+  if( *baue == NULL )
+    rv = lfds700_btree_au_get_by_absolute_position( baus, baue, absolute_position );
+  else
+    rv = lfds700_btree_au_get_by_relative_position( baue, relative_position );
+
+  return( rv );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..7dd0efd6c01629053326cca950af01fe95298206
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_init.c
@@ -0,0 +1,32 @@
+/***** includes *****/
+#include "lfds700_btree_addonly_unbalanced_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_btree_au_init_valid_on_current_logical_core( struct lfds700_btree_au_state *baus,
+                                                          int (*key_compare_function)(void const *new_key, void const *existing_key),
+                                                          enum lfds700_btree_au_existing_key existing_key,
+                                                          void *user_state )
+{
+  LFDS700_PAL_ASSERT( baus != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baus->root % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baus->key_compare_function % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( key_compare_function != NULL );
+  // TRD : existing_key can be any value in its range
+  // TRD : user_state can be NULL
+
+  baus->root = NULL;
+  baus->key_compare_function = key_compare_function;
+  baus->existing_key = existing_key;
+  baus->user_state = user_state;
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_insert.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_insert.c
new file mode 100644
index 0000000000000000000000000000000000000000..8808177a4c6dbfd9ed69f21bbd78036ff7789ec8
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_insert.c
@@ -0,0 +1,156 @@
+/***** includes *****/
+#include "lfds700_btree_addonly_unbalanced_internal.h"
+
+
+
+
+
+/****************************************************************************/
+enum lfds700_btree_au_insert_result lfds700_btree_au_insert( struct lfds700_btree_au_state *baus,
+                                                             struct lfds700_btree_au_element *baue,
+                                                             struct lfds700_btree_au_element **existing_baue,
+                                                             struct lfds700_misc_prng_state *ps )
+{
+  char unsigned 
+    result = 0;
+
+  int
+    compare_result = 0;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  struct lfds700_btree_au_element
+    *volatile compare = NULL,
+    *volatile baue_next = NULL,
+    *volatile baue_parent = NULL,
+    *volatile baue_temp;
+
+  LFDS700_PAL_ASSERT( baus != NULL );
+  LFDS700_PAL_ASSERT( baue != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->left % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->right % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->up % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &baue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  // TRD : existing_baue can be NULL
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  /* TRD : we follow a normal search for the insert node and which side to insert
+
+           the difference is that insertion may fail because someone else inserts
+           there before we do
+
+           in this case, we resume searching for the insert node from the node
+           we were attempting to insert upon
+
+           (if we attempted to insert the root node and this failed, i.e. we thought
+            the tree was empty but then it wasn't, then we start searching from the
+            new root)
+  */
+
+  baue->up = baue->left = baue->right = NULL;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  baue_temp = baus->root;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  while( result == 0 )
+  {
+    // TRD : first we find where to insert
+    while( baue_temp != NULL )
+    {
+      compare_result = baus->key_compare_function( baue->key, baue_temp->key );
+
+      if( compare_result == 0 )
+      {
+        if( existing_baue != NULL )
+          *existing_baue = baue_temp;
+
+        switch( baus->existing_key )
+        {
+          case LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE:
+            LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( *baue_temp, baue->value );
+            return( LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE );
+          break;
+
+          case LFDS700_BTREE_AU_EXISTING_KEY_FAIL:
+            return( LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY );
+          break;
+        }
+      }
+
+      if( compare_result < 0 )
+        baue_next = baue_temp->left;
+
+      if( compare_result > 0 )
+        baue_next = baue_temp->right;
+
+      baue_parent = baue_temp;
+      baue_temp = baue_next;
+      if( baue_temp != NULL )
+        LFDS700_MISC_BARRIER_LOAD;
+    }
+
+    /* TRD : second, we actually insert
+
+             at this point baue_temp has come to NULL
+             and baue_parent is the element to insert at
+             and result of the last compare indicates
+             the direction of insertion
+
+             it may be that another tree has already inserted an element with
+             the same key as ourselves, or other elements which mean our position
+             is now wrong
+
+             in this case, it is either inserted in the position we're trying
+             to insert in now, in which case our insert will fail
+
+             or, similarly, other elements will have come in where we are,
+             and our insert will fail
+    */
+
+    if( baue_parent == NULL )
+    {
+      compare = NULL;
+      baue->up = baus->root;
+      LFDS700_MISC_BARRIER_STORE;
+      LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &baus->root, &compare, baue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+
+      if( result == 0 )
+        baue_temp = baus->root;
+    }
+
+    if( baue_parent != NULL )
+    {
+      if( compare_result <= 0 )
+      {
+        compare = NULL;
+        baue->up = baue_parent;
+        LFDS700_MISC_BARRIER_STORE;
+        LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &baue_parent->left, &compare, baue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+      }
+
+      if( compare_result > 0 )
+      {
+        compare = NULL;
+        baue->up = baue_parent;
+        LFDS700_MISC_BARRIER_STORE;
+        LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &baue_parent->right, &compare, baue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+      }
+
+      // TRD : if the insert fails, resume searching at the insert node
+      if( result == 0 )
+        baue_temp = baue_parent;
+    }
+  }
+
+  // TRD : if we get to here, we added (not failed or overwrite on exist) a new element
+  if( existing_baue != NULL )
+    *existing_baue = NULL;
+
+  return( LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..54149bac9941bf33a45f3426b90ea09b0f8a3c65
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_internal.h
@@ -0,0 +1,23 @@
+/***** the library-wide header file *****/
+#include "../liblfds700_internal.h"
+
+/***** enums *****/
+enum lfds700_btree_au_move
+{
+  LFDS700_BTREE_AU_MOVE_INVALID,
+  LFDS700_BTREE_AU_MOVE_SMALLEST_FROM_RIGHT_CHILD,
+  LFDS700_BTREE_AU_MOVE_LARGEST_FROM_LEFT_CHILD,
+  LFDS700_BTREE_AU_MOVE_GET_PARENT,
+  LFDS700_BTREE_AU_MOVE_MOVE_UP_TREE
+};
+
+enum lfds700_btree_au_delete_action
+{
+  LFDS700_BTREE_AU_DELETE_SELF,
+  LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_LEFT_CHILD,
+  LFDS700_BTREE_AU_DELETE_SELF_REPLACE_WITH_RIGHT_CHILD,
+  LFDS700_BTREE_AU_DELETE_MOVE_LEFT
+};
+
+/***** private prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..dce958792988dcf3b86202d4a1e55917b34a9325
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_query.c
@@ -0,0 +1,121 @@
+/***** includes *****/
+#include "lfds700_btree_addonly_unbalanced_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_btree_au_internal_validate( struct lfds700_btree_au_state *abs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_btree_au_validity );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_btree_au_query( struct lfds700_btree_au_state *baus, enum lfds700_btree_au_query query_type, void *query_input, void *query_output )
+{
+  LFDS700_PAL_ASSERT( baus != NULL );
+  // TRD : query_type can be any value in its range
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  switch( query_type )
+  {
+    case LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
+    {
+      struct lfds700_btree_au_element
+        *baue = NULL;
+
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      *(lfds700_pal_uint_t *) query_output = 0;
+
+      while( lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position(baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE) )
+        ( *(lfds700_pal_uint_t *) query_output )++;
+    }
+    break;
+
+    case LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE:
+      // TRD : query_input can be NULL
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_btree_au_internal_validate( baus, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_btree_au_internal_validate( struct lfds700_btree_au_state *baus, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_btree_au_validity )
+{
+  lfds700_pal_uint_t
+    number_elements_from_query_tree = 0,
+    number_elements_from_walk = 0;
+
+  struct lfds700_btree_au_element
+    *baue = NULL,
+    *baue_prev = NULL;
+
+  LFDS700_PAL_ASSERT( baus!= NULL );
+  // TRD : vi can be NULL
+  LFDS700_PAL_ASSERT( lfds700_btree_au_validity != NULL );
+
+  *lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_VALID;
+
+  /* TRD : validation is performed by;
+
+           performing an in-order walk
+           we should see every element is larger than the preceeding element
+           we count elements as we go along (visited elements, that is)
+           and check our tally equals the expected count
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  while( lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position(baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE) )
+  {
+    // TRD : baue_prev should always be smaller than or equal to baue
+    if( baue_prev != NULL )
+      if( baus->key_compare_function(baue_prev->key, baue->key) > 0 )
+      {
+        *lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_ORDER;
+        return;
+      }
+
+    baue_prev = baue;
+    number_elements_from_walk++;
+  }
+
+  if( *lfds700_btree_au_validity == LFDS700_MISC_VALIDITY_VALID )
+  {
+    lfds700_btree_au_query( (struct lfds700_btree_au_state *) baus, LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &number_elements_from_query_tree );
+
+    if( number_elements_from_walk > number_elements_from_query_tree )
+      *lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( number_elements_from_walk < number_elements_from_query_tree )
+      *lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+  }
+
+  /* TRD : now check for expected number of elements
+           vi can be NULL, in which case we do not check
+           we know we don't have a loop from our earlier check
+  */
+
+  if( *lfds700_btree_au_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
+  {
+    lfds700_btree_au_query( (struct lfds700_btree_au_state *) baus, LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &number_elements_from_query_tree );
+
+    if( number_elements_from_query_tree < vi->min_elements )
+      *lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( number_elements_from_query_tree > vi->max_elements )
+      *lfds700_btree_au_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..f7a088a39a7111c7c2605aa7da751481eef74776
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_cleanup.c
@@ -0,0 +1,36 @@
+/***** includes *****/
+#include "lfds700_freelist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_freelist_cleanup( struct lfds700_freelist_state *fs,
+                               void (*element_cleanup_callback)(struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe) )
+{
+  struct lfds700_freelist_element
+    *fe,
+    *fe_temp;
+
+  LFDS700_PAL_ASSERT( fs != NULL );
+  // TRD : element_cleanup_callback can be NULL
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  if( element_cleanup_callback != NULL )
+  {
+    fe = fs->top[POINTER];
+
+    while( fe != NULL )
+    {
+      fe_temp = fe;
+      fe = fe->next;
+
+      element_cleanup_callback( fs, fe_temp );
+    }
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..fcacd1b32f06ef5d4497994c5ab506a2fbffd48f
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_init.c
@@ -0,0 +1,27 @@
+/***** includes *****/
+#include "lfds700_freelist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_freelist_init_valid_on_current_logical_core( struct lfds700_freelist_state *fs, void *user_state )
+{
+  LFDS700_PAL_ASSERT( fs != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) fs->top % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &fs->user_state % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  // TRD : user_state can be NULL
+
+  fs->top[POINTER] = NULL;
+  fs->top[COUNTER] = 0;
+
+  fs->user_state = user_state;
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a7d54180421c96cce9b0a1b6529d4cee90b5564
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_internal.h
@@ -0,0 +1,5 @@
+/***** the library wide include file *****/
+#include "../liblfds700_internal.h"
+
+/***** private prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_pop.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_pop.c
new file mode 100644
index 0000000000000000000000000000000000000000..c0a3545d9194ab0011381003524a71fac8aef37a
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_pop.c
@@ -0,0 +1,52 @@
+/***** includes *****/
+#include "lfds700_freelist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int lfds700_freelist_pop( struct lfds700_freelist_state *fs, struct lfds700_freelist_element **fe, struct lfds700_misc_prng_state *ps )
+{
+  char unsigned
+    result;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  struct lfds700_freelist_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
+    *new_top[PAC_SIZE],
+    *volatile original_top[PAC_SIZE];
+
+  LFDS700_PAL_ASSERT( fs != NULL );
+  LFDS700_PAL_ASSERT( fe != NULL );
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  LFDS700_PAL_BARRIER_PROCESSOR_LOAD;
+
+  original_top[COUNTER] = fs->top[COUNTER];
+  original_top[POINTER] = fs->top[POINTER];
+
+  do
+  {
+    if( original_top[POINTER] == NULL )
+    {
+      *fe = NULL;
+      return( 0 );
+    }
+
+    new_top[COUNTER] = original_top[COUNTER] + 1;
+    new_top[POINTER] = original_top[POINTER]->next;
+
+    LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( &fs->top, original_top, new_top, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+
+    if( result != 1 )
+      LFDS700_PAL_BARRIER_PROCESSOR_LOAD;
+  }
+  while( result != 1 );
+
+  *fe = original_top[POINTER];
+
+  return( 1 );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_push.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_push.c
new file mode 100644
index 0000000000000000000000000000000000000000..67fe38dadbe948feb8f14cc3059627929816cc87
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_push.c
@@ -0,0 +1,42 @@
+/***** includes *****/
+#include "lfds700_freelist_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_freelist_push( struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe, struct lfds700_misc_prng_state *ps )
+{
+  char unsigned
+    result;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  struct lfds700_freelist_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
+    *new_top[PAC_SIZE],
+    *volatile original_top[PAC_SIZE];
+
+  LFDS700_PAL_ASSERT( fs != NULL );
+  LFDS700_PAL_ASSERT( fe != NULL );
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  new_top[POINTER] = fe;
+
+  original_top[COUNTER] = fs->top[COUNTER];
+  original_top[POINTER] = fs->top[POINTER];
+
+  do
+  {
+    new_top[COUNTER] = original_top[COUNTER] + 1;
+    fe->next = original_top[POINTER];
+
+    LFDS700_PAL_BARRIER_PROCESSOR_STORE;
+    LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( &fs->top, original_top, new_top, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+  }
+  while( result != 1 );
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..43b8bc263dc8b26b7448b4a6da914b84c664e38a
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_freelist/lfds700_freelist_query.c
@@ -0,0 +1,123 @@
+/***** includes *****/
+#include "lfds700_freelist_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_freelist_internal_freelist_validate( struct lfds700_freelist_state *fs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_freelist_validity );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_freelist_query( struct lfds700_freelist_state *fs, enum lfds700_freelist_query query_type, void *query_input, void *query_output )
+{
+  struct lfds700_freelist_element
+    *fe;
+
+  LFDS700_PAL_ASSERT( fs != NULL );
+  // TRD : query_type can be any value in its range
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  switch( query_type )
+  {
+    case LFDS700_FREELIST_QUERY_SINGLETHREADED_GET_COUNT:
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      *(lfds700_pal_uint_t *) query_output = 0;
+
+      fe = (struct lfds700_freelist_element *) fs->top[POINTER];
+
+      while( fe != NULL )
+      {
+        ( *(lfds700_pal_uint_t *) query_output )++;
+        fe = (struct lfds700_freelist_element *) fe->next;
+      }
+    break;
+
+    case LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE:
+      // TRD : query_input can be NULL
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_freelist_internal_freelist_validate( fs, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_freelist_internal_freelist_validate( struct lfds700_freelist_state *fs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_freelist_validity )
+{
+  lfds700_pal_uint_t
+    number_elements = 0;
+
+  struct lfds700_freelist_element
+    *fe_slow,
+    *fe_fast;
+
+  LFDS700_PAL_ASSERT( fs != NULL );
+  // TRD : vi can be NULL
+  LFDS700_PAL_ASSERT( lfds700_freelist_validity != NULL );
+
+  *lfds700_freelist_validity = LFDS700_MISC_VALIDITY_VALID;
+
+  fe_slow = fe_fast = (struct lfds700_freelist_element *) fs->top[POINTER];
+
+  /* TRD : first, check for a loop
+           we have two pointers
+           both of which start at the top of the freelist
+           we enter a loop
+           and on each iteration
+           we advance one pointer by one element
+           and the other by two
+
+           we exit the loop when both pointers are NULL
+           (have reached the end of the freelist)
+
+           or
+
+           if we fast pointer 'sees' the slow pointer
+           which means we have a loop
+  */
+
+  if( fe_slow != NULL )
+    do
+    {
+      fe_slow = fe_slow->next;
+
+      if( fe_fast != NULL )
+        fe_fast = fe_fast->next;
+
+      if( fe_fast != NULL )
+        fe_fast = fe_fast->next;
+    }
+    while( fe_slow != NULL and fe_fast != fe_slow );
+
+  if( fe_fast != NULL and fe_slow != NULL and fe_fast == fe_slow )
+    *lfds700_freelist_validity = LFDS700_MISC_VALIDITY_INVALID_LOOP;
+
+  /* TRD : now check for expected number of elements
+           vi can be NULL, in which case we do not check
+           we know we don't have a loop from our earlier check
+  */
+
+  if( *lfds700_freelist_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
+  {
+    lfds700_freelist_query( fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_GET_COUNT, NULL, (void *) &number_elements );
+
+    if( number_elements < vi->min_elements )
+      *lfds700_freelist_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( number_elements > vi->max_elements )
+      *lfds700_freelist_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..af88b19179727689e4437f7d848a8b530c755b39
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.c
@@ -0,0 +1,61 @@
+/***** includes *****/
+#include "lfds700_hash_addonly_internal.h"
+
+/***** private prototypes*****/
+static void btree_au_element_cleanup_function( struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element *baue );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_hash_a_cleanup( struct lfds700_hash_a_state *has,
+                             void (*element_cleanup_callback)(struct lfds700_hash_a_state *has, struct lfds700_hash_a_element *hae) )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  LFDS700_PAL_ASSERT( has != NULL );
+  // TRD : element_cleanup_callback can be NULL
+
+  if( element_cleanup_callback == NULL )
+    return;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  has->element_cleanup_callback = element_cleanup_callback;
+
+  for( loop = 0 ; loop < has->array_size ; loop++ )
+    lfds700_btree_au_cleanup( has->baus_array+loop, btree_au_element_cleanup_function );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static void btree_au_element_cleanup_function( struct lfds700_btree_au_state *baus, struct lfds700_btree_au_element *baue )
+{
+  struct lfds700_hash_a_state
+    *has;
+
+  struct lfds700_hash_a_element
+    *hae;
+
+  LFDS700_PAL_ASSERT( baus != NULL );
+  LFDS700_PAL_ASSERT( baue != NULL );
+
+  hae = (struct lfds700_hash_a_element *) LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *baue );
+  has = (struct lfds700_hash_a_state *) LFDS700_BTREE_AU_GET_USER_STATE_FROM_STATE( *baus );
+
+  has->element_cleanup_callback( has, hae );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_get.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_get.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d010664abfc96f0dcdaace7129b09d555e26de6
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_get.c
@@ -0,0 +1,37 @@
+/***** includes *****/
+#include "lfds700_hash_addonly_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int lfds700_hash_a_get_by_key( struct lfds700_hash_a_state *has,
+                               void *key,
+                               struct lfds700_hash_a_element **hae )
+{
+  int
+    rv;
+
+  lfds700_pal_uint_t
+    hash = 0;
+
+  struct lfds700_btree_au_element
+    *baue;
+
+  LFDS700_PAL_ASSERT( has != NULL );
+  // TRD : key can be NULL
+  LFDS700_PAL_ASSERT( hae != NULL );
+
+  has->key_hash_function( key, &hash );
+
+  rv = lfds700_btree_au_get_by_key( has->baus_array + (hash % has->array_size), key, &baue );
+
+  if( rv == 1 )
+    *hae = LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *baue );
+  else
+    *hae = NULL;
+
+  return( rv );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..022024ce27a76f3f0124c156d6bd7ab71392172e
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_init.c
@@ -0,0 +1,54 @@
+/***** includes *****/
+#include "lfds700_hash_addonly_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_hash_a_init_valid_on_current_logical_core( struct lfds700_hash_a_state *has,
+                          struct lfds700_btree_au_state *baus_array,
+                          lfds700_pal_uint_t array_size,
+                          int (*key_compare_function)(void const *new_key, void const *existing_key),
+                          void (*key_hash_function)(void const *key, lfds700_pal_uint_t *hash),
+                          enum lfds700_hash_a_existing_key existing_key,
+                          void *user_state )
+{
+  enum lfds700_btree_au_existing_key
+    btree_au_existing_key = LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE; // TRD : for compiler warning
+
+  lfds700_pal_uint_t
+    loop;
+
+  LFDS700_PAL_ASSERT( has != NULL );
+  LFDS700_PAL_ASSERT( baus_array != NULL );
+  LFDS700_PAL_ASSERT( array_size > 0 );
+  LFDS700_PAL_ASSERT( key_compare_function != NULL );
+  LFDS700_PAL_ASSERT( key_hash_function != NULL );
+  // TRD : existing_key can be any value in its range
+  // TRD : user_state can be NULL
+
+  has->array_size = array_size;
+  has->key_compare_function = key_compare_function;
+  has->key_hash_function = key_hash_function;
+  has->existing_key = existing_key;
+  has->baus_array = baus_array;
+  has->user_state = user_state;
+
+  if( has->existing_key == LFDS700_HASH_A_EXISTING_KEY_OVERWRITE )
+    btree_au_existing_key = LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE;
+
+  if( has->existing_key == LFDS700_HASH_A_EXISTING_KEY_FAIL )
+    btree_au_existing_key = LFDS700_BTREE_AU_EXISTING_KEY_FAIL;
+
+  // TRD : since the addonly_hash atomic counts, if that flag is set, the btree_addonly_unbalanceds don't have to
+  for( loop = 0 ; loop < array_size ; loop++ )
+    lfds700_btree_au_init_valid_on_current_logical_core( has->baus_array+loop, key_compare_function, btree_au_existing_key, user_state );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_insert.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_insert.c
new file mode 100644
index 0000000000000000000000000000000000000000..25df3e7f9396dcd1101e14fb36c081a5e9956172
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_insert.c
@@ -0,0 +1,62 @@
+/***** includes *****/
+#include "lfds700_hash_addonly_internal.h"
+
+
+
+
+
+/****************************************************************************/
+enum lfds700_hash_a_insert_result lfds700_hash_a_insert( struct lfds700_hash_a_state *has,
+                                                         struct lfds700_hash_a_element *hae,
+                                                         struct lfds700_hash_a_element **existing_hae,
+                                                         struct lfds700_misc_prng_state *ps )
+{
+  enum lfds700_hash_a_insert_result
+    apr = LFDS700_HASH_A_PUT_RESULT_SUCCESS;
+
+  enum lfds700_btree_au_insert_result
+    alr;
+
+  lfds700_pal_uint_t
+    hash = 0;
+
+  struct lfds700_btree_au_element
+    *existing_baue;
+
+  LFDS700_PAL_ASSERT( has != NULL );
+  LFDS700_PAL_ASSERT( hae != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &hae->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  // TRD : existing_hae can be NULL
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  // TRD : alignment checks
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &hae->baue % LFDS700_PAL_ALIGN_SINGLE_POINTER == 0 );
+
+  has->key_hash_function( hae->key, &hash );
+
+  LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( hae->baue, hae->key );
+  LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( hae->baue, hae );
+
+  alr = lfds700_btree_au_insert( has->baus_array + (hash % has->array_size), &hae->baue, &existing_baue, ps );
+
+  switch( alr )
+  {
+    case LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY:
+      if( existing_hae != NULL )
+        *existing_hae = LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *existing_baue );
+
+      apr = LFDS700_HASH_A_PUT_RESULT_FAILURE_EXISTING_KEY;
+    break;
+
+    case LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE:
+      apr = LFDS700_HASH_A_PUT_RESULT_SUCCESS_OVERWRITE;
+    break;
+
+    case LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS:
+      apr = LFDS700_HASH_A_PUT_RESULT_SUCCESS;
+    break;
+  }
+
+  return( apr );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a7d54180421c96cce9b0a1b6529d4cee90b5564
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_internal.h
@@ -0,0 +1,5 @@
+/***** the library wide include file *****/
+#include "../liblfds700_internal.h"
+
+/***** private prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_iterate.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_iterate.c
new file mode 100644
index 0000000000000000000000000000000000000000..3e06be3f901d2ed4cef8b0741eb52ff0e8237a77
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_iterate.c
@@ -0,0 +1,58 @@
+/***** includes *****/
+#include "lfds700_hash_addonly_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_hash_a_iterate_init( struct lfds700_hash_a_state *has, struct lfds700_hash_a_iterate *hai )
+{
+  LFDS700_PAL_ASSERT( has != NULL );
+  LFDS700_PAL_ASSERT( hai != NULL );
+
+  hai->baus = has->baus_array;
+  hai->baus_end = has->baus_array + has->array_size;
+  hai->baue = NULL;
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+int lfds700_hash_a_iterate( struct lfds700_hash_a_iterate *hai, struct lfds700_hash_a_element **hae )
+{
+  enum lfds700_misc_flag
+    finished_flag = LFDS700_MISC_FLAG_LOWERED;
+
+  int
+    rv = 0;
+
+  LFDS700_PAL_ASSERT( hai != NULL );
+  LFDS700_PAL_ASSERT( hae != NULL );
+
+  while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
+  {
+    lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position( hai->baus, &hai->baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE );
+
+    if( hai->baue != NULL )
+    {
+      *hae = LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *hai->baue );
+      finished_flag = LFDS700_MISC_FLAG_RAISED;
+      rv = 1;
+    }
+
+    if( hai->baue == NULL )
+      if( ++hai->baus == hai->baus_end )
+      {
+        *hae = NULL;
+        finished_flag = LFDS700_MISC_FLAG_RAISED;
+      }
+  }
+
+  return( rv );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..9d89a8838de9bdc576805a1ad39e7736d5f73164
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_hash_addonly/lfds700_hash_addonly_query.c
@@ -0,0 +1,112 @@
+/***** includes *****/
+#include "lfds700_hash_addonly_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_hash_a_internal_validate( struct lfds700_hash_a_state *has, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_hash_a_validity );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_hash_a_query( struct lfds700_hash_a_state *has, enum lfds700_hash_a_query query_type, void *query_input, void *query_output )
+{
+  LFDS700_PAL_ASSERT( has != NULL );
+  // TRD : query_type can be any value in its range
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  switch( query_type )
+  {
+    case LFDS700_HASH_A_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
+    {
+      struct lfds700_hash_a_iterate
+        ai;
+
+      struct lfds700_hash_a_element
+        *hae;
+
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      *(lfds700_pal_uint_t *) query_output = 0;
+
+      lfds700_hash_a_iterate_init( has, &ai );
+
+      while( lfds700_hash_a_iterate(&ai, &hae) )
+        ( *(lfds700_pal_uint_t *) query_output )++;
+    }
+    break;
+
+    case LFDS700_HASH_A_QUERY_SINGLETHREADED_VALIDATE:
+      // TRD: query_input can be any value in its range
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_hash_a_internal_validate( has, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_hash_a_internal_validate( struct lfds700_hash_a_state *has, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_hash_a_validity )
+{
+  lfds700_pal_uint_t
+    lfds700_hash_a_total_number_elements = 0,
+    lfds700_btree_au_total_number_elements = 0,
+    number_elements;
+
+  lfds700_pal_uint_t
+    loop;
+
+  LFDS700_PAL_ASSERT( has!= NULL );
+  // TRD : vi can be NULL
+  LFDS700_PAL_ASSERT( lfds700_hash_a_validity != NULL );
+
+  /* TRD : validate every btree_addonly_unbalanced in the addonly_hash
+           sum elements in each btree_addonly_unbalanced
+           check matches expected element counts (if vi is provided)
+  */
+
+  *lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_VALID;
+
+  for( loop = 0 ; *lfds700_hash_a_validity == LFDS700_MISC_VALIDITY_VALID and loop < has->array_size ; loop++ )
+    lfds700_btree_au_query( has->baus_array+loop, LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE, NULL, (void *) lfds700_hash_a_validity );
+
+  if( *lfds700_hash_a_validity == LFDS700_MISC_VALIDITY_VALID )
+  {
+    for( loop = 0 ; loop < has->array_size ; loop++ )
+    {
+      lfds700_btree_au_query( has->baus_array+loop, LFDS700_BTREE_AU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void *) &number_elements );
+      lfds700_btree_au_total_number_elements += number_elements;
+    }
+
+    // TRD : first, check btree_addonly_unbalanced total vs the addonly_hash total
+    lfds700_hash_a_query( has, LFDS700_HASH_A_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &lfds700_hash_a_total_number_elements );
+
+    // TRD : the btree_addonly_unbalanceds are assumed to speak the truth
+    if( lfds700_hash_a_total_number_elements < lfds700_btree_au_total_number_elements )
+      *lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( lfds700_hash_a_total_number_elements > lfds700_btree_au_total_number_elements )
+      *lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    // TRD : second, if we're still valid and vi is provided, check the btree_addonly_unbalanced total against vi
+    if( *lfds700_hash_a_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
+    {
+      if( lfds700_btree_au_total_number_elements < vi->min_elements )
+        *lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+      if( lfds700_btree_au_total_number_elements > vi->max_elements )
+        *lfds700_hash_a_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+    }
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..580fa9b3ac41c92491b6bb08b3d2a3eb7722dce7
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_cleanup.c
@@ -0,0 +1,37 @@
+/***** includes *****/
+#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_list_aos_cleanup( struct lfds700_list_aos_state *laoss,
+                               void (*element_cleanup_callback)(struct lfds700_list_aos_state *laoss, struct lfds700_list_aos_element *laose) )
+{
+  struct lfds700_list_aos_element
+    *laose,
+    *temp;
+
+  LFDS700_PAL_ASSERT( laoss != NULL );
+  // TRD : element_cleanup_callback can be NULL
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  if( element_cleanup_callback == NULL )
+    return;
+
+  laose = LFDS700_LIST_AOS_GET_START( *laoss );
+
+  while( laose != NULL )
+  {
+    temp = laose;
+
+    laose = LFDS700_LIST_AOS_GET_NEXT( *laose );
+
+    element_cleanup_callback( laoss, temp );
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_get.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_get.c
new file mode 100644
index 0000000000000000000000000000000000000000..9d4cab5e53a6cce69c06ccc77747df8e9cd76589
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_get.c
@@ -0,0 +1,29 @@
+/***** includes *****/
+#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int lfds700_list_aos_get_by_key( struct lfds700_list_aos_state *laoss,
+                                  void *key,
+                                  struct lfds700_list_aos_element **laose )
+{
+  int
+    cr = !0,
+    rv = 1;
+
+  LFDS700_PAL_ASSERT( laoss != NULL );
+  LFDS700_PAL_ASSERT( key != NULL );
+  LFDS700_PAL_ASSERT( laose != NULL );
+
+  while( cr != 0 and LFDS700_LIST_AOS_GET_START_AND_THEN_NEXT(*laoss, *laose) )
+    cr = laoss->key_compare_function( key, (*laose)->key );
+
+  if( *laose == NULL )
+    rv = 0;
+
+  return( rv );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c92835ce56581ad1298b61fed19046a3f8c0a76
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_init.c
@@ -0,0 +1,37 @@
+/***** includes *****/
+#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_list_aos_init_valid_on_current_logical_core( struct lfds700_list_aos_state *laoss,
+                            int (*key_compare_function)(void const *new_key, void const *existing_key),
+                            enum lfds700_list_aos_existing_key existing_key,
+                            void *user_state )
+{
+  LFDS700_PAL_ASSERT( laoss != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laoss->start % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laoss->dummy_element % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laoss->key_compare_function % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( key_compare_function != NULL );
+  // TRD : existing_key can be any value in its range
+  // TRD : user_state can be NULL
+
+  // TRD : dummy start element - makes code easier when you can always use ->next
+  laoss->start = &laoss->dummy_element;
+
+  laoss->start->next = NULL;
+  laoss->start->value = NULL;
+  laoss->key_compare_function = key_compare_function;
+  laoss->existing_key = existing_key;
+  laoss->user_state = user_state;
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_insert.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_insert.c
new file mode 100644
index 0000000000000000000000000000000000000000..9beead4e1d1b023b66c3e6036a0017422e8e4e03
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_insert.c
@@ -0,0 +1,134 @@
+/***** includes *****/
+#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
+
+
+
+
+
+/****************************************************************************/
+enum lfds700_list_aos_insert_result lfds700_list_aos_insert( struct lfds700_list_aos_state *laoss,
+                                                         struct lfds700_list_aos_element *laose,
+                                                         struct lfds700_list_aos_element **existing_laose,
+                                                         struct lfds700_misc_prng_state *ps )
+{
+  char unsigned 
+    result;
+
+  enum lfds700_misc_flag
+    finished_flag = LFDS700_MISC_FLAG_LOWERED;
+
+  int
+    compare_result = 0;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  struct lfds700_list_aos_element
+    *volatile laose_temp = NULL,
+    *volatile laose_trailing;
+
+  LFDS700_PAL_ASSERT( laoss != NULL );
+  LFDS700_PAL_ASSERT( laose != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laose->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laose->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &laose->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  // TRD : existing_laose can be NULL
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  /* TRD : imagine a list, sorted small to large
+
+           we arrive at an element
+           we obtain its next pointer
+           we check we are greater than the current element and smaller than the next element
+           this means we have found the correct location to insert
+           we try to CAS ourselves in; in the meantime,
+           someone else has *aready* swapped in an element which is smaller than we are
+
+           e.g.
+
+           the list is { 1, 10 } and we are the value 5
+
+           we arrive at 1; we check the next element and see it is 10
+           so we are larger than the current element and smaller than the next
+           we are in the correct location to insert and we go to insert...
+
+           in the meantime, someone else with the value 3 comes along
+           he too finds this is the correct location and inserts before we do
+           the list is now { 1, 3, 10 } and we are trying to insert now after
+           1 and before 3!
+
+           our insert CAS fails, because the next pointer of 1 has changed aready;
+           but we see we are in the wrong location - we need to move forward an
+           element
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  /* TRD : we need to begin with the leading dummy element
+           as the element to be inserted
+           may be smaller than all elements in the list
+  */
+
+  laose_trailing = laoss->start;
+  laose_temp = laoss->start->next;
+
+  while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
+  {
+    if( laose_temp == NULL )
+      compare_result = -1;
+
+    if( laose_temp != NULL )
+    {
+      LFDS700_MISC_BARRIER_LOAD;
+      compare_result = laoss->key_compare_function( laose->key, laose_temp->key );
+    }
+
+    if( compare_result == 0 )
+    {
+      if( existing_laose != NULL )
+        *existing_laose = laose_temp;
+
+      switch( laoss->existing_key )
+      {
+        case LFDS700_LIST_AOS_EXISTING_KEY_OVERWRITE:
+          LFDS700_LIST_AOS_SET_VALUE_IN_ELEMENT( *laose_temp, laose->value );
+          return( LFDS700_LIST_AOS_INSERT_RESULT_SUCCESS_OVERWRITE );
+        break;
+
+        case LFDS700_LIST_AOS_EXISTING_KEY_FAIL:
+          return( LFDS700_LIST_AOS_INSERT_RESULT_FAILURE_EXISTING_KEY );
+        break;
+      }
+
+      finished_flag = LFDS700_MISC_FLAG_RAISED;
+    }
+
+    if( compare_result < 0 )
+    {
+      laose->next = laose_temp;
+      LFDS700_MISC_BARRIER_STORE;
+      LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &laose_trailing->next, &laose->next, laose, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+
+      if( result == 1 )
+        finished_flag = LFDS700_MISC_FLAG_RAISED;
+      else
+        // TRD : if we fail to link, someone else has linked and so we need to redetermine our position is correct
+        laose_temp = laose_trailing->next;
+    }
+
+    if( compare_result > 0 )
+    {
+      // TRD : move trailing along by one element
+      laose_trailing = laose_trailing->next;
+
+      /* TRD : set temp as the element after trailing
+               if the new element we're linking is larger than all elements in the list,
+               laose_temp will now go to NULL and we'll link at the end
+      */
+      laose_temp = laose_trailing->next;
+    }
+  }
+
+  return( LFDS700_LIST_AOS_INSERT_RESULT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a7d54180421c96cce9b0a1b6529d4cee90b5564
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_internal.h
@@ -0,0 +1,5 @@
+/***** the library wide include file *****/
+#include "../liblfds700_internal.h"
+
+/***** private prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..a1d990ab79b3b2ff2c390d401f81205ee30908c5
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_query.c
@@ -0,0 +1,121 @@
+/***** includes *****/
+#include "lfds700_list_addonly_ordered_singlylinked_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_list_aos_internal_validate( struct lfds700_list_aos_state *laoss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_list_aos_validity );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_list_aos_query( struct lfds700_list_aos_state *laoss, enum lfds700_list_aos_query query_type, void *query_input, void *query_output )
+{
+  LFDS700_PAL_ASSERT( laoss != NULL );
+  // TRD : query_type can be any value in its range
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  switch( query_type )
+  {
+    case LFDS700_LIST_AOS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
+    {
+      struct lfds700_list_aos_element
+        *laose = NULL;
+
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      *(lfds700_pal_uint_t *) query_output = 0;
+
+      while( LFDS700_LIST_AOS_GET_START_AND_THEN_NEXT(*laoss, laose) )
+        ( *(lfds700_pal_uint_t *) query_output )++;
+    }
+    break;
+
+    case LFDS700_LIST_AOS_QUERY_SINGLETHREADED_VALIDATE:
+      // TRD : query_input can be NULL
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_list_aos_internal_validate( laoss, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_list_aos_internal_validate( struct lfds700_list_aos_state *laoss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_list_aos_validity )
+{
+  lfds700_pal_uint_t
+    number_elements = 0;
+
+  struct lfds700_list_aos_element
+    *laose_fast,
+    *laose_slow;
+
+  LFDS700_PAL_ASSERT( laoss!= NULL );
+  // TRD : vi can be NULL
+  LFDS700_PAL_ASSERT( lfds700_list_aos_validity != NULL );
+
+  *lfds700_list_aos_validity = LFDS700_MISC_VALIDITY_VALID;
+
+  laose_slow = laose_fast = laoss->start->next;
+
+  /* TRD : first, check for a loop
+           we have two pointers
+           both of which start at the start of the list
+           we enter a loop
+           and on each iteration
+           we advance one pointer by one element
+           and the other by two
+
+           we exit the loop when both pointers are NULL
+           (have reached the end of the queue)
+
+           or
+
+           if we fast pointer 'sees' the slow pointer
+           which means we have a loop
+  */
+
+  if( laose_slow != NULL )
+    do
+    {
+      laose_slow = laose_slow->next;
+
+      if( laose_fast != NULL )
+        laose_fast = laose_fast->next;
+
+      if( laose_fast != NULL )
+        laose_fast = laose_fast->next;
+    }
+    while( laose_slow != NULL and laose_fast != laose_slow );
+
+  if( laose_fast != NULL and laose_slow != NULL and laose_fast == laose_slow )
+    *lfds700_list_aos_validity = LFDS700_MISC_VALIDITY_INVALID_LOOP;
+
+  /* TRD : now check for expected number of elements
+           vi can be NULL, in which case we do not check
+           we know we don't have a loop from our earlier check
+  */
+
+  if( *lfds700_list_aos_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
+  {
+    lfds700_list_aos_query( laoss, LFDS700_LIST_AOS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &number_elements );
+
+    if( number_elements < vi->min_elements )
+      *lfds700_list_aos_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( number_elements > vi->max_elements )
+      *lfds700_list_aos_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..ef19ce1f86994d6c4a56c8a525e31c8e7c5f8b2b
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_cleanup.c
@@ -0,0 +1,37 @@
+/***** includes *****/
+#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_list_asu_cleanup( struct lfds700_list_asu_state *lasus,
+                               void (*element_cleanup_callback)(struct lfds700_list_asu_state *lasus, struct lfds700_list_asu_element *lasue) )
+{
+  struct lfds700_list_asu_element
+    *lasue,
+    *temp;
+
+  LFDS700_PAL_ASSERT( lasus != NULL );
+  // TRD : element_cleanup_callback can be NULL
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  if( element_cleanup_callback == NULL )
+    return;
+
+  lasue = LFDS700_LIST_ASU_GET_START( *lasus );
+
+  while( lasue != NULL )
+  {
+    temp = lasue;
+
+    lasue = LFDS700_LIST_ASU_GET_NEXT( *lasue );
+
+    element_cleanup_callback( lasus, temp );
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_get.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_get.c
new file mode 100644
index 0000000000000000000000000000000000000000..ae99ebfca47d67a994bb84583d7bd62078013d1d
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_get.c
@@ -0,0 +1,29 @@
+/***** includes *****/
+#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int lfds700_list_asu_get_by_key( struct lfds700_list_asu_state *lasus,
+                                 void *key,
+                                 struct lfds700_list_asu_element **lasue )
+{
+  int
+    cr = !0,
+    rv = 1;
+
+  LFDS700_PAL_ASSERT( lasus != NULL );
+  LFDS700_PAL_ASSERT( key != NULL );
+  LFDS700_PAL_ASSERT( lasue != NULL );
+
+  while( cr != 0 and LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*lasus, *lasue) )
+    cr = lasus->key_compare_function( key, (*lasue)->key );
+
+  if( *lasue == NULL )
+    rv = 0;
+
+  return( rv );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..78b0d8eae66305e87fa4788117d9478f78f4f4b6
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_init.c
@@ -0,0 +1,35 @@
+/***** includes *****/
+#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_list_asu_init_valid_on_current_logical_core( struct lfds700_list_asu_state *lasus,
+                            int (*key_compare_function)(void const *new_key, void const *existing_key),
+                            void *user_state )
+{
+  LFDS700_PAL_ASSERT( lasus != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasus->end % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasus->start % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasus->dummy_element % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasus->key_compare_function % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  // TRD : key_compare_function can be NULL
+  // TRD : user_state can be NULL
+
+  // TRD : dummy start element - makes code easier when you can always use ->next
+  lasus->start = lasus->end = &lasus->dummy_element;
+
+  lasus->start->next = NULL;
+  lasus->start->value = NULL;
+  lasus->key_compare_function = key_compare_function;
+  lasus->user_state = user_state;
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce2ee825aac80a2358d34ac7f29aeb721c75cb1e
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.c
@@ -0,0 +1,193 @@
+/***** includes *****/
+#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_list_asu_insert_at_position( struct lfds700_list_asu_state *lasus,
+                                          struct lfds700_list_asu_element *lasue,
+                                          struct lfds700_list_asu_element *lasue_predecessor,
+                                          enum lfds700_list_asu_position position,
+                                          struct lfds700_misc_prng_state *ps )
+{
+  LFDS700_PAL_ASSERT( lasus != NULL );
+  LFDS700_PAL_ASSERT( lasue != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  // TRD : lasue_predecessor asserted in the switch
+  // TRD : position can be any value in its range
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  switch( position )
+  {
+    case LFDS700_LIST_ASU_POSITION_START:
+      lfds700_list_asu_insert_at_start( lasus, lasue, ps );
+    break;
+
+    case LFDS700_LIST_ASU_POSITION_END:
+      lfds700_list_asu_insert_at_end( lasus, lasue, ps );
+    break;
+
+    case LFDS700_LIST_ASU_POSITION_AFTER:
+      lfds700_list_asu_insert_after_element( lasus, lasue, lasue_predecessor, ps );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void lfds700_list_asu_insert_at_start( struct lfds700_list_asu_state *lasus,
+                                       struct lfds700_list_asu_element *lasue,
+                                       struct lfds700_misc_prng_state *ps )
+{
+  char unsigned 
+    result;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  LFDS700_PAL_ASSERT( lasus != NULL );
+  LFDS700_PAL_ASSERT( lasue != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  lasue->next = lasus->start->next;
+
+  do
+  {
+    LFDS700_MISC_BARRIER_STORE;
+    LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &lasus->start->next, &lasue->next, lasue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+  }
+  while( result != 1 );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void lfds700_list_asu_insert_at_end( struct lfds700_list_asu_state *lasus,
+                                     struct lfds700_list_asu_element *lasue,
+                                     struct lfds700_misc_prng_state *ps )
+{
+  char unsigned 
+    result;
+
+  enum lfds700_misc_flag
+    finished_flag = LFDS700_MISC_FLAG_LOWERED;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  struct lfds700_list_asu_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_SINGLE_POINTER)
+    *compare;
+
+  struct lfds700_list_asu_element
+    *volatile lasue_next,
+    *volatile lasue_end;
+
+  LFDS700_PAL_ASSERT( lasus != NULL );
+  LFDS700_PAL_ASSERT( lasue != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  /* TRD : begin by assuming end is correctly pointing to the final element
+           try to link (comparing for next being NULL)
+           if we fail, move down list till we find last element
+           and retry
+           when successful, update end to ourselves
+
+           note there's a leading dummy element
+           so lasus->end always points to an element
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  lasue->next = NULL;
+  lasue_end = lasus->end;
+
+  while( finished_flag == LFDS700_MISC_FLAG_LOWERED )
+  {
+    compare = NULL;
+
+    LFDS700_MISC_BARRIER_STORE;
+    LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &lasue_end->next, &compare, lasue, LFDS700_MISC_CAS_STRENGTH_STRONG, result, backoff_iteration, ps );
+
+    if( result == 1 )
+      finished_flag = LFDS700_MISC_FLAG_RAISED;
+    else
+    {
+      lasue_end = compare;
+      lasue_next = LFDS700_LIST_ASU_GET_NEXT( *lasue_end );
+
+      while( lasue_next != NULL )
+      {
+        lasue_end = lasue_next;
+        lasue_next = LFDS700_LIST_ASU_GET_NEXT( *lasue_end );
+      }
+    }
+  }
+
+  lasus->end = lasue;
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+void lfds700_list_asu_insert_after_element( struct lfds700_list_asu_state *lasus,
+                                            struct lfds700_list_asu_element *lasue,
+                                            struct lfds700_list_asu_element *lasue_predecessor,
+                                            struct lfds700_misc_prng_state *ps )
+{
+  char unsigned 
+    result;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  LFDS700_PAL_ASSERT( lasus != NULL );
+  LFDS700_PAL_ASSERT( lasue != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->value % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &lasue->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( lasue_predecessor != NULL );
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  lasue->next = lasue_predecessor->next;
+
+  do
+  {
+    LFDS700_MISC_BARRIER_STORE;
+    LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( &lasue_predecessor->next, &lasue->next, lasue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+  }
+  while( result != 1 );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a7d54180421c96cce9b0a1b6529d4cee90b5564
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_internal.h
@@ -0,0 +1,5 @@
+/***** the library wide include file *****/
+#include "../liblfds700_internal.h"
+
+/***** private prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..0adf5a8032697d468e297977fd8d3dd9cf6ab6f4
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_query.c
@@ -0,0 +1,121 @@
+/***** includes *****/
+#include "lfds700_list_addonly_singlylinked_unordered_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_list_asu_internal_validate( struct lfds700_list_asu_state *lasus, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_list_asu_validity );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_list_asu_query( struct lfds700_list_asu_state *lasus, enum lfds700_list_asu_query query_type, void *query_input, void *query_output )
+{
+  LFDS700_PAL_ASSERT( lasus != NULL );
+  // TRD : query_type can be any value in its range
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  switch( query_type )
+  {
+    case LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
+    {
+      struct lfds700_list_asu_element
+        *lasue = NULL;
+
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      *(lfds700_pal_uint_t *) query_output = 0;
+
+      while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*lasus, lasue) )
+        ( *(lfds700_pal_uint_t *) query_output )++;
+    }
+    break;
+
+    case LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE:
+      // TRD : query_input can be NULL
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_list_asu_internal_validate( lasus, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_list_asu_internal_validate( struct lfds700_list_asu_state *lasus, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_list_asu_validity )
+{
+  lfds700_pal_uint_t
+    number_elements = 0;
+
+  struct lfds700_list_asu_element
+    *lasue_fast,
+    *lasue_slow;
+
+  LFDS700_PAL_ASSERT( lasus!= NULL );
+  // TRD : vi can be NULL
+  LFDS700_PAL_ASSERT( lfds700_list_asu_validity != NULL );
+
+  *lfds700_list_asu_validity = LFDS700_MISC_VALIDITY_VALID;
+
+  lasue_slow = lasue_fast = lasus->start->next;
+
+  /* TRD : first, check for a loop
+           we have two pointers
+           both of which start at the start of the list
+           we enter a loop
+           and on each iteration
+           we advance one pointer by one element
+           and the other by two
+
+           we exit the loop when both pointers are NULL
+           (have reached the end of the queue)
+
+           or
+
+           if we fast pointer 'sees' the slow pointer
+           which means we have a loop
+  */
+
+  if( lasue_slow != NULL )
+    do
+    {
+      lasue_slow = lasue_slow->next;
+
+      if( lasue_fast != NULL )
+        lasue_fast = lasue_fast->next;
+
+      if( lasue_fast != NULL )
+        lasue_fast = lasue_fast->next;
+    }
+    while( lasue_slow != NULL and lasue_fast != lasue_slow );
+
+  if( lasue_fast != NULL and lasue_slow != NULL and lasue_fast == lasue_slow )
+    *lfds700_list_asu_validity = LFDS700_MISC_VALIDITY_INVALID_LOOP;
+
+  /* TRD : now check for expected number of elements
+           vi can be NULL, in which case we do not check
+           we know we don't have a loop from our earlier check
+  */
+
+  if( *lfds700_list_asu_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
+  {
+    lfds700_list_asu_query( lasus, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, &number_elements );
+
+    if( number_elements < vi->min_elements )
+      *lfds700_list_asu_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( number_elements > vi->max_elements )
+      *lfds700_list_asu_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..d93c95db0f1054f1705003b71d2f7ebb59df4661
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_cleanup.c
@@ -0,0 +1,15 @@
+/***** includes *****/
+#include "lfds700_misc_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_misc_library_cleanup( void )
+{
+  // TRD : we do nuuuuuuthin'
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_globals.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_globals.c
new file mode 100644
index 0000000000000000000000000000000000000000..af2826675a11230d8a4dff20fb8503b52fcb1228
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_globals.c
@@ -0,0 +1,11 @@
+/***** includes *****/
+#include "lfds700_misc_internal.h"
+
+
+
+
+
+/****************************************************************************/
+struct lfds700_misc_globals
+  lfds700_misc_globals;
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..32685077bf112d74e4360d8753ce52684d503b2d
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_init.c
@@ -0,0 +1,53 @@
+/***** includes *****/
+#include "lfds700_misc_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_misc_library_init_valid_on_current_logical_core()
+{
+  /* TRD : the PRNG arrangement is that each thread has its own state, for a maximum-speed PRNG, where output
+           quality is second consideration to performance
+
+           on 64-bit platforms this is xorshift64*, on 32-bit platforms, an unadorned xorshift32
+
+           the seed for each thread however comes from a single, global, maximum-quality PRNG, where quality of
+           output is the primary consideration
+
+           for this, I'm using a xorshift1024*
+
+           since the generation from this global PRNG state is not thread safe, but is still quick in
+           thread start-up terms, I run a little spin-lock around it
+
+           regarding the seed for this high quality PRNG; it is customary to use time(), but this has a number of
+           drawbacks;
+
+           1. liblfds would depend on time() (currently it does not depend on a hosted implementation of standard library)
+           2. the output from time may only be 32 bit, and even when it isn't, the top 32 bits are currently all zero...
+           3. many threads can begin in the same second; I'd need to add in their thread number,
+              which means I'd need to *get* their thread number...
+
+           as such, I've decided to use a *fixed* 64-bit seed for the high-quality PRNG; this seed is run
+           through the MurmerHash3 avalanche phase to generate successive 64-bit values, which populate
+           the 1024 state of xorshift1024*
+
+           if you have access to a high-frequency clock (often 64-bit), you can use this for the seed
+           (don't use it for the per-thread PRNG, unless you know the clock can be read without a context switch)
+
+           murmurhash3 code from here; http://xorshift.di.unimi.it/murmurhash3.c
+  */
+
+  lfds700_misc_prng_internal_big_slow_high_quality_init( LFDS700_MISC_PRNG_SEED );
+
+  lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_cas = EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_INCS_FOR_CAS;
+  lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas = EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_INCS_FOR_DWCAS;
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ed927efc9f4061ce96c701b571f43748ec9b121
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_internal.h
@@ -0,0 +1,10 @@
+/***** the library wide include file *****/
+#include "../liblfds700_internal.h"
+
+/***** defines *****/
+#define EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_INCS_FOR_CAS    8
+#define EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_INCS_FOR_DWCAS  16
+
+/***** private prototypes *****/
+void lfds700_misc_prng_internal_big_slow_high_quality_init( int long long unsigned seed );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_prng.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_prng.c
new file mode 100644
index 0000000000000000000000000000000000000000..84ae25fe71c1a530f14461a75446fee6db44aad4
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_prng.c
@@ -0,0 +1,144 @@
+/***** includes *****/
+#include "lfds700_misc_internal.h"
+
+/***** defines *****/
+#define LFDS700_PRNG_STATE_SIZE  16
+
+/***** struct *****/
+struct lfds700_misc_prng_big_slow_high_quality_state
+{
+  lfds700_pal_atom_t LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    xorshift1024star_spinlock;
+
+  // TRD : must be a 32 bit signed int
+  int
+    xorshift1024star_index;
+
+  int long long unsigned
+    xorshift1024star_state[LFDS700_PRNG_STATE_SIZE];
+};
+
+/***** locals *****/
+struct lfds700_misc_prng_big_slow_high_quality_state
+  pbshqs;
+
+/***** private prototypes *****/
+static void lfds700_misc_prng_internal_hash_murmurhash3( int long long unsigned *murmurhash3_state );
+static void lfds700_misc_prng_internal_big_slow_high_quality_generate( struct lfds700_misc_prng_big_slow_high_quality_state *ps, lfds700_pal_uint_t *random_value );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_misc_prng_init( struct lfds700_misc_prng_state *ps )
+{
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  /* TRD : we use the big, slow, high quality PRNG to generate the initial value
+           for the small, fast, low qulity PRNG, which is used in exponential backoff
+
+           we need the load barrier to catch any changes to the backoff periods
+  */
+
+  lfds700_misc_prng_internal_big_slow_high_quality_generate( &pbshqs, &ps->prng_state );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  ps->local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_cas = lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_cas;
+  ps->local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas = lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void lfds700_misc_prng_internal_big_slow_high_quality_init( int long long unsigned seed )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  LFDS700_PAL_ASSERT( seed != 0 );   // TRD : a 0 seed causes all zeros in the entropy state, so is forbidden
+
+  pbshqs.xorshift1024star_spinlock = LFDS700_MISC_FLAG_LOWERED;
+
+  for( loop = 0 ; loop < LFDS700_PRNG_STATE_SIZE ; loop++ )
+  {
+    lfds700_misc_prng_internal_hash_murmurhash3( &seed );
+    pbshqs.xorshift1024star_state[loop] = seed;
+  }
+
+  pbshqs.xorshift1024star_index = 0;
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_misc_prng_internal_hash_murmurhash3( int long long unsigned *murmurhash3_state )
+{
+  LFDS700_PAL_ASSERT( murmurhash3_state != NULL );
+
+	*murmurhash3_state ^= *murmurhash3_state >> 33;
+	*murmurhash3_state *= 0xff51afd7ed558ccdULL;
+	*murmurhash3_state ^= *murmurhash3_state >> 33;
+	*murmurhash3_state *= 0xc4ceb9fe1a85ec53ULL;
+	*murmurhash3_state ^= *murmurhash3_state >> 33;
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_misc_prng_internal_big_slow_high_quality_generate( struct lfds700_misc_prng_big_slow_high_quality_state *ps, lfds700_pal_uint_t *random_value )
+{
+  char unsigned 
+    result;
+
+  int long long unsigned
+    xs_temp_one,
+    xs_temp_two;
+
+  lfds700_pal_atom_t
+    compare = LFDS700_MISC_FLAG_LOWERED,
+    exchange = LFDS700_MISC_FLAG_LOWERED;
+
+  LFDS700_PAL_ASSERT( ps != NULL );
+  LFDS700_PAL_ASSERT( random_value != NULL );
+
+  // TRD : this is single-threaded code, on a per-state basis
+  do
+  {
+    compare = LFDS700_MISC_FLAG_LOWERED;
+    LFDS700_PAL_ATOMIC_CAS( &ps->xorshift1024star_spinlock, &compare, (lfds700_pal_atom_t) LFDS700_MISC_FLAG_RAISED, LFDS700_MISC_CAS_STRENGTH_STRONG, result );
+  }
+  while( result == 0 );
+
+  // TRD : xorshift1024* code from here; http://xorshift.di.unimi.it/xorshift1024star.c
+
+  xs_temp_one = ps->xorshift1024star_state[ ps->xorshift1024star_index ];
+  ps->xorshift1024star_index = ( ps->xorshift1024star_index + 1 ) & 15;
+  xs_temp_two = ps->xorshift1024star_state[ ps->xorshift1024star_index ];
+
+  xs_temp_two ^= xs_temp_two << 31;
+  xs_temp_two ^= xs_temp_two >> 11;
+  xs_temp_one ^= xs_temp_one >> 30;
+
+  ps->xorshift1024star_state[ ps->xorshift1024star_index ] = xs_temp_one ^ xs_temp_two;
+
+  *random_value = (lfds700_pal_uint_t) ( ps->xorshift1024star_state[ ps->xorshift1024star_index ] * 1181783497276652981LL );
+
+  LFDS700_PAL_ATOMIC_EXCHANGE( &ps->xorshift1024star_spinlock, &exchange );
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..fd3595d86a66c25cc0910ccb51e89cada291c3fd
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_misc/lfds700_misc_query.c
@@ -0,0 +1,48 @@
+/***** includes *****/
+#include "lfds700_misc_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_misc_query( enum lfds700_misc_query query_type, void *query_input, void *query_output )
+{
+  // TRD : query type can be any value in its range
+  // TRD : query_input can be NULL in some cases
+  // TRD : query_outputput can be NULL in some cases
+
+  switch( query_type )
+  {
+    case LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS:
+      *(lfds700_pal_atom_t *) query_output = lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_cas;
+    break;
+
+    case LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS:
+      LFDS700_PAL_ATOMIC_EXCHANGE( &lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_cas, (lfds700_pal_atom_t *) query_input );
+    break;
+
+    case LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS:
+      *(lfds700_pal_atom_t *) query_output = lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
+    break;
+
+    case LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS:
+      LFDS700_PAL_ATOMIC_EXCHANGE( &lfds700_misc_globals.exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas, (lfds700_pal_atom_t *) query_input );
+    break;
+
+    case LFDS700_MISC_QUERY_GET_BUILD_AND_VERSION_STRING:
+    {
+      char static const
+        * const build_and_version_string = "liblfds " LFDS700_MISC_VERSION_STRING " (" BUILD_TYPE_STRING ", " LFDS700_PAL_OS_STRING ", " MODE_TYPE_STRING ", " LFDS700_PAL_PROCESSOR_STRING ", " LFDS700_PAL_COMPILER_STRING ")";
+
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      *(char const **) query_output = build_and_version_string;
+    }
+    break;
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..f2da905dbe12b5ff44ad959247ecb0dacdde4cdd
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_cleanup.c
@@ -0,0 +1,48 @@
+/***** includes *****/
+#include "lfds700_queue_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_queue_cleanup( struct lfds700_queue_state *qs,
+                            void (*element_cleanup_callback)(struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag) )
+{
+  struct lfds700_queue_element
+    *qe;
+
+  void
+    *value;
+
+  LFDS700_PAL_ASSERT( qs != NULL );
+  // TRD : element_cleanup_callback can be NULL
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  if( element_cleanup_callback != NULL )
+  {
+    while( qs->dequeue[POINTER] != qs->enqueue[POINTER] )
+    {
+      // TRD : trailing dummy element, so the first real value is in the next element
+      value = qs->dequeue[POINTER]->next[POINTER]->value;
+
+      // TRD : user is given back *an* element, but not the one his user data was in
+      qe = qs->dequeue[POINTER];
+
+      // TRD : remove the element from queue
+      qs->dequeue[POINTER] = qs->dequeue[POINTER]->next[POINTER];
+
+      // TRD : write value into the qe we're going to give the user
+      qe->value = value;
+
+      element_cleanup_callback( qs, qe, LFDS700_MISC_FLAG_LOWERED );
+    }
+
+    // TRD : and now the final element
+    element_cleanup_callback( qs, (struct lfds700_queue_element *) qs->dequeue[POINTER], LFDS700_MISC_FLAG_RAISED );
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_dequeue.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_dequeue.c
new file mode 100644
index 0000000000000000000000000000000000000000..853c585039ee02900aab080ff989b1fa712f70aa
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_dequeue.c
@@ -0,0 +1,109 @@
+/***** includes *****/
+#include "lfds700_queue_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int lfds700_queue_dequeue( struct lfds700_queue_state *qs,
+                           struct lfds700_queue_element **qe,
+                           struct lfds700_misc_prng_state *ps )
+{
+  char unsigned
+    result = 0,
+    unwanted_result;
+
+  enum lfds700_queue_queue_state
+    state = LFDS700_QUEUE_QUEUE_STATE_UNKNOWN;
+
+  int
+    rv = 1,
+    finished_flag = LFDS700_MISC_FLAG_LOWERED;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
+    *dequeue[PAC_SIZE],
+    *enqueue[PAC_SIZE],
+    *next[PAC_SIZE];
+
+  void
+    *key = NULL,
+    *value = NULL;
+
+  LFDS700_PAL_ASSERT( qs != NULL );
+  LFDS700_PAL_ASSERT( qe != NULL );
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  do
+  {
+    dequeue[COUNTER] = qs->dequeue[COUNTER];
+    dequeue[POINTER] = qs->dequeue[POINTER];
+
+    enqueue[COUNTER] = qs->enqueue[COUNTER];
+    enqueue[POINTER] = qs->enqueue[POINTER];
+
+    next[COUNTER] = qs->dequeue[POINTER]->next[COUNTER];
+    next[POINTER] = qs->dequeue[POINTER]->next[POINTER];
+
+    LFDS700_MISC_BARRIER_LOAD;
+
+    if( dequeue[COUNTER] == qs->dequeue[COUNTER] and dequeue[POINTER] == qs->dequeue[POINTER] )
+    {
+      if( enqueue[POINTER] == dequeue[POINTER] and next[POINTER] == NULL )
+        state = LFDS700_QUEUE_QUEUE_STATE_EMPTY;
+
+      if( enqueue[POINTER] == dequeue[POINTER] and next[POINTER] != NULL )
+        state = LFDS700_QUEUE_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE;
+
+      if( enqueue[POINTER] != dequeue[POINTER] )
+        state = LFDS700_QUEUE_QUEUE_STATE_ATTEMPT_DEQUEUE;
+
+      switch( state )
+      {
+        case LFDS700_QUEUE_QUEUE_STATE_UNKNOWN:
+          // TRD : eliminates compiler warning
+        break;
+
+        case LFDS700_QUEUE_QUEUE_STATE_EMPTY:
+          rv = 0;
+          *qe = NULL;
+          finished_flag = LFDS700_MISC_FLAG_RAISED;
+        break;
+
+        case LFDS700_QUEUE_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE:
+          next[COUNTER] = enqueue[COUNTER] + 1;
+          LFDS700_MISC_BARRIER_STORE;
+          LFDS700_PAL_ATOMIC_DWCAS( qs->enqueue, enqueue, next, LFDS700_MISC_CAS_STRENGTH_WEAK, unwanted_result );
+        break;
+
+        case LFDS700_QUEUE_QUEUE_STATE_ATTEMPT_DEQUEUE:
+          key = next[POINTER]->key;
+          value = next[POINTER]->value;
+
+          next[COUNTER] = dequeue[COUNTER] + 1;
+          LFDS700_MISC_BARRIER_STORE;
+          LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( qs->dequeue, dequeue, next, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+
+          if( result == 1 )
+            finished_flag = LFDS700_MISC_FLAG_RAISED;
+        break;
+      }
+    }
+  }
+  while( finished_flag == LFDS700_MISC_FLAG_LOWERED );
+
+  if( result == 1 )
+  {
+    *qe = dequeue[POINTER];
+    (*qe)->key = key;
+    (*qe)->value = value;
+  }
+
+  return( rv );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_enqueue.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_enqueue.c
new file mode 100644
index 0000000000000000000000000000000000000000..07df84d851a0bc2dd733e14851842c007de780f9
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_enqueue.c
@@ -0,0 +1,74 @@
+/***** includes *****/
+#include "lfds700_queue_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_queue_enqueue( struct lfds700_queue_state *qs,
+                            struct lfds700_queue_element *qe,
+                            struct lfds700_misc_prng_state *ps )
+{
+  char unsigned
+    result = 0,
+    unwanted_result;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  struct lfds700_queue_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
+    *volatile enqueue[PAC_SIZE],
+    *new_enqueue[PAC_SIZE],
+    *volatile next[PAC_SIZE];
+
+  LFDS700_PAL_ASSERT( qs != NULL );
+  LFDS700_PAL_ASSERT( qe != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) qe->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qe->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  qe->next[COUNTER] = (struct lfds700_queue_element *) LFDS700_MISC_PRNG_GENERATE( ps );
+  qe->next[POINTER] = NULL;
+
+  new_enqueue[POINTER] = qe;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  do
+  {
+    enqueue[COUNTER] = qs->enqueue[COUNTER];
+    enqueue[POINTER] = qs->enqueue[POINTER];
+
+    next[COUNTER] = qs->enqueue[POINTER]->next[COUNTER];
+    next[POINTER] = qs->enqueue[POINTER]->next[POINTER];
+
+    LFDS700_MISC_BARRIER_LOAD;
+
+    if( qs->enqueue[COUNTER] == enqueue[COUNTER] and qs->enqueue[POINTER] == enqueue[POINTER] )
+    {
+      if( next[POINTER] == NULL )
+      {
+        new_enqueue[COUNTER] = next[COUNTER] + 1;
+        LFDS700_MISC_BARRIER_STORE;
+        LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( enqueue[POINTER]->next, next, new_enqueue, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+      }
+      else
+      {
+        next[COUNTER] = enqueue[COUNTER] + 1;
+        LFDS700_MISC_BARRIER_STORE;
+        // TRD : strictly, this is a weak CAS, but we do an extra iteration of the main loop on a fake failure, so we set it to be strong
+        LFDS700_PAL_ATOMIC_DWCAS( qs->enqueue, enqueue, next, LFDS700_MISC_CAS_STRENGTH_STRONG, unwanted_result );
+      }
+    }
+  }
+  while( result != 1 );
+
+  new_enqueue[COUNTER] = enqueue[COUNTER] + 1;
+  LFDS700_MISC_BARRIER_STORE;
+  // TRD : move enqueue along; only a weak CAS as the dequeue will solve this if its out of place
+  LFDS700_PAL_ATOMIC_DWCAS( qs->enqueue, enqueue, new_enqueue, LFDS700_MISC_CAS_STRENGTH_WEAK, unwanted_result );
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..15f4e64d8d9ce6879b969837dd7c99a7533483c3
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_init.c
@@ -0,0 +1,43 @@
+/***** includes *****/
+#include "lfds700_queue_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_queue_init_valid_on_current_logical_core( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe_dummy, struct lfds700_misc_prng_state *ps, void *user_state )
+{
+  LFDS700_PAL_ASSERT( qs != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qs->enqueue % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qs->dequeue % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qs->user_state % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( qe_dummy != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) qe_dummy->next % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &qe_dummy->key % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( ps != NULL );
+  // TRD : user_state can be UNLL
+
+  /* TRD : qe_dummy is a dummy element, needed for init
+           the qs->enqueue and qs->dequeue counters do not need to be initialized
+           but it does no harm to do so, and stops a valgrind complaint
+  */
+
+  qs->enqueue[POINTER] = qe_dummy;
+  qs->enqueue[COUNTER] = (struct lfds700_queue_element *) 0;
+  qs->dequeue[POINTER] = qe_dummy;
+  qs->dequeue[COUNTER] = (struct lfds700_queue_element *) 0;
+
+  qe_dummy->next[POINTER] = NULL;
+  qe_dummy->next[COUNTER] = (struct lfds700_queue_element *) LFDS700_MISC_PRNG_GENERATE( ps );
+  qe_dummy->value = NULL;
+
+  qs->user_state = user_state;
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..81c9b69f481e7afe9a9723d13a375dbb53e77abd
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_internal.h
@@ -0,0 +1,14 @@
+/***** the library wide include file *****/
+#include "../liblfds700_internal.h"
+
+/***** enums *****/
+enum lfds700_queue_queue_state
+{
+  LFDS700_QUEUE_QUEUE_STATE_UNKNOWN, 
+  LFDS700_QUEUE_QUEUE_STATE_EMPTY,
+  LFDS700_QUEUE_QUEUE_STATE_ENQUEUE_OUT_OF_PLACE,
+  LFDS700_QUEUE_QUEUE_STATE_ATTEMPT_DEQUEUE
+};
+
+/***** private prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..15b4307ff2c94d467c8251a32877f8c8469cdd6e
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue/lfds700_queue_query.c
@@ -0,0 +1,126 @@
+/***** includes *****/
+#include "lfds700_queue_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_queue_internal_validate( struct lfds700_queue_state *qs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_queue_validity );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_queue_query( struct lfds700_queue_state *qs, enum lfds700_queue_query query_type, void *query_input, void *query_output )
+{
+  struct lfds700_queue_element
+    *qe;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  LFDS700_PAL_ASSERT( qs != NULL );
+  // TRD : query_type can be any value in its range
+
+  switch( query_type )
+  {
+    case LFDS700_QUEUE_QUERY_SINGLETHREADED_GET_COUNT:
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      *(lfds700_pal_uint_t *) query_output = 0;
+
+      qe = (struct lfds700_queue_element *) qs->dequeue[POINTER];
+
+      while( qe != NULL )
+      {
+        ( *(lfds700_pal_uint_t *) query_output )++;
+        qe = (struct lfds700_queue_element *) qe->next[POINTER];
+      }
+
+      // TRD : remember there is a dummy element in the queue
+      ( *(lfds700_pal_uint_t *) query_output )--;
+    break;
+
+    case LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE:
+      // TRD : query_input can be NULL
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_queue_internal_validate( qs, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_queue_internal_validate( struct lfds700_queue_state *qs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_queue_validity )
+{
+  lfds700_pal_uint_t
+    number_elements = 0;
+
+  struct lfds700_queue_element
+    *qe_fast,
+    *qe_slow;
+
+  LFDS700_PAL_ASSERT( qs != NULL );
+  // TRD : vi can be NULL
+  LFDS700_PAL_ASSERT( lfds700_queue_validity != NULL );
+
+  *lfds700_queue_validity = LFDS700_MISC_VALIDITY_VALID;
+
+  qe_slow = qe_fast = (struct lfds700_queue_element *) qs->dequeue[POINTER];
+
+  /* TRD : first, check for a loop
+           we have two pointers
+           both of which start at the dequeue end of the queue
+           we enter a loop
+           and on each iteration
+           we advance one pointer by one element
+           and the other by two
+
+           we exit the loop when both pointers are NULL
+           (have reached the end of the queue)
+
+           or
+
+           if we fast pointer 'sees' the slow pointer
+           which means we have a loop
+  */
+
+  if( qe_slow != NULL )
+    do
+    {
+      qe_slow = qe_slow->next[POINTER];
+
+      if( qe_fast != NULL )
+        qe_fast = qe_fast->next[POINTER];
+
+      if( qe_fast != NULL )
+        qe_fast = qe_fast->next[POINTER];
+    }
+    while( qe_slow != NULL and qe_fast != qe_slow );
+
+  if( qe_fast != NULL and qe_slow != NULL and qe_fast == qe_slow )
+    *lfds700_queue_validity = LFDS700_MISC_VALIDITY_INVALID_LOOP;
+
+  /* TRD : now check for expected number of elements
+           vi can be NULL, in which case we do not check
+           we know we don't have a loop from our earlier check
+  */
+
+  if( *lfds700_queue_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
+  {
+    lfds700_queue_query( qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_GET_COUNT, NULL, (void *) &number_elements );
+
+    if( number_elements < vi->min_elements )
+      *lfds700_queue_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( number_elements > vi->max_elements )
+      *lfds700_queue_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..2b157bd973cbeba75f010b4e715b85e898909ee4
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c
@@ -0,0 +1,30 @@
+/***** includes *****/
+#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_queue_bss_cleanup( struct lfds700_queue_bss_state *qbsss,
+                                void (*element_cleanup_callback)(struct lfds700_queue_bss_state *qbsss, void *key, void *value) )
+{
+  int long long unsigned
+    loop;
+
+  struct lfds700_queue_bss_element
+    *qbsse;
+
+  LFDS700_PAL_ASSERT( qbsss != NULL );
+  // TRD : element_cleanup_callback can be NULL
+
+  if( element_cleanup_callback != NULL )
+    for( loop = qbsss->read_index ; loop < qbsss->read_index + qbsss->number_elements ; loop++ )
+    {
+      qbsse = qbsss->element_array + (loop % qbsss->number_elements);
+      element_cleanup_callback( qbsss, qbsse->key, qbsse->value );
+    }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c
new file mode 100644
index 0000000000000000000000000000000000000000..28f735f6101be6c45c5a1fdc0e68844899949df1
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c
@@ -0,0 +1,42 @@
+/***** includes *****/
+#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int lfds700_queue_bss_dequeue( struct lfds700_queue_bss_state *qbsss, void **key, void **value )
+{
+  int
+    rv = 0;
+
+  struct lfds700_queue_bss_element
+    *qbsse;
+
+  LFDS700_PAL_ASSERT( qbsss != NULL );
+  // TRD : key can be NULL
+  // TRD : value can be NULL
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  if( qbsss->read_index != qbsss->write_index )
+  {
+    qbsse = qbsss->element_array + qbsss->read_index;
+
+    if( key != NULL )
+      *key = qbsse->key;
+
+    if( value != NULL )
+      *value = qbsse->value;
+
+    qbsss->read_index = (qbsss->read_index + 1) & qbsss->mask;
+
+    LFDS700_MISC_BARRIER_STORE;
+
+    rv = 1;
+  }
+
+  return( rv );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c
new file mode 100644
index 0000000000000000000000000000000000000000..c74091a23eacd257472153b2f10f4082566073b7
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c
@@ -0,0 +1,39 @@
+/***** includes *****/
+#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int lfds700_queue_bss_enqueue( struct lfds700_queue_bss_state *qbsss, void *key, void *value )
+{
+  int
+    rv = 0;
+
+  struct lfds700_queue_bss_element
+    *qbsse;
+
+  LFDS700_PAL_ASSERT( qbsss != NULL );
+  // TRD : key can be NULL
+  // TRD : value can be NULL
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  if( ( (qbsss->write_index+1) & qbsss->mask ) != qbsss->read_index )
+  {
+    qbsse = qbsss->element_array + qbsss->write_index;
+
+    qbsse->key = key;
+    qbsse->value = value;
+
+    LFDS700_MISC_BARRIER_STORE;
+
+    qbsss->write_index = (qbsss->write_index + 1) & qbsss->mask;
+
+    rv = 1;
+  }
+
+  return( rv );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..9127fef443811670579702b39be660d0d3ba50b4
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_init.c
@@ -0,0 +1,63 @@
+/***** includes *****/
+#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_queue_bss_init_valid_on_current_logical_core( struct lfds700_queue_bss_state *qbsss,
+                             struct lfds700_queue_bss_element *element_array,
+                             lfds700_pal_uint_t number_elements,
+                             void *user_state )
+{
+  LFDS700_PAL_ASSERT( qbsss != NULL );
+  LFDS700_PAL_ASSERT( element_array != NULL );
+  LFDS700_PAL_ASSERT( number_elements >= 2 );
+  LFDS700_PAL_ASSERT( ( number_elements & (number_elements-1) ) == 0 ); // TRD : number_elements must be a positive integer power of 2
+  // TRD : user_state can be NULL
+
+  /* TRD : the use of mask and the restriction on a power of two
+           upon the number of elements bears some remark
+
+           in this queue, there are a fixed number of elements
+           we have a read index and a write index
+           when we write, and thre is space to write, we increment the write index
+           (if no space to write, we just return)
+           when we read, and there are elements to be read, we after reading increment the read index
+           (if no elements to read, we just return)
+           the problem is - how do we handle wrap around?
+           e.g. when I write, but my write index is now equal to the number of elements
+           the usual solution is to modulus the write index by the nunmber of elements
+           problem is modulus is slow
+           there is a better way
+           first, we restrict the number of elements to be a power of two
+           so imagine we have a 64-bit system and we set the number of elements to be 2^64
+           this gives us a bit pattern of 1000 0000 0000 0000 (...etc, lots of zeros)
+           now (just roll with this for a bit) subtract one from this
+           this gives us a mask (on a two's compliment machine)
+           0111 1111 1111 1111 (...etc, lots of ones)
+           so what we do now, when we increment an index (think of the write index as the example)
+           we bitwise and it with the mask
+           now think about thwt happens
+           all the numbers up to 2^64 will be unchanged - their MSB is never set, and we and with all the other bits
+           but when we finally hit 2^64 and need to roll over... bingo!
+           we drop MSB (which we finally have) and have the value 0!
+           this is exactly what we want
+           bitwise and is much faster than modulus
+  */
+
+  qbsss->number_elements = number_elements;
+  qbsss->mask = qbsss->number_elements - 1;
+  qbsss->read_index = 0;
+  qbsss->write_index = 0;
+  qbsss->element_array = element_array;
+  qbsss->user_state = user_state;
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a7d54180421c96cce9b0a1b6529d4cee90b5564
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_internal.h
@@ -0,0 +1,5 @@
+/***** the library wide include file *****/
+#include "../liblfds700_internal.h"
+
+/***** private prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..aabcae23f3de3a9929264406fe6e584b3684fc61
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_query.c
@@ -0,0 +1,70 @@
+/***** includes *****/
+#include "lfds700_queue_bounded_singleconsumer_singleproducer_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_queue_bss_internal_validate( struct lfds700_queue_bss_state *qbsss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_validity );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_queue_bss_query( struct lfds700_queue_bss_state *qbsss, enum lfds700_queue_bss_query query_type, void *query_input, void *query_output )
+{
+  LFDS700_PAL_ASSERT( qbsss != NULL );
+  // TRD : query_type can be any value in its range
+
+  switch( query_type )
+  {
+    case LFDS700_QUEUE_BSS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT:
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      LFDS700_MISC_BARRIER_LOAD;
+
+      *(lfds700_pal_uint_t *) query_output = +( qbsss->write_index - qbsss->read_index );
+      if( qbsss->read_index > qbsss->write_index )
+        *(lfds700_pal_uint_t *) query_output = qbsss->number_elements - *(lfds700_pal_uint_t *) query_output;
+    break;
+
+    case LFDS700_QUEUE_BSS_QUERY_VALIDATE:
+      // TRD : query_input can be NULL
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_queue_bss_internal_validate( qbsss, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_queue_bss_internal_validate( struct lfds700_queue_bss_state *qbsss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_validity )
+{
+  LFDS700_PAL_ASSERT( qbsss != NULL );
+  // TRD : vi can be NULL
+  LFDS700_PAL_ASSERT( lfds700_validity != NULL );
+
+  *lfds700_validity = LFDS700_MISC_VALIDITY_VALID;
+
+  if( vi != NULL )
+  {
+    lfds700_pal_uint_t
+      number_elements;
+
+    lfds700_queue_bss_query( qbsss, LFDS700_QUEUE_BSS_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void *) &number_elements );
+
+    if( number_elements < vi->min_elements )
+      *lfds700_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( number_elements > vi->max_elements )
+      *lfds700_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..447c93041e36e8b626d2da09610b94c919efd61d
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_cleanup.c
@@ -0,0 +1,86 @@
+/***** includes *****/
+#include "lfds700_ringbuffer_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_ringbuffer_internal_queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag );
+static void lfds700_ringbuffer_internal_freelist_element_cleanup_callback( struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_ringbuffer_cleanup( struct lfds700_ringbuffer_state *rs,
+                                 void (*element_cleanup_callback)(struct lfds700_ringbuffer_state *rs, void *key, void *value, enum lfds700_misc_flag unread_flag) )
+{
+  LFDS700_PAL_ASSERT( rs != NULL );
+  // TRD : element_cleanup_callback can be NULL
+
+  if( element_cleanup_callback != NULL )
+  {
+    rs->element_cleanup_callback = element_cleanup_callback;
+    lfds700_queue_cleanup( &rs->qs, lfds700_ringbuffer_internal_queue_element_cleanup_callback );
+    lfds700_freelist_cleanup( &rs->fs, lfds700_ringbuffer_internal_freelist_element_cleanup_callback );
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static void lfds700_ringbuffer_internal_queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag )
+{
+  struct lfds700_ringbuffer_element
+    *re;
+
+  struct lfds700_ringbuffer_state
+    *rs;
+
+  LFDS700_PAL_ASSERT( qs != NULL );
+  LFDS700_PAL_ASSERT( qe != NULL );
+  // TRD : dummy_element can be any value in its range
+
+  rs = (struct lfds700_ringbuffer_state *) LFDS700_QUEUE_GET_USER_STATE_FROM_STATE( *qs );
+  re = (struct lfds700_ringbuffer_element *) LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
+
+  if( dummy_element_flag == LFDS700_MISC_FLAG_LOWERED )
+    rs->element_cleanup_callback( rs, re->key, re->value, LFDS700_MISC_FLAG_RAISED );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static void lfds700_ringbuffer_internal_freelist_element_cleanup_callback( struct lfds700_freelist_state *fs, struct lfds700_freelist_element *fe )
+{
+  struct lfds700_ringbuffer_element
+    *re;
+
+  struct lfds700_ringbuffer_state
+    *rs;
+
+  LFDS700_PAL_ASSERT( fs != NULL );
+  LFDS700_PAL_ASSERT( fe != NULL );
+
+  rs = (struct lfds700_ringbuffer_state *) LFDS700_FREELIST_GET_USER_STATE_FROM_STATE( *fs );
+  re = (struct lfds700_ringbuffer_element *) LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
+
+  rs->element_cleanup_callback( rs, re->key, re->value, LFDS700_MISC_FLAG_LOWERED );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..a6cd1e36161272ec6fec43ce1878413a6839cbb5
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_init.c
@@ -0,0 +1,51 @@
+/***** includes *****/
+#include "lfds700_ringbuffer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_ringbuffer_init_valid_on_current_logical_core( struct lfds700_ringbuffer_state *rs,
+                                                            struct lfds700_ringbuffer_element *re_array_inc_dummy,
+                                                            lfds700_pal_uint_t number_elements,
+                                                            struct lfds700_misc_prng_state *ps,
+                                                            void *user_state )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  LFDS700_PAL_ASSERT( rs != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &rs->fs % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &rs->qs % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( re_array_inc_dummy != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &re_array_inc_dummy[0].fe % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &re_array_inc_dummy[0].qe % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( number_elements >= 2 );
+  LFDS700_PAL_ASSERT( ps != NULL );
+  // TRD : user_state can be NULL
+
+  rs->user_state = user_state;
+
+  re_array_inc_dummy[0].qe_use = &re_array_inc_dummy[0].qe;
+
+  lfds700_freelist_init_valid_on_current_logical_core( &rs->fs, rs );
+  lfds700_queue_init_valid_on_current_logical_core( &rs->qs, &re_array_inc_dummy[0].qe, ps, rs );
+
+  for( loop = 1 ; loop < number_elements ; loop++ )
+  {
+    LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &re_array_inc_dummy[loop].fe % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+    LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &re_array_inc_dummy[loop].qe % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+
+    re_array_inc_dummy[loop].qe_use = &re_array_inc_dummy[loop].qe;
+    LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( re_array_inc_dummy[loop].fe, &re_array_inc_dummy[loop] );
+    lfds700_freelist_push( &rs->fs, &re_array_inc_dummy[loop].fe, ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a7d54180421c96cce9b0a1b6529d4cee90b5564
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_internal.h
@@ -0,0 +1,5 @@
+/***** the library wide include file *****/
+#include "../liblfds700_internal.h"
+
+/***** private prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..58b7b3a9cbc0e23dbd25ae8d7d461e368089bd14
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_query.c
@@ -0,0 +1,72 @@
+/***** includes *****/
+#include "lfds700_ringbuffer_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_ringbuffer_internal_validate( struct lfds700_ringbuffer_state *rs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_queue_validity, enum lfds700_misc_validity *lfds700_freelist_validity );
+
+
+
+/****************************************************************************/
+void lfds700_ringbuffer_query( struct lfds700_ringbuffer_state *rs, enum lfds700_ringbuffer_query query_type, void *query_input, void *query_output )
+{
+  LFDS700_PAL_ASSERT( rs != NULL );
+  // TRD : query_type can be any value in its range
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  switch( query_type )
+  {
+    case LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_GET_COUNT:
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_queue_query( &rs->qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_GET_COUNT, NULL, query_output );
+    break;
+
+    case LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE:
+      // TRD : query_input can be NULL
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_ringbuffer_internal_validate( rs, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output, ((enum lfds700_misc_validity *) query_output)+1 );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_ringbuffer_internal_validate( struct lfds700_ringbuffer_state *rs, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_queue_validity, enum lfds700_misc_validity *lfds700_freelist_validity )
+{
+  LFDS700_PAL_ASSERT( rs != NULL );
+  // TRD : vi can be NULL
+  LFDS700_PAL_ASSERT( lfds700_queue_validity != NULL );
+  LFDS700_PAL_ASSERT( lfds700_freelist_validity != NULL );
+
+  if( vi == NULL )
+  {
+    lfds700_queue_query( &rs->qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, NULL, lfds700_queue_validity );
+    lfds700_freelist_query( &rs->fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, NULL, lfds700_freelist_validity );
+  }
+
+  if( vi != NULL )
+  {
+    struct lfds700_misc_validation_info
+      freelist_vi,
+      queue_vi;
+
+    queue_vi.min_elements = 0;
+    freelist_vi.min_elements = 0;
+    queue_vi.max_elements = vi->max_elements;
+    freelist_vi.max_elements = vi->max_elements;
+
+    lfds700_queue_query( &rs->qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &queue_vi, lfds700_queue_validity );
+    lfds700_freelist_query( &rs->fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, &freelist_vi, lfds700_freelist_validity );
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_read.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_read.c
new file mode 100644
index 0000000000000000000000000000000000000000..42dbe189e2307ce937790501e6c7476fe6d24155
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_read.c
@@ -0,0 +1,44 @@
+/***** includes *****/
+#include "lfds700_ringbuffer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int lfds700_ringbuffer_read( struct lfds700_ringbuffer_state *rs,
+                             void **key,
+                             void **value,
+                             struct lfds700_misc_prng_state *ps )
+{
+  int
+    rv;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct lfds700_ringbuffer_element
+    *re;
+
+  LFDS700_PAL_ASSERT( rs != NULL );
+  // TRD : key can be NULL
+  // TRD : value can be NULL
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  rv = lfds700_queue_dequeue( &rs->qs, &qe, ps );
+
+  if( rv == 1 )
+  {
+    re = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
+    re->qe_use = (struct lfds700_queue_element *) qe;
+    if( key != NULL )
+      *key = re->key;
+    if( value != NULL )
+      *value = re->value;
+    LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( re->fe, re );
+    lfds700_freelist_push( &rs->fs, &re->fe, ps );
+  }
+
+  return( rv );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_write.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_write.c
new file mode 100644
index 0000000000000000000000000000000000000000..a16a8686c104f486a6b8981bf89033b9a237502c
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_ringbuffer/lfds700_ringbuffer_write.c
@@ -0,0 +1,78 @@
+/***** includes *****/
+#include "lfds700_ringbuffer_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_ringbuffer_write( struct lfds700_ringbuffer_state *rs,
+                               void *key,
+                               void *value,
+                               enum lfds700_misc_flag *overwrite_occurred_flag,
+                               void **overwritten_key,
+                               void **overwritten_value,
+                               struct lfds700_misc_prng_state *ps )
+{
+  int
+    rv = 0;
+
+  struct lfds700_freelist_element
+    *fe;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct lfds700_ringbuffer_element
+    *re = NULL;
+
+  LFDS700_PAL_ASSERT( rs != NULL );
+  // TRD : key can be NULL
+  // TRD : value can be NULL
+  // TRD : overwrite_occurred_flag can be NULL
+  // TRD : overwritten_key can be NULL
+  // TRD : overwritten_value can be NULL
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  if( overwrite_occurred_flag != NULL )
+    *overwrite_occurred_flag = LFDS700_MISC_FLAG_LOWERED;
+
+  do
+  {
+    rv = lfds700_freelist_pop( &rs->fs, &fe, ps );
+
+    if( rv == 1 )
+      re = LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
+
+    if( rv == 0 )
+    {
+      // TRD : the queue can return empty as well - remember, we're lock-free; anything could have happened since the previous instruction
+      rv = lfds700_queue_dequeue( &rs->qs, &qe, ps );
+
+      if( rv == 1 )
+      {
+        re = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
+        re->qe_use = (struct lfds700_queue_element *) qe;
+
+        if( overwrite_occurred_flag != NULL )
+          *overwrite_occurred_flag = LFDS700_MISC_FLAG_RAISED;
+
+        if( overwritten_key != NULL )
+          *overwritten_key = re->key;
+
+        if( overwritten_value != NULL )
+          *overwritten_value = re->value;
+      }
+    }
+  }
+  while( rv == 0 );
+
+  re->key = key;
+  re->value = value;
+
+  LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( *re->qe_use, re );
+  lfds700_queue_enqueue( &rs->qs, re->qe_use, ps );
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_cleanup.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_cleanup.c
new file mode 100644
index 0000000000000000000000000000000000000000..efcebf35436301c3300dbc3be6ef029a7fe08acf
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_cleanup.c
@@ -0,0 +1,36 @@
+/***** includes *****/
+#include "lfds700_stack_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_stack_cleanup( struct lfds700_stack_state *ss,
+                            void (*element_cleanup_callback)(struct lfds700_stack_state *ss, struct lfds700_stack_element *se) )
+{
+  struct lfds700_stack_element
+    *se,
+    *se_temp;
+
+  LFDS700_PAL_ASSERT( ss != NULL );
+  // TRD : element_cleanup_callback can be NULL
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  if( element_cleanup_callback != NULL )
+  {
+    se = ss->top[POINTER];
+
+    while( se != NULL )
+    {
+      se_temp = se;
+      se = se->next;
+
+      element_cleanup_callback( ss, se_temp );
+    }
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_init.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..745017c029c390bf360b9bd821a843ee70d6c2d1
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_init.c
@@ -0,0 +1,27 @@
+/***** includes *****/
+#include "lfds700_stack_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_stack_init_valid_on_current_logical_core( struct lfds700_stack_state *ss, void *user_state )
+{
+  LFDS700_PAL_ASSERT( ss != NULL );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) ss->top % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  LFDS700_PAL_ASSERT( (lfds700_pal_uint_t) &ss->user_state % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES == 0 );
+  // TRD : user_state can be NULL
+
+  ss->top[POINTER] = NULL;
+  ss->top[COUNTER] = 0;
+
+  ss->user_state = user_state;
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a7d54180421c96cce9b0a1b6529d4cee90b5564
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_internal.h
@@ -0,0 +1,5 @@
+/***** the library wide include file *****/
+#include "../liblfds700_internal.h"
+
+/***** private prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_pop.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_pop.c
new file mode 100644
index 0000000000000000000000000000000000000000..3cae2e563e160e526f62bd9ec04d6e553f4a2a0c
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_pop.c
@@ -0,0 +1,52 @@
+/***** includes *****/
+#include "lfds700_stack_internal.h"
+
+
+
+
+
+/****************************************************************************/
+int lfds700_stack_pop( struct lfds700_stack_state *ss, struct lfds700_stack_element **se, struct lfds700_misc_prng_state *ps )
+{
+  char unsigned
+    result;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  struct lfds700_stack_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
+    *new_top[PAC_SIZE],
+    *volatile original_top[PAC_SIZE];
+
+  LFDS700_PAL_ASSERT( ss != NULL );
+  LFDS700_PAL_ASSERT( se != NULL );
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  LFDS700_PAL_BARRIER_PROCESSOR_LOAD;
+
+  original_top[COUNTER] = ss->top[COUNTER];
+  original_top[POINTER] = ss->top[POINTER];
+
+  do
+  {
+    if( original_top[POINTER] == NULL )
+    {
+      *se = NULL;
+      return( 0 );
+    }
+
+    new_top[COUNTER] = original_top[COUNTER] + 1;
+    new_top[POINTER] = original_top[POINTER]->next;
+
+    LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( &ss->top, original_top, new_top, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+
+    if( result != 1 )
+      LFDS700_PAL_BARRIER_PROCESSOR_LOAD;
+  }
+  while( result != 1 );
+
+  *se = original_top[POINTER];
+
+  return( 1 );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_push.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_push.c
new file mode 100644
index 0000000000000000000000000000000000000000..ff84c5ed553009506bcfe0e29da0f102bad283dd
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_push.c
@@ -0,0 +1,42 @@
+/***** includes *****/
+#include "lfds700_stack_internal.h"
+
+
+
+
+
+/****************************************************************************/
+void lfds700_stack_push( struct lfds700_stack_state *ss, struct lfds700_stack_element *se, struct lfds700_misc_prng_state *ps )
+{
+  char unsigned
+    result;
+
+  lfds700_pal_uint_t
+    backoff_iteration = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;
+
+  struct lfds700_stack_element LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
+    *new_top[PAC_SIZE],
+    *volatile original_top[PAC_SIZE];
+
+  LFDS700_PAL_ASSERT( ss != NULL );
+  LFDS700_PAL_ASSERT( se != NULL );
+  LFDS700_PAL_ASSERT( ps != NULL );
+
+  new_top[POINTER] = se;
+
+  original_top[COUNTER] = ss->top[COUNTER];
+  original_top[POINTER] = ss->top[POINTER];
+
+  do
+  {
+    new_top[COUNTER] = original_top[COUNTER] + 1;
+    se->next = original_top[POINTER];
+
+    LFDS700_PAL_BARRIER_PROCESSOR_STORE;
+    LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( &ss->top, original_top, new_top, LFDS700_MISC_CAS_STRENGTH_WEAK, result, backoff_iteration, ps );
+  }
+  while( result != 1 );
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_query.c b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_query.c
new file mode 100644
index 0000000000000000000000000000000000000000..b9abdf9f2d8020be448099a225ab450c4786a0c4
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/lfds700_stack/lfds700_stack_query.c
@@ -0,0 +1,123 @@
+/***** includes *****/
+#include "lfds700_stack_internal.h"
+
+/***** private prototypes *****/
+static void lfds700_stack_internal_stack_validate( struct lfds700_stack_state *ss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_stack_validity );
+
+
+
+
+
+/****************************************************************************/
+void lfds700_stack_query( struct lfds700_stack_state *ss, enum lfds700_stack_query query_type, void *query_input, void *query_output )
+{
+  struct lfds700_stack_element
+    *se;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  LFDS700_PAL_ASSERT( ss != NULL );
+  // TRD : query_type can be any value in its range
+
+  switch( query_type )
+  {
+    case LFDS700_STACK_QUERY_SINGLETHREADED_GET_COUNT:
+      LFDS700_PAL_ASSERT( query_input == NULL );
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      *(lfds700_pal_uint_t *) query_output = 0;
+
+      se = (struct lfds700_stack_element *) ss->top[POINTER];
+
+      while( se != NULL )
+      {
+        ( *(lfds700_pal_uint_t *) query_output )++;
+        se = (struct lfds700_stack_element *) se->next;
+      }
+    break;
+
+    case LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE:
+      // TRD : query_input can be NULL
+      LFDS700_PAL_ASSERT( query_output != NULL );
+
+      lfds700_stack_internal_stack_validate( ss, (struct lfds700_misc_validation_info *) query_input, (enum lfds700_misc_validity *) query_output );
+    break;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static void lfds700_stack_internal_stack_validate( struct lfds700_stack_state *ss, struct lfds700_misc_validation_info *vi, enum lfds700_misc_validity *lfds700_stack_validity )
+{
+  lfds700_pal_uint_t
+    number_elements = 0;
+
+  struct lfds700_stack_element
+    *se_fast,
+    *se_slow;
+
+  LFDS700_PAL_ASSERT( ss != NULL );
+  // TRD : vi can be NULL
+  LFDS700_PAL_ASSERT( lfds700_stack_validity != NULL );
+
+  *lfds700_stack_validity = LFDS700_MISC_VALIDITY_VALID;
+
+  se_slow = se_fast = (struct lfds700_stack_element *) ss->top[POINTER];
+
+  /* TRD : first, check for a loop
+           we have two pointers
+           both of which start at the top of the stack
+           we enter a loop
+           and on each iteration
+           we advance one pointer by one element
+           and the other by two
+
+           we exit the loop when both pointers are NULL
+           (have reached the end of the stack)
+
+           or
+
+           if we fast pointer 'sees' the slow pointer
+           which means we have a loop
+  */
+
+  if( se_slow != NULL )
+    do
+    {
+      se_slow = se_slow->next;
+
+      if( se_fast != NULL )
+        se_fast = se_fast->next;
+
+      if( se_fast != NULL )
+        se_fast = se_fast->next;
+    }
+    while( se_slow != NULL and se_fast != se_slow );
+
+  if( se_fast != NULL and se_slow != NULL and se_fast == se_slow )
+    *lfds700_stack_validity = LFDS700_MISC_VALIDITY_INVALID_LOOP;
+
+  /* TRD : now check for expected number of elements
+           vi can be NULL, in which case we do not check
+           we know we don't have a loop from our earlier check
+  */
+
+  if( *lfds700_stack_validity == LFDS700_MISC_VALIDITY_VALID and vi != NULL )
+  {
+    lfds700_stack_query( ss, LFDS700_STACK_QUERY_SINGLETHREADED_GET_COUNT, NULL, (void *) &number_elements );
+
+    if( number_elements < vi->min_elements )
+      *lfds700_stack_validity = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( number_elements > vi->max_elements )
+      *lfds700_stack_validity = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/liblfds700_internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/liblfds700_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..fdd8c363eb026f5be0a424eb5e3955e96b5fe87c
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/liblfds700/src/liblfds700_internal.h
@@ -0,0 +1,93 @@
+/***** public prototypes *****/
+#include "../inc/liblfds700.h"
+
+/***** defines *****/
+#define and &&
+#define or  ||
+
+#define NO_FLAGS 0x0
+
+#define LFDS700_ABSTRACTION_BACKOFF_LIMIT  (0x1 << 10)
+
+#if( defined _KERNEL_MODE )
+  #define MODE_TYPE_STRING "kernel-mode"
+#endif
+
+#if( !defined _KERNEL_MODE )
+  #define MODE_TYPE_STRING "user-mode"
+#endif
+
+#if( defined NDEBUG && !defined COVERAGE && !defined TSAN )
+  #define BUILD_TYPE_STRING "release"
+#endif
+
+#if( !defined NDEBUG && !defined COVERAGE && !defined TSAN )
+  #define BUILD_TYPE_STRING "debug"
+#endif
+
+#if( !defined NDEBUG && defined COVERAGE && !defined TSAN )
+  #define BUILD_TYPE_STRING "coverage"
+#endif
+
+#if( !defined NDEBUG && !defined COVERAGE && defined TSAN )
+  #define BUILD_TYPE_STRING "threadsanitizer"
+#endif
+
+// TRD : lfds700_pal_atom_t volatile *destination, lfds700_pal_atom_t *compare, lfds700_pal_atom_t new_destination, enum lfds700_misc_cas_strength cas_strength, char unsigned result, lfds700_pal_uint_t *backoff_iteration
+#define LFDS700_PAL_ATOMIC_CAS_WITH_BACKOFF( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result, backoff_iteration, ps )              \
+{                                                                                                                                                                    \
+  LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result );                                                       \
+                                                                                                                                                                     \
+  if( result == 0 )                                                                                                                                                  \
+  {                                                                                                                                                                  \
+    lfds700_pal_uint_t                                                                                                                                               \
+      endloop;                                                                                                                                                       \
+                                                                                                                                                                     \
+    lfds700_pal_uint_t volatile                                                                                                                                      \
+      loop;                                                                                                                                                          \
+                                                                                                                                                                     \
+    if( (backoff_iteration) == LFDS700_ABSTRACTION_BACKOFF_LIMIT )                                                                                                   \
+      (backoff_iteration) = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;                                                                                          \
+                                                                                                                                                                     \
+    if( (backoff_iteration) == LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE )                                                                                      \
+      (backoff_iteration) = 1;                                                                                                                                       \
+    else                                                                                                                                                             \
+    {                                                                                                                                                                \
+      endloop = ( LFDS700_MISC_PRNG_GENERATE(ps) % (backoff_iteration) ) * ps->local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_cas;  \
+      for( loop = 0 ; loop < endloop ; loop++ );                                                                                                                     \
+    }                                                                                                                                                                \
+                                                                                                                                                                     \
+    (backoff_iteration) <<= 1;                                                                                                                                       \
+  }                                                                                                                                                                  \
+}
+
+// TRD : lfds700_pal_atom_t volatile (*destination)[2], lfds700_pal_atom_t (*compare)[2], lfds700_pal_atom_t (*new_destination)[2], enum lfds700_misc_cas_strength cas_strength, char unsigned result, lfds700_pal_uint_t *backoff_iteration
+#define LFDS700_PAL_ATOMIC_DWCAS_WITH_BACKOFF( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result, backoff_iteration, ps )   \
+{                                                                                                                                                                      \
+  LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result );                                            \
+                                                                                                                                                                       \
+  if( result == 0 )                                                                                                                                                    \
+  {                                                                                                                                                                    \
+    lfds700_pal_uint_t                                                                                                                                                 \
+      endloop;                                                                                                                                                         \
+                                                                                                                                                                       \
+    lfds700_pal_uint_t volatile                                                                                                                                        \
+      loop;                                                                                                                                                            \
+                                                                                                                                                                       \
+    if( (backoff_iteration) == LFDS700_ABSTRACTION_BACKOFF_LIMIT )                                                                                                     \
+      (backoff_iteration) = LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE;                                                                                            \
+                                                                                                                                                                       \
+    if( (backoff_iteration) == LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE )                                                                                        \
+      (backoff_iteration) = 1;                                                                                                                                         \
+    else                                                                                                                                                               \
+    {                                                                                                                                                                  \
+      endloop = ( LFDS700_MISC_PRNG_GENERATE(ps) % (backoff_iteration) ) * ps->local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;  \
+      for( loop = 0 ; loop < endloop ; loop++ );                                                                                                                       \
+    }                                                                                                                                                                  \
+                                                                                                                                                                       \
+    (backoff_iteration) <<= 1;                                                                                                                                         \
+  }                                                                                                                                                                    \
+}
+
+/***** library-wide prototypes *****/
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/build/gcc_and_gnumake/Makefile b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/gcc_and_gnumake/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..489e5b19e573623e9adc92487303d808ea70d270
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/gcc_and_gnumake/Makefile
@@ -0,0 +1,129 @@
+##### paths #####
+BINDIR     := ../../bin
+OBJDIR     := ../../obj
+SRCDIR     := ../../src
+LIBINCDIRS := ../../../liblfds700/inc/
+LIBBINDIRS := ../../../liblfds700/bin/
+
+##### misc #####
+QUIETLY := 1>nul 2>nul
+
+##### sources, objects and libraries #####
+BINNAME := test
+BINARY  := $(BINDIR)/$(BINNAME)
+SRCDIRS := .
+SOURCES := main.c misc.c \
+           test_lfds700_btree_addonly_unbalanced.c test_lfds700_btree_addonly_unbalanced_alignment.c test_lfds700_btree_addonly_unbalanced_random_adds_fail.c test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c \
+           test_lfds700_freelist.c test_lfds700_freelist_alignment.c test_lfds700_freelist_popping.c test_lfds700_freelist_popping_and_pushing.c test_lfds700_freelist_pushing.c test_lfds700_freelist_rapid_popping_and_pushing.c \
+           test_lfds700_hash_addonly.c test_lfds700_hash_addonly_alignment.c test_lfds700_hash_addonly_iterate.c test_lfds700_hash_addonly_random_adds_fail.c test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c test_lfds700_hash_addonly_random_adds_overwrite.c \
+           test_lfds700_list_addonly_ordered_singlylinked.c test_lfds700_list_addonly_ordered_singlylinked_alignment.c test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c \
+           test_lfds700_list_addonly_singlylinked_unordered.c test_lfds700_list_addonly_singlylinked_unordered_alignment.c test_lfds700_list_addonly_singlylinked_unordered_new_after.c test_lfds700_list_addonly_singlylinked_unordered_new_end.c test_lfds700_list_addonly_singlylinked_unordered_new_start.c \
+           test_lfds700_porting_abstraction_layer_atomic.c test_lfds700_porting_abstraction_layer_atomic_cas.c test_lfds700_porting_abstraction_layer_atomic_dcas.c test_lfds700_porting_abstraction_layer_atomic_exchange.c \
+           test_lfds700_queue.c test_lfds700_queue_alignment.c test_lfds700_queue_dequeuing.c test_lfds700_queue_enqueuing.c test_lfds700_queue_enqueuing_and_dequeuing.c test_lfds700_queue_enqueuing_and_dequeuing_with_free.c test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c test_lfds700_queue_rapid_enqueuing_and_dequeuing.c \
+           test_lfds700_queue_bounded_singleconsumer_singleproducer.c test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c \
+           test_lfds700_ringbuffer.c test_lfds700_ringbuffer_reading.c test_lfds700_ringbuffer_reading_and_writing.c test_lfds700_ringbuffer_writing.c \
+           test_lfds700_stack.c test_lfds700_stack_alignment.c test_lfds700_stack_popping.c test_lfds700_stack_popping_and_pushing.c test_lfds700_stack_pushing.c test_lfds700_stack_rapid_popping_and_pushing.c \
+           test_porting_abstraction_layer_get_logical_core_ids.c test_porting_abstraction_layer_thread_start.c test_porting_abstraction_layer_thread_wait.c \
+           util_cmdline.c util_memory_helpers.c util_thread_starter.c
+OBJECTS := $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
+SYSLIBS := -lm -lpthread -lrt
+USRLIBS := -llfds700
+
+##### default paths #####
+CPATH        += $(LIBINCDIRS)
+LIBRARY_PATH += $(LIBBINDIRS)
+export CPATH
+export LIBRARY_PATH
+
+##### tools #####
+MAKE    := make
+MFLAGS  := 
+
+DG      := gcc
+DGFLAGS := -MM -std=gnu89
+
+CC      := gcc
+CFBASE  := -c -pthread -std=gnu89 -Wall -Wno-unknown-pragmas
+CFCOV   := -O0 -ggdb -DCOVERAGE -fprofile-arcs -ftest-coverage
+CFDBG   := -O0 -ggdb -D_DEBUG
+CFPROF  := -O0 -ggdb -DPROF     -pg
+CFREL   := -O2       -DNDEBUG   -finline-functions -Wno-strict-aliasing
+CFTSAN  := -O0 -ggdb -DTSAN     -fsanitize=thread -fPIE
+
+LD      := gcc
+LFBASE  := -pthread -std=gnu89 -Wall -Werror
+LFCOV   := -O0 -fprofile-arcs -ftest-coverage
+LFDBG   := -O0 -ggdb
+LFPROF  := -O0 -pg
+LFREL   := -O2 -s -finline-functions
+LFTSAN  := -O0 -fsanitize=thread -pie
+
+PROF    := gprof
+PFBASE  := -b -p -Q $(BINARY) gmon.out
+
+##### variants and libnuma check #####
+CFLAGS += $(CFBASE)
+LFLAGS += $(LFBASE)
+
+ifeq ($(MAKECMDGOALS),)
+  CFLAGS += $(CFDBG)
+  LFLAGS += $(LFDBG)
+endif
+
+ifeq ($(MAKECMDGOALS),cov)
+  CFLAGS  += $(CFCOV)
+  LFLAGS  += $(LFCOV)
+  SYSLIBS += -lgcov
+endif
+
+ifeq ($(MAKECMDGOALS),dbg)
+  CFLAGS += $(CFDBG)
+  LFLAGS += $(LFDBG)
+endif
+
+ifeq ($(MAKECMDGOALS),prof)
+  CFLAGS += $(CFPROF)
+  LFLAGS += $(LFPROF)
+endif
+
+ifeq ($(MAKECMDGOALS),rel)
+  CFLAGS += $(CFREL)
+  LFLAGS += $(LFREL)
+endif
+
+ifeq ($(MAKECMDGOALS),tsan)
+  CFLAGS += $(CFTSAN)
+  LFLAGS += $(LFTSAN)
+endif
+
+##### search paths #####
+vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
+
+##### implicit rules #####
+$(OBJDIR)/%.o : %.c
+	$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
+	$(CC) $(CFLAGS) -o $@ $<
+
+##### explicit rules #####
+$(BINARY) : $(OBJECTS)
+	$(LD) -o $(BINARY) $(LFLAGS) $(OBJECTS) $(USRLIBS) $(SYSLIBS)
+	chmod +x $(BINARY)
+
+##### phony #####
+.PHONY : clean cov dbg prof rel tsan
+
+clean : 
+	@rm -f $(BINDIR)/$(BINNAME) $(OBJDIR)/*.o $(OBJDIR)/*.d $(OBJDIR)/*.gcno
+
+cov  : $(BINARY)
+dbg  : $(BINARY)
+prof : $(BINARY)
+rel  : $(BINARY)
+tsan : $(BINARY)
+
+genprof :
+	@$(PROF) $(PFBASE)
+
+##### dependencies #####
+-include $(DEPENDS)
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/build/sdk_for_windows_7_and_gnumake/makefile b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/sdk_for_windows_7_and_gnumake/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c54d16635b09f7e52185bdc75730377b2e9b01ed
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/sdk_for_windows_7_and_gnumake/makefile
@@ -0,0 +1,106 @@
+##### paths #####
+BINDIR := ..\..\bin
+OBJDIR := ..\..\obj
+SRCDIR := ..\..\src
+
+##### misc #####
+QUIETLY := 1>nul 2>nul
+NULL    := 
+SPACE   := $(NULL) # TRD : necessary trailing space after the close bracket
+
+##### sources, objects and libraries #####
+BINNAME := test
+BINARY  := $(BINDIR)\$(BINNAME).exe
+SRCDIRS := .
+SOURCES := main.c misc.c \
+           test_lfds700_btree_addonly_unbalanced.c test_lfds700_btree_addonly_unbalanced_alignment.c test_lfds700_btree_addonly_unbalanced_random_adds_fail.c test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c \
+           test_lfds700_freelist.c test_lfds700_freelist_alignment.c test_lfds700_freelist_popping.c test_lfds700_freelist_popping_and_pushing.c test_lfds700_freelist_pushing.c test_lfds700_freelist_rapid_popping_and_pushing.c \
+           test_lfds700_hash_addonly.c test_lfds700_hash_addonly_alignment.c test_lfds700_hash_addonly_iterate.c test_lfds700_hash_addonly_random_adds_fail.c test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c test_lfds700_hash_addonly_random_adds_overwrite.c \
+           test_lfds700_list_addonly_ordered_singlylinked.c test_lfds700_list_addonly_ordered_singlylinked_alignment.c test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c \
+           test_lfds700_list_addonly_singlylinked_unordered.c test_lfds700_list_addonly_singlylinked_unordered_alignment.c test_lfds700_list_addonly_singlylinked_unordered_new_after.c test_lfds700_list_addonly_singlylinked_unordered_new_end.c test_lfds700_list_addonly_singlylinked_unordered_new_start.c \
+           test_lfds700_porting_abstraction_layer_atomic.c test_lfds700_porting_abstraction_layer_atomic_cas.c test_lfds700_porting_abstraction_layer_atomic_dcas.c test_lfds700_porting_abstraction_layer_atomic_exchange.c \
+           test_lfds700_queue.c test_lfds700_queue_alignment.c test_lfds700_queue_dequeuing.c test_lfds700_queue_enqueuing.c test_lfds700_queue_enqueuing_and_dequeuing.c test_lfds700_queue_enqueuing_and_dequeuing_with_free.c test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c test_lfds700_queue_rapid_enqueuing_and_dequeuing.c \
+           test_lfds700_queue_bounded_singleconsumer_singleproducer.c test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c \
+           test_lfds700_ringbuffer.c test_lfds700_ringbuffer_reading.c test_lfds700_ringbuffer_reading_and_writing.c test_lfds700_ringbuffer_writing.c \
+           test_lfds700_stack.c test_lfds700_stack_alignment.c test_lfds700_stack_popping.c test_lfds700_stack_popping_and_pushing.c test_lfds700_stack_pushing.c test_lfds700_stack_rapid_popping_and_pushing.c \
+           test_porting_abstraction_layer_get_logical_core_ids.c test_porting_abstraction_layer_thread_start.c test_porting_abstraction_layer_thread_wait.c \
+           util_cmdline.c util_memory_helpers.c util_thread_starter.c
+OBJECTS := $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
+RESFILE := $(patsubst %.rc,$(OBJDIR)/%.res,$(notdir $(RCFILE)))
+SYSLIBS := kernel32.lib
+EXTLIBS := 
+USRLIBS := ../../../liblfds700/bin/liblfds700.lib
+
+##### default paths fix up #####
+INCLUDE += ;../../../../liblfds700/inc/
+LIB     += ;../../../../liblfds700/bin/
+
+##### tools #####
+MAKE    := make
+MFLAGS  := 
+
+CC      := cl
+CFBASE  := /c /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN /DUNICODE /D_UNICODE /DUNICODE "/Fd$(BINDIR)\$(BINNAME).pdb" /nologo /W4 /WX
+CFREL   := /DNDEBUG /Ox
+CFDBG   := /D_DEBUG /Od /Gm /Zi
+
+LD      := link
+LFBASE  := /nologo /subsystem:console /nodefaultlib /nxcompat /wx
+LFREL   := /incremental:no
+LFDBG   := /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
+
+##### variants #####
+CFLAGS  := $(CFBASE) $(CFDBG) /MTd
+LFLAGS  := $(LFBASE) $(LFDBG)
+CLIB    := libcmtd.lib
+
+ifeq ($(MAKECMDGOALS),librel)
+  CFLAGS := $(CFBASE) $(CFREL) /MT
+  LFLAGS := $(LFBASE) $(LFREL)
+  CLIB   := libcmt.lib
+endif
+
+ifeq ($(MAKECMDGOALS),libdbg)
+  CFLAGS := $(CFBASE) $(CFDBG) /MTd
+  LFLAGS := $(LFBASE) $(LFDBG)
+  CLIB   := libcmtd.lib
+endif
+
+ifeq ($(MAKECMDGOALS),dllrel)
+  CFLAGS := $(CFBASE) $(CFREL) /MD
+  LFLAGS := $(LFBASE) $(LFREL)
+  CLIB   := msvcrt.lib
+endif
+
+ifeq ($(MAKECMDGOALS),dlldbg)
+  CFLAGS := $(CFBASE) $(CFDBG) /MDd
+  LFLAGS := $(LFBASE) $(LFDBG)
+  CLIB   := msvcrtd.lib
+endif
+
+##### search paths #####
+vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS))
+
+##### implicit rules #####
+$(OBJDIR)/%.obj : %.c
+	$(CC) $(CFLAGS) "/Fo$@" $<
+
+##### explicit rules #####
+$(BINARY) : $(OBJECTS) $(USRLIBS)
+	$(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(EXTLIBS) $(USRLIBS) $(OBJECTS) /out:$(BINARY)
+
+##### phony #####
+.PHONY : clean librel libdbg dllrel dlldbg
+
+clean : 
+	@erase /Q $(OBJDIR)\*.obj $(OBJDIR)\*.res $(BINDIR)\$(BINNAME).* $(QUIETLY)
+
+dlldbg : $(BINARY)
+dllrel : $(BINARY)
+
+libdbg : $(BINARY)
+librel : $(BINARY)
+
+##### notes #####
+# TRD : we fix up the default paths because cl and link require an extra argument per additional path, which is ugly as hell
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.sln b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.sln
new file mode 100644
index 0000000000000000000000000000000000000000..cc8727482fbf464386817e2585714f68cbc3eac3
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.sln
@@ -0,0 +1,67 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcxproj", "{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}"
+	ProjectSection(ProjectDependencies) = postProject
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0} = {1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds700", "..\..\..\liblfds700\build\visual_studio_professional_2012\liblfds700.vcxproj", "{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug DLL|Win32 = Debug DLL|Win32
+		Debug DLL|x64 = Debug DLL|x64
+		Debug LIB|Win32 = Debug LIB|Win32
+		Debug LIB|x64 = Debug LIB|x64
+		Release DLL|Win32 = Release DLL|Win32
+		Release DLL|x64 = Release DLL|x64
+		Release LIB|Win32 = Release LIB|Win32
+		Release LIB|x64 = Release LIB|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|Win32.Deploy.0 = Debug DLL|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|x64.Build.0 = Debug DLL|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug DLL|x64.Deploy.0 = Debug DLL|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|Win32.Deploy.0 = Debug LIB|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|x64.Build.0 = Debug LIB|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Debug LIB|x64.Deploy.0 = Debug LIB|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|Win32.Build.0 = Release DLL|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|Win32.Deploy.0 = Release DLL|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|x64.ActiveCfg = Release DLL|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|x64.Build.0 = Release DLL|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release DLL|x64.Deploy.0 = Release DLL|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|Win32.Build.0 = Release LIB|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|Win32.Deploy.0 = Release LIB|Win32
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|x64.ActiveCfg = Release LIB|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|x64.Build.0 = Release LIB|x64
+		{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}.Release LIB|x64.Deploy.0 = Release LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Build.0 = Debug DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Build.0 = Debug LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Build.0 = Release DLL|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.ActiveCfg = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Build.0 = Release DLL|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Build.0 = Release LIB|Win32
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.ActiveCfg = Release LIB|x64
+		{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Build.0 = Release LIB|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..3fbf8d78ee5d21ea4327f3438ba3d54d1e819933
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj
@@ -0,0 +1,554 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug DLL|Win32">
+      <Configuration>Debug DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug DLL|x64">
+      <Configuration>Debug DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug LIB|Win32">
+      <Configuration>Debug LIB</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug LIB|x64">
+      <Configuration>Debug LIB</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release DLL|Win32">
+      <Configuration>Release DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release DLL|x64">
+      <Configuration>Release DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release LIB|Win32">
+      <Configuration>Release LIB</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release LIB|x64">
+      <Configuration>Release LIB</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\internal.h" />
+    <ClInclude Include="..\..\src\test_porting_abstraction_layer_operating_system.h" />
+    <ClInclude Include="..\..\src\util_cmdline.h" />
+    <ClInclude Include="..\..\src\util_memory_helpers.h" />
+    <ClInclude Include="..\..\src\util_thread_starter.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\main.c" />
+    <ClCompile Include="..\..\src\misc.c" />
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced.c" />
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_alignment.c" />
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_fail.c" />
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c" />
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c" />
+    <ClCompile Include="..\..\src\test_lfds700_freelist.c" />
+    <ClCompile Include="..\..\src\test_lfds700_freelist_alignment.c" />
+    <ClCompile Include="..\..\src\test_lfds700_freelist_popping.c" />
+    <ClCompile Include="..\..\src\test_lfds700_freelist_popping_and_pushing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_freelist_pushing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_freelist_rapid_popping_and_pushing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly.c" />
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_alignment.c" />
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_iterate.c" />
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_fail.c" />
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c" />
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_overwrite.c" />
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked.c" />
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_alignment.c" />
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c" />
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c" />
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered.c" />
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_alignment.c" />
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_after.c" />
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_end.c" />
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_start.c" />
+    <ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic.c" />
+    <ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_cas.c" />
+    <ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_dcas.c" />
+    <ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_exchange.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_alignment.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_dequeuing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_enqueuing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_and_dequeuing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_and_dequeuing_with_free.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c" />
+    <ClCompile Include="..\..\src\test_lfds700_queue_rapid_enqueuing_and_dequeuing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_ringbuffer.c" />
+    <ClCompile Include="..\..\src\test_lfds700_ringbuffer_reading.c" />
+    <ClCompile Include="..\..\src\test_lfds700_ringbuffer_reading_and_writing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_ringbuffer_writing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_stack.c" />
+    <ClCompile Include="..\..\src\test_lfds700_stack_alignment.c" />
+    <ClCompile Include="..\..\src\test_lfds700_stack_popping.c" />
+    <ClCompile Include="..\..\src\test_lfds700_stack_popping_and_pushing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_stack_pushing.c" />
+    <ClCompile Include="..\..\src\test_lfds700_stack_rapid_popping_and_pushing.c" />
+    <ClCompile Include="..\..\src\test_porting_abstraction_layer_get_logical_core_ids.c" />
+    <ClCompile Include="..\..\src\test_porting_abstraction_layer_thread_start.c" />
+    <ClCompile Include="..\..\src\test_porting_abstraction_layer_thread_wait.c" />
+    <ClCompile Include="..\..\src\util_cmdline.c" />
+    <ClCompile Include="..\..\src\util_memory_helpers.c" />
+    <ClCompile Include="..\..\src\util_thread_starter.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\liblfds700\build\visual_studio_professional_2012\liblfds700.vcxproj">
+      <Project>{1e5d7d09-94f2-455d-ae5e-6c7f4c96bce0}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{A6BA3A68-A1D4-4C07-A0D5-7EAE73272A43}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(ProjectDir)..\..\bin\$(Platform) $(Configuration)\</OutDir>
+    <IntDir>$(ProjectDir)..\..\obj\$(Platform) $(Configuration)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <SDLCheck>true</SDLCheck>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <MinimalRebuild>false</MinimalRebuild>
+      <ExceptionHandling>false</ExceptionHandling>
+      <FunctionLevelLinking>false</FunctionLevelLinking>
+      <EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <ErrorReporting>None</ErrorReporting>
+      <AdditionalIncludeDirectories>..\liblfds700\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <BufferSecurityCheck>true</BufferSecurityCheck>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <LinkTimeCodeGeneration>
+      </LinkTimeCodeGeneration>
+      <LinkStatus>
+      </LinkStatus>
+      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <SDLCheck>true</SDLCheck>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <MinimalRebuild>false</MinimalRebuild>
+      <ExceptionHandling>false</ExceptionHandling>
+      <FunctionLevelLinking>false</FunctionLevelLinking>
+      <EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <ErrorReporting>None</ErrorReporting>
+      <AdditionalIncludeDirectories>..\liblfds700\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <BufferSecurityCheck>true</BufferSecurityCheck>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <LinkTimeCodeGeneration>
+      </LinkTimeCodeGeneration>
+      <LinkStatus>
+      </LinkStatus>
+      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug DLL|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <SDLCheck>true</SDLCheck>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <MinimalRebuild>false</MinimalRebuild>
+      <ExceptionHandling>false</ExceptionHandling>
+      <FunctionLevelLinking>false</FunctionLevelLinking>
+      <EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <ErrorReporting>None</ErrorReporting>
+      <BufferSecurityCheck>true</BufferSecurityCheck>
+      <OmitFramePointers>false</OmitFramePointers>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <LinkTimeCodeGeneration>
+      </LinkTimeCodeGeneration>
+      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug LIB|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <SDLCheck>true</SDLCheck>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <StringPooling>true</StringPooling>
+      <MinimalRebuild>false</MinimalRebuild>
+      <ExceptionHandling>false</ExceptionHandling>
+      <FunctionLevelLinking>false</FunctionLevelLinking>
+      <EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <BrowseInformation>true</BrowseInformation>
+      <CompileAs>CompileAsC</CompileAs>
+      <ErrorReporting>None</ErrorReporting>
+      <BufferSecurityCheck>true</BufferSecurityCheck>
+      <OmitFramePointers>false</OmitFramePointers>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <LinkTimeCodeGeneration>
+      </LinkTimeCodeGeneration>
+      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <ProjectReference>
+      <LinkLibraryDependencies>true</LinkLibraryDependencies>
+    </ProjectReference>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <ExceptionHandling>false</ExceptionHandling>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <CompileAs>CompileAsC</CompileAs>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <SDLCheck>
+      </SDLCheck>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+      <StringPooling>true</StringPooling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <ErrorReporting>None</ErrorReporting>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <SetChecksum>true</SetChecksum>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <ExceptionHandling>false</ExceptionHandling>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <CompileAs>CompileAsC</CompileAs>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <SDLCheck>
+      </SDLCheck>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+      <StringPooling>true</StringPooling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <ErrorReporting>None</ErrorReporting>
+    </ClCompile>
+    <Link>
+      <TargetMachine>MachineX86</TargetMachine>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <SetChecksum>true</SetChecksum>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <ExceptionHandling>false</ExceptionHandling>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <CompileAs>CompileAsC</CompileAs>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <SDLCheck>
+      </SDLCheck>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+      <StringPooling>true</StringPooling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <ErrorReporting>None</ErrorReporting>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <SetChecksum>true</SetChecksum>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LIB|x64'">
+    <ClCompile>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <WarningLevel>Level4</WarningLevel>
+      <DebugInformationFormat>None</DebugInformationFormat>
+      <CompileAsManaged>false</CompileAsManaged>
+      <CompileAsWinRT>false</CompileAsWinRT>
+      <ExceptionHandling>false</ExceptionHandling>
+      <CreateHotpatchableImage>false</CreateHotpatchableImage>
+      <CompileAs>CompileAsC</CompileAs>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <SDLCheck>
+      </SDLCheck>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <OmitFramePointers>true</OmitFramePointers>
+      <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
+      <StringPooling>true</StringPooling>
+      <BufferSecurityCheck>false</BufferSecurityCheck>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
+      <FloatingPointExceptions>false</FloatingPointExceptions>
+      <RuntimeTypeInfo>false</RuntimeTypeInfo>
+      <OpenMPSupport>false</OpenMPSupport>
+      <ErrorReporting>None</ErrorReporting>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
+      <SetChecksum>true</SetChecksum>
+      <LinkErrorReporting>NoErrorReport</LinkErrorReporting>
+      <AdditionalDependencies>kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj.filters b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..69da4b9836a87a84e42d2e73d58efcbfb9e9b028
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj.filters
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\src\internal.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\test_porting_abstraction_layer_operating_system.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\util_cmdline.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\util_memory_helpers.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\util_thread_starter.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\main.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\misc.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_alignment.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_fail.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_freelist.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_freelist_alignment.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_freelist_popping.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_freelist_popping_and_pushing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_freelist_pushing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_freelist_rapid_popping_and_pushing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_alignment.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_iterate.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_fail.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_hash_addonly_random_adds_overwrite.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_alignment.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_alignment.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_after.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_end.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_list_addonly_singlylinked_unordered_new_start.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_cas.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_dcas.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_porting_abstraction_layer_atomic_exchange.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_alignment.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_dequeuing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_enqueuing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_and_dequeuing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_and_dequeuing_with_free.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_queue_rapid_enqueuing_and_dequeuing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_ringbuffer.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_ringbuffer_reading.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_ringbuffer_reading_and_writing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_ringbuffer_writing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_stack.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_stack_alignment.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_stack_popping.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_stack_popping_and_pushing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_stack_pushing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_lfds700_stack_rapid_popping_and_pushing.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_porting_abstraction_layer_get_logical_core_ids.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_porting_abstraction_layer_thread_start.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_porting_abstraction_layer_thread_wait.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\util_cmdline.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\util_memory_helpers.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\util_thread_starter.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj.user b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj.user
new file mode 100644
index 0000000000000000000000000000000000000000..7cbb3216adb733fd25e1bd27d504ac8419b8c5bb
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/build/visual_studio_professional_2012/test.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/internal.h b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..14bf02c74c9278eed5b59bc669d0d3f25e0fe293
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/internal.h
@@ -0,0 +1,157 @@
+/***** includes *****/
+#define _GNU_SOURCE
+#include <assert.h>
+#include <ctype.h>
+#include <limits.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "../../liblfds700/inc/liblfds700.h"
+#include "test_porting_abstraction_layer_operating_system.h"
+
+/***** defines *****/
+#define and &&
+#define or  ||
+
+#define NO_FLAGS 0x0
+
+#define BITS_PER_BYTE 8
+
+#define TEST_DURATION_IN_SECONDS             5
+#define TIME_LOOP_COUNT                      10000
+#define REDUCED_TIME_LOOP_COUNT              1000
+#define NUMBER_OF_NANOSECONDS_IN_ONE_SECOND  1000000000LLU
+#define ONE_MEGABYTE_IN_BYTES                (1024 * 1024)
+#define DEFAULT_TEST_MEMORY_IN_MEGABYTES     512U
+#define TEST_PAL_DEFAULT_NUMA_NODE_ID        0
+#define LFDS700_TEST_VERSION_STRING          "7.0.0"
+#define LFDS700_TEST_VERSION_INTEGER         700
+
+#if( defined _KERNEL_MODE )
+  #define MODE_TYPE_STRING "kernel-mode"
+#endif
+
+#if( !defined _KERNEL_MODE )
+  #define MODE_TYPE_STRING "user-mode"
+#endif
+
+#if( defined NDEBUG && !defined COVERAGE && !defined TSAN )
+  #define BUILD_TYPE_STRING "release"
+#endif
+
+#if( !defined NDEBUG && !defined COVERAGE && !defined TSAN )
+  #define BUILD_TYPE_STRING "debug"
+#endif
+
+#if( !defined NDEBUG && defined COVERAGE && !defined TSAN )
+  #define BUILD_TYPE_STRING "coverage"
+#endif
+
+#if( !defined NDEBUG && !defined COVERAGE && defined TSAN )
+  #define BUILD_TYPE_STRING "threadsanitizer"
+#endif
+
+/***** enums *****/
+enum flag
+{
+  LOWERED,
+  RAISED
+};
+
+/***** structs *****/
+struct test_pal_logical_processor
+{
+  lfds700_pal_uint_t
+    logical_processor_number,
+    windows_logical_processor_group_number;
+
+  struct lfds700_list_asu_element
+    lasue;
+};
+
+/***** prototypes *****/
+int main( int argc, char **argv );
+
+void internal_display_test_name( char *format_string, ... );
+void internal_display_test_result( lfds700_pal_uint_t number_name_dvs_pairs, ... );
+void internal_display_data_structure_validity( enum lfds700_misc_validity dvs );
+void internal_show_version( void );
+void internal_logical_core_id_element_cleanup_callback( struct lfds700_list_asu_state *lasus, struct lfds700_list_asu_element *lasue );
+
+int test_pal_thread_start( test_pal_thread_state_t *thread_state, struct test_pal_logical_processor *lp, test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state), void *thread_user_state );
+void test_pal_thread_wait( test_pal_thread_state_t thread_state );
+void test_pal_get_logical_core_ids( struct lfds700_list_asu_state *lasus );
+
+void test_lfds700_pal_atomic( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_pal_atomic_cas( struct lfds700_list_asu_state *list_of_logical_processors );
+  void test_lfds700_pal_atomic_dwcas( struct lfds700_list_asu_state *list_of_logical_processors );
+  void test_lfds700_pal_atomic_exchange( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+
+void test_lfds700_hash_a( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_hash_a_alignment( void );
+  void test_lfds700_hash_a_fail_and_overwrite_on_existing_key( void );
+  void test_lfds700_hash_a_random_adds_fail_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_hash_a_random_adds_overwrite_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_hash_a_iterate( void );
+
+void test_lfds700_list_aos( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_list_aos_alignment( void );
+  void test_lfds700_list_aos_new_ordered( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_list_aos_new_ordered_with_cursor( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+
+void test_lfds700_list_asu( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_list_asu_alignment( void );
+  void test_lfds700_list_asu_new_start( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_list_asu_new_end( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_list_asu_new_after( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+
+void test_lfds700_btree_au( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_btree_au_alignment( void );
+  void test_lfds700_btree_au_fail_and_overwrite_on_existing_key( void );
+  void test_lfds700_btree_au_random_adds_fail_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_btree_au_random_adds_overwrite_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+
+void test_lfds700_freelist( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_freelist_alignment( void );
+  void test_lfds700_freelist_popping( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_freelist_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_freelist_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_freelist_rapid_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors );
+  void test_lfds700_freelist_pushing_array( void );
+
+void test_lfds700_queue( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_queue_alignment( void );
+  void test_lfds700_queue_enqueuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_queue_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_queue_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors );
+  void test_lfds700_queue_rapid_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_queue_enqueuing_and_dequeuing_with_free( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free( struct lfds700_list_asu_state *list_of_logical_processors );
+
+void test_lfds700_queue_bss( struct lfds700_list_asu_state *list_of_logical_processors );
+  void test_lfds700_queue_bss_enqueuing( void );
+  void test_lfds700_queue_bss_dequeuing( void );
+  void test_lfds700_queue_bss_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors );
+
+void test_lfds700_ringbuffer( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_ringbuffer_reading( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_ringbuffer_reading_and_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_ringbuffer_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+
+void test_lfds700_stack( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_stack_alignment( void );
+  void test_lfds700_stack_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_stack_popping( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_stack_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes );
+  void test_lfds700_stack_rapid_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors );
+  void test_lfds700_stack_pushing_array( void );
+
+/***** late includes *****/
+#include "util_cmdline.h"
+#include "util_memory_helpers.h"
+#include "util_thread_starter.h"
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/main.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..fa6afc8747f5d56f70bcfd3373a3081c448b5ae3
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/main.c
@@ -0,0 +1,135 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+int main( int argc, char **argv )
+{
+  enum flag
+    run_flag = LOWERED,
+    show_error_flag = LOWERED,
+    show_help_flag = LOWERED,
+    show_version_flag = LOWERED;
+
+  int
+    rv;
+
+  lfds700_pal_uint_t
+    loop,
+    iterations = 1,
+    memory_in_megabytes = DEFAULT_TEST_MEMORY_IN_MEGABYTES;
+
+  struct lfds700_list_asu_state
+    list_of_logical_processors;
+
+  struct util_cmdline_state
+    cs;
+
+  union util_cmdline_arg_data
+    *arg_data;
+
+  assert( argc >= 1 );
+  assert( argv != NULL );
+
+  lfds700_misc_library_init_valid_on_current_logical_core();
+
+  util_cmdline_init( &cs );
+
+  util_cmdline_add_arg( &cs, 'h', LIBCOMMON_CMDLINE_ARG_TYPE_FLAG );
+  util_cmdline_add_arg( &cs, 'i', LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER );
+  util_cmdline_add_arg( &cs, 'm', LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER );
+  util_cmdline_add_arg( &cs, 'r', LIBCOMMON_CMDLINE_ARG_TYPE_FLAG );
+  util_cmdline_add_arg( &cs, 'v', LIBCOMMON_CMDLINE_ARG_TYPE_FLAG );
+
+  rv = util_cmdline_process_args( &cs, argc, argv );
+
+  if( rv == 0 )
+    show_error_flag = RAISED;
+
+  if( rv == 1 )
+  {
+    util_cmdline_get_arg_data( &cs, 'h', &arg_data );
+    if( arg_data != NULL )
+      show_help_flag = RAISED;
+
+    util_cmdline_get_arg_data( &cs, 'i', &arg_data );
+    if( arg_data != NULL )
+      iterations = (lfds700_pal_uint_t) arg_data->integer.integer;
+
+    util_cmdline_get_arg_data( &cs, 'm', &arg_data );
+    if( arg_data != NULL )
+      memory_in_megabytes = (lfds700_pal_uint_t) arg_data->integer.integer;
+
+    util_cmdline_get_arg_data( &cs, 'r', &arg_data );
+    if( arg_data != NULL )
+      run_flag = RAISED;
+
+    util_cmdline_get_arg_data( &cs, 'v', &arg_data );
+    if( arg_data != NULL )
+      show_version_flag = RAISED;
+  }
+
+  util_cmdline_cleanup( &cs );
+
+  if( argc == 1 or (run_flag == LOWERED and show_version_flag == LOWERED) )
+    show_help_flag = RAISED;
+
+  if( show_error_flag == RAISED )
+  {
+    printf( "\nInvalid arguments.  Sorry - it's a simple parser, so no clues.\n"
+            "-h or run with no args to see the help text.\n" );
+
+    return( EXIT_SUCCESS );
+  }
+
+  if( show_help_flag == RAISED )
+  {
+    printf( "test -h -i [n] -m [n] -r -v\n"
+            "  -h     : help\n"
+            "  -i [n] : number of iterations     (default : 1)\n"
+            "  -m [n] : memory for tests, in mb  (default : %u)\n"
+            "  -r     : run (causes test to run; present so no args gives help)\n"
+            "  -v     : version\n", DEFAULT_TEST_MEMORY_IN_MEGABYTES );
+
+    return( EXIT_SUCCESS );
+  }
+
+  if( show_version_flag == RAISED )
+  {
+    internal_show_version();
+    return( EXIT_SUCCESS );
+  }
+
+  if( run_flag == RAISED )
+  {
+    test_pal_get_logical_core_ids( &list_of_logical_processors );
+
+    for( loop = 0 ; loop < (lfds700_pal_uint_t) iterations ; loop++ )
+    {
+      printf( "\n"
+              "Test Iteration %02llu\n"
+              "=================\n", (int long long unsigned) (loop+1) );
+
+      test_lfds700_pal_atomic( &list_of_logical_processors, memory_in_megabytes );
+      test_lfds700_btree_au( &list_of_logical_processors, memory_in_megabytes );
+      test_lfds700_freelist( &list_of_logical_processors, memory_in_megabytes );
+      test_lfds700_hash_a( &list_of_logical_processors, memory_in_megabytes );
+      test_lfds700_list_aos( &list_of_logical_processors, memory_in_megabytes );
+      test_lfds700_list_asu( &list_of_logical_processors, memory_in_megabytes );
+      test_lfds700_queue( &list_of_logical_processors, memory_in_megabytes );
+      test_lfds700_queue_bss( &list_of_logical_processors );
+      test_lfds700_ringbuffer( &list_of_logical_processors, memory_in_megabytes );
+      test_lfds700_stack( &list_of_logical_processors, memory_in_megabytes );
+    }
+
+    lfds700_list_asu_cleanup( &list_of_logical_processors, internal_logical_core_id_element_cleanup_callback );
+  }
+
+  lfds700_misc_library_cleanup();
+
+  return( EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/misc.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/misc.c
new file mode 100644
index 0000000000000000000000000000000000000000..4fa794f68dd02a08767f42584595305e136b38f3
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/misc.c
@@ -0,0 +1,191 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void internal_display_test_name( char *format_string, ... )
+{
+  va_list
+    va;
+
+  assert( format_string != NULL );
+
+  va_start( va, format_string );
+
+  vprintf( format_string, va );
+
+  printf( "..." );
+
+  va_end( va );
+
+  fflush( stdout );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void internal_display_test_result( lfds700_pal_uint_t number_name_dvs_pairs, ... )
+{
+  char
+    *name;
+
+  enum flag
+    passed_flag = RAISED;
+
+  enum lfds700_misc_validity
+    dvs;
+
+  lfds700_pal_uint_t
+    loop;
+
+  va_list
+    va;
+
+  // TRD : number_name_dvs_pairs can be any value in its range
+
+  va_start( va, number_name_dvs_pairs );
+
+  for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ )
+  {
+    name = va_arg( va, char * );
+    dvs = va_arg( va, enum lfds700_misc_validity );
+
+    if( dvs != LFDS700_MISC_VALIDITY_VALID )
+    {
+      passed_flag = LOWERED;
+      break;
+    }
+  }
+
+  va_end( va );
+
+  if( passed_flag == RAISED )
+    puts( "passed" );
+
+  if( passed_flag == LOWERED )
+  {
+    printf( "failed (" );
+
+    va_start( va, number_name_dvs_pairs );
+
+    for( loop = 0 ; loop < number_name_dvs_pairs ; loop++ )
+    {
+      name = va_arg( va, char * );
+      dvs = va_arg( va, enum lfds700_misc_validity );
+
+      printf( "%s ", name );
+      internal_display_data_structure_validity( dvs );
+
+      if( loop+1 < number_name_dvs_pairs )
+        printf( ", " );
+    }
+
+    va_end( va );
+
+    printf( ")\n" );
+
+    /* TRD : quick hack
+             the whole test programme needs rewriting
+             and for now I just want to make it so we
+             exit with failure upon any test failing
+    */
+
+    exit( EXIT_FAILURE );
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void internal_display_data_structure_validity( enum lfds700_misc_validity dvs )
+{
+  char
+    *string = NULL;
+
+  switch( dvs )
+  {
+    case LFDS700_MISC_VALIDITY_VALID:
+      string = "valid";
+    break;
+
+    case LFDS700_MISC_VALIDITY_INVALID_LOOP:
+      string = "invalid - loop detected";
+    break;
+
+    case LFDS700_MISC_VALIDITY_INVALID_ORDER:
+      string = "invalid - invalid order detected";
+    break;
+
+    case LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS:
+      string = "invalid - missing elements";
+    break;
+
+    case LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS:
+      string = "invalid - additional elements";
+    break;
+
+    case LFDS700_MISC_VALIDITY_INVALID_TEST_DATA:
+      string = "invalid - invalid test data";
+    break;
+  }
+
+  printf( "%s", string );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void internal_show_version()
+{
+  char const
+    *version_and_build_string;
+
+  printf( "test %s (%s, %s) (" __DATE__ " " __TIME__ ")\n", LFDS700_TEST_VERSION_STRING, BUILD_TYPE_STRING, MODE_TYPE_STRING );
+
+  lfds700_misc_query( LFDS700_MISC_QUERY_GET_BUILD_AND_VERSION_STRING, NULL, (void **) &version_and_build_string );
+
+  printf( "%s\n", version_and_build_string );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+void internal_logical_core_id_element_cleanup_callback( struct lfds700_list_asu_state *lasus, struct lfds700_list_asu_element *lasue )
+{
+  struct test_pal_logical_processor
+    *lp;
+
+  assert( lasus != NULL );
+  assert( lasue != NULL );
+
+  lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+
+  util_aligned_free( lp );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced.c
new file mode 100644
index 0000000000000000000000000000000000000000..55b94ca5bbf50caa037519092228a1af66c180b4
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced.c
@@ -0,0 +1,32 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_btree_au( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_CAS and LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE )
+  {
+    printf( "\n"
+            "Binary Tree (add-only, unbalanced) Tests\n"
+            "========================================\n" );
+
+    test_lfds700_btree_au_alignment();
+    test_lfds700_btree_au_fail_and_overwrite_on_existing_key();
+    test_lfds700_btree_au_random_adds_fail_on_existing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_btree_au_random_adds_overwrite_on_existing( list_of_logical_processors, memory_in_megabytes );
+  }
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_alignment.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_alignment.c
new file mode 100644
index 0000000000000000000000000000000000000000..ecdaf29adb6a4de87c47ad0497a19d907c0da48a
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_alignment.c
@@ -0,0 +1,64 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_btree_au_alignment()
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  /* TRD : these are compile time checks
+           but we do them here because this is a test programme
+           and it should indicate issues to users when it is *run*,
+           not when it is compiled, because a compile error normally
+           indicates a problem with the code itself and so is misleading
+  */
+
+  internal_display_test_name( "Alignment" );
+
+
+
+  // TRD : struct lfds700_btree_au_element
+  if( offsetof(struct lfds700_btree_au_element,up) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_btree_au_element,left) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_btree_au_element,right) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_btree_au_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_btree_au_element,value) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_btree_au_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : struct lfds700_btree_au_state
+  if( offsetof(struct lfds700_btree_au_state,root) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_btree_au_state,key_compare_function) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "btree_au", dvs );
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_fail.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_fail.c
new file mode 100644
index 0000000000000000000000000000000000000000..ae043a06691a7889f8c740df3d8ee6ab5bee3a5d
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_fail.c
@@ -0,0 +1,319 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_btree_au_element
+    baue;
+
+  lfds700_pal_uint_t
+    key;
+};
+
+struct test_state
+{
+  lfds700_pal_uint_t
+    insert_fail_count,
+    number_elements;
+
+  struct lfds700_btree_au_state
+    *baus;
+
+  struct test_element
+    *element_array;
+};
+
+/***** private prototypes *****/
+static int key_compare_function( void const *new_value, void const *value_in_tree );
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_btree_au_random_adds_fail_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    actual_sum_insert_failure_count,
+    expected_sum_insert_failure_count,
+    index = 0,
+    *key_count_array,
+    loop,
+    number_elements,
+    number_logical_processors,
+    random_value,
+    subloop;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_btree_au_element
+    *baue = NULL;
+
+  struct lfds700_btree_au_state
+    baus;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  void
+    *key;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a single btree_au
+           we generate 10k elements per thread (one per logical processor) in an array
+           we set a random number in each element, which is the key
+           random numbers are generated are from 0 to 5000, so we must have some duplicates
+           (we don't use value, so we always pass in a NULL for that when we insert)
+
+           each thread loops, adds those elements into the btree, and counts the total number of insert fails
+           (we don't count on a per value basis because of the performance hit - we'll be TLBing all the time)
+           this test has the btree_au set to fail on add, so duplicates should be eliminated
+
+           we then merge the per-thread arrays
+
+           we should find in the tree one of every value, and the sum of the counts of each value (beyond the
+           first value, which was inserted) in the merged arrays should equal the sum of the insert fails from
+           each thread
+
+           we check the count of unique values in the merged array and use that when calling the btree_au validation function
+
+           we in-order walk and check that what we have in the tree matches what we have in the merged array
+           and then check the fail counts
+  */
+
+  internal_display_test_name( "Random adds and walking (fail on existing key)" );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_btree_au_init_valid_on_current_logical_core( &baus, key_compare_function, LFDS700_BTREE_AU_EXISTING_KEY_FAIL, NULL );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->baus = &baus;
+    (ts+loop)->element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+    (ts+loop)->number_elements = number_elements;
+    (ts+loop)->insert_fail_count = 0;
+
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+    {
+      random_value = LFDS700_MISC_PRNG_GENERATE( &ps );
+      ((ts+loop)->element_array+subloop)->key = (lfds700_pal_uint_t) floor( (number_elements/2) * ((double) random_value / (double) LFDS700_MISC_PRNG_MAX) );
+    }
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_adding, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  /* TRD : now for validation
+           make an array equal to number_elements, set all to 0
+           iterate over every per-thread array, counting the number of each value into this array
+           so we can know how many elements ought to have failed to be inserted
+           as well as being able to work out the actual number of elements which should be present in the btree, for the btree validation call
+  */
+
+  key_count_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements );
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    *(key_count_array+loop) = 0;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+      ( *(key_count_array+( (ts+loop)->element_array+subloop)->key) )++;
+
+  // TRD : first, btree validation function
+  vi.min_elements = number_elements;
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    if( *(key_count_array+loop) == 0 )
+      vi.min_elements--;
+
+  vi.max_elements = vi.min_elements;
+
+  lfds700_btree_au_query( &baus, LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
+
+  /* TRD : now check the sum of per-thread insert failures
+           is what it should be, which is the sum of key_count_array,
+           but with every count minus one (for the single succesful insert)
+           and where elements of 0 are ignored (i.e. do not have -1 applied)
+  */
+
+  expected_sum_insert_failure_count = 0;
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    if( *(key_count_array+loop) != 0 )
+      expected_sum_insert_failure_count += *(key_count_array+loop) - 1;
+
+  actual_sum_insert_failure_count = 0;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    actual_sum_insert_failure_count += (ts+loop)->insert_fail_count;
+
+  if( expected_sum_insert_failure_count != actual_sum_insert_failure_count )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  /* TRD : now compared the combined array and an in-order walk of the tree
+           ignoring array elements with the value 0, we should find an exact match
+  */
+
+  if( dvs == LFDS700_MISC_VALIDITY_VALID )
+  {
+    // TRD : in-order walk over btree_au and check key_count_array matches
+    while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position(&baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE) )
+    {
+      key = LFDS700_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
+
+      while( *(key_count_array+index) == 0 )
+        index++;
+
+      if( index++ != (lfds700_pal_uint_t) key )
+        dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+    }
+  }
+
+  // TRD : cleanup
+  free( key_count_array );
+
+  lfds700_btree_au_cleanup( &baus, NULL );
+
+  // TRD : cleanup
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    util_aligned_free( (ts+loop)->element_array );
+
+  free( ts );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "btree_au", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static int key_compare_function( void const *new_key, void const *key_in_tree )
+{
+  int
+    cr = 0;
+
+  // TRD : key_new can be any value in its range
+  // TRD : key_in_tree can be any value in its range
+
+  if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) key_in_tree )
+    cr = -1;
+
+  if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) key_in_tree )
+    cr = 1;
+
+  return( cr );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state )
+{
+  enum lfds700_btree_au_insert_result
+    alr;
+
+  lfds700_pal_uint_t
+    index = 0;
+
+  struct test_state
+    *ts;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( index < ts->number_elements )
+  {
+    LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( (ts->element_array+index)->baue, (ts->element_array+index)->key );
+    LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( (ts->element_array+index)->baue, 0 );
+    alr = lfds700_btree_au_insert( ts->baus, &(ts->element_array+index)->baue, NULL, &ps );
+
+    if( alr == LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY )
+      ts->insert_fail_count++;
+
+    index++;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c638c86005722e04a059ca2383959c9f3f6119e
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_fail_and_overwrite.c
@@ -0,0 +1,140 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** private prototypes *****/
+static int key_compare_function( void const *new_value, void const *value_in_tree );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_btree_au_fail_and_overwrite_on_existing_key()
+{
+  enum lfds700_btree_au_insert_result
+    alr;
+
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  struct lfds700_btree_au_element
+    baue_one,
+    baue_two,
+    *existing_baue;
+
+  struct lfds700_btree_au_state
+    baus;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  void
+    *value;
+
+  /* TRD : the random_adds tests with fail and overwrite don't (can't, not in a performant manner)
+           test that the fail and/or overwrite of user data has *actually* happened - they use the
+           return value from the link function call, rather than empirically observing the final
+           state of the tree
+
+           as such, we now have a couple of single threaded tests where we check that the user data
+           value really is being modified (or not modified, as the case may be)
+  */
+
+  internal_display_test_name( "Fail and overwrite on existing key" );
+
+  lfds700_misc_prng_init( &ps );
+
+  /* TRD : so, we make a tree which is fail on existing
+           add one element, with a known user data
+           we then try to add the same key again, with a different user data
+           the call should fail, and then we get the element by its key
+           and check its user data is unchanged
+           (and confirm the failed link returned the correct existing_baue)
+           that's the first test done
+  */
+
+  lfds700_btree_au_init_valid_on_current_logical_core( &baus, key_compare_function, LFDS700_BTREE_AU_EXISTING_KEY_FAIL, NULL );
+
+  LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( baue_one, 0 );
+  LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( baue_one, 1 );
+  alr = lfds700_btree_au_insert( &baus, &baue_one, NULL, &ps );
+
+  if( alr != LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( baue_two, 0 );
+  LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( baue_two, 2 );
+  alr = lfds700_btree_au_insert( &baus, &baue_two, &existing_baue, &ps );
+
+  if( alr != LFDS700_BTREE_AU_INSERT_RESULT_FAILURE_EXISTING_KEY )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( existing_baue != &baue_one )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  value = LFDS700_BTREE_AU_GET_VALUE_FROM_ELEMENT( *existing_baue );
+
+  if( (void *) (lfds700_pal_uint_t) value != (void *) (lfds700_pal_uint_t) 1 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  lfds700_btree_au_cleanup( &baus, NULL );
+
+  /* TRD : second test, make a tree which is overwrite on existing
+           add one element, with a known user data
+           we then try to add the same key again, with a different user data
+           the call should succeed, and then we get the element by its key
+           and check its user data is changed
+           (and confirm the failed link returned the correct existing_baue)
+           that's the secondtest done
+  */
+
+  lfds700_btree_au_init_valid_on_current_logical_core( &baus, key_compare_function, LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE, NULL );
+
+  LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( baue_one, 0 );
+  LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( baue_one, 1 );
+  alr = lfds700_btree_au_insert( &baus, &baue_one, NULL, &ps );
+
+  if( alr != LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( baue_two, 0 );
+  LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( baue_two, 2 );
+  alr = lfds700_btree_au_insert( &baus, &baue_two, NULL, &ps );
+
+  if( alr != LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  lfds700_btree_au_cleanup( &baus, NULL );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "btree_au", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static int key_compare_function( void const *new_key, void const *key_in_tree )
+{
+  int
+    cr = 0;
+
+  // TRD : key_new can be any value in its range
+  // TRD : key_in_tree can be any value in its range
+
+  if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) key_in_tree )
+    cr = -1;
+
+  if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) key_in_tree )
+    cr = 1;
+
+  return( cr );
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c
new file mode 100644
index 0000000000000000000000000000000000000000..c9b162128b3e0316e05c0065e8fc22405df39662
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_btree_addonly_unbalanced_random_adds_overwrite.c
@@ -0,0 +1,322 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_btree_au_element
+    baue;
+
+  lfds700_pal_uint_t
+    key;
+};
+
+struct test_state
+{
+  lfds700_pal_uint_t
+    insert_existing_count,
+    number_elements;
+
+  struct lfds700_btree_au_state
+    *baus;
+
+  struct test_element
+    *element_array;
+};
+
+/***** private prototypes *****/
+static int key_compare_function( void const *new_value, void const *value_in_tree );
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_btree_au_random_adds_overwrite_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    actual_sum_insert_existing_count,
+    expected_sum_insert_existing_count,
+    index = 0,
+    *key_count_array,
+    loop,
+    number_elements,
+    number_logical_processors,
+    random_value,
+    subloop;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_btree_au_element
+    *baue = NULL;
+
+  struct lfds700_btree_au_state
+    baus;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  void
+    *key;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a single btree_au
+           we generate 10k elements per thread (one per logical processor) in an array
+           we set a random number in each element, which is the key
+           random numbers are generated are from 0 to 5000, so we must have some duplicates
+           (we don't use value, so we always pass in a NULL for that when we insert)
+
+           each thread loops, adds those elements into the btree, and counts the total number of insert fails
+           (we don't count on a per value basis because of the performance hit - we'll be TLBing all the time)
+           this test has the btree_au set to overwrite on add, so duplicates should be eliminated
+
+           we then merge the per-thread arrays
+
+           we should find in the tree one of every value, and the sum of the counts of each value (beyond the
+           first value, which was inserted) in the merged arrays should equal the sum of the existing_baues returned
+           from each thread when they inserted and found an existing element
+
+           we check the count of unique values in the merged array and use that when calling the btree_au validation function
+
+           we in-order walk and check that what we have in the tree matches what we have in the merged array
+           and then check the fail counts
+  */
+
+  internal_display_test_name( "Random adds and walking (overwrite on existing key)" );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_btree_au_init_valid_on_current_logical_core( &baus, key_compare_function, LFDS700_BTREE_AU_EXISTING_KEY_OVERWRITE, NULL );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->baus = &baus;
+    (ts+loop)->element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+    (ts+loop)->number_elements = number_elements;
+    (ts+loop)->insert_existing_count = 0;
+
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+    {
+      random_value = LFDS700_MISC_PRNG_GENERATE( &ps );
+      ((ts+loop)->element_array+subloop)->key = (lfds700_pal_uint_t) floor( (number_elements/2) * ((double) random_value / (double) LFDS700_MISC_PRNG_MAX) );
+    }
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_adding, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  /* TRD : now for validation
+           make an array equal to number_elements, set all to 0
+           iterate over every per-thread array, counting the number of each value into this array
+           so we can know how many elements ought to have failed to be inserted
+           as well as being able to work out the actual number of elements which should be present in the btree, for the btree validation call
+  */
+
+  key_count_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements );
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    *(key_count_array+loop) = 0;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+      ( *(key_count_array+( (ts+loop)->element_array+subloop)->key) )++;
+
+  // TRD : first, btree validation function
+  vi.min_elements = number_elements;
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    if( *(key_count_array+loop) == 0 )
+      vi.min_elements--;
+
+  vi.max_elements = vi.min_elements;
+
+  lfds700_btree_au_query( &baus, LFDS700_BTREE_AU_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
+
+  /* TRD : now check the sum of per-thread insert failures
+           is what it should be, which is the sum of key_count_array,
+           but with every count minus one (for the single succesful insert)
+           and where elements of 0 are ignored (i.e. do not have -1 applied)
+  */
+
+  expected_sum_insert_existing_count = 0;
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    if( *(key_count_array+loop) != 0 )
+      expected_sum_insert_existing_count += *(key_count_array+loop) - 1;
+
+  actual_sum_insert_existing_count = 0;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    actual_sum_insert_existing_count += (ts+loop)->insert_existing_count;
+
+  if( expected_sum_insert_existing_count != actual_sum_insert_existing_count )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  /* TRD : now compared the combined array and an in-order walk of the tree
+           ignoring array elements with the value 0, we should find an exact match
+  */
+
+  if( dvs == LFDS700_MISC_VALIDITY_VALID )
+  {
+    // TRD : in-order walk over btree_au and check key_count_array matches
+    while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position(&baus, &baue, LFDS700_BTREE_AU_ABSOLUTE_POSITION_SMALLEST_IN_TREE, LFDS700_BTREE_AU_RELATIVE_POSITION_NEXT_LARGER_ELEMENT_IN_ENTIRE_TREE) )
+    {
+      key = LFDS700_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
+
+      while( *(key_count_array+index) == 0 )
+        index++;
+
+      if( index++ != (lfds700_pal_uint_t) key )
+        dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+    }
+  }
+
+  // TRD : cleanup
+  free( key_count_array );
+
+  lfds700_btree_au_cleanup( &baus, NULL );
+
+  // TRD : cleanup
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    util_aligned_free( (ts+loop)->element_array );
+
+  free( ts );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "btree_au", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static int key_compare_function( void const *new_key, void const *key_in_tree )
+{
+  int
+    cr = 0;
+
+  // TRD : key_new can be any value in its range
+  // TRD : key_in_tree can be any value in its range
+
+  if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) key_in_tree )
+    cr = -1;
+
+  if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) key_in_tree )
+    cr = 1;
+
+  return( cr );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state )
+{
+  enum lfds700_btree_au_insert_result
+    alr;
+
+  lfds700_pal_uint_t
+    index = 0;
+
+  struct test_state
+    *ts;
+
+  struct lfds700_btree_au_element
+    *existing_baue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( index < ts->number_elements )
+  {
+    LFDS700_BTREE_AU_SET_KEY_IN_ELEMENT( (ts->element_array+index)->baue, (ts->element_array+index)->key );
+    LFDS700_BTREE_AU_SET_VALUE_IN_ELEMENT( (ts->element_array+index)->baue, 0 );
+    alr = lfds700_btree_au_insert( ts->baus, &(ts->element_array+index)->baue, &existing_baue, &ps );
+
+    if( alr == LFDS700_BTREE_AU_INSERT_RESULT_SUCCESS_OVERWRITE )
+      ts->insert_existing_count++;
+
+    index++;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist.c
new file mode 100644
index 0000000000000000000000000000000000000000..1968ae7167c04d30bf4bb61e23f4b6efaae50503
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist.c
@@ -0,0 +1,33 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_freelist( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
+  {
+    printf( "\n"
+            "Freelist Tests\n"
+            "==============\n" );
+
+    test_lfds700_freelist_alignment();
+    test_lfds700_freelist_popping( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_freelist_pushing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_freelist_popping_and_pushing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_freelist_rapid_popping_and_pushing( list_of_logical_processors );
+  }
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_alignment.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_alignment.c
new file mode 100644
index 0000000000000000000000000000000000000000..885ecbf8c4ab6bfb9c7ee16e95cc1845f5624d95
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_alignment.c
@@ -0,0 +1,43 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_freelist_alignment()
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  /* TRD : these are compile time checks
+           but we do them here because this is a test programme
+           and it should indicate issues to users when it is *run*,
+           not when it is compiled, because a compile error normally
+           indicates a problem with the code itself and so is misleading
+  */
+
+  internal_display_test_name( "Alignment" );
+
+
+
+  // TRD : struct lfds700_freelist_state
+  if( offsetof(struct lfds700_freelist_state,top) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_freelist_state,user_state) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_popping.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_popping.c
new file mode 100644
index 0000000000000000000000000000000000000000..6dcbd0847abbca5839e2b0cb8055a457d1ff546a
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_popping.c
@@ -0,0 +1,205 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  struct lfds700_freelist_state
+    *fs;
+};
+
+struct test_element
+{
+  struct lfds700_freelist_element
+    fe;
+
+  enum flag
+    popped_flag;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_freelist_popping( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_freelist_state
+    fs;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi = { 0, 0 };
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a freelist with 1,000,000 elements
+
+           the creation function runs in a single thread and creates
+           and pushes those elements onto the freelist
+
+           each element contains a void pointer to the container test element
+
+           we then run one thread per CPU
+           where each thread loops, popping as quickly as possible
+           each test element has a flag which indicates it has been popped
+
+           the threads run till the source freelist is empty
+
+           we then check the test elements
+           every element should have been popped
+
+           then tidy up
+
+           we have no extra code for CAS/GC as we're only popping
+  */
+
+  internal_display_test_name( "Popping" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element);
+
+  te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+  {
+    (te_array+loop)->popped_flag = LOWERED;
+    LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
+    lfds700_freelist_push( &fs, &(te_array+loop)->fe, &ps );
+  }
+
+  ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    (ts+loop)->fs = &fs;
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  lfds700_freelist_query( &fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  // TRD : now we check each element has popped_flag set to RAISED
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    if( (te_array+loop)->popped_flag == LOWERED )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  // TRD : cleanup
+  lfds700_freelist_cleanup( &fs, NULL );
+  util_aligned_free( ts );
+  util_aligned_free( te_array );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state )
+{
+  struct lfds700_freelist_element
+    *fe;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_element
+    *te;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( lfds700_freelist_pop(ts->fs, &fe, &ps) )
+  {
+    te = LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
+    te->popped_flag = RAISED;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_popping_and_pushing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_popping_and_pushing.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c411151d3795967962c62f4a0f82031d05685bb
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_popping_and_pushing.c
@@ -0,0 +1,319 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element;
+
+struct test_state
+{
+  struct lfds700_freelist_state
+    fs_thread_local,
+    *fs;
+
+  lfds700_pal_uint_t
+    number_elements;
+
+  struct test_element
+    *fs_thread_local_te_array;
+};
+
+struct test_element
+{
+  struct lfds700_freelist_element
+    fe,
+    thread_local_fe;
+
+  lfds700_pal_uint_t
+    datum;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state );
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_freelist_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors,
+    subloop;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_freelist_state
+    fs;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we have two threads per CPU
+           the threads loop for ten seconds
+           the first thread pushes 10000 elements then pops 10000 elements
+           the second thread pops 10000 elements then pushes 10000 elements
+           all pushes and pops go onto the single main freelist
+           with a per-thread local freelist to store the pops
+
+           after time is up, all threads push what they have remaining onto
+           the main freelist
+
+           we then validate the main freelist
+  */
+
+  internal_display_test_name( "Popping and pushing (%d seconds)", TEST_DURATION_IN_SECONDS );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors * 2 );
+
+  lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
+
+  // TRD : we allocate half the total elements here, and half again later, which is why *2 above, but not here
+  te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  // TRD : initial elements in the main freelist so the popping threads can start immediately
+  for( loop = 0 ; loop < number_elements * number_logical_processors ; loop++ )
+  {
+    (te_array+loop)->datum = loop;
+    LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
+    lfds700_freelist_push( &fs, &(te_array+loop)->fe, &ps );
+  }
+
+  ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors * 2, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    // TRD : first set of threads (poppers)
+    (ts+loop)->fs = &fs;
+    (ts+loop)->number_elements = number_elements;
+    lfds700_freelist_init_valid_on_current_logical_core( &(ts+loop)->fs_thread_local, NULL );
+
+    // TRD : second set of threads (pushers - who need elements in their per-thread freelists)
+    (ts+loop+number_logical_processors)->fs = &fs;
+    (ts+loop+number_logical_processors)->number_elements = number_elements;
+    lfds700_freelist_init_valid_on_current_logical_core( &(ts+loop+number_logical_processors)->fs_thread_local, NULL );
+
+    // TRD : fill the pushing thread freelists
+    (ts+loop+number_logical_processors)->fs_thread_local_te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+    {
+      ((ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop)->datum = loop;
+      LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( ((ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop)->thread_local_fe, (ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop );
+      lfds700_freelist_push( &(ts+loop+number_logical_processors)->fs_thread_local, &((ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop)->thread_local_fe, &ps );
+    }
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors * 2 );
+
+  util_thread_starter_new( &tts, number_logical_processors * 2 );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping_and_pushing_start_popping, ts+loop );
+    util_thread_starter_start( tts, &thread_handles[loop+number_logical_processors], loop+number_logical_processors, lp, thread_popping_and_pushing_start_pushing, ts+loop+number_logical_processors );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors * 2 ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = number_elements * number_logical_processors * 2;
+
+  lfds700_freelist_query( &fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
+
+  lfds700_freelist_cleanup( &fs, NULL );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    lfds700_freelist_cleanup( &(ts+loop)->fs_thread_local, NULL );
+    lfds700_freelist_cleanup( &(ts+loop+number_logical_processors)->fs_thread_local, NULL );
+    util_aligned_free( (ts+loop+number_logical_processors)->fs_thread_local_te_array );
+  }
+
+  util_aligned_free( ts );
+
+  util_aligned_free( te_array );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    count;
+
+  struct lfds700_freelist_element
+    *fe;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  struct test_state
+    *ts;
+
+  time_t
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  start_time = time( NULL );
+
+  while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    count = 0;
+
+    while( count < ts->number_elements )
+      if( lfds700_freelist_pop(ts->fs, &fe, &ps) )
+      {
+        // TRD : we do nothing with the test data, so there'ss no GET or SET here
+        lfds700_freelist_push( &ts->fs_thread_local, fe, &ps );
+        count++;
+      }
+
+    // TRD : return our local freelist to the main freelist
+    while( lfds700_freelist_pop(&ts->fs_thread_local, &fe, &ps) )
+      lfds700_freelist_push( ts->fs, fe, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    count;
+
+  struct lfds700_freelist_element
+    *fe;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  start_time = time( NULL );
+
+  while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    // TRD : return our local freelist to the main freelist
+    while( lfds700_freelist_pop(&ts->fs_thread_local, &fe, &ps) )
+      lfds700_freelist_push( ts->fs, fe, &ps );
+
+    count = 0;
+
+    while( count < ts->number_elements )
+      if( lfds700_freelist_pop(ts->fs, &fe, &ps) )
+      {
+        lfds700_freelist_push( &ts->fs_thread_local, fe, &ps );
+        count++;
+      }
+  }
+
+  // TRD : now push whatever we have in our local freelist
+  while( lfds700_freelist_pop(&ts->fs_thread_local, &fe, &ps) )
+    lfds700_freelist_push( ts->fs, fe, &ps );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_pushing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_pushing.c
new file mode 100644
index 0000000000000000000000000000000000000000..0e756c5e2d42f37dad150229204d11d68a106bd7
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_pushing.c
@@ -0,0 +1,246 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_elements,
+    thread_number;
+
+  struct lfds700_freelist_state
+    *fs;
+
+  struct test_element
+    *te_array;
+};
+
+struct test_element
+{
+  struct lfds700_freelist_element
+    fe;
+
+  lfds700_pal_uint_t
+    datum,
+    thread_number;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_freelist_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors,
+    *per_thread_counters;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_freelist_element
+    *fe;
+
+  struct lfds700_freelist_state
+    fs;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te,
+    *first_te = NULL;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create an empty freelist
+
+           we then create one thread per CPU, where each thread
+           pushes 100,000 elements each as quickly as possible to the freelist
+
+           the data pushed is a counter and a thread ID
+
+           the threads exit when the freelist is full
+
+           we then validate the freelist;
+
+           checking that the counts increment on a per unique ID basis
+           and that the number of elements we pop equals 100,000 per thread
+           (since each element has an incrementing counter which is
+            unique on a per unique ID basis, we can know we didn't lose
+            any elements)
+  */
+
+  internal_display_test_name( "Pushing" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+
+  // TRD : the main freelist
+  lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->fs = &fs;
+    (ts+loop)->thread_number = loop;
+    (ts+loop)->number_elements = number_elements;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_pushing, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    *(per_thread_counters+loop) = number_elements - 1;
+
+  vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
+
+  lfds700_freelist_query( &fs, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_freelist_pop(&fs, &fe, &ps) )
+  {
+    te = LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
+
+    if( first_te == NULL )
+      first_te = te;
+
+    if( te->thread_number >= number_logical_processors )
+    {
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( te->datum > per_thread_counters[te->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( te->datum < per_thread_counters[te->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( te->datum == per_thread_counters[te->thread_number] )
+      per_thread_counters[te->thread_number]--;
+  }
+
+  // TRD : clean up
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    util_aligned_free( (ts+loop)->te_array );
+
+  free( per_thread_counters );
+
+  free( ts );
+
+  lfds700_freelist_cleanup( &fs, NULL );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  ts->te_array = util_aligned_malloc( sizeof(struct test_element) * ts->number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < ts->number_elements ; loop++ )
+  {
+    (ts->te_array+loop)->thread_number = ts->thread_number;
+    (ts->te_array+loop)->datum = loop;
+  }
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  for( loop = 0 ; loop < ts->number_elements ; loop++ )
+  {
+    LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (ts->te_array+loop)->fe, ts->te_array+loop );
+    lfds700_freelist_push( ts->fs, &(ts->te_array+loop)->fe, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_rapid_popping_and_pushing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_rapid_popping_and_pushing.c
new file mode 100644
index 0000000000000000000000000000000000000000..15a0f9fd69a3ce186b35a2cf5221dde3a0a94741
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_freelist_rapid_popping_and_pushing.c
@@ -0,0 +1,216 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  struct lfds700_freelist_state
+    *fs;
+};
+
+struct test_element
+{
+  struct lfds700_freelist_element
+    fe;
+
+  lfds700_pal_uint_t
+    datum;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_freelist_rapid_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_logical_processors;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_freelist_state
+    fs;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi = { 0, 0 };
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+
+  /* TRD : in these tests there is a fundamental antagonism between
+           how much checking/memory clean up that we do and the
+           likelyhood of collisions between threads in their lock-free
+           operations
+
+           the lock-free operations are very quick; if we do anything
+           much at all between operations, we greatly reduce the chance
+           of threads colliding
+
+           so we have some tests which do enough checking/clean up that
+           they can tell the freelist is valid and don't leak memory
+           and here, this test now is one of those which does minimal
+           checking - in fact, the nature of the test is that you can't
+           do any real checking - but goes very quickly
+
+           what we do is create a small freelist and then run one thread
+           per CPU, where each thread simply pushes and then immediately
+           pops
+
+           the test runs for ten seconds
+
+           after the test is done, the only check we do is to traverse
+           the freelist, checking for loops and ensuring the number of
+           elements is correct
+  */
+
+  internal_display_test_name( "Rapid popping and pushing (10 seconds)" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    (ts+loop)->fs = &fs;
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  // TRD : we need one element per thread
+  te_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
+    lfds700_freelist_push( &fs, &(te_array+loop)->fe, &ps );
+  }
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_rapid_popping_and_pushing, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = number_logical_processors;
+
+  lfds700_freelist_query( &fs, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  lfds700_freelist_cleanup( &fs, NULL );
+
+  util_aligned_free( te_array );
+
+  free( ts );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    time_loop = 0;
+
+  struct lfds700_freelist_element
+    *fe;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    lfds700_freelist_pop( ts->fs, &fe, &ps );
+    lfds700_freelist_push( ts->fs, fe, &ps );
+
+    if( time_loop++ == TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly.c
new file mode 100644
index 0000000000000000000000000000000000000000..eeb98727c5251da0eddfd00ba470e6dc989f3191
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly.c
@@ -0,0 +1,33 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_hash_a( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_CAS )
+  {
+    printf( "\n"
+            "Hash (add-only) Tests\n"
+            "=====================\n" );
+
+    test_lfds700_hash_a_alignment();
+    test_lfds700_hash_a_fail_and_overwrite_on_existing_key();
+    test_lfds700_hash_a_random_adds_fail_on_existing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_hash_a_random_adds_overwrite_on_existing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_hash_a_iterate();
+  }
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_alignment.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_alignment.c
new file mode 100644
index 0000000000000000000000000000000000000000..2d0a0a5b8e235435815544c291dea14c523c0bd7
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_alignment.c
@@ -0,0 +1,40 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_hash_a_alignment()
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  /* TRD : these are compile time checks
+           but we do them here because this is a test programme
+           and it should indicate issues to users when it is *run*,
+           not when it is compiled, because a compile error normally
+           indicates a problem with the code itself and so is misleading
+  */
+
+  internal_display_test_name( "Alignment" );
+
+
+
+  // TRD : struct lfds700_hash_a_element
+  if( offsetof(struct lfds700_hash_a_element,value) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "freelist", dvs );
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_iterate.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_iterate.c
new file mode 100644
index 0000000000000000000000000000000000000000..cf4899e31bdad4b41b23f8fb772b6ce7e58a4d0a
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_iterate.c
@@ -0,0 +1,224 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_btree_au_element
+    baue;
+
+  lfds700_pal_uint_t
+    datum;
+};
+
+struct test_state
+{
+  enum lfds700_misc_flag
+    error_flag;
+
+  struct lfds700_hash_a_state
+    *has;
+
+  struct test_element
+    *element_array;
+};
+
+/***** private prototypes *****/
+static int key_compare_function( void const *new_key, void const *existing_key );
+static void key_hash_function( void const *key, lfds700_pal_uint_t *hash );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_hash_a_iterate( void )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    *counter_array,
+    loop;
+
+  struct lfds700_hash_a_element
+    *hae;
+
+  struct lfds700_hash_a_iterate
+    hai;
+
+  struct lfds700_hash_a_state
+    has;
+
+  struct lfds700_hash_a_element
+    *element_array;
+
+  struct lfds700_btree_au_state
+    *baus;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  void
+    *value;
+
+  /* TRD : single-threaded test
+           we create a single hash_a
+           we populate with 1000 elements
+           where key and value is the number of the element (e.g. 0 to 999)
+           we then allocate 1000 counters, init to 0
+           we then iterate
+           we increment each element as we see it in the iterate
+           if any are missing or seen more than once, problemo!
+
+           we do this once with a table of 10, to ensure each table has (or almost certainly has) something in
+           and then a second tiem with a table of 10000, to ensure some empty tables exist
+  */
+
+  internal_display_test_name( "Iterate" );
+
+  lfds700_misc_prng_init( &ps );
+
+  element_array = util_aligned_malloc( sizeof(struct lfds700_hash_a_element) * 1000, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  counter_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * 1000 );
+
+  // TRD : first time around
+  baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 10, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 10, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_FAIL, NULL );
+
+  for( loop = 0 ; loop < 1000 ; loop++ )
+  {
+    LFDS700_HASH_A_SET_KEY_IN_ELEMENT( *(element_array+loop), loop );
+    LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( *(element_array+loop), loop );
+    lfds700_hash_a_insert( &has, element_array+loop, NULL, &ps );
+  }
+
+  for( loop = 0 ; loop < 1000 ; loop++ )
+    *(counter_array+loop) = 0;
+
+  lfds700_hash_a_iterate_init( &has, &hai );
+
+  while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_hash_a_iterate(&hai, &hae) )
+  {
+    value = LFDS700_HASH_A_GET_VALUE_FROM_ELEMENT( *hae );
+    ( *(counter_array + (lfds700_pal_uint_t) value) )++;
+  }
+
+  if( dvs == LFDS700_MISC_VALIDITY_VALID )
+    for( loop = 0 ; loop < 1000 ; loop++ )
+    {
+      if( *(counter_array+loop) > 1 )
+        dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+      if( *(counter_array+loop) == 0 )
+        dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+    }
+
+  lfds700_hash_a_cleanup( &has, NULL );
+
+  util_aligned_free( baus );
+
+  // TRD : second time around
+  if( dvs == LFDS700_MISC_VALIDITY_VALID )
+  {
+    baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 10000, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+    lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 10000, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_FAIL, NULL );
+
+    for( loop = 0 ; loop < 1000 ; loop++ )
+    {
+      LFDS700_HASH_A_SET_KEY_IN_ELEMENT( *(element_array+loop), loop );
+      LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( *(element_array+loop), loop );
+      lfds700_hash_a_insert( &has, element_array+loop, NULL, &ps );
+    }
+
+    for( loop = 0 ; loop < 1000 ; loop++ )
+      *(counter_array+loop) = 0;
+
+    lfds700_hash_a_iterate_init( &has, &hai );
+
+    while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_hash_a_iterate(&hai, &hae) )
+    {
+      value = LFDS700_HASH_A_GET_VALUE_FROM_ELEMENT( *hae );
+      ( *(counter_array + (lfds700_pal_uint_t) value ) )++;
+    }
+
+    if( dvs == LFDS700_MISC_VALIDITY_VALID )
+      for( loop = 0 ; loop < 1000 ; loop++ )
+      {
+        if( *(counter_array+loop) > 1 )
+          dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+        if( *(counter_array+loop) == 0 )
+          dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+      }
+
+    lfds700_hash_a_cleanup( &has, NULL );
+
+    util_aligned_free( baus );
+  }
+
+  // TRD : cleanup
+  util_aligned_free( element_array );
+  free( counter_array );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "hash_a", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static int key_compare_function( void const *new_key, void const *existing_key )
+{
+  int
+    cr = 0;
+
+  // TRD : new_key can be NULL (i.e. 0)
+  // TRD : existing_key can be NULL (i.e. 0)
+
+  if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) existing_key )
+    cr = -1;
+
+  if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) existing_key )
+    cr = 1;
+
+  return( cr );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static void key_hash_function( void const *key, lfds700_pal_uint_t *hash )
+{
+  // TRD : key can be NULL
+  assert( hash != NULL );
+
+  *hash = 0;
+
+  /* TRD : this function iterates over the user data
+           and we are using the void pointer AS user data
+           so here we need to pass in the addy of value
+  */
+
+  LFDS700_HASH_A_32BIT_HASH_FUNCTION( (void *) &key, sizeof(lfds700_pal_uint_t), *hash );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_fail.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_fail.c
new file mode 100644
index 0000000000000000000000000000000000000000..5d36e47a3164da9bde30fea5cb3467c9541fa135
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_fail.c
@@ -0,0 +1,314 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_hash_a_element
+    hae;
+
+  lfds700_pal_uint_t
+    datum,
+    key;
+};
+
+struct test_state
+{
+  enum flag
+    error_flag;
+
+  lfds700_pal_uint_t
+    number_elements_per_thread;
+
+  struct lfds700_hash_a_state
+    *has;
+
+  struct test_element
+    *element_array;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state );
+static int key_compare_function( void const *new_key, void const *existing_key );
+static void key_hash_function( void const *key, lfds700_pal_uint_t *hash );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_hash_a_random_adds_fail_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements_per_thread,
+    number_elements_total,
+    number_logical_processors,
+    offset,
+    temp,
+    value;
+
+  struct lfds700_hash_a_element
+    *hae;
+
+  struct lfds700_hash_a_state
+    has;
+
+  struct lfds700_list_asu_element
+    *lasue = NULL;
+
+  struct lfds700_btree_au_state
+    *baus;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *element_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a single hash_a
+           we generate 100k elements per thread (with one thread per logical processor) in an array
+           each element is unique
+           we randomly sort the elements
+           then each thread loops, adds those elements into the hash_a
+           we check that each datum inserts okay - failure will occur on non-unique data, i.e. two identical keys
+           we should have no failures
+           we then call the hash_a validation function
+           then using the hash_a get() we check all the elements we added are present
+  */
+
+  internal_display_test_name( "Random adds and get (fail on existing key)" );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 1000, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 1000, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_FAIL, NULL );
+
+  number_elements_per_thread = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+  number_elements_total = number_elements_per_thread * number_logical_processors;
+
+  // TRD : created an ordered list of unique numbers
+  element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_total, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+  {
+    (element_array+loop)->key = loop;
+    // TRD : + number_elements just to make it different to the key
+    (element_array+loop)->datum = loop + number_elements_total;
+  }
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+  {
+    offset = LFDS700_MISC_PRNG_GENERATE( &ps );
+    offset %= number_elements_total;
+    temp = (element_array + offset)->key;
+    (element_array + offset)->key = (element_array + loop)->key;
+    (element_array + loop)->key = temp;
+  }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->has = &has;
+    (ts+loop)->element_array = element_array + number_elements_per_thread*loop;
+    (ts+loop)->error_flag = LOWERED;
+    (ts+loop)->number_elements_per_thread = number_elements_per_thread;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_adding, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  // TRD : now for validation
+  vi.min_elements = vi.max_elements = number_elements_total;
+  lfds700_hash_a_query( &has, LFDS700_HASH_A_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
+
+  /* TRD : now we attempt to lfds700_hash_a_get_by_key() for every element in number_array
+           any failure to find is an error
+           we also check we've obtained the correct element
+  */
+
+  for( loop = 0 ; dvs == LFDS700_MISC_VALIDITY_VALID and loop < number_elements_total ; loop++ )
+    if( 0 == lfds700_hash_a_get_by_key(&has, (void *) (ts->element_array+loop)->key, &hae) )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+    else
+    {
+      value = (lfds700_pal_uint_t) LFDS700_HASH_A_GET_VALUE_FROM_ELEMENT( *hae );
+      if( (ts->element_array+loop)->datum != value )
+        dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+    }
+
+  // TRD : just check error_flags weren't raised
+  if( dvs == LFDS700_MISC_VALIDITY_VALID )
+    for( loop = 0 ; loop < number_logical_processors ; loop++ )
+      if( (ts+loop)->error_flag == RAISED )
+        dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  // TRD : cleanup
+  lfds700_hash_a_cleanup( &has, NULL );
+
+  util_aligned_free( baus );
+
+  free( ts );
+
+  util_aligned_free( element_array );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "hash_a", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state )
+{
+  enum lfds700_hash_a_insert_result
+    apr;
+
+  lfds700_pal_uint_t
+    index = 0;
+
+  struct test_state
+    *ts;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( index < ts->number_elements_per_thread )
+  {
+    LFDS700_HASH_A_SET_KEY_IN_ELEMENT( (ts->element_array+index)->hae, (ts->element_array+index)->key );
+    LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( (ts->element_array+index)->hae, (ts->element_array+index)->datum );
+    apr = lfds700_hash_a_insert( ts->has, &(ts->element_array+index)->hae, NULL, &ps );
+
+    if( apr == LFDS700_HASH_A_PUT_RESULT_FAILURE_EXISTING_KEY )
+      ts->error_flag = RAISED;
+
+    index++;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static int key_compare_function( void const *new_key, void const *existing_key )
+{
+  int
+    cr = 0;
+
+  // TRD : new_key can be NULL (i.e. 0)
+  // TRD : existing_key can be NULL (i.e. 0)
+
+  if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) existing_key )
+    cr = -1;
+
+  if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) existing_key )
+    cr = 1;
+
+  return( cr );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static void key_hash_function( void const *key, lfds700_pal_uint_t *hash )
+{
+  // TRD : key can be NULL
+  assert( hash != NULL );
+
+  *hash = 0;
+
+  /* TRD : this function iterates over the user data
+           and we are using the void pointer *as* key data
+           so here we need to pass in the addy of key
+  */
+
+  LFDS700_HASH_A_32BIT_HASH_FUNCTION( (void *) &key, sizeof(lfds700_pal_uint_t), *hash );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c
new file mode 100644
index 0000000000000000000000000000000000000000..cc18900273cf4699b0e6a3b9e1a85539824ff135
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_fail_and_overwrite.c
@@ -0,0 +1,137 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** private prototypes *****/
+static int key_compare_function( void const *new_value, void const *value_in_tree );
+static void key_hash_function( void const *key, lfds700_pal_uint_t *hash );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_hash_a_fail_and_overwrite_on_existing_key()
+{
+  enum lfds700_hash_a_insert_result
+    apr;
+
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  struct lfds700_hash_a_element
+    hae_one,
+    hae_two;
+
+  struct lfds700_hash_a_state
+    has;
+
+  struct lfds700_btree_au_state
+    *baus;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  internal_display_test_name( "Fail and overwrite on existing key" );
+
+  lfds700_misc_prng_init( &ps );
+
+  baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 10, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  // TRD : fail on overwrite
+  lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 10, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_FAIL, NULL );
+
+  LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hae_one, 1 );
+  LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hae_one, 0 );
+  apr = lfds700_hash_a_insert( &has, &hae_one, NULL, &ps );
+
+  if( apr != LFDS700_HASH_A_PUT_RESULT_SUCCESS )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hae_two, 1 );
+  LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hae_two, 1 );
+  apr = lfds700_hash_a_insert( &has, &hae_two, NULL, &ps );
+
+  if( apr != LFDS700_HASH_A_PUT_RESULT_FAILURE_EXISTING_KEY )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  lfds700_hash_a_cleanup( &has, NULL );
+
+  // TRD : success on overwrite
+  lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 10, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_OVERWRITE, NULL );
+
+  LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hae_one, 1 );
+  LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hae_one, 1 );
+  apr = lfds700_hash_a_insert( &has, &hae_one, NULL, &ps );
+
+  if( apr != LFDS700_HASH_A_PUT_RESULT_SUCCESS )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  LFDS700_HASH_A_SET_KEY_IN_ELEMENT( hae_two, 1 );
+  LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( hae_two, 1 );
+  apr = lfds700_hash_a_insert( &has, &hae_two, NULL, &ps );
+
+  if( apr != LFDS700_HASH_A_PUT_RESULT_SUCCESS_OVERWRITE )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  lfds700_hash_a_cleanup( &has, NULL );
+
+  util_aligned_free( baus );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "hash_a", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static int key_compare_function( void const *new_key, void const *key_in_tree )
+{
+  int
+    cr = 0;
+
+  // TRD : key_new can be any value in its range
+  // TRD : key_in_tree can be any value in its range
+
+  if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) key_in_tree )
+    cr = -1;
+
+  if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) key_in_tree )
+    cr = 1;
+
+  return( cr );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static void key_hash_function( void const *key, lfds700_pal_uint_t *hash )
+{
+  // TRD : key can be NULL
+  assert( hash != NULL );
+
+  *hash = 0;
+
+  /* TRD : this function iterates over the user data
+           and we are using the void pointer *as* key data
+           so here we need to pass in the addy of key
+  */
+
+  LFDS700_HASH_A_32BIT_HASH_FUNCTION( (void *) &key, sizeof(lfds700_pal_uint_t), *hash );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_overwrite.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_overwrite.c
new file mode 100644
index 0000000000000000000000000000000000000000..29c5fae8653d11e23bec29fdb47a9eaf47696773
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_hash_addonly_random_adds_overwrite.c
@@ -0,0 +1,388 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_hash_a_element
+    hae;
+
+  lfds700_pal_uint_t
+    key;
+};
+
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_elements_per_thread,
+    overwrite_count;
+
+  struct lfds700_hash_a_state
+    *has;
+
+  struct test_element
+    *element_array;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state );
+static int key_compare_function( void const *new_key, void const *existing_key );
+static void key_hash_function( void const *key, lfds700_pal_uint_t *hash );
+static int qsort_and_bsearch_key_compare_function( void const *e1, void const *e2 );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_hash_a_random_adds_overwrite_on_existing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  int
+    rv;
+
+  lfds700_pal_uint_t
+    actual_sum_overwrite_existing_count,
+    expected_sum_overwrite_existing_count,
+    *key_count_array,
+    loop,
+    number_elements_per_thread,
+    number_elements_total,
+    number_logical_processors,
+    random_value;
+
+  struct lfds700_hash_a_iterate
+    hai;
+
+  struct lfds700_hash_a_element
+    *hae;
+
+  struct lfds700_hash_a_state
+    has;
+
+  struct lfds700_list_asu_element
+    *lasue = NULL;
+
+  struct lfds700_btree_au_state
+    *baus;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *element_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  void
+    *key_pointer,
+    *key;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a single hash_a
+           we generate n elements per thread
+           each element contains a key value, which is set to a random value
+           (we don't use value, so it's just set to 0)
+           the threads then run, putting
+           the threads count their number of overwrite hits
+           once the threads are done, then we
+           count the number of each key
+           from this we figure out the min/max element for hash_a validation, so we call validation
+           we check the sum of overwrites for each thread is what it should be
+           then using the hash_a get() we check all the elements we expect are present
+           and then we iterate over the hash_a
+           checking we see each key once
+  */
+
+  internal_display_test_name( "Random adds, get and iterate (overwrite on existing key)" );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  baus = util_aligned_malloc( sizeof(struct lfds700_btree_au_state) * 1000, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_hash_a_init_valid_on_current_logical_core( &has, baus, 1000, key_compare_function, key_hash_function, LFDS700_HASH_A_EXISTING_KEY_OVERWRITE, NULL );
+
+  // TRD : we divide by 2 beccause we have to allocate a second array of this size later
+  number_elements_per_thread = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors ) / 2;
+  number_elements_total = number_elements_per_thread * number_logical_processors;
+
+  // TRD : created an ordered list of unique numbers
+  element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_total, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+  {
+    random_value = LFDS700_MISC_PRNG_GENERATE( &ps );
+    (element_array+loop)->key = (lfds700_pal_uint_t) floor( (number_elements_total/2) * ((double) random_value / (double) LFDS700_MISC_PRNG_MAX) );
+  }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->has = &has;
+    (ts+loop)->element_array = element_array + number_elements_per_thread*loop;
+    (ts+loop)->overwrite_count = 0;
+    (ts+loop)->number_elements_per_thread = number_elements_per_thread;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_adding, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  // TRD : now for validation
+  key_count_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements_total );
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+    *(key_count_array+loop) = 0;
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+    ( *(key_count_array + (element_array+loop)->key) )++;
+
+  vi.min_elements = number_elements_total;
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+    if( *(key_count_array+loop) == 0 )
+      vi.min_elements--;
+
+  vi.max_elements = vi.min_elements;
+
+  lfds700_hash_a_query( &has, LFDS700_HASH_A_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
+
+  expected_sum_overwrite_existing_count = 0;
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+    if( *(key_count_array+loop) != 0 )
+      expected_sum_overwrite_existing_count += *(key_count_array+loop) - 1;
+
+  actual_sum_overwrite_existing_count = 0;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    actual_sum_overwrite_existing_count += (ts+loop)->overwrite_count;
+
+  if( expected_sum_overwrite_existing_count != actual_sum_overwrite_existing_count )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  // TRD : now loop over the expected array and check we can get() every element
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+    if( *(key_count_array+loop) > 0 )
+    {
+      rv = lfds700_hash_a_get_by_key( &has, (void *) loop, &hae );
+
+      if( rv != 1 )
+        dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+    }
+
+  /* TRD : now iterate, checking we find every element and no others
+           to do this in a timely manner, we need to qsort() the key values
+           and use bsearch() to check for items in the array
+  */
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+    if( *(key_count_array+loop) != 0 )
+      *(key_count_array+loop) = loop;
+    else
+      *(key_count_array+loop) = 0;
+
+  qsort( key_count_array, number_elements_total, sizeof(lfds700_pal_uint_t), qsort_and_bsearch_key_compare_function );
+
+  lfds700_hash_a_iterate_init( &has, &hai );
+
+  while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_hash_a_iterate(&hai, &hae) )
+  {
+    key = LFDS700_HASH_A_GET_KEY_FROM_ELEMENT( *hae );
+
+    key_pointer = bsearch( &key, key_count_array, number_elements_total, sizeof(lfds700_pal_uint_t), qsort_and_bsearch_key_compare_function );
+
+    if( key_pointer == NULL )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+  }
+
+  // TRD : cleanup
+  lfds700_hash_a_cleanup( &has, NULL );
+
+  util_aligned_free( baus );
+
+  free( ts );
+
+  util_aligned_free( element_array );
+
+  free( key_count_array );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "hash_a", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_adding( void *util_thread_starter_thread_state )
+{
+  enum lfds700_hash_a_insert_result
+    apr;
+
+  lfds700_pal_uint_t
+    index = 0;
+
+  struct test_state
+    *ts;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( index < ts->number_elements_per_thread )
+  {
+    LFDS700_HASH_A_SET_KEY_IN_ELEMENT( (ts->element_array+index)->hae, (ts->element_array+index)->key );
+    LFDS700_HASH_A_SET_VALUE_IN_ELEMENT( (ts->element_array+index)->hae, 0 );
+    apr = lfds700_hash_a_insert( ts->has, &(ts->element_array+index)->hae, NULL, &ps );
+
+    if( apr == LFDS700_HASH_A_PUT_RESULT_SUCCESS_OVERWRITE )
+      ts->overwrite_count++;
+
+    index++;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static int key_compare_function( void const *new_key, void const *existing_key )
+{
+  int
+    cr = 0;
+
+  // TRD : new_key can be NULL (i.e. 0)
+  // TRD : existing_key can be NULL (i.e. 0)
+
+  if( (lfds700_pal_uint_t) new_key < (lfds700_pal_uint_t) existing_key )
+    cr = -1;
+
+  if( (lfds700_pal_uint_t) new_key > (lfds700_pal_uint_t) existing_key )
+    cr = 1;
+
+  return( cr );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static void key_hash_function( void const *key, lfds700_pal_uint_t *hash )
+{
+  // TRD : key can be NULL
+  assert( hash != NULL );
+
+  *hash = 0;
+
+  /* TRD : this function iterates over the user data
+           and we are using the void pointer *as* key data
+           so here we need to pass in the addy of key
+  */
+
+  LFDS700_HASH_A_32BIT_HASH_FUNCTION( (void *) &key, sizeof(lfds700_pal_uint_t), *hash );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+static int qsort_and_bsearch_key_compare_function( void const *e1, void const *e2 )
+{
+  int
+    cr = 0;
+
+  lfds700_pal_uint_t
+    s1,
+    s2;
+
+  s1 = *(lfds700_pal_uint_t *) e1;
+  s2 = *(lfds700_pal_uint_t *) e2;
+
+  if( s1 > s2 )
+    cr = 1;
+
+  if( s1 < s2 )
+    cr = -1;
+
+  return( cr );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked.c
new file mode 100644
index 0000000000000000000000000000000000000000..5720aa24282ed9fdf87a85d7f3487d4907f1fbaa
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked.c
@@ -0,0 +1,31 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_list_aos( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_CAS )
+  {
+    printf( "\n"
+            "List (add-only, ordered, singly-linked) Tests\n"
+            "=============================================\n" );
+
+    test_lfds700_list_aos_alignment();
+    test_lfds700_list_aos_new_ordered( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_list_aos_new_ordered_with_cursor( list_of_logical_processors, memory_in_megabytes );
+  }
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_alignment.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_alignment.c
new file mode 100644
index 0000000000000000000000000000000000000000..77263463667e5ac03643fc6fe74faf63f106f1f5
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_alignment.c
@@ -0,0 +1,58 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_list_aos_alignment()
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  /* TRD : these are compile time checks
+           but we do them here because this is a test programme
+           and it should indicate issues to users when it is *run*,
+           not when it is compiled, because a compile error normally
+           indicates a problem with the code itself and so is misleading
+  */
+
+  internal_display_test_name( "Alignment" );
+
+
+
+  // TRD : struct lfds700_list_aos_element
+  if( offsetof(struct lfds700_list_aos_element,next) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_list_aos_element,value) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_list_aos_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : struct lfds700_list_asu_state
+  if( offsetof(struct lfds700_list_aos_state,start) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_list_aos_state,dummy_element) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_list_aos_state,key_compare_function) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "list_aos", dvs );
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c
new file mode 100644
index 0000000000000000000000000000000000000000..3a392b33bd4de7fbba7a048f556ca4d7e8d8dffd
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_new_ordered.c
@@ -0,0 +1,278 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_list_aos_element
+    laose;
+
+  lfds700_pal_uint_t
+    element_number,
+    thread_number;
+};
+
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_elements_per_thread;
+
+  struct lfds700_list_aos_state
+    *laoss;
+
+  struct test_element
+    *element_array;
+};
+
+/***** private prototypes *****/
+static int new_ordered_compare_function( void const *value_new, void const *value_in_list );
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_thread( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_list_aos_new_ordered( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    expected_element_number,
+    number_elements_per_thread,
+    number_elements_total,
+    number_logical_processors,
+    offset,
+    temp;
+
+  struct lfds700_list_aos_element
+    *laose = NULL;
+
+  struct lfds700_list_asu_element
+    *lasue = NULL;
+
+  struct lfds700_list_aos_state
+    laoss;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct test_element
+    *element_array,
+    *element;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_state
+    *tts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : run one thread per logical processor
+           we have a single array of 10k elements per thread
+           this is set to be randomly ordered (but with contigious numbers from 0 to n)
+           we give 10k to each thread (a pointer into the array at the correct point)
+           which then loops through that array
+           calling lfds700_list_aos_insert_element_by_position( LFDS700_LIST_AOS_POSITION_ORDERED )
+           verification should show list is sorted
+  */
+
+  internal_display_test_name( "New ordered" );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_list_aos_init_valid_on_current_logical_core( &laoss, new_ordered_compare_function, LFDS700_LIST_AOS_INSERT_RESULT_FAILURE_EXISTING_KEY, NULL );
+
+  /* TRD : create randomly ordered number array with unique elements
+
+           unique isn't necessary - the list will sort anyway - but
+           it permits slightly better validation
+  */
+
+  number_elements_per_thread = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+
+  // TRD : or the test takes a looooooong time...
+  if( number_elements_per_thread > 10000 )
+    number_elements_per_thread = 10000;
+
+  number_elements_total = number_elements_per_thread * number_logical_processors;
+
+  element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_total, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+    (element_array+loop)->element_number = loop;
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+  {
+    offset = LFDS700_MISC_PRNG_GENERATE( &ps );
+    offset %= number_elements_total;
+    temp = (element_array + offset)->element_number;
+    (element_array + offset)->element_number = (element_array + loop)->element_number;
+    (element_array + loop)->element_number = temp;
+  }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->laoss = &laoss;
+    (ts+loop)->element_array = element_array + (loop*number_elements_per_thread);
+    (ts+loop)->number_elements_per_thread = number_elements_per_thread;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_ordered_thread, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  free( ts );
+
+  /* TRD : validate the resultant list
+           iterate over the list
+           we expect to find the list is sorted, 
+           which means that element_number will
+           increment from zero
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = number_elements_total;
+
+  lfds700_list_aos_query( &laoss, LFDS700_LIST_AOS_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  if( dvs == LFDS700_MISC_VALIDITY_VALID )
+  {
+    expected_element_number = 0;
+
+    // TRD : traverse the list and check combined_data_array matches
+    while( dvs == LFDS700_MISC_VALIDITY_VALID and LFDS700_LIST_AOS_GET_START_AND_THEN_NEXT(laoss, laose) )
+    {
+      element = LFDS700_LIST_AOS_GET_VALUE_FROM_ELEMENT( *laose );
+
+      if( element->element_number != expected_element_number++ )
+        dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+    }
+  }
+
+  lfds700_list_aos_cleanup( &laoss, NULL );
+
+  util_aligned_free( element_array );
+
+  internal_display_test_result( 1, "list_aos", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static int new_ordered_compare_function( void const *value_new, void const *value_in_list )
+{
+  int
+    cr = 0;
+
+  struct test_element
+    *e1,
+    *e2;
+
+  // TRD : value_new can be any value in its range
+  // TRD : value_in_list can be any value in its range
+
+  e1 = (struct test_element *) value_new;
+  e2 = (struct test_element *) value_in_list;
+
+  if( e1->element_number < e2->element_number )
+    cr = -1;
+
+  if( e1->element_number > e2->element_number )
+    cr = 1;
+
+  return( cr );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_thread( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  for( loop = 0 ; loop < ts->number_elements_per_thread ; loop++ )
+  {
+    LFDS700_LIST_AOS_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->laose, ts->element_array+loop );
+    LFDS700_LIST_AOS_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->laose, ts->element_array+loop );
+    lfds700_list_aos_insert( ts->laoss, &(ts->element_array+loop)->laose, NULL, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c
new file mode 100644
index 0000000000000000000000000000000000000000..42e0ebc7a5f1e9461e0279217253587d5840978f
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_ordered_singlylinked_new_ordered_with_cursor.c
@@ -0,0 +1,366 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_list_aos_element
+    laose;
+
+  lfds700_pal_uint_t
+    element_number,
+    thread_number;
+};
+
+struct test_state
+{
+  enum flag
+    error_flag;
+
+  lfds700_pal_uint_t
+    number_elements_per_thread;
+
+  struct lfds700_list_aos_state
+    *laoss;
+
+  struct test_element
+    *element_array;
+};
+
+/***** private prototypes *****/
+static int new_ordered_with_cursor_compare_function( void const *value_new, void const *value_in_list );
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_with_cursor_insert_thread( void *util_thread_starter_thread_state );
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_with_cursor_cursor_thread( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_list_aos_new_ordered_with_cursor( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements_per_thread,
+    number_elements_total,
+    number_logical_processors,
+    offset,
+    temp;
+
+  struct lfds700_list_aos_state
+    laoss;
+
+  struct lfds700_list_asu_element
+    *lasue = NULL;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *element_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : run two threads per logical processor
+
+           the test runs for 10 seconds
+
+           the first thread loops over a pre-set list of random numbers
+           continually adding them using ordered insert
+
+           the second thread keeps iterating over the list, checking that
+           each element is larger than its predecessor
+  */
+
+  internal_display_test_name( "New ordered with cursor (%d seconds)", TEST_DURATION_IN_SECONDS );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_list_aos_init_valid_on_current_logical_core( &laoss, new_ordered_with_cursor_compare_function, LFDS700_LIST_AOS_INSERT_RESULT_FAILURE_EXISTING_KEY, NULL );
+
+  /* TRD : create randomly ordered number array with unique elements
+
+           unique isn't necessary - the list will sort anyway - but
+           it permits slightly better validation
+  */
+
+  number_elements_per_thread = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+
+  // TRD : or the test takes a looooooong time...
+  if( number_elements_per_thread > 1000 )
+    number_elements_per_thread = 1000;
+
+  number_elements_total = number_elements_per_thread * number_logical_processors;
+
+  element_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_total, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+    (element_array+loop)->element_number = loop;
+
+  for( loop = 0 ; loop < number_elements_total ; loop++ )
+  {
+    offset = LFDS700_MISC_PRNG_GENERATE( &ps );
+    offset %= number_elements_total;
+    temp = (element_array + offset)->element_number;
+    (element_array + offset)->element_number = (element_array + loop)->element_number;
+    (element_array + loop)->element_number = temp;
+  }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors * 2 );
+
+  // TRD : the insert threads
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->laoss = &laoss;
+    (ts+loop)->element_array = element_array + number_elements_per_thread*loop;
+    (ts+loop)->error_flag = LOWERED;
+    (ts+loop)->number_elements_per_thread = number_elements_per_thread;
+  }
+
+  // TRD : the cursor threads
+  for( loop = number_logical_processors ; loop < number_logical_processors * 2 ; loop++ )
+  {
+    (ts+loop)->laoss = &laoss;
+    (ts+loop)->element_array = NULL;
+    (ts+loop)->error_flag = LOWERED;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors * 2 );
+
+  util_thread_starter_new( &tts, number_logical_processors * 2 );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_ordered_with_cursor_insert_thread, ts+loop );
+    util_thread_starter_start( tts, &thread_handles[loop+number_logical_processors], loop+number_logical_processors, lp, new_ordered_with_cursor_cursor_thread, ts+loop+number_logical_processors );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors * 2 ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  /* TRD : validate the resultant list
+
+           the cursor threads were checking for orderedness
+           if that failed, they raise their error_flag
+           so validate the list, then check error_flags
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = number_elements_total;
+
+  lfds700_list_aos_query( &laoss, LFDS700_LIST_AOS_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  if( dvs == LFDS700_MISC_VALIDITY_VALID )
+    for( loop = number_logical_processors ; loop < number_logical_processors * 2 ; loop++ )
+      if( (ts+loop)->error_flag == RAISED )
+        dvs = LFDS700_MISC_VALIDITY_INVALID_ORDER;
+
+  lfds700_list_aos_cleanup( &laoss, NULL );
+
+  util_aligned_free( element_array );
+
+  free( ts );
+
+  internal_display_test_result( 1, "list_aos", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static int new_ordered_with_cursor_compare_function( void const *value_new, void const *value_in_list )
+{
+  int
+    cr = 0;
+
+  struct test_element
+    *e1,
+    *e2;
+
+  // TRD : value_new can be any value in its range
+  // TRD : value_in_list can be any value in its range
+
+  e1 = (struct test_element *) value_new;
+  e2 = (struct test_element *) value_in_list;
+
+  if( e1->element_number < e2->element_number )
+    cr = -1;
+
+  if( e1->element_number > e2->element_number )
+    cr = 1;
+
+  return( cr );
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_with_cursor_insert_thread( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  for( loop = 0 ; loop < ts->number_elements_per_thread ; loop++ )
+  {
+    LFDS700_LIST_AOS_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->laose, ts->element_array+loop );
+    LFDS700_LIST_AOS_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->laose, ts->element_array+loop );
+    lfds700_list_aos_insert( ts->laoss, &(ts->element_array+loop)->laose, NULL, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_ordered_with_cursor_cursor_thread( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    prev_element_number;
+
+  lfds700_pal_uint_t
+    time_loop = 0;
+
+  struct lfds700_list_aos_element
+    *laose;
+
+  struct test_element
+    *element;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    prev_element_number = 0;
+
+    laose = LFDS700_LIST_AOS_GET_START( *ts->laoss );
+
+    // TRD : we may get start before any element has been added to the list
+    if( laose == NULL )
+      continue;
+
+    element = LFDS700_LIST_AOS_GET_VALUE_FROM_ELEMENT( *laose );
+
+    if( element->element_number < prev_element_number )
+      ts->error_flag = RAISED;
+
+    prev_element_number = element->element_number;
+
+    laose = LFDS700_LIST_AOS_GET_NEXT( *laose );
+
+    while( laose != NULL )
+    {
+      element = LFDS700_LIST_AOS_GET_VALUE_FROM_ELEMENT( *laose );
+
+      if( element->element_number <= prev_element_number )
+        ts->error_flag = RAISED;
+
+      prev_element_number = element->element_number;
+
+      laose = LFDS700_LIST_AOS_GET_NEXT( *laose );
+    }
+
+    if( time_loop++ == REDUCED_TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered.c
new file mode 100644
index 0000000000000000000000000000000000000000..37c37f252990e281f70ed4d48d746a94d24d5d62
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered.c
@@ -0,0 +1,32 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_list_asu( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_CAS )
+  {
+    printf( "\n"
+            "List (add-only, singly-linked, unordered) Tests\n"
+            "===============================================\n" );
+
+    test_lfds700_list_asu_alignment();
+    test_lfds700_list_asu_new_start( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_list_asu_new_end( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_list_asu_new_after( list_of_logical_processors, memory_in_megabytes );
+  }
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_alignment.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_alignment.c
new file mode 100644
index 0000000000000000000000000000000000000000..43f451d4bf58887005736872ca74ce22ef3561d0
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_alignment.c
@@ -0,0 +1,61 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_list_asu_alignment()
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  /* TRD : these are compile time checks
+           but we do them here because this is a test programme
+           and it should indicate issues to users when it is *run*,
+           not when it is compiled, because a compile error normally
+           indicates a problem with the code itself and so is misleading
+  */
+
+  internal_display_test_name( "Alignment" );
+
+
+
+  // TRD : struct lfds700_list_asu_element
+  if( offsetof(struct lfds700_list_asu_element,next) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_list_asu_element,value) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_list_asu_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : struct lfds700_list_asu_state
+  if( offsetof(struct lfds700_list_asu_state,end) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_list_asu_state,start) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_list_asu_state,dummy_element) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_list_asu_state,key_compare_function) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "list_asu", dvs );
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_after.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_after.c
new file mode 100644
index 0000000000000000000000000000000000000000..5dcd6954aac4d65708e0d35bf4d5080fef6cb3ac
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_after.c
@@ -0,0 +1,254 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_list_asu_element
+    lasue;
+
+  lfds700_pal_uint_t
+    element_number,
+    thread_number;
+};
+
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_elements;
+
+  struct lfds700_list_asu_state
+    *lasus;
+
+  struct test_element
+    *element_array;
+
+  struct lfds700_list_asu_element
+    *first_element;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_after_thread( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_list_asu_new_after( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors,
+    *per_thread_counters,
+    subloop;
+
+  struct lfds700_list_asu_element
+    *lasue,
+    first_element;
+
+  struct lfds700_list_asu_state
+    lasus;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *element_array,
+    *element;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : run one thread per logical processor
+           run for 250k elements
+           we put a single first element into the list and
+           each thread loops, calling lfds700_list_asu_new_element_by_position( LFDS700_LIST_ASU_POSITION_AFTER ),
+           inserting after the single first element
+           data element contain s thread_number and element_number
+           verification should show element_number decreasing on a per thread basis
+  */
+
+  internal_display_test_name( "New after" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_list_asu_init_valid_on_current_logical_core( &lasus, NULL, NULL );
+
+  LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( first_element, NULL );
+  LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( first_element, NULL );
+  lfds700_list_asu_insert_at_position( &lasus, &first_element, NULL, LFDS700_LIST_ASU_POSITION_START, &ps );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+
+  element_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+    {
+      (element_array+(loop*number_elements)+subloop)->thread_number = loop;
+      (element_array+(loop*number_elements)+subloop)->element_number = subloop;
+    }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {\
+    (ts+loop)->lasus = &lasus;
+    (ts+loop)->element_array = element_array + (loop*number_elements);
+    (ts+loop)->first_element = &first_element;
+    (ts+loop)->number_elements = number_elements;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_after_thread, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  free( ts );
+
+  /* TRD : validate the resultant list
+           iterate over each element
+           we expect to find element numbers increment on a per thread basis
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = number_elements * number_logical_processors + 1;
+
+  lfds700_list_asu_query( &lasus, LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    *(per_thread_counters+loop) = number_elements - 1;
+
+  /* TRD : we have a leading element, after which all inserts occurred
+           we need to get past that element for validation
+           this is why we're not using lfds700_list_asu_get_start_and_then_next()
+  */
+
+  lasue = LFDS700_LIST_ASU_GET_START( lasus );
+
+  lasue = LFDS700_LIST_ASU_GET_NEXT( *lasue );
+
+  while( dvs == LFDS700_MISC_VALIDITY_VALID and lasue != NULL )
+  {
+    element = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+
+    if( element->thread_number >= number_logical_processors )
+    {
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( element->element_number < per_thread_counters[element->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( element->element_number > per_thread_counters[element->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( element->element_number == per_thread_counters[element->thread_number] )
+      per_thread_counters[element->thread_number]--;
+
+    lasue = LFDS700_LIST_ASU_GET_NEXT( *lasue );
+  }
+
+  free( per_thread_counters );
+
+  lfds700_list_asu_cleanup( &lasus, NULL );
+
+  util_aligned_free( element_array );
+
+  internal_display_test_result( 1, "list_asu", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_after_thread( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  for( loop = 0 ; loop < ts->number_elements ; loop++ )
+  {
+    LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
+    LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
+    lfds700_list_asu_insert_at_position( ts->lasus, &(ts->element_array+loop)->lasue, ts->first_element, LFDS700_LIST_ASU_POSITION_AFTER, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_end.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_end.c
new file mode 100644
index 0000000000000000000000000000000000000000..c6c66d007c516a4f61890946965d3ebefcf239d9
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_end.c
@@ -0,0 +1,229 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_list_asu_element
+    lasue;
+
+  lfds700_pal_uint_t
+    element_number,
+    thread_number;
+};
+
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_elements;
+
+  struct lfds700_list_asu_state
+    *lasus;
+
+  struct test_element
+    *element_array;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_end_thread( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_list_asu_new_end( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors,
+    *per_thread_counters,
+    subloop;
+
+  struct lfds700_list_asu_element
+    *lasue = NULL;
+
+  struct lfds700_list_asu_state
+    lasus;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *element_array,
+    *element;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : run one thread per logical processor
+           run for 250k elements
+           each thread loops, calling lfds700_list_asu_new_element_by_position( LFDS700_LIST_ASU_POSITION_END )
+           data element contain a thread_number and element_number
+           verification should show element_number increasing on a per thread basis
+  */
+
+  internal_display_test_name( "New end" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_list_asu_init_valid_on_current_logical_core( &lasus, NULL, NULL );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+
+  element_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+    {
+      (element_array+(loop*number_elements)+subloop)->thread_number = loop;
+      (element_array+(loop*number_elements)+subloop)->element_number = subloop;
+    }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->lasus = &lasus;
+    (ts+loop)->element_array = element_array + (loop*number_elements);
+    (ts+loop)->number_elements = number_elements;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_end_thread, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  free( ts );
+
+  /* TRD : validate the resultant list
+           iterate over each element
+           we expect to find element numbers increment on a per thread basis
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
+
+  lfds700_list_asu_query( &lasus, LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    *(per_thread_counters+loop) = 0;
+
+  lasue = NULL;
+
+  while( dvs == LFDS700_MISC_VALIDITY_VALID and LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(lasus, lasue) )
+  {
+    element = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+
+    if( element->thread_number >= number_logical_processors )
+    {
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( element->element_number > per_thread_counters[element->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( element->element_number < per_thread_counters[element->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( element->element_number == per_thread_counters[element->thread_number] )
+      per_thread_counters[element->thread_number]++;
+  }
+
+  free( per_thread_counters );
+
+  lfds700_list_asu_cleanup( &lasus, NULL );
+
+  util_aligned_free( element_array );
+
+  internal_display_test_result( 1, "list_asu", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_end_thread( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  for( loop = 0 ; loop < ts->number_elements ; loop++ )
+  {
+    LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
+    LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
+    lfds700_list_asu_insert_at_position( ts->lasus, &(ts->element_array+loop)->lasue, NULL, LFDS700_LIST_ASU_POSITION_END, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_start.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_start.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4244e2a120e42cb80a22bcdbbd05fb009f5aebf
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_list_addonly_singlylinked_unordered_new_start.c
@@ -0,0 +1,229 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  struct lfds700_list_asu_element
+    lasue;
+
+  lfds700_pal_uint_t
+    element_number,
+    thread_number;
+};
+
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_elements;
+
+  struct lfds700_list_asu_state
+    *lasus;
+
+  struct test_element
+    *element_array;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_start_thread( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_list_asu_new_start( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors,
+    *per_thread_counters,
+    subloop;
+
+  struct lfds700_list_asu_element
+    *lasue = NULL;
+
+  struct lfds700_list_asu_state
+    lasus;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_element
+    *element_array,
+    *element;
+
+  struct test_state
+    *ts;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : run one thread per logical processor
+           run for 250k elements
+           each thread loops, calling lfds700_list_asu_new_element_by_position( LFDS700_LIST_ASU_POSITION_START )
+           data element contain s thread_number and element_number
+           verification should show element_number decreasing on a per thread basis
+  */
+
+  internal_display_test_name( "New start" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_list_asu_init_valid_on_current_logical_core( &lasus, NULL, NULL );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+
+  element_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+    {
+      (element_array+(loop*number_elements)+subloop)->thread_number = loop;
+      (element_array+(loop*number_elements)+subloop)->element_number = subloop;
+    }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->lasus = &lasus;
+    (ts+loop)->element_array = element_array + (loop*number_elements);
+    (ts+loop)->number_elements = number_elements;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, new_start_thread, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  free( ts );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  /* TRD : validate the resultant list
+           iterate over each element
+           we expect to find element numbers increment on a per thread basis
+  */
+
+  vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
+
+  lfds700_list_asu_query( &lasus, LFDS700_LIST_ASU_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    *(per_thread_counters+loop) = number_elements - 1;
+
+  lasue = NULL;
+
+  while( dvs == LFDS700_MISC_VALIDITY_VALID and LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(lasus, lasue) )
+  {
+    element = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+
+    if( element->thread_number >= number_logical_processors )
+    {
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( element->element_number < per_thread_counters[element->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( element->element_number > per_thread_counters[element->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( element->element_number == per_thread_counters[element->thread_number] )
+      per_thread_counters[element->thread_number]--;
+  }
+
+  free( per_thread_counters );
+
+  lfds700_list_asu_cleanup( &lasus, NULL );
+
+  util_aligned_free( element_array );
+
+  internal_display_test_result( 1, "list_asu", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION new_start_thread( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  for( loop = 0 ; loop < ts->number_elements ; loop++ )
+  {
+    LFDS700_LIST_ASU_SET_KEY_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
+    LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( (ts->element_array+loop)->lasue, ts->element_array+loop );
+    lfds700_list_asu_insert_at_position( ts->lasus, &(ts->element_array+loop)->lasue, NULL, LFDS700_LIST_ASU_POSITION_START, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic.c
new file mode 100644
index 0000000000000000000000000000000000000000..2f733909a74f0b4b281ee8e77dd37f9ea989d082
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic.c
@@ -0,0 +1,33 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_pal_atomic( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  printf( "\n"
+          "Abstraction Atomic Tests\n"
+          "========================\n" );
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_CAS )
+    test_lfds700_pal_atomic_cas( list_of_logical_processors );
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
+    test_lfds700_pal_atomic_dwcas( list_of_logical_processors );
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE )
+    test_lfds700_pal_atomic_exchange( list_of_logical_processors, memory_in_megabytes );
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_cas.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_cas.c
new file mode 100644
index 0000000000000000000000000000000000000000..543528d99c7eac5ea9e2d938a5ce9b6419f8bb49
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_cas.c
@@ -0,0 +1,176 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_lfds700_pal_atomic_cas_state
+{
+  lfds700_pal_uint_t
+    local_counter;
+
+  lfds700_pal_atom_t volatile
+    *shared_counter;
+};
+
+/***** private prototyps *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_cas( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_pal_atomic_cas( struct lfds700_list_asu_state *list_of_logical_processors )
+{
+  lfds700_pal_atom_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    shared_counter;
+
+  lfds700_pal_uint_t
+    local_total = 0;
+
+  lfds700_pal_uint_t
+    loop,
+    number_logical_processors;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_lfds700_pal_atomic_cas_state
+    *atcs;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+
+  /* TRD : here we test pal_cas
+
+           we run one thread per CPU
+           we use pal_cas() to increment a shared counter
+           every time a thread successfully increments the counter,
+           it increments a thread local counter
+           the threads run for ten seconds
+           after the threads finish, we total the local counters
+           they should equal the shared counter
+  */
+
+  internal_display_test_name( "Atomic CAS" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  shared_counter = 0;
+
+  atcs = util_malloc_wrapper( sizeof(struct test_lfds700_pal_atomic_cas_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (atcs+loop)->shared_counter = &shared_counter;
+    (atcs+loop)->local_counter = 0;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_cas, atcs+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  // TRD : results
+  LFDS700_MISC_BARRIER_LOAD;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    local_total += (atcs+loop)->local_counter;
+
+  if( local_total == shared_counter )
+    puts( "passed" );
+
+  if( local_total != shared_counter )
+  {
+    puts( "failed" );
+    exit( EXIT_FAILURE );
+  }
+
+  // TRD : cleanup
+  free( atcs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_cas( void *util_thread_starter_thread_state )
+{
+  char unsigned 
+    result;
+
+  lfds700_pal_uint_t
+    loop = 0;
+
+  lfds700_pal_atom_t LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_SINGLE_POINTER)
+    exchange,
+    compare;
+
+  struct test_lfds700_pal_atomic_cas_state
+    *atcs;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  atcs = (struct test_lfds700_pal_atomic_cas_state *) tsts->thread_user_state;
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( loop++ < 10000000 )
+  {
+    compare = *atcs->shared_counter;
+
+    do
+    {
+      exchange = compare + 1;
+      LFDS700_PAL_ATOMIC_CAS( atcs->shared_counter, &compare, exchange, LFDS700_MISC_CAS_STRENGTH_WEAK, result );
+    }
+    while( result == 0 );
+
+    atcs->local_counter++;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_dcas.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_dcas.c
new file mode 100644
index 0000000000000000000000000000000000000000..4973e73770b1d52b10f5aaa74a6e51ddfe3d454a
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_dcas.c
@@ -0,0 +1,177 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_lfds700_pal_atomic_dwcas_state
+{
+  lfds700_pal_uint_t
+    local_counter;
+
+  lfds700_pal_atom_t volatile
+    (*shared_counter)[2];
+};
+
+/***** private prototyps *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_dwcas( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_pal_atomic_dwcas( struct lfds700_list_asu_state *list_of_logical_processors )
+{
+  lfds700_pal_uint_t
+    local_total = 0,
+    loop,
+    number_logical_processors;
+
+  lfds700_pal_atom_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    shared_counter[2] = { 0, 0 };
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_lfds700_pal_atomic_dwcas_state
+    *atds;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+
+  /* TRD : here we test pal_dwcas
+
+           we run one thread per CPU
+           we use pal_dwcas() to increment a shared counter
+           every time a thread successfully increments the counter,
+           it increments a thread local counter
+           the threads run for ten seconds
+           after the threads finish, we total the local counters
+           they should equal the shared counter
+  */
+
+  internal_display_test_name( "Atomic DWCAS" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  atds = util_malloc_wrapper( sizeof(struct test_lfds700_pal_atomic_dwcas_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (atds+loop)->shared_counter = &shared_counter;
+    (atds+loop)->local_counter = 0;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_dwcas, atds+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  // TRD : results
+  LFDS700_MISC_BARRIER_LOAD;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    local_total += (atds+loop)->local_counter;
+
+  if( local_total == shared_counter[0] )
+    puts( "passed" );
+
+  if( local_total != shared_counter[0] )
+  {
+    printf( "%llu != %llu\n", (int long long unsigned) local_total, (int long long unsigned) shared_counter[0] );
+    puts( "failed" );
+    exit( EXIT_FAILURE );
+  }
+
+  // TRD : cleanup
+  free( atds );
+
+  return;
+}
+
+#pragma warning( disable : 4702 )
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_dwcas( void *util_thread_starter_thread_state )
+{
+  char unsigned
+    result;
+
+  lfds700_pal_uint_t
+    loop = 0;
+
+  lfds700_pal_atom_t LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_DOUBLE_POINTER)
+    exchange[2],
+    compare[2];
+
+  struct test_lfds700_pal_atomic_dwcas_state
+    *atds;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  atds = (struct test_lfds700_pal_atomic_dwcas_state *) tsts->thread_user_state;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( loop++ < 10000000 )
+  {
+    compare[0] = (*atds->shared_counter)[0];
+    compare[1] = (*atds->shared_counter)[1];
+
+    do
+    {
+      exchange[0] = compare[0] + 1;
+      exchange[1] = compare[1];
+      LFDS700_PAL_ATOMIC_DWCAS( atds->shared_counter, compare, exchange, LFDS700_MISC_CAS_STRENGTH_WEAK, result );
+    }
+    while( result == 0 );
+
+    atds->local_counter++;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_exchange.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_exchange.c
new file mode 100644
index 0000000000000000000000000000000000000000..ba6366e524f2e3a6cefd1e2a0af8b2e256b0dc9b
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_exchange.c
@@ -0,0 +1,333 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  lfds700_pal_uint_t
+    counter,
+    *counter_array,
+    number_elements,
+    number_logical_processors;
+
+  lfds700_pal_uint_t volatile
+    *shared_exchange;
+};
+
+/***** private prototyps *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_exchange( void *util_thread_starter_thread_state );
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_atomic_exchange( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_pal_atomic_exchange( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum flag
+    atomic_exchange_success_flag = RAISED,
+    exchange_success_flag = RAISED;
+
+  lfds700_pal_uint_t
+    loop,
+    *merged_counter_arrays,
+    number_elements,
+    number_logical_processors,
+    subloop;
+
+  lfds700_pal_uint_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
+    exchange;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct test_state
+    *ts;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : here we test pal_atomic_exchange
+
+           we have one thread per logical core
+           there is one variable which every thread will exchange to/from 
+           we know the number of logical cores
+           the threads have a counter each, which begins with their logical core number plus one
+           (plus one because the exchange counter begins with 0 already in place)
+           (e.g. thread 0 begins with its counter at 1, thread 1 begins with its counter at 2, etc)
+
+           there is an array per thread of 1 million elements, each a counter, set to 0
+
+           when running, each thread increments its counter by the number of threads
+           the threads busy loop, exchanging
+           every time aa thread pulls a number off the central, shared exchange variable,
+           it increments the counter for that variable in its thread-local counter array
+
+           (we're not using a global array, because we'd have to be atomic in our increments,
+            which is a slow-down we don't want)
+
+           at the end, we merge all the counter arrays and if the frequency for a counter is a value
+           other than 1, the exchange was not atomic
+
+           we perform the test twice, once with pal_atomic_exchange, once with a non-atomic exchange
+
+           we expect the atomic to pass and the non-atomic to fail
+  */
+
+  internal_display_test_name( "Atomic exchange" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(lfds700_pal_uint_t) * (number_logical_processors + 1) );
+
+  merged_counter_arrays = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements );
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    *(merged_counter_arrays+loop) = 0;
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->counter = loop + 1;
+    (ts+loop)->counter_array = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_elements );
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+      *((ts+loop)->counter_array+subloop) = 0;
+    (ts+loop)->number_logical_processors = number_logical_processors;
+    (ts+loop)->shared_exchange = &exchange;
+    (ts+loop)->number_elements = number_elements;
+  }
+
+  exchange = 0;
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  // TRD : non-atomic
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_exchange, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
+      *(merged_counter_arrays+loop) += *( (ts+subloop)->counter_array+loop );
+
+  /* TRD : the worker threads exit when their per-thread counter exceeds 1,000,000
+           as such the final number_logical_processors numbers are not read
+           we could change the threads to exit when the number they read exceeds 1,000,000
+           but then we'd need an if() in their work-loop,
+           and we need to go as fast as possible
+  */
+
+  for( loop = 0 ; loop < number_elements - number_logical_processors ; loop++ )
+    if( *(merged_counter_arrays+loop) != 1 )
+      exchange_success_flag = LOWERED;
+
+  // TRD : now for atomic exchange - we need to re-init the data structures
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    *(merged_counter_arrays+loop) = 0;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+      *((ts+loop)->counter_array+subloop) = 0;
+
+  exchange = 0;
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_atomic_exchange, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
+      *(merged_counter_arrays+loop) += *( (ts+subloop)->counter_array+loop );
+
+  for( loop = 0 ; loop < number_elements - number_logical_processors ; loop++ )
+    if( *(merged_counter_arrays+loop) != 1 )
+      atomic_exchange_success_flag = LOWERED;
+
+  // TRD : cleanup
+  free( merged_counter_arrays );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    free( (ts+loop)->counter_array );
+
+  util_thread_starter_delete( tts );
+  free( thread_handles );
+  free( ts );
+
+  /* TRD : results
+
+           on a single core, atomic and non-atomic exchange should both work
+
+           if we find our non-atomic test passes, then we can't really say anything
+           about whether or not the atomic test is really working
+  */
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  if( number_logical_processors == 1 )
+  {
+    if( exchange_success_flag == RAISED and atomic_exchange_success_flag == RAISED )
+      puts( "passed" );
+
+    if( exchange_success_flag != RAISED or atomic_exchange_success_flag != RAISED )
+      puts( "failed (atomic and non-atomic both failed)" );
+  }
+
+  if( number_logical_processors >= 2 )
+  {
+    if( atomic_exchange_success_flag == RAISED and exchange_success_flag == LOWERED )
+      puts( "passed" );
+
+    if( atomic_exchange_success_flag == RAISED and exchange_success_flag == RAISED )
+      puts( "indeterminate (atomic and non-atomic both passed)" );
+
+    if( atomic_exchange_success_flag == LOWERED )
+    {
+      puts( "failed (atomic failed)" );
+      exit( EXIT_FAILURE );
+    }
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_exchange( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    local_counter,
+    exchange;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  local_counter = ts->counter;
+
+  while( local_counter < ts->number_elements )
+  {
+    exchange = *ts->shared_exchange;
+    *ts->shared_exchange = local_counter;
+
+    ( *(ts->counter_array + exchange) )++;
+
+    local_counter += ts->number_logical_processors;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_atomic_exchange( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    local_counter,
+    exchange;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  local_counter = ts->counter;
+
+  while( local_counter < ts->number_elements )
+  {
+    exchange = local_counter;
+
+    LFDS700_PAL_ATOMIC_EXCHANGE( ts->shared_exchange, &exchange );
+
+    ( *(ts->counter_array + exchange) )++;
+
+    local_counter += ts->number_logical_processors;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e41b01b5dc360a2c2ffcb417fcec2d371bcf4d0
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue.c
@@ -0,0 +1,35 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_queue( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
+  {
+    printf( "\n"
+            "Queue Tests\n"
+            "===========\n" );
+
+    test_lfds700_queue_alignment();
+    test_lfds700_queue_enqueuing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_queue_dequeuing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_queue_enqueuing_and_dequeuing( list_of_logical_processors );
+    test_lfds700_queue_rapid_enqueuing_and_dequeuing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_queue_enqueuing_and_dequeuing_with_free( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free( list_of_logical_processors );
+  }
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_alignment.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_alignment.c
new file mode 100644
index 0000000000000000000000000000000000000000..6f723825eae65ab32e618861c8447e259aaf5443
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_alignment.c
@@ -0,0 +1,55 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_queue_alignment()
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  /* TRD : these are compile time checks
+           but we do them here because this is a test programme
+           and it should indicate issues to users when it is *run*,
+           not when it is compiled, because a compile error normally
+           indicates a problem with the code itself and so is misleading
+  */
+
+  internal_display_test_name( "Alignment" );
+
+
+
+  // TRD : struct lfds700_queue_element
+  if( offsetof(struct lfds700_queue_element,next) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_queue_element,key) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : struct lfds700_queue_state
+  if( offsetof(struct lfds700_queue_state,enqueue) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_queue_state,dequeue) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_queue_state,user_state) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "queue", dvs );
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c660ab3e1c2d3cac25d8103ac87018f92aeedd5
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer.c
@@ -0,0 +1,25 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_bss( struct lfds700_list_asu_state *list_of_logical_processors )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  printf( "\n"
+          "Queue (bounded, single consumer, single producer) Tests\n"
+          "=======================================================\n" );
+
+  // TRD : no alignment checks are required for queue_bss
+  test_lfds700_queue_bss_enqueuing();
+  test_lfds700_queue_bss_dequeuing();
+  test_lfds700_queue_bss_enqueuing_and_dequeuing( list_of_logical_processors );
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c
new file mode 100644
index 0000000000000000000000000000000000000000..971555c4436934cb9f36a84554f21f5636076136
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_dequeuing.c
@@ -0,0 +1,61 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_bss_dequeuing()
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_queue_bss_element
+    element_array[128];
+
+  struct lfds700_queue_bss_state
+    qs;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  void
+    *value;
+
+  /* TRD : create an empty queue
+           enqueue 128 elements
+           then dequeue the elements, in the same thread - we're API testing
+           it's a single producer queue, so we just do this in our current thread
+           since we're enqueuing and dequeuing in the same thread,
+           
+  */
+
+  internal_display_test_name( "Dequeuing" );
+
+  lfds700_queue_bss_init_valid_on_current_logical_core( &qs, element_array, 128, NULL );
+
+  for( loop = 0 ; loop < 127 ; loop++ )
+    lfds700_queue_bss_enqueue( &qs, NULL, (void *) loop );
+
+  for( loop = 0 ; loop < 127 ; loop++ )
+  {
+    lfds700_queue_bss_dequeue( &qs, NULL, &value );
+    if( (lfds700_pal_uint_t) value != 127 - loop )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+  }
+
+  vi.min_elements = vi.max_elements = 0;
+
+  lfds700_queue_bss_query( &qs, LFDS700_QUEUE_BSS_QUERY_VALIDATE, &vi, &dvs );
+
+  lfds700_queue_bss_cleanup( &qs, NULL );
+
+  internal_display_test_result( 1, "queue_bss", dvs );
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c
new file mode 100644
index 0000000000000000000000000000000000000000..807337864aa02ce67781d954eefed05ea16a5e62
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing.c
@@ -0,0 +1,59 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_bss_enqueuing()
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  int
+    rv;
+
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_queue_bss_element
+    element_array[128];
+
+  struct lfds700_queue_bss_state
+    qs;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  /* TRD : create an empty queue
+           enqueue 128 elements
+           it's a single producer queue, so we just do this in our current thread
+           it's an API test
+  */
+
+  internal_display_test_name( "Enqueuing" );
+
+  lfds700_queue_bss_init_valid_on_current_logical_core( &qs, element_array, 128, NULL );
+
+  for( loop = 0 ; loop < 127 ; loop++ )
+    if( 1 != lfds700_queue_bss_enqueue(&qs, NULL, (void *) loop) )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  // TRD : at this point enqueuing one more should return 0
+  rv = lfds700_queue_bss_enqueue( &qs, NULL, (void *) loop );
+
+  if( rv != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  vi.min_elements = vi.max_elements = 127;
+
+  lfds700_queue_bss_query( &qs, LFDS700_QUEUE_BSS_QUERY_VALIDATE, &vi, &dvs );
+
+  lfds700_queue_bss_cleanup( &qs, NULL );
+
+  internal_display_test_result( 1, "queue_bss", dvs );
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c
new file mode 100644
index 0000000000000000000000000000000000000000..ad218609fd36204681ea9002c1d39d092bee0aed
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_bounded_singleconsumer_singleproducer_enqueuing_and_dequeuing.c
@@ -0,0 +1,260 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  enum flag
+    error_flag;
+
+  struct lfds700_queue_bss_state
+    *qs;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer( void *util_thread_starter_thread_state );
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_dequeuer( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_bss_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_logical_processors,
+    subloop;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_queue_bss_element
+    element_array[4];
+
+  struct lfds700_queue_bss_state
+    qs;
+
+  struct test_pal_logical_processor
+    *lp,
+    *lp_first;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+
+  /* TRD : so, this is the real test
+           problem is, because we use memory barriers only
+           and we only support one producer and one consumer
+           we need to ensure these threads are on different physical cores
+           if they're on the same core, the code would work even without memory barriers
+
+           problem is, in the test application, we only know the *number* of logical cores
+           obtaining topology information adds a great deal of complexity to the test app
+           and makes porting much harder
+
+           so, we know how many logical cores there are; my thought is to partially
+           permutate over them - we always run the producer on core 0, but we iterate
+           over the other logical cores, running the test once each time, with the
+           consumer being run on core 0, then core 1, then core 2, etc
+
+           (we run on core 0 for the single-cpu case; it's redundent, since a single
+            logical core running both producer and consumer will work, but otherwise
+            we have to skip the test, which is confusing for the user)
+
+           the test is one thread enqueuing and one thread dequeuing for two seconds
+  */
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  internal_display_test_name( "Enqueuing and dequeuing (%d seconds)", number_logical_processors * 2 );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * 2 );
+
+  for( loop = 0 ; loop < 2 ; loop++ )
+  {
+    (ts+loop)->qs = &qs;
+    (ts+loop)->error_flag = LOWERED;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * 2 );
+
+  /* TRD : producer always on core 0
+           iterate over the other cores with consumer
+  */
+  
+  lasue = LFDS700_LIST_ASU_GET_START( *list_of_logical_processors );
+  lp_first = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+
+  while( lasue != NULL )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+
+    lfds700_queue_bss_init_valid_on_current_logical_core( &qs, element_array, 4, NULL );
+
+    util_thread_starter_new( &tts, 2 );
+
+    LFDS700_MISC_BARRIER_STORE;
+
+    lfds700_misc_force_store();
+
+    util_thread_starter_start( tts, &thread_handles[0], 0, lp_first, thread_enqueuer, ts );
+    util_thread_starter_start( tts, &thread_handles[1], 1, lp, thread_dequeuer, ts+1 );
+
+    util_thread_starter_run( tts );
+
+    for( subloop = 0 ; subloop < 2 ; subloop++ )
+      test_pal_thread_wait( thread_handles[subloop] );
+
+    util_thread_starter_delete( tts );
+
+    LFDS700_MISC_BARRIER_LOAD;
+
+    lfds700_queue_bss_cleanup( &qs, NULL );
+
+    lasue = LFDS700_LIST_ASU_GET_NEXT( *lasue );
+  }
+
+  if( (ts+1)->error_flag == RAISED )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  free( thread_handles );
+
+  free( ts );
+
+  internal_display_test_result( 1, "queue_bss", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer( void *util_thread_starter_thread_state )
+{
+  int
+    rv;
+
+  lfds700_pal_uint_t
+    datum = 0,
+    time_loop = 0;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + 2 )
+  {
+    rv = lfds700_queue_bss_enqueue( ts->qs, NULL, (void *) datum );
+
+    if( rv == 1 )
+      if( ++datum == 4 )
+        datum = 0;
+
+    if( time_loop++ == TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_dequeuer( void *util_thread_starter_thread_state )
+{
+  int
+    rv;
+
+  lfds700_pal_uint_t
+    datum,
+    expected_datum = 0,
+    time_loop = 0;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + 2 )
+  {
+    rv = lfds700_queue_bss_dequeue( ts->qs, NULL, (void *) &datum );
+
+    if( rv == 1 )
+    {
+      if( datum != expected_datum )
+        ts->error_flag = RAISED;
+
+      if( ++expected_datum == 4 )
+        expected_datum = 0;
+    }
+
+    if( time_loop++ == TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_dequeuing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_dequeuing.c
new file mode 100644
index 0000000000000000000000000000000000000000..74f271d320012044527e1f89a5d06fb3b6a289df
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_dequeuing.c
@@ -0,0 +1,215 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  enum flag
+    error_flag;
+
+  struct lfds700_queue_state
+    *qs;
+};
+
+struct test_element
+{
+  struct lfds700_queue_element
+    qe;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_dequeuer( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements_with_dummy_element,
+    number_elements_without_dummy_element,
+    number_logical_processors;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_state
+    qs;
+
+  struct lfds700_misc_validation_info
+    vi = { 0, 0 };
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : create a queue, add 1,000,000 elements
+
+           use a single thread to enqueue every element
+           each elements user data is an incrementing counter
+
+           then run one thread per CPU
+           where each busy-works dequeuing
+
+           when an element is dequeued, we check (on a per-thread basis) the
+           value dequeued is greater than the element previously dequeued
+
+           note we have no variation in the test for CAS+GC vs DWCAS
+           this is because all we do is dequeue
+           what we actually want to stress test is the queue
+           not CAS
+           so it's better to let the dequeue run as fast as possible
+  */
+
+  internal_display_test_name( "Dequeuing" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element);
+  number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
+
+  te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array + number_elements_without_dummy_element)->qe, &ps, NULL );
+
+  for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
+  {
+    LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, loop );
+    lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
+  }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->qs = &qs;
+    (ts+loop)->error_flag = LOWERED;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_dequeuer, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  // TRD : check queue is empty
+  lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  // TRD : check for raised error flags
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    if( (ts+loop)->error_flag == RAISED )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  free( ts );
+
+  util_aligned_free( te_array );
+
+  lfds700_queue_cleanup( &qs, NULL );
+
+  internal_display_test_result( 1, "queue", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_dequeuer( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    *prev_value,
+    *value;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_queue_dequeue( ts->qs, &qe, &ps );
+  prev_value = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( lfds700_queue_dequeue(ts->qs, &qe, &ps) )
+  {
+    value = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
+
+    if( value <= prev_value )
+      ts->error_flag = RAISED;
+
+    prev_value = value;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing.c
new file mode 100644
index 0000000000000000000000000000000000000000..89ccf30fcbd184b9fea2440e8dcb643f3cf7c32a
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing.c
@@ -0,0 +1,239 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_elements,
+    thread_number;
+
+  struct lfds700_queue_state
+    *qs;
+
+  struct test_element
+    *te_array;
+};
+
+struct test_element
+{
+  struct lfds700_queue_element
+    qe;
+
+  lfds700_pal_uint_t
+    counter,
+    thread_number;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_enqueuer( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_enqueuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    *per_thread_counters,
+    loop,
+    number_elements,
+    number_logical_processors;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_element
+    dummy_qe,
+    *qe;
+
+  struct lfds700_queue_state
+    qs;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : create an empty queue
+           then run one thread per CPU
+           where each thread busy-works, enqueuing elements from a freelist (one local freelist per thread)
+           until 100000 elements are enqueued, per thread
+           each element's void pointer of user data is a struct containing thread number and element number
+           where element_number is a thread-local counter starting at 0
+
+           when we're done, we check that all the elements are present
+           and increment on a per-thread basis
+  */
+
+  internal_display_test_name( "Enqueuing" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+
+  lfds700_queue_init_valid_on_current_logical_core( &qs, &dummy_qe, &ps, NULL );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->qs = &qs;
+    (ts+loop)->thread_number = loop;
+    (ts+loop)->number_elements = number_elements;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_enqueuer, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  /* TRD : first, validate the queue
+
+           then dequeue
+           we expect to find element numbers increment on a per thread basis
+  */
+
+  vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
+
+  lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    *(per_thread_counters+loop) = 0;
+
+  while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_queue_dequeue(&qs, &qe, &ps) )
+  {
+    te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
+
+    if( te->thread_number >= number_logical_processors )
+    {
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( te->counter > per_thread_counters[te->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( te->counter < per_thread_counters[te->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( te->counter == per_thread_counters[te->thread_number] )
+      per_thread_counters[te->thread_number]++;
+  }
+
+  free( per_thread_counters );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    util_aligned_free( (ts+loop)->te_array );
+
+  free( ts );
+
+  lfds700_queue_cleanup( &qs, NULL );
+
+  internal_display_test_result( 1, "queue", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_enqueuer( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  ts->te_array = util_aligned_malloc( sizeof(struct test_element) * ts->number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < ts->number_elements ; loop++ )
+  {
+    (ts->te_array+loop)->thread_number = ts->thread_number;
+    (ts->te_array+loop)->counter = loop;
+  }
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  for( loop = 0 ; loop < ts->number_elements ; loop++ )
+  {
+    LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (ts->te_array+loop)->qe, ts->te_array+loop );
+    lfds700_queue_enqueue( ts->qs, &(ts->te_array+loop)->qe, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_and_dequeuing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_and_dequeuing.c
new file mode 100644
index 0000000000000000000000000000000000000000..1469635fd4592b39107b1a17b9d1511a10c077b2
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_and_dequeuing.c
@@ -0,0 +1,250 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  enum flag
+    error_flag;
+
+  lfds700_pal_uint_t
+    counter,
+    number_logical_processors,
+    *per_thread_counters,
+    thread_number;
+
+  struct lfds700_queue_state
+    *qs;
+};
+
+struct test_element
+{
+  struct lfds700_queue_element
+    qe,
+    *qe_use;
+
+  lfds700_pal_uint_t
+    counter,
+    thread_number;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_and_dequeuer( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_logical_processors,
+    subloop;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_state
+    qs;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : qt can be any value in its range
+
+  /* TRD : create a queue with one element per thread
+           each thread constly dequeues and enqueues from that one queue
+           where when enqueuing sets in the element
+           its thread number and counter
+           and when dequeuing, checks the thread number and counter
+           against previously seen counter for that thread
+           where it should always see a higher number
+  */
+
+  internal_display_test_name( "Enqueuing and dequeuing (%d seconds)", TEST_DURATION_IN_SECONDS );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  te_array = util_aligned_malloc( sizeof(struct test_element) * (number_logical_processors+1), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array+number_logical_processors)->qe, &ps, NULL );
+
+  // TRD : we assume the test will iterate at least once (or we'll have a false negative)
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (te_array+loop)->thread_number = loop;
+    (te_array+loop)->counter = 0;
+    LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, te_array+loop );
+    lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
+  }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->qs = &qs;
+    (ts+loop)->thread_number = loop;
+    (ts+loop)->counter = 0;
+    (ts+loop)->error_flag = LOWERED;
+    (ts+loop)->per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+    (ts+loop)->number_logical_processors = number_logical_processors;
+
+    for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
+      *((ts+loop)->per_thread_counters+subloop) = 0;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_enqueuer_and_dequeuer, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = number_logical_processors;
+
+  lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    if( (ts+loop)->error_flag == RAISED )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    free( (ts+loop)->per_thread_counters );
+
+  util_aligned_free( te_array );
+
+  free( ts );
+
+  lfds700_queue_cleanup( &qs, NULL );
+
+  internal_display_test_result( 1, "queue", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_and_dequeuer( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    time_loop = 0;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct test_element
+    *te;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    lfds700_queue_dequeue( ts->qs, &qe, &ps );
+    te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
+
+    if( te->thread_number >= ts->number_logical_processors )
+      ts->error_flag = RAISED;
+    else
+    {
+      if( te->counter < ts->per_thread_counters[te->thread_number] )
+        ts->error_flag = RAISED;
+
+      if( te->counter >= ts->per_thread_counters[te->thread_number] )
+        ts->per_thread_counters[te->thread_number] = te->counter+1;
+    }
+
+    te->thread_number = ts->thread_number;
+    te->counter = ++ts->counter;
+
+    LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( *qe, te );
+    lfds700_queue_enqueue( ts->qs, qe, &ps );
+
+    if( time_loop++ == TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_and_dequeuing_with_free.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_and_dequeuing_with_free.c
new file mode 100644
index 0000000000000000000000000000000000000000..21be07052d59ac0d30dc186ab2da83260feb32a8
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_and_dequeuing_with_free.c
@@ -0,0 +1,241 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_of_elements_per_thread;
+
+  struct lfds700_queue_state
+    *qs;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueue_dequeuer_with_free( void *util_thread_starter_thread_state );
+static void queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_enqueuing_and_dequeuing_with_free( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors,
+    number_of_elements_per_thread;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct lfds700_queue_state
+    qs;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_state
+    *tts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : the M&Q queue supports free()ing queue elements after they've been dequeued
+           we need to test this
+           we spawn one thread per logical core
+           there's one master queue which all threads work on
+           we create one freelist per thread
+           and allocate as many queue elements as we can (no payload)
+           - but note each allocate is its own malloc()
+           each freelist receives an equal share (i.e. we get the mallocs out of the way)
+           each thread enqueues as rapidly as possible
+           and dequeues as rapidly as possible
+           (i.e. each thread loops, doing an enqueue and a dequeue)
+           when the dequeue is done, the element is free()ed
+  */
+
+  internal_display_test_name( "Enqueuing and dequeuing with free" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct lfds700_freelist_element) + sizeof(struct lfds700_queue_element) );
+  number_of_elements_per_thread = number_elements / number_logical_processors;
+  qe = util_aligned_malloc( sizeof(struct lfds700_queue_element), (lfds700_pal_uint_t) LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+  lfds700_queue_init_valid_on_current_logical_core( &qs, qe, &ps, NULL );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->qs = &qs;
+    (ts+loop)->number_of_elements_per_thread = number_of_elements_per_thread;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_enqueue_dequeuer_with_free, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = 0;
+  vi.max_elements = 0;
+
+  lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  lfds700_queue_cleanup( &qs, queue_element_cleanup_callback );
+
+  free( ts );
+
+  internal_display_test_result( 1, "queue", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueue_dequeuer_with_free( void *util_thread_starter_thread_state )
+{
+  enum flag
+    finished_flag = LOWERED;
+
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_freelist_element
+    *fe,
+    *fe_array;
+
+  struct lfds700_freelist_state
+    fs;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
+
+  fe_array = util_malloc_wrapper( sizeof(struct lfds700_freelist_element) * ts->number_of_elements_per_thread );
+
+  for( loop = 0 ; loop < ts->number_of_elements_per_thread ; loop++ )
+  {
+    qe = util_aligned_malloc( sizeof(struct lfds700_queue_element), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+    LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( fe_array[loop], qe );
+    lfds700_freelist_push( &fs, &fe_array[loop], &ps );
+  }
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( finished_flag == LOWERED )
+  {
+    loop = 0;
+    while( loop++ < 1000 and lfds700_freelist_pop(&fs, &fe, &ps) )
+    {
+      qe = LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
+      lfds700_queue_enqueue( ts->qs, qe, &ps );
+    }
+
+    if( loop < 1000 )
+      finished_flag = RAISED;
+
+    loop = 0;
+    while( loop++ < 1000 and lfds700_queue_dequeue(ts->qs, &qe, &ps) )
+      util_aligned_free( qe );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  lfds700_freelist_cleanup( &fs, NULL );
+
+  free( fe_array );
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static void queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag )
+{
+  assert( qs != NULL );
+  assert( qe != NULL );
+  // TRD : dummy_element_flag can be any value in its range
+
+  util_aligned_free( qe );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c
new file mode 100644
index 0000000000000000000000000000000000000000..0f0fa7f08104f48c5a820fe9fdc30faacb1dc103
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free.c
@@ -0,0 +1,208 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  struct lfds700_queue_state
+    *qs;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_with_malloc_and_dequeuer_with_free( void *util_thread_starter_thread_state );
+static void queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_enqueuing_with_malloc_and_dequeuing_with_free( struct lfds700_list_asu_state *list_of_logical_processors )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_logical_processors;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct lfds700_queue_state
+    qs;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : qt can be any value in its range
+
+  /* TRD : one thread per logical core
+           each thread loops for ten seconds
+           mallocs and enqueues 1k elements, then dequeues and frees 1k elements
+  */
+
+  internal_display_test_name( "Enqueuing with malloc dequeuing with free (%d seconds)", TEST_DURATION_IN_SECONDS );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  qe = util_aligned_malloc( sizeof(struct lfds700_queue_element), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_queue_init_valid_on_current_logical_core( &qs, qe, &ps, NULL );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    (ts+loop)->qs = &qs;
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_enqueuer_with_malloc_and_dequeuer_with_free, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = 0;
+
+  lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  free( ts );
+
+  lfds700_queue_cleanup( &qs, queue_element_cleanup_callback );
+
+  internal_display_test_result( 1, "queue", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_with_malloc_and_dequeuer_with_free( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    loop,
+    time_loop = 0;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    for( loop = 0 ; loop < 1000 ; loop++ )
+    {
+      qe = util_aligned_malloc( sizeof(struct lfds700_queue_element), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+      lfds700_queue_enqueue( ts->qs, qe, &ps );
+    }
+
+    for( loop = 0 ; loop < 1000 ; loop++ )
+    {
+      lfds700_queue_dequeue( ts->qs, &qe, &ps );
+      util_aligned_free( qe );
+    }
+
+    if( time_loop++ == REDUCED_TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+static void queue_element_cleanup_callback( struct lfds700_queue_state *qs, struct lfds700_queue_element *qe, enum lfds700_misc_flag dummy_element_flag )
+{
+  assert( qs != NULL );
+  assert( qe != NULL );
+  // TRD : dummy_element_flag can be any value in its range
+
+  util_aligned_free( qe );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_rapid_enqueuing_and_dequeuing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_rapid_enqueuing_and_dequeuing.c
new file mode 100644
index 0000000000000000000000000000000000000000..ec3963a336b7d94c8b60e928e34f827628a1ea12
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_queue_rapid_enqueuing_and_dequeuing.c
@@ -0,0 +1,264 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  lfds700_pal_uint_t
+    counter,
+    thread_number;
+
+  struct lfds700_queue_state
+    *qs;
+};
+
+struct test_element
+{
+  struct lfds700_queue_element
+    qe,
+    *qe_use;
+
+  lfds700_pal_uint_t
+    counter,
+    thread_number;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_enqueuer_and_dequeuer( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_queue_rapid_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements_with_dummy_element,
+    number_elements_without_dummy_element,
+    number_logical_processors,
+    *per_thread_counters;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct lfds700_queue_state
+    qs;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array,
+    *te;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a single queue with 50,000 elements
+           we don't want too many elements, so we ensure plenty of element re-use
+           each thread simply loops dequeuing and enqueuing
+           where the user data indicates thread number and an increment counter
+           vertification is that the counter increments on a per-thread basis
+  */
+
+  internal_display_test_name( "Rapid enqueuing and dequeuing (%d seconds)", TEST_DURATION_IN_SECONDS );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element);
+
+  if( number_elements_with_dummy_element > (10000 * number_logical_processors) + 1 )
+    number_elements_with_dummy_element = (10000 * number_logical_processors) + 1;
+
+  number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
+
+  vi.min_elements = number_elements_without_dummy_element;
+  vi.max_elements = number_elements_without_dummy_element;
+
+  te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array+number_elements_without_dummy_element)->qe, &ps, NULL );
+
+  // TRD : we assume the test will iterate at least once (or we'll have a false negative)
+  for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
+  {
+    (te_array+loop)->thread_number = loop;
+    (te_array+loop)->counter = 0;
+    LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, te_array+loop );
+    lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
+  }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->qs = &qs;
+    (ts+loop)->thread_number = loop;
+    (ts+loop)->counter = 0;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_rapid_enqueuer_and_dequeuer, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  // TRD : now check results
+  per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    *(per_thread_counters+loop) = 0;
+
+  while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_queue_dequeue(&qs, &qe, &ps) )
+  {
+    te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
+
+    if( te->thread_number >= number_logical_processors )
+    {
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( per_thread_counters[te->thread_number] == 0 )
+      per_thread_counters[te->thread_number] = te->counter;
+
+    if( te->counter > per_thread_counters[te->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( te->counter < per_thread_counters[te->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( te->counter == per_thread_counters[te->thread_number] )
+      per_thread_counters[te->thread_number]++;
+  }
+
+  free( per_thread_counters );
+
+  lfds700_queue_cleanup( &qs, NULL );
+
+  util_aligned_free( te_array );
+
+  free( ts );
+
+  internal_display_test_result( 1, "queue", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_enqueuer_and_dequeuer( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    time_loop = 0;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_queue_element
+    *qe;
+
+  struct test_element
+    *te;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    lfds700_queue_dequeue( ts->qs, &qe, &ps );
+    te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
+
+    te->thread_number = ts->thread_number;
+    te->counter = ts->counter++;
+
+    LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( *qe, te );
+    lfds700_queue_enqueue( ts->qs, qe, &ps );
+
+    if( time_loop++ == TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer.c
new file mode 100644
index 0000000000000000000000000000000000000000..0a7de0761be4662d46145a85442350b325cdd95b
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer.c
@@ -0,0 +1,31 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_ringbuffer( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
+  {
+    printf( "\n"
+            "Ringbuffer Tests\n"
+            "================\n" );
+
+    test_lfds700_ringbuffer_reading( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_ringbuffer_reading_and_writing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_ringbuffer_writing( list_of_logical_processors, memory_in_megabytes );
+  }
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading.c
new file mode 100644
index 0000000000000000000000000000000000000000..00d378992e1aa3fd8fdfd5e0c3a1050a52be8c41
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading.c
@@ -0,0 +1,217 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  enum flag
+    error_flag;
+
+  lfds700_pal_uint_t
+    read_count;
+
+  struct lfds700_ringbuffer_state
+    *rs;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_reader( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_ringbuffer_reading( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements_with_dummy_element,
+    number_elements_without_dummy_element,
+    number_logical_processors,
+    total_read = 0;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_ringbuffer_element
+    *re_array;
+
+  struct lfds700_ringbuffer_state
+    rs;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a single ringbuffer
+           with 1,000,000 elements
+           we populate the ringbuffer, where the
+           user data is an incrementing counter
+
+           we create one thread per CPU
+           where each thread busy-works,
+           reading until the ringbuffer is empty
+
+           each thread keep track of the number of reads it manages
+           and that each user data it reads is greater than the
+           previous user data that was read
+  */
+
+  internal_display_test_name( "Reading" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct lfds700_ringbuffer_element);
+  number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
+
+  vi.min_elements = 0;
+  vi.max_elements = number_elements_without_dummy_element;
+
+  re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
+
+  // TRD : init the ringbuffer contents for the test
+  for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
+    lfds700_ringbuffer_write( &rs, NULL, (void *) (size_t) loop, NULL, NULL, NULL, &ps );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->rs = &rs;
+    (ts+loop)->read_count = 0;
+    (ts+loop)->error_flag = LOWERED;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_reader, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
+
+  // TRD : check for raised error flags
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    if( (ts+loop)->error_flag == RAISED )
+      dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  // TRD : check thread reads total to 1,000,000
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    total_read += (ts+loop)->read_count;
+
+  if( total_read < number_elements_without_dummy_element )
+    dvs[0] = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+  if( total_read > number_elements_without_dummy_element )
+    dvs[0] = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+  free( ts );
+
+  lfds700_ringbuffer_cleanup( &rs, NULL );
+
+  util_aligned_free( re_array );
+
+  internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_reader( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    *prev_value,
+    *value;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_ringbuffer_read( ts->rs, NULL, (void **) &prev_value, &ps );
+  ts->read_count++;
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( lfds700_ringbuffer_read(ts->rs, NULL, (void **) &value, &ps) )
+  {
+    if( value <= prev_value )
+      ts->error_flag = RAISED;
+
+    prev_value = value;
+
+    ts->read_count++;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading_and_writing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading_and_writing.c
new file mode 100644
index 0000000000000000000000000000000000000000..152c3318923c40b47a2d9699c7e6f10478d357b7
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading_and_writing.c
@@ -0,0 +1,261 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  enum flag
+    error_flag;
+
+  lfds700_pal_uint_t
+    counter,
+    number_logical_processors,
+    *per_thread_counters,
+    thread_number;
+
+  struct lfds700_ringbuffer_state
+    *rs;
+};
+
+struct test_element
+{
+  lfds700_pal_uint_t
+    datum,
+    thread_number;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_reader_writer( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_ringbuffer_reading_and_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements_with_dummy_element,
+    number_elements_without_dummy_element,
+    number_logical_processors,
+    subloop;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_ringbuffer_element
+    *re_array;
+
+  struct lfds700_ringbuffer_state
+    rs;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a single ringbuffer
+           with 100,000 elements
+           the ringbuffers starts empty
+
+           we create one thread per CPU
+           where each thread busy-works writing
+           and then immediately reading
+           for ten seconds
+
+           the user data in each written element is a combination
+           of the thread number and the counter
+
+           while a thread runs, it keeps track of the
+           counters for the other threads and throws an error
+           if it sees the number stay the same or decrease
+  */
+
+  internal_display_test_name( "Reading and writing (%d seconds)", TEST_DURATION_IN_SECONDS );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) + sizeof(struct lfds700_ringbuffer_element) );
+  number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
+
+  vi.min_elements = 0;
+  vi.max_elements = number_elements_without_dummy_element;
+
+  re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
+
+  te_array = util_malloc_wrapper( sizeof(struct test_element) * number_elements_without_dummy_element );
+
+  // TRD : populate the ringbuffer
+  for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
+  {
+    te_array[loop].thread_number = 0;
+    te_array[loop].datum = (lfds700_pal_uint_t) -1 ;
+    lfds700_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL, &ps );
+  }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->rs = &rs;
+    (ts+loop)->thread_number = loop;
+    (ts+loop)->counter = 0;
+    (ts+loop)->number_logical_processors = number_logical_processors;
+    (ts+loop)->error_flag = LOWERED;
+    (ts+loop)->per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+
+    for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
+      *((ts+loop)->per_thread_counters+subloop) = 0;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_reader_writer, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    if( (ts+loop)->error_flag == RAISED )
+      dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    free( (ts+loop)->per_thread_counters );
+
+  free( ts );
+
+  lfds700_ringbuffer_cleanup( &rs, NULL );
+
+  util_aligned_free( re_array );
+
+  free( te_array );
+
+  internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_reader_writer( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    time_loop = 0;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_element
+    *te;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    lfds700_ringbuffer_read( ts->rs, NULL, (void **) &te, &ps );
+
+    if( te->thread_number >= ts->number_logical_processors )
+      ts->error_flag = RAISED;
+    else
+    {
+      if( te->datum < ts->per_thread_counters[te->thread_number] )
+        ts->error_flag = RAISED;
+
+      if( te->datum >= ts->per_thread_counters[te->thread_number] )
+        ts->per_thread_counters[te->thread_number] = te->datum+1;
+    }
+
+    te->thread_number = ts->thread_number;
+    te->datum = ts->counter++;
+
+    lfds700_ringbuffer_write( ts->rs, NULL, te, NULL, NULL, NULL, &ps );
+
+    if( time_loop++ == TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer_writing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer_writing.c
new file mode 100644
index 0000000000000000000000000000000000000000..702aabc58d4209718f75152c00fa54653fe5befd
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_ringbuffer_writing.c
@@ -0,0 +1,272 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element
+{
+  lfds700_pal_uint_t
+    thread_number,
+    datum;
+};
+
+struct test_state
+{
+  lfds700_pal_uint_t
+    thread_number,
+    write_count;
+
+  struct test_element
+    te;
+
+  struct lfds700_ringbuffer_state
+    *rs;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_writer( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_ringbuffer_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements_with_dummy_element,
+    number_elements_without_dummy_element,
+    number_logical_processors,
+    *per_thread_counters;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_ringbuffer_element
+    *re_array;
+
+  struct lfds700_ringbuffer_state
+    rs;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te,
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a single ringbuffer
+           with n elements
+           we create n test elements
+           which are thread_number/counter pairs
+           init them to safe values
+           and fully populate the ringbuffer
+
+           we create one thread per CPU
+           where each thread busy-works writing
+           for ten seconds; each thread has one extra element
+           which it uses for the first write and after that
+           it uses the element it picks up from overwriting
+
+           the user data in each written element is a combination
+           of the thread number and the counter
+
+           after the threads are complete, we validate by
+           checking the user data counters increment on a per thread
+           basis
+  */
+
+  internal_display_test_name( "Writing (%d seconds)", TEST_DURATION_IN_SECONDS );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) + sizeof(struct lfds700_ringbuffer_element) );
+  number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
+
+  vi.min_elements = number_elements_without_dummy_element;
+  vi.max_elements = number_elements_without_dummy_element;
+
+  re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
+
+  te_array = util_malloc_wrapper( sizeof(struct lfds700_ringbuffer_element) * number_elements_without_dummy_element );
+
+  // TRD : init the test elements and write them into the ringbuffer
+  for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
+  {
+    te_array[loop].thread_number = 0;
+    te_array[loop].datum = 0;
+    lfds700_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL, &ps );
+  }
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->rs = &rs;
+    (ts+loop)->thread_number = loop;
+    (ts+loop)->write_count = 0;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_writer, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  // TRD : now check results
+  per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    *(per_thread_counters+loop) = 0;
+
+  lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
+
+  while( dvs[0] == LFDS700_MISC_VALIDITY_VALID and dvs[1] == LFDS700_MISC_VALIDITY_VALID and lfds700_ringbuffer_read(&rs, NULL, (void **) &te, &ps) )
+  {
+    if( te->thread_number >= number_logical_processors )
+    {
+      dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( per_thread_counters[te->thread_number] == 0 )
+      per_thread_counters[te->thread_number] = te->datum;
+
+    if( te->datum < per_thread_counters[te->thread_number] )
+      dvs[0] = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( te->datum >= per_thread_counters[te->thread_number] )
+      per_thread_counters[te->thread_number] = te->datum+1;
+  }
+
+  free( per_thread_counters );
+
+  lfds700_ringbuffer_cleanup( &rs, NULL );
+
+  free( ts );
+
+  util_aligned_free( re_array );
+
+  free( te_array );
+
+  internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_writer( void *util_thread_starter_thread_state )
+{
+  enum lfds700_misc_flag
+    overwrite_occurred_flag;
+
+  lfds700_pal_uint_t
+    time_loop = 0;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_element
+    *te;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  ts->te.thread_number = 0;
+  ts->te.datum = 0;
+
+  lfds700_ringbuffer_write( ts->rs, NULL, &ts->te, &overwrite_occurred_flag, NULL, (void **) &te, &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    te->thread_number = ts->thread_number;
+    te->datum = ts->write_count++;
+
+    lfds700_ringbuffer_write( ts->rs, NULL, te, &overwrite_occurred_flag, NULL, (void **) &te, &ps );
+
+    if( time_loop++ == TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack.c
new file mode 100644
index 0000000000000000000000000000000000000000..af3a37512a09b49ed37384bc2d59e9bb6aa04063
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack.c
@@ -0,0 +1,33 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_stack( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  if( LFDS700_MISC_ATOMIC_SUPPORT_DWCAS )
+  {
+    printf( "\n"
+            "Stack Tests\n"
+            "===========\n" );
+
+    test_lfds700_stack_alignment();
+    test_lfds700_stack_popping( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_stack_pushing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_stack_popping_and_pushing( list_of_logical_processors, memory_in_megabytes );
+    test_lfds700_stack_rapid_popping_and_pushing( list_of_logical_processors );
+  }
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_alignment.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_alignment.c
new file mode 100644
index 0000000000000000000000000000000000000000..7add41bd480b7e95979228dcc4455ff9831f7ce6
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_alignment.c
@@ -0,0 +1,43 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4127 ) // TRD : disables MSVC warning for condition expressions being const
+
+void test_lfds700_stack_alignment()
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  /* TRD : these are compile time checks
+           but we do them here because this is a test programme
+           and it should indicate issues to users when it is *run*,
+           not when it is compiled, because a compile error normally
+           indicates a problem with the code itself and so is misleading
+  */
+
+  internal_display_test_name( "Alignment" );
+
+
+
+  // TRD : struct lfds700_stack_state
+  if( offsetof(struct lfds700_stack_state,top) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  if( offsetof(struct lfds700_stack_state,user_state) % LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES != 0 )
+    dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "stack", dvs );
+
+  return;
+}
+
+#pragma warning( default : 4127 )
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_popping.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_popping.c
new file mode 100644
index 0000000000000000000000000000000000000000..461730604c5dbe7726667087183943aadf05394b
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_popping.c
@@ -0,0 +1,202 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  struct lfds700_stack_state
+    *ss;
+};
+
+struct test_element
+{
+  struct lfds700_stack_element
+    se;
+
+  enum flag
+    popped_flag;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_stack_popping( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_stack_state
+    ss;
+
+  struct lfds700_misc_validation_info
+    vi = { 0, 0 };
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create a stack
+
+           we then populate the stack with 1,000,000 elements
+           each void pointer of data points to the containing test element
+
+           we then run one thread per CPU
+           where each thread loops, popping as quickly as possible
+           upon popping, a flag is set in the containing test element
+
+           the threads run till the source stack is empty
+
+           we then check the poppged flag, all should be raised
+
+           then tidy up
+
+           no CAS+GC code, as we only pop
+  */
+
+  internal_display_test_name( "Popping" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element) ;
+
+  te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_elements ; loop++ )
+  {
+    (te_array+loop)->popped_flag = LOWERED;
+    LFDS700_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
+    lfds700_stack_push( &ss, &(te_array+loop)->se, &ps );
+  }
+
+  ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    (ts+loop)->ss = &ss;
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, (void *) &dvs );
+
+  // TRD : now we check each element has popped_flag set to RAISED
+  for( loop = 0 ; loop < number_elements ; loop++ )
+    if( (te_array+loop)->popped_flag == LOWERED )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+
+  // TRD : cleanup
+  lfds700_stack_cleanup( &ss, NULL );
+  util_aligned_free( te_array );
+  util_aligned_free( ts );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "stack", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state )
+{
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_stack_element
+    *se;
+
+  struct test_element
+    *te;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  while( lfds700_stack_pop(ts->ss, &se, &ps) )
+  {
+    te = LFDS700_STACK_GET_VALUE_FROM_ELEMENT( *se );
+    te->popped_flag = RAISED;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_popping_and_pushing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_popping_and_pushing.c
new file mode 100644
index 0000000000000000000000000000000000000000..03c3254c77181014199e22a6ee3bde2623ecc368
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_popping_and_pushing.c
@@ -0,0 +1,316 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_element;
+
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_elements;
+
+  struct lfds700_stack_state
+    *ss,
+    ss_thread_local;
+
+  struct test_element
+    *ss_thread_local_te_array;
+};
+
+struct test_element
+{
+  struct lfds700_stack_element
+    se,
+    thread_local_se;
+
+  lfds700_pal_uint_t
+    datum;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state );
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_stack_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors,
+    subloop;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_stack_state
+    ss;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we have two threads per CPU
+           the threads loop for ten seconds
+           the first thread pushes 10000 elements then pops 10000 elements
+           the second thread pops 10000 elements then pushes 10000 elements
+           all pushes and pops go onto the single main stack
+
+           after time is up, all threads push what they have remaining onto
+           the main stack
+
+           we then validate the main stack
+  */
+
+  internal_display_test_name( "Popping and pushing (%d seconds)", TEST_DURATION_IN_SECONDS );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors * 2 );
+
+  lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
+
+  te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  // TRD : some initial elements so the pushing threads can start immediately
+  for( loop = 0 ; loop < number_elements * number_logical_processors ; loop++ )
+  {
+    (te_array+loop)->datum = loop;
+    LFDS700_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
+    lfds700_stack_push( &ss, &(te_array+loop)->se, &ps );
+  }
+
+  ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors * 2, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    // TRD : first set of threads
+    (ts+loop)->ss = &ss;
+    (ts+loop)->number_elements = number_elements;
+    lfds700_stack_init_valid_on_current_logical_core( &(ts+loop)->ss_thread_local, NULL );
+
+    // TRD : second set of threads
+    (ts+loop+number_logical_processors)->ss = &ss;
+    (ts+loop+number_logical_processors)->number_elements = number_elements;
+    lfds700_stack_init_valid_on_current_logical_core( &(ts+loop+number_logical_processors)->ss_thread_local, NULL );
+
+    // TRD : fill the pushing thread stacks
+    (ts+loop+number_logical_processors)->ss_thread_local_te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+    for( subloop = 0 ; subloop < number_elements ; subloop++ )
+    {
+      ((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->datum = loop;
+      LFDS700_STACK_SET_VALUE_IN_ELEMENT( ((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->thread_local_se, (ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop );
+      lfds700_stack_push( &(ts+loop+number_logical_processors)->ss_thread_local, &((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->thread_local_se, &ps );
+    }
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors * 2 );
+
+  util_thread_starter_new( &tts, number_logical_processors * 2 );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping_and_pushing_start_popping, ts+loop );
+    util_thread_starter_start( tts, &thread_handles[loop+number_logical_processors], loop+number_logical_processors, lp, thread_popping_and_pushing_start_pushing, ts+loop+number_logical_processors );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors * 2 ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = number_elements * number_logical_processors * 2;
+
+  lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  lfds700_stack_cleanup( &ss, NULL );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    lfds700_stack_cleanup( &(ts+loop)->ss_thread_local, NULL );
+    lfds700_stack_cleanup( &(ts+loop+number_logical_processors)->ss_thread_local, NULL );
+    util_aligned_free( (ts+loop+number_logical_processors)->ss_thread_local_te_array );
+  }
+
+  util_aligned_free( ts );
+
+  util_aligned_free( te_array );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "stack", dvs );
+
+  return;
+}
+
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    count;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_stack_element
+    *se;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  start_time = time( NULL );
+
+  while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    count = 0;
+
+    while( count < ts->number_elements )
+      if( lfds700_stack_pop(ts->ss, &se, &ps) )
+      {
+        lfds700_stack_push( &ts->ss_thread_local, se, &ps );
+        count++;
+      }
+
+    // TRD : return our local stack to the main stack
+    while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
+      lfds700_stack_push( ts->ss, se, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    count;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_stack_element
+    *se;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  start_time = time( NULL );
+
+  while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    // TRD : return our local stack to the main stack
+    while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
+      lfds700_stack_push( ts->ss, se, &ps );
+
+    count = 0;
+
+    while( count < ts->number_elements )
+      if( lfds700_stack_pop(ts->ss, &se, &ps) )
+      {
+        lfds700_stack_push( &ts->ss_thread_local, se, &ps );
+        count++;
+      }
+  }
+
+  // TRD : now push whatever we have in our local stack
+  while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
+    lfds700_stack_push( ts->ss, se, &ps );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_pushing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_pushing.c
new file mode 100644
index 0000000000000000000000000000000000000000..bdf2b9b64020909f1aa63b1d1f51362346fb82b8
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_pushing.c
@@ -0,0 +1,251 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  lfds700_pal_uint_t
+    number_elements,
+    thread_number;
+
+  struct lfds700_stack_state
+    *ss;
+
+  struct test_element
+    *te_array;
+};
+
+struct test_element
+{
+  struct lfds700_stack_element
+    se;
+
+  lfds700_pal_uint_t
+    datum,
+    thread_number;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_stack_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_elements,
+    number_logical_processors,
+    *per_thread_counters;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_stack_element
+    *se;
+
+  struct lfds700_stack_state
+    ss;
+
+  struct lfds700_misc_validation_info
+    vi;
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te,
+    *first_te = NULL;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : memory_in_megabytes can be any value in its range
+
+  /* TRD : we create an empty stack
+
+           we then create one thread per CPU, where each thread
+           pushes 100,000 elements each as quickly as possible to the stack
+           (the threads themselves alloc these elements, to obtain NUMA closeness)
+
+           the data pushed is a counter and a thread ID
+
+           the threads exit when the stack is full
+
+           we then validate the stack;
+
+           checking that the counts increment on a per unique ID basis
+           and that the number of elements we pop equals 100,000 per thread
+           (since each element has an incrementing counter which is
+            unique on a per unique ID basis, we can know we didn't lose
+            any elements)
+
+           there's no CAS+GC code, as we only push
+  */
+
+  internal_display_test_name( "Pushing" );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  // TRD : the main stack
+  lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    (ts+loop)->ss = &ss;
+    (ts+loop)->thread_number = loop;
+    (ts+loop)->number_elements = number_elements;
+  }
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_pushing, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  // TRD : the stack is now fully pushed; time to verify
+  per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    *(per_thread_counters+loop) = number_elements - 1;
+
+  vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
+
+  lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_stack_pop(&ss, &se, &ps) )
+  {
+    te = LFDS700_STACK_GET_VALUE_FROM_ELEMENT( *se );
+
+    if( first_te == NULL )
+      first_te = te;
+
+    if( te->thread_number >= number_logical_processors )
+    {
+      dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
+      break;
+    }
+
+    if( te->datum > per_thread_counters[te->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
+
+    if( te->datum < per_thread_counters[te->thread_number] )
+      dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
+
+    if( te->datum == per_thread_counters[te->thread_number] )
+      per_thread_counters[te->thread_number]--;
+  }
+
+  // TRD : clean up
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    util_aligned_free( (ts+loop)->te_array );
+
+  free( per_thread_counters );
+
+  free( ts );
+
+  lfds700_stack_cleanup( &ss, NULL );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "stack", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_pushing( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  // TRD : alloc local 100,000 elements
+  ts->te_array = util_aligned_malloc( sizeof(struct test_element) * ts->number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < ts->number_elements ; loop++ )
+  {
+    (ts->te_array+loop)->thread_number = ts->thread_number;
+    (ts->te_array+loop)->datum = loop;
+  }
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  for( loop = 0 ; loop < ts->number_elements ; loop++ )
+  {
+    LFDS700_STACK_SET_VALUE_IN_ELEMENT( (ts->te_array+loop)->se, ts->te_array+loop );
+    lfds700_stack_push( ts->ss, &(ts->te_array+loop)->se, &ps );
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_rapid_popping_and_pushing.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_rapid_popping_and_pushing.c
new file mode 100644
index 0000000000000000000000000000000000000000..d771457c86d58986f7c8ed377896125d059f4555
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_lfds700_stack_rapid_popping_and_pushing.c
@@ -0,0 +1,217 @@
+/***** includes *****/
+#include "internal.h"
+
+/***** structs *****/
+struct test_state
+{
+  struct lfds700_stack_state
+    *ss;
+};
+
+struct test_element
+{
+  struct lfds700_stack_element
+    se;
+
+  lfds700_pal_uint_t
+    datum;
+};
+
+/***** private prototypes *****/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state );
+
+
+
+
+
+/****************************************************************************/
+void test_lfds700_stack_rapid_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors )
+{
+  enum lfds700_misc_validity
+    dvs = LFDS700_MISC_VALIDITY_VALID;
+
+  lfds700_pal_uint_t
+    loop,
+    number_logical_processors;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_list_asu_element
+    *lasue;
+
+  struct lfds700_stack_state
+    ss;
+
+  struct lfds700_misc_validation_info
+    vi = { 0, 0 };
+
+  struct test_pal_logical_processor
+    *lp;
+
+  struct util_thread_starter_state
+    *tts;
+
+  struct test_element
+    *te_array;
+
+  struct test_state
+    *ts;
+
+  test_pal_thread_state_t
+    *thread_handles;
+
+  assert( list_of_logical_processors != NULL );
+  // TRD : st can be any value in its range
+
+  /* TRD : in these tests there is a fundamental antagonism between
+           how much checking/memory clean up that we do and the
+           likelyhood of collisions between threads in their lock-free
+           operations
+
+           the lock-free operations are very quick; if we do anything
+           much at all between operations, we greatly reduce the chance
+           of threads colliding
+
+           so we have some tests which do enough checking/clean up that
+           they can tell the stack is valid and don't leak memory
+           and here, this test now is one of those which does minimal
+           checking - in fact, the nature of the test is that you can't
+           do any real checking - but goes very quickly
+
+           what we do is create a small stack and then run one thread
+           per CPU, where each thread simply pushes and then immediately
+           pops
+
+           the test runs for ten seconds
+
+           after the test is done, the only check we do is to traverse
+           the stack, checking for loops and ensuring the number of
+           elements is correct
+  */
+
+  internal_display_test_name( "Rapid popping and pushing (%d seconds)", TEST_DURATION_IN_SECONDS );
+
+  lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
+
+  lfds700_misc_prng_init( &ps );
+
+  ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
+
+  lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    (ts+loop)->ss = &ss;
+
+  thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
+
+  // TRD : we need one element per thread
+  te_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+  {
+    LFDS700_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
+    lfds700_stack_push( &ss, &(te_array+loop)->se, &ps );
+  }
+
+  util_thread_starter_new( &tts, number_logical_processors );
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  loop = 0;
+  lasue = NULL;
+
+  while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
+  {
+    lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
+    util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_rapid_popping_and_pushing, ts+loop );
+    loop++;
+  }
+
+  util_thread_starter_run( tts );
+
+  for( loop = 0 ; loop < number_logical_processors ; loop++ )
+    test_pal_thread_wait( thread_handles[loop] );
+
+  util_thread_starter_delete( tts );
+
+  free( thread_handles );
+
+  LFDS700_MISC_BARRIER_LOAD;
+
+  vi.min_elements = vi.max_elements = number_logical_processors;
+
+  lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
+
+  lfds700_stack_cleanup( &ss, NULL );
+
+  util_aligned_free( te_array );
+
+  free( ts );
+
+  // TRD : print the test result
+  internal_display_test_result( 1, "stack", dvs );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state )
+{
+  lfds700_pal_uint_t
+    time_loop = 0;
+
+  struct lfds700_misc_prng_state
+    ps;
+
+  struct lfds700_stack_element
+    *se;
+
+  struct test_state
+    *ts;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+
+  time_t
+    current_time,
+    start_time;
+
+  LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
+
+  assert( util_thread_starter_thread_state != NULL );
+
+  tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
+  ts = (struct test_state *) tsts->thread_user_state;
+
+  lfds700_misc_prng_init( &ps );
+
+  util_thread_starter_ready_and_wait( tsts );
+
+  current_time = start_time = time( NULL );
+
+  while( current_time < start_time + TEST_DURATION_IN_SECONDS )
+  {
+    lfds700_stack_pop( ts->ss, &se, &ps );
+    lfds700_stack_push( ts->ss, se, &ps );
+
+    if( time_loop++ == TIME_LOOP_COUNT )
+    {
+      time_loop = 0;
+      time( &current_time );
+    }
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return( (test_pal_thread_return_t) EXIT_SUCCESS );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_get_logical_core_ids.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_get_logical_core_ids.c
new file mode 100644
index 0000000000000000000000000000000000000000..eb62c5b4ccc55fb66724f8bb2068e049330f2d59
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_get_logical_core_ids.c
@@ -0,0 +1,245 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if( defined _WIN32 && !defined _KERNEL_MODE && NTDDI_VERSION >= NTDDI_WIN7 )
+
+  /* TRD : _WIN32         indicates 64-bit or 32-bit Windows
+           !_KERNEL_MODE  indicates Windows user-mode
+           NTDDI_VERSION  indicates Windows version
+                            - GetLogicalProcessorInformationEx requires Windows 7
+  */
+
+  #ifdef TEST_PAL_GET_LOGICAL_CORE_IDS
+    #error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_get_logical_core_ids.c
+  #endif
+
+  #define TEST_PAL_GET_LOGICAL_CORE_IDS
+
+  void test_pal_get_logical_core_ids( struct lfds700_list_asu_state *lasus )
+  {
+    BOOL
+      rv;
+
+    DWORD
+      loop,
+      number_slpie,
+      slpie_length = 0;
+
+    lfds700_pal_uint_t
+      bitmask,
+      logical_processor_number,
+      windows_logical_processor_group_number;
+
+    struct lfds700_misc_prng_state
+      ps;
+
+    struct test_pal_logical_processor
+      *lp;
+
+    SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
+      *slpie = NULL;
+
+    assert( lasus != NULL );
+
+    lfds700_misc_prng_init( &ps );
+
+    lfds700_list_asu_init_valid_on_current_logical_core( lasus, NULL, NULL );
+
+    rv = GetLogicalProcessorInformationEx( RelationGroup, slpie, &slpie_length );
+    slpie = malloc( slpie_length );
+    rv = GetLogicalProcessorInformationEx( RelationGroup, slpie, &slpie_length );
+    number_slpie = slpie_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX);
+
+    for( loop = 0 ; loop < number_slpie ; loop++ )
+      if( (slpie+loop)->Relationship == RelationGroup )
+        for( windows_logical_processor_group_number = 0 ; windows_logical_processor_group_number < (slpie+loop)->Group.ActiveGroupCount ; windows_logical_processor_group_number++ )
+          for( logical_processor_number = 0 ; logical_processor_number < sizeof(KAFFINITY) * BITS_PER_BYTE ; logical_processor_number++ )
+          {
+            bitmask = (lfds700_pal_uint_t) 1 << logical_processor_number;
+
+            // TRD : if we've found a processor for this group, add it to the list
+            if( (slpie+loop)->Group.GroupInfo[windows_logical_processor_group_number].ActiveProcessorMask & bitmask )
+            {
+              lp = util_aligned_malloc( sizeof(struct test_pal_logical_processor), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+              lp->logical_processor_number = logical_processor_number;
+              lp->windows_logical_processor_group_number = windows_logical_processor_group_number;
+
+              LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( lp->lasue, lp );
+              lfds700_list_asu_insert_at_start( lasus, &lp->lasue, &ps );
+            }
+          }
+
+    free( slpie );
+
+    return;
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined _WIN32 && !defined _KERNEL_MODE && NTDDI_VERSION >= NTDDI_WINXP && NTDDI_VERSION < NTDDI_WIN7 )
+
+  /* TRD : _WIN32         indicates 64-bit or 32-bit Windows
+           !_KERNEL_MODE  indicates Windows user-mode
+           NTDDI_VERSION  indicates Windows version
+                            - GetLogicalProcessorInformation requires XP SP3
+  */
+
+  #ifdef TEST_PAL_GET_LOGICAL_CORE_IDS
+    #error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_get_logical_core_ids.c
+  #endif
+
+  #define TEST_PAL_GET_LOGICAL_CORE_IDS
+
+  void test_pal_get_logical_core_ids( struct lfds700_list_asu_state *lasus )
+  {
+    DWORD
+      slpi_length = 0;
+
+    lfds700_pal_uint_t
+      number_slpi,
+      loop;
+
+    struct lfds700_misc_prng_state
+      ps;
+
+    struct test_pal_logical_processor
+      *lp;
+
+    SYSTEM_LOGICAL_PROCESSOR_INFORMATION
+      *slpi = NULL;
+
+    ULONG_PTR
+      mask;
+
+    assert( lasus != NULL );
+
+    lfds700_misc_prng_init( &ps );
+
+    lfds700_list_asu_init_valid_on_current_logical_core( lasus, NULL, NULL );
+
+    *number_logical_processors = 0;
+
+    GetLogicalProcessorInformation( slpi, &slpi_length );
+    slpi = malloc( slpi_length );
+    GetLogicalProcessorInformation( slpi, &slpi_length );
+    number_slpi = slpi_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+
+    for( loop = 0 ; loop < number_slpi ; loop++ )
+      if( (slpi+loop)->Relationship == RelationProcessorCore )
+        for( logical_processor_number = 0 ; logical_processor_number < sizeof(ULONG_PTR) * BITS_PER_BYTE ; logical_processor_number++ )
+        {
+          bitmask = 1 << logical_processor_number;
+
+          if( (slpi+loop)->ProcessorMask & bitmask )
+          {
+            lp = util_aligned_malloc( sizeof(struct test_pal_logical_processor), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+            lp->logical_processor_number = logical_processor_number;
+            lp->windows_logical_processor_group_number = 0;
+
+            LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( lp->lasue, lp );
+            lfds700_list_asu_insert_at_start( lasus, &lp->lasue, &ps );
+          }
+
+    free( slpi );
+
+    return;
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __linux__ )
+
+  /* TRD : __linux__        indicates Linux
+           __STDC__         indicates Standard Library
+           __STDC_HOSTED__  indicates Standard Library hosted implementation
+                              - fopen requires a Standard Library hosted environment
+                              - setbuf requires a Standard Library hosted environment
+                              - fgets requires a Standard Library hosted environment
+                              - sscanf requires a Standard Library hosted environment
+                              - fclose requires a Standard Library hosted environment
+  */
+
+  #ifdef TEST_PAL_GET_LOGICAL_CORE_IDS
+    #error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_get_logical_core_ids.c
+  #endif
+
+  #define TEST_PAL_GET_LOGICAL_CORE_IDS
+
+  void test_pal_get_logical_core_ids( struct lfds700_list_asu_state *lasus )
+  {
+    char
+      diskbuffer[BUFSIZ],
+      string[1024];
+
+    FILE
+      *diskfile;
+
+    int long long unsigned
+      logical_processor_number;
+
+    struct lfds700_misc_prng_state
+      ps;
+
+    struct test_pal_logical_processor
+      *lp;
+
+    assert( lasus != NULL );
+
+    lfds700_misc_prng_init( &ps );
+
+    lfds700_list_asu_init_valid_on_current_logical_core( lasus, NULL, NULL );
+
+    diskfile = fopen( "/proc/cpuinfo", "r" );
+
+    if( diskfile != NULL )
+    {
+      setbuf( diskfile, diskbuffer );
+
+      while( NULL != fgets(string, 1024, diskfile) )
+        if( 1 == sscanf(string, "processor : %llu", &logical_processor_number) )
+        {
+          lp = util_aligned_malloc( sizeof(struct test_pal_logical_processor), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
+
+          lp->logical_processor_number = (lfds700_pal_uint_t) logical_processor_number;
+          lp->windows_logical_processor_group_number = 0;
+
+          LFDS700_LIST_ASU_SET_VALUE_IN_ELEMENT( lp->lasue, lp );
+          lfds700_list_asu_insert_at_start( lasus, &lp->lasue, &ps );
+        }
+
+      fclose( diskfile );
+    }
+
+    return;
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( !defined TEST_PAL_GET_LOGICAL_CORE_IDS )
+
+  #error test_pal_get_logical_core_ids() not implemented for this platform.
+
+#endif
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_operating_system.h b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_operating_system.h
new file mode 100644
index 0000000000000000000000000000000000000000..1c0ab03eee7677003f6a51094e55629a3dbfab33
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_operating_system.h
@@ -0,0 +1,82 @@
+/****************************************************************************/
+#if( defined _MSC_VER )
+  /* TRD : MSVC compiler
+
+           an unfortunately necessary hack for MSVC
+           MSVC only defines __STDC__ if /Za is given, where /Za turns off MSVC C extensions - 
+           which prevents Windows header files from compiling.
+  */
+
+  #define __STDC__         1
+  #define __STDC_HOSTED__  1
+#endif
+
+#if( defined __linux__ )
+  #define _GNU_SOURCE
+  #include <unistd.h>
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined _MSC_VER && _MSC_VER >= 1310 && NTDDI_VERSION >= NTDDI_WINXP && defined _WIN32 )
+
+  #ifdef TEST_PAL_PORTING_ABSTRACTION_LAYER
+    #error More than one porting abstraction layer matches current platform.
+  #endif
+
+  #define TEST_PAL_PORTING_ABSTRACTION_LAYER
+
+  #define TEST_PAL_OS_STRING "Windows"
+
+  #include <windows.h>
+
+  typedef HANDLE  test_pal_thread_state_t;
+  typedef DWORD   test_pal_thread_return_t;
+
+  #define TEST_PAL_CALLING_CONVENTION  WINAPI
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __GNUC__ && defined __linux__ && _POSIX_THREADS > 0 )
+
+  #ifdef TEST_PAL_PORTING_ABSTRACTION_LAYER
+    #error More than one porting abstraction layer matches current platform.
+  #endif
+
+  #define TEST_PAL_PORTING_ABSTRACTION_LAYER
+
+  #define TEST_PAL_OS_STRING "Linux"
+
+  #define _GNU_SOURCE
+
+  #include <pthread.h>
+  #include <sched.h>
+  #include <sys/syscall.h>
+  #include <sys/types.h>
+
+  typedef pthread_t  test_pal_thread_state_t;
+  typedef void *     test_pal_thread_return_t;
+
+  #define TEST_PAL_CALLING_CONVENTION  
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( !defined TEST_PAL_PORTING_ABSTRACTION_LAYER )
+
+  #error No matching porting abstraction layer in test_porting_abstraction_layer_operating_system.h
+
+#endif
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_thread_start.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_thread_start.c
new file mode 100644
index 0000000000000000000000000000000000000000..83a09814aa17bd1c1b8af24fd18d6ebbba7d6b22
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_thread_start.c
@@ -0,0 +1,336 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if( defined _WIN32 && !defined _KERNEL_MODE && NTDDI_VERSION >= NTDDI_WIN7 )
+
+  /* TRD : _WIN32         indicates 32-bit or 64-bit Windows
+           !_KERNEL_MODE  indicates Windows user-mode
+           NTDDI_VERSION  indicates Windows version
+                            - GetCurrentProcess requires XP
+                            - InitializeProcThreadAttributeList requires Windows 7
+                            - CreateRemoteThreadEx requires Windows 7
+  */
+
+  #ifdef TEST_PAL_THREAD_START
+    #error More than one porting abstraction layer matches the current platform in test_porting_abstraction_layer_thread_start.c
+  #endif
+
+  #define TEST_PAL_THREAD_START
+
+  int test_pal_thread_start( test_pal_thread_state_t *thread_state,
+                             struct test_pal_logical_processor *lp, 
+                             test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
+                             void *thread_user_state )
+  {
+    BOOL
+      brv;
+
+    DWORD
+      thread_id;
+
+    GROUP_AFFINITY
+      ga;
+
+    int
+      rv = 0;
+
+    LPPROC_THREAD_ATTRIBUTE_LIST
+      attribute_list;
+
+    SIZE_T
+      attribute_list_length;
+
+    assert( thread_state != NULL );
+    assert( lp != NULL );
+    assert( thread_function != NULL );
+    // TRD : thread_user_state can be NULL
+
+    /* TRD : here we're using CreateRemoteThreadEx() to start a thread in our own process
+             we do this because as a function, it allows us to specify processor and processor group affinity in the create call
+    */
+
+    brv = InitializeProcThreadAttributeList( NULL, 1, 0, &attribute_list_length );
+    attribute_list = malloc( attribute_list_length );
+    brv = InitializeProcThreadAttributeList( attribute_list, 1, 0, &attribute_list_length );
+
+    ga.Mask = ( (KAFFINITY) 1 << lp->logical_processor_number );
+    ga.Group = (WORD) lp->windows_logical_processor_group_number;
+    memset( ga.Reserved, 0, sizeof(WORD) * 3 );
+
+    brv = UpdateProcThreadAttribute( attribute_list, 0, PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY, &ga, sizeof(GROUP_AFFINITY), NULL, NULL );
+    *thread_state = CreateRemoteThreadEx( GetCurrentProcess(), NULL, 0, thread_function, thread_user_state, NO_FLAGS, attribute_list, &thread_id );
+
+    DeleteProcThreadAttributeList( attribute_list );
+    free( attribute_list );
+
+    if( *thread_state != NULL )
+      rv = 1;
+
+    return( rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined _WIN32 && !defined _KERNEL_MODE && NTDDI_VERSION >= NTDDI_WINXP && NTDDI_VERSION < NTDDI_WIN7 )
+
+  /* TRD : _WIN32         indicates 64-bit or 32-bit Windows
+           NTDDI_VERSION  indicates Windows version
+                            - CreateThread requires XP
+                            - SetThreadAffinityMask requires XP
+                            - ResumeThread requires XP
+  */
+
+  #ifdef TEST_PAL_THREAD_START
+    #error More than one porting abstraction layer matches the current platform in test_porting_abstraction_layer_thread_start.c
+  #endif
+
+  #define TEST_PAL_THREAD_START
+
+  int test_pal_thread_start( test_pal_thread_state_t *thread_state,
+                             struct test_pal_logical_processor *lp,
+                             test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
+                             void *thread_user_state )
+  {
+    int
+      rv = 0;
+
+    DWORD
+      thread_id;
+
+    DWORD_PTR
+      affinity_mask,
+      result;
+
+    assert( thread_state != NULL );
+    assert( lp != NULL );
+    assert( thread_function != NULL );
+    // TRD : thread_user_state can be NULL
+
+    /* TRD : Vista and earlier do not support processor groups
+             as such, there is a single implicit processor group
+             also, there's no support for actually starting a thread in its correct NUMA node / logical processor
+             so we make the best of it; we start suspended, set the affinity, and then resume
+             the thread itself internally is expected to be making allocs from the correct NUMA node
+    */
+
+    *thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, CREATE_SUSPENDED, &thread_id );
+
+    affinity_mask = (DWORD_PTR) (1 << lp->logical_processor_number);
+
+    SetThreadAffinityMask( *thread_state, affinity_mask );
+
+    ResumeThread( *thread_state );
+
+    if( *thread_state != NULL )
+      rv = 1;
+
+    return( rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( defined __linux__ && _POSIX_THREADS > 0 )
+
+  /* TRD : __linux__       indicates Linux
+                             - gettid requires Linux
+                             - sched_setaffinity requires Linux
+           _POSIX_THREADS  indicates POSIX threads
+                             - pthread_create requires POSIX
+  */
+
+  #ifdef TEST_PAL_THREAD_START
+    #error More than one porting abstraction layer matches the current platform in test_porting_abstraction_layer_thread_start.c
+  #endif
+
+  #define TEST_PAL_THREAD_START
+
+  /***** structs *****/
+  struct test_pal_internal_thread_state
+  {
+    struct test_pal_logical_processor
+      lp;
+
+    test_pal_thread_return_t
+      (TEST_PAL_CALLING_CONVENTION *thread_function)( void *thread_user_state );
+
+    void
+      *thread_user_state;
+  };
+
+  /***** prototypes *****/
+  test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION test_pal_internal_thread_function( void *thread_user_state );
+
+  /****************************************************************************/
+  int test_pal_thread_start( test_pal_thread_state_t *thread_state,
+                             struct test_pal_logical_processor *lp,
+                             test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
+                             void *thread_user_state )
+  {
+    int
+      rv;
+
+    struct test_pal_internal_thread_state
+      *its;
+
+    /* TRD : this implementation works on Linux only as it uses sched_setaffinity(), which is Linux specific
+             although I cannot currently test, I believe this function also works on Android
+
+             this implementation exists because the pthreads function for setting thread affinity,
+             pthread_attr_setaffinity_np(), works on Linux, but not Android
+    */
+
+    assert( thread_state != NULL );
+    assert( lp != NULL );
+    assert( thread_function != NULL );
+    // TRD : thread_user_state can be NULL
+
+    its = malloc( sizeof(struct test_pal_internal_thread_state) );
+
+    its->lp = *lp;
+    its->thread_function = thread_function;
+    its->thread_user_state = thread_user_state;
+
+    rv = pthread_create( thread_state, NULL, test_pal_internal_thread_function, its );
+
+    if( rv == 0 )
+      rv = 1;
+
+    return( rv );
+  }
+
+  /****************************************************************************/
+  test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION test_pal_internal_thread_function( void *thread_user_state )
+  {
+    cpu_set_t
+      cpuset;
+
+    pid_t
+      tid;
+
+    struct test_pal_internal_thread_state
+      *its;
+
+    test_pal_thread_return_t
+      rv;
+
+    assert( thread_user_state != NULL );
+
+    /* TRD : the APIs under Linux/POSIX for setting thread affinity are in a mess
+             pthreads offers pthread_attr_setaffinity_np(), which glibc supports,
+             but which is not supported by Android
+             Linux offers sched_setaffinity(), but this needs a *thread pid*,
+             and the only API to get a thread pid is gettid(), which works for
+             and only for *the calling thread*
+
+             so we come to this - a wrapper thread function, which is the function used
+             when starting a thread; this calls gettid() and then sched_setaffinity(),
+             and then calls into the actual thread function
+
+             generally shaking my head in disbelief at this point
+    */
+
+    assert( thread_user_state != NULL );
+
+    its = (struct test_pal_internal_thread_state *) thread_user_state;
+
+    CPU_ZERO( &cpuset );
+    CPU_SET( its->lp.logical_processor_number, &cpuset );
+
+    tid = syscall( SYS_gettid );
+
+    sched_setaffinity( tid, sizeof(cpu_set_t), &cpuset );
+
+    rv = its->thread_function( its->thread_user_state );
+
+    free( its );
+
+    return( rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( !defined __linux__ && _POSIX_THREADS > 0 )
+
+  /* TRD : !__linux__      indicates not Linux
+           _POSIX_THREADS  indicates POSIX threads
+                             - pthread_attr_init requires POSIX
+                             - pthread_attr_setaffinity_np requires POSIX
+                             - pthread_create requires POSIX
+                             - pthread_attr_destroy requires POSIX
+  */
+
+  #ifdef TEST_PAL_THREAD_START
+    #error More than one porting abstraction layer matches the current platform in test_porting_abstraction_layer_thread_start.c
+  #endif
+
+  #define TEST_PAL_THREAD_START
+
+  int test_pal_thread_start( test_pal_thread_state_t *thread_state,
+                             struct test_pal_logical_processor *lp,
+                             test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
+                             void *thread_user_state )
+  {
+    int
+      rv = 0,
+      rv_create;
+
+    cpu_set_t
+      cpuset;
+
+    pthread_attr_t
+      attr;
+
+    assert( thread_state != NULL );
+    assert( lp != NULL );
+    assert( thread_function != NULL );
+    // TRD : thread_user_state can be NULL
+
+    pthread_attr_init( &attr );
+
+    CPU_ZERO( &cpuset );
+    CPU_SET( lp->logical_processor_number, &cpuset );
+    pthread_attr_setaffinity_np( &attr, sizeof(cpuset), &cpuset );
+
+    rv_create = pthread_create( thread_state, &attr, thread_function, thread_user_state );
+
+    if( rv_create == 0 )
+      rv = 1;
+
+    pthread_attr_destroy( &attr );
+
+    return( rv );
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( !defined TEST_PAL_THREAD_START )
+
+  #error test_pal_thread_start() not implemented for this platform.
+
+#endif
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_thread_wait.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_thread_wait.c
new file mode 100644
index 0000000000000000000000000000000000000000..bd4a8c01f70de182433809c14049e8764a381e09
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/test_porting_abstraction_layer_thread_wait.c
@@ -0,0 +1,69 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+#if( defined _WIN32 && NTDDI_VERSION >= NTDDI_WINXP )
+
+  /* TRD : _WIN32         indicates 32-bit or 64-bit Windows
+           NTDDI_VERSION  indicates Windows version
+                            - WaitForSingleObject requires XP
+  */
+
+  #ifdef TEST_PAL_THREAD_WAIT
+    #error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_thread_wait.c
+  #endif
+
+  #define TEST_PAL_THREAD_WAIT
+
+  void test_pal_thread_wait( test_pal_thread_state_t thread_state )
+  {
+    WaitForSingleObject( thread_state, INFINITE );
+
+    return;
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( _POSIX_THREADS > 0 )
+
+  /* TRD : POSIX threads
+
+           _POSIX_THREADS  indicates POSIX threads
+                           - pthread_join requires POSIX
+  */
+
+  #ifdef TEST_PAL_THREAD_WAIT
+    #error More than one porting abstraction layer matches current platform in test_porting_abstraction_layer_thread_wait.c
+  #endif
+
+  #define TEST_PAL_THREAD_WAIT
+
+  void test_pal_thread_wait( test_pal_thread_state_t thread_state )
+  {
+    pthread_join( thread_state, NULL );
+
+    return;
+  }
+
+#endif
+
+
+
+
+
+/****************************************************************************/
+#if( !defined TEST_PAL_THREAD_WAIT )
+
+  #error test_pal_thread_wait() not implemented for this platform.
+
+#endif
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_cmdline.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_cmdline.c
new file mode 100644
index 0000000000000000000000000000000000000000..9173d607c96c5a3ceb8037a9b17e30bf58759d17
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_cmdline.c
@@ -0,0 +1,184 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void util_cmdline_init( struct util_cmdline_state *cs )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  assert( cs != NULL );
+
+  for( loop = 0 ; loop < NUMBER_OF_LOWERCASE_LETTERS_IN_LATIN_ALPHABET ; loop++ )
+  {
+    cs->args[loop].arg_type = LIBCOMMON_CMDLINE_ARG_TYPE_UNSET;
+    cs->args[loop].processed_flag = LOWERED;
+  }
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+#pragma warning( disable : 4100 )
+
+void util_cmdline_cleanup( struct util_cmdline_state *cs )
+{
+  assert( cs != NULL );
+
+  return;
+}
+
+#pragma warning( default : 4100 )
+
+
+
+
+
+/****************************************************************************/
+void util_cmdline_add_arg( struct util_cmdline_state *cs, char arg_letter, enum util_cmdline_arg_type arg_type )
+{
+  lfds700_pal_uint_t
+    index;
+
+  assert( cs != NULL );
+  assert( arg_letter >= 'a' and arg_letter <= 'z' );
+  // TRD : arg_type can be any value in its range
+
+  index = arg_letter - 'a';
+
+  cs->args[index].arg_type = arg_type;
+
+  if( arg_type == LIBCOMMON_CMDLINE_ARG_TYPE_FLAG )
+    cs->args[index].arg_data.flag.flag = LOWERED;
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+int util_cmdline_process_args( struct util_cmdline_state *cs, int argc, char **argv )
+{
+  char
+    *arg;
+
+  int
+    arg_letter,
+    cc,
+    loop,
+    rv = 1;
+
+  lfds700_pal_uint_t
+    index;
+
+  assert( cs != NULL );
+  assert( argc >= 1 );
+  assert( argv != NULL );
+
+  for( loop = 1 ; loop < argc ; loop++ )
+  {
+    arg = *(argv+loop);
+
+    switch( *arg )
+    {
+      case '-':
+        arg_letter = tolower( *(arg+1) );
+
+        if( arg_letter >= 'a' and arg_letter <= 'z' )
+        {
+          index = arg_letter - 'a';
+
+          switch( cs->args[index].arg_type )
+          {
+            case LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER_RANGE:
+              if( loop+1 >= argc )
+                rv = 0;
+
+              if( loop+1 < argc )
+              {
+                cc = sscanf( *(argv+loop+1), "%llu-%llu", &cs->args[index].arg_data.integer_range.integer_start, &cs->args[index].arg_data.integer_range.integer_end );
+
+                if( cc != 2 )
+                  rv = 0;
+
+                if( cc == 2 )
+                {
+                  cs->args[index].processed_flag = RAISED;
+                  loop++;
+                }
+              }
+            break;
+
+            case LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER:
+              if( loop+1 >= argc )
+                rv = 0;
+
+              if( loop+1 < argc )
+              {
+                cc = sscanf( *(argv+loop+1), "%llu", &cs->args[index].arg_data.integer.integer );
+
+                if( cc != 1 )
+                  rv = 0;
+
+                if( cc == 1 )
+                {
+                  cs->args[index].processed_flag = RAISED;
+                  loop++;
+                }
+              }
+            break;
+
+            case LIBCOMMON_CMDLINE_ARG_TYPE_FLAG:
+              cs->args[index].arg_data.flag.flag = RAISED;
+              cs->args[index].processed_flag = RAISED;
+            break;
+
+            case LIBCOMMON_CMDLINE_ARG_TYPE_UNSET:
+            break;
+          }
+        }
+      break;
+
+      default:
+        rv = 0;
+      break;
+    }
+  }
+
+  return( rv );
+}
+
+
+
+
+
+/****************************************************************************/
+void util_cmdline_get_arg_data( struct util_cmdline_state *cs, char arg_letter, union util_cmdline_arg_data **arg_data )
+{
+  lfds700_pal_uint_t
+    index;
+
+  assert( cs != NULL );
+  assert( arg_letter >= 'a' and arg_letter <= 'z' );
+  assert( arg_data != NULL );
+
+  index = arg_letter - 'a';
+
+  if( cs->args[index].processed_flag == RAISED )
+    *arg_data = &cs->args[index].arg_data;
+  else
+    *arg_data = NULL;
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_cmdline.h b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_cmdline.h
new file mode 100644
index 0000000000000000000000000000000000000000..a19b073499e3e3a4d92ce0fd656581ba5412f4a2
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_cmdline.h
@@ -0,0 +1,69 @@
+/***** defines *****/
+#define NUMBER_OF_LOWERCASE_LETTERS_IN_LATIN_ALPHABET 26
+
+/***** enums *****/
+enum util_cmdline_arg_type
+{
+  LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER_RANGE,
+  LIBCOMMON_CMDLINE_ARG_TYPE_INTEGER,
+  LIBCOMMON_CMDLINE_ARG_TYPE_FLAG,
+  LIBCOMMON_CMDLINE_ARG_TYPE_UNSET
+};
+
+/***** structs *****/
+struct util_cmdline_arg_integer_range
+{
+  int long long unsigned
+    integer_start,
+    integer_end;
+};
+
+struct util_cmdline_arg_integer
+{
+  int long long unsigned
+    integer;
+};
+
+struct util_cmdline_arg_flag
+{
+  enum flag
+    flag;
+};
+
+union util_cmdline_arg_data
+{
+  struct util_cmdline_arg_integer_range
+    integer_range;
+
+  struct util_cmdline_arg_integer
+    integer;
+
+  struct util_cmdline_arg_flag
+    flag;
+};
+
+struct util_cmdline_arg_letter_and_data
+{
+  enum util_cmdline_arg_type
+    arg_type;
+
+  enum flag
+    processed_flag;
+
+  union util_cmdline_arg_data
+    arg_data;
+};
+
+struct util_cmdline_state
+{
+  struct util_cmdline_arg_letter_and_data
+    args[NUMBER_OF_LOWERCASE_LETTERS_IN_LATIN_ALPHABET];
+};
+
+/***** public protoypes *****/
+void util_cmdline_init( struct util_cmdline_state *cs );
+void util_cmdline_cleanup( struct util_cmdline_state *cs );
+void util_cmdline_add_arg( struct util_cmdline_state *cs, char arg_letter, enum util_cmdline_arg_type arg_type );
+int  util_cmdline_process_args( struct util_cmdline_state *cs, int argc, char **argv );
+void util_cmdline_get_arg_data( struct util_cmdline_state *cs, char arg_letter, union util_cmdline_arg_data **arg_data );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_memory_helpers.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_memory_helpers.c
new file mode 100644
index 0000000000000000000000000000000000000000..3d4c0e79f40a96a7df2ef3a761276e4f893199c3
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_memory_helpers.c
@@ -0,0 +1,75 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void *util_aligned_malloc( lfds700_pal_uint_t size, lfds700_pal_uint_t align_in_bytes )
+{
+  lfds700_pal_uint_t
+    offset;
+
+  void
+    *memory,
+    *original_memory;
+
+  // TRD : size can be any value in its range
+  // TRD : align_in_bytes can be any value in its range
+
+  /* TRD : helper function to provide aligned allocations
+           no porting required
+  */
+
+  original_memory = memory = util_malloc_wrapper( size + sizeof(void *) + align_in_bytes );
+
+  if( memory != NULL )
+  {
+    memory = (void **) memory + 1;
+    offset = align_in_bytes - (lfds700_pal_uint_t) memory % align_in_bytes;
+    memory = (char unsigned *) memory + offset;
+    *( (void **) memory - 1 ) = original_memory;
+  }
+
+  return( memory );
+}
+
+
+
+
+
+/****************************************************************************/
+void util_aligned_free( void *memory )
+{
+  assert( memory != NULL );
+
+  // TRD : the "void *" stored above memory points to the root of the allocation
+  free( *( (void **) memory - 1 ) );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void *util_malloc_wrapper( lfds700_pal_uint_t size )
+{
+  void
+    *memory;
+
+  // TRD : size can be any value in its range
+
+  memory = malloc( size );
+
+  if( memory == NULL )
+  {
+    puts( "malloc() failed, exiting." );
+    exit( EXIT_FAILURE );
+  }
+
+  return( memory );
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_memory_helpers.h b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_memory_helpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..8341a1f2e3b95870b38b47126dd5e96f7d6bc851
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_memory_helpers.h
@@ -0,0 +1,5 @@
+/***** public prototypes *****/
+void *util_aligned_malloc( lfds700_pal_uint_t size, lfds700_pal_uint_t align_in_bytes );
+void util_aligned_free( void *memory );
+void *util_malloc_wrapper( lfds700_pal_uint_t size );
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_thread_starter.c b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_thread_starter.c
new file mode 100644
index 0000000000000000000000000000000000000000..c008fa2c5d60c227c18c5dfc73e3526483c2c325
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_thread_starter.c
@@ -0,0 +1,151 @@
+/***** includes *****/
+#include "internal.h"
+
+
+
+
+
+/****************************************************************************/
+void util_thread_starter_new( struct util_thread_starter_state **tts, lfds700_pal_uint_t number_threads )
+{
+  lfds700_pal_uint_t
+    loop;
+
+  assert( tts != NULL );
+  // TRD : number_threads cam be any value in its range
+
+  *tts = util_malloc_wrapper( sizeof(struct util_thread_starter_state) );
+
+  (*tts)->tsts = util_malloc_wrapper( sizeof(struct util_thread_starter_thread_state) * number_threads );
+  (*tts)->thread_start_flag = LOWERED;
+  (*tts)->number_thread_states = number_threads;
+
+  for( loop = 0 ; loop < number_threads ; loop++ )
+  {
+    ((*tts)->tsts+loop)->thread_ready_flag = LOWERED;
+    ((*tts)->tsts+loop)->thread_start_flag = &(*tts)->thread_start_flag;
+  }
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void util_thread_starter_start( struct util_thread_starter_state *tts,
+                                     test_pal_thread_state_t *thread_state,
+                                     lfds700_pal_uint_t thread_number,
+                                     struct test_pal_logical_processor *lp,
+                                     test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)( void *thread_user_state ),
+                                     void *thread_user_state )
+{
+  assert( tts != NULL );
+  assert( thread_state != NULL );
+  assert( lp != NULL );
+  assert( thread_function != NULL );
+  // TRD : thread_user_state can be NULL
+
+  (tts->tsts+thread_number)->thread_user_state = thread_user_state;
+
+  util_thread_start_wrapper( thread_state, lp, thread_function, tts->tsts+thread_number );
+
+  // TRD : wait for the thread to indicate it is ready and waiting
+  while( (tts->tsts+thread_number)->thread_ready_flag == LOWERED );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void util_thread_starter_ready_and_wait( struct util_thread_starter_thread_state *tsts )
+{
+  assert( tsts != NULL );
+
+  tsts->thread_ready_flag = RAISED;
+
+  LFDS700_MISC_BARRIER_FULL;
+
+  // TRD : threads here are all looping, so we don't need to force a store
+
+  while( *tsts->thread_start_flag == LOWERED )
+    LFDS700_MISC_BARRIER_LOAD;
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void util_thread_starter_run( struct util_thread_starter_state *tts )
+{
+  assert( tts != NULL );
+
+  /* TRD : all threads at this point are ready to go
+           as we wait for their ready flag immediately after their spawn
+  */
+
+  tts->thread_start_flag = RAISED;
+
+  LFDS700_MISC_BARRIER_STORE;
+
+  lfds700_misc_force_store();
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void util_thread_starter_delete( struct util_thread_starter_state *tts )
+{
+  assert( tts != NULL );
+
+  free( tts->tsts );
+
+  free( tts );
+
+  return;
+}
+
+
+
+
+
+/****************************************************************************/
+void util_thread_start_wrapper( test_pal_thread_state_t *thread_state,
+                                     struct test_pal_logical_processor *lp,
+                                     test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
+                                     void *thread_user_state )
+{
+  int
+    rv;
+
+  assert( thread_state != NULL );
+  assert( lp != NULL );
+  assert( thread_function != NULL );
+  // TRD : thread_user_state can be NULL
+
+  rv = test_pal_thread_start( thread_state, lp, thread_function, thread_user_state );
+
+  if( rv == 0 )
+  {
+    puts( "test_pal_thread_start() failed." );
+    exit( EXIT_FAILURE );
+  }
+
+  return;
+}
+
diff --git a/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_thread_starter.h b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_thread_starter.h
new file mode 100644
index 0000000000000000000000000000000000000000..5587edf1c071ad90ccead36d018abbcc7c6b735d
--- /dev/null
+++ b/openair2/UTIL/LFDS/liblfds7.0.0/test/src/util_thread_starter.h
@@ -0,0 +1,41 @@
+/***** structs *****/
+struct util_thread_starter_thread_state
+{
+  // TRD : must be volatile or the compiler optimizes it away into a single load
+  enum flag volatile
+    thread_ready_flag,
+    *thread_start_flag;
+
+  void
+    *thread_user_state;
+};
+
+struct util_thread_starter_state
+{
+  enum flag volatile
+    thread_start_flag;
+
+  lfds700_pal_uint_t
+    number_thread_states;
+
+  struct util_thread_starter_thread_state
+    *tsts;
+};
+
+/***** prototypes *****/
+void util_thread_starter_new( struct util_thread_starter_state **tts, lfds700_pal_uint_t number_threads );
+void util_thread_starter_start( struct util_thread_starter_state *tts,
+                                test_pal_thread_state_t *thread_state,
+                                lfds700_pal_uint_t thread_number,
+                                struct test_pal_logical_processor *lp, 
+                                test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)( void *thread_user_state ),
+                                void *thread_user_state );
+void util_thread_starter_ready_and_wait( struct util_thread_starter_thread_state *tsts );
+void util_thread_starter_run( struct util_thread_starter_state *tts );
+void util_thread_starter_delete( struct util_thread_starter_state *tts );
+
+void util_thread_start_wrapper( test_pal_thread_state_t *thread_state,
+                                struct test_pal_logical_processor *lp,
+                                test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state),
+                                void *thread_user_state );
+
diff --git a/openair2/UTIL/LOG/log.c b/openair2/UTIL/LOG/log.c
index 2626d18c19d8ef4ac11259d5f6d11656d655b358..49f00325f8c70d528bf6c1f3cc700928d0cbc601 100644
--- a/openair2/UTIL/LOG/log.c
+++ b/openair2/UTIL/LOG/log.c
@@ -325,6 +325,14 @@ int logInit (void)
   g_log->log_component[ENB_APP].filelog = 0;
   g_log->log_component[ENB_APP].filelog_name = "";
 
+  g_log->log_component[FLEXRAN_AGENT].name = "FLEXRAN_AGENT";
+  g_log->log_component[FLEXRAN_AGENT].level = LOG_DEBUG;
+  g_log->log_component[FLEXRAN_AGENT].flag = LOG_MED;
+  g_log->log_component[FLEXRAN_AGENT].interval = 1;
+  g_log->log_component[FLEXRAN_AGENT].fd = 0;
+  g_log->log_component[FLEXRAN_AGENT].filelog = 0;
+  g_log->log_component[FLEXRAN_AGENT].filelog_name = "";
+  
   g_log->log_component[TMR].name = "TMR";
   g_log->log_component[TMR].level = LOG_EMERG;
   g_log->log_component[TMR].flag = LOG_MED;
diff --git a/openair2/UTIL/LOG/log.h b/openair2/UTIL/LOG/log.h
index d5ab549aef25e18d727730436fc6734e7d1fd951..6a6569c1a585499bb314574cb70a0d26a35d4e36 100644
--- a/openair2/UTIL/LOG/log.h
+++ b/openair2/UTIL/LOG/log.h
@@ -270,6 +270,7 @@ typedef enum {
   RAL_ENB,
   RAL_UE,
   ENB_APP,
+  FLEXRAN_AGENT,
   TMR,
   USIM,
   LOCALIZE,
diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c
index 226f8f0754feb51cb2a517724024b584cc7f6602..34fc8e97b8a8ede096c68451f891725ff7c91cd3 100644
--- a/openair2/UTIL/LOG/vcd_signal_dumper.c
+++ b/openair2/UTIL/LOG/vcd_signal_dumper.c
@@ -174,6 +174,8 @@ const char* eurecomVariablesNames[] = {
   "ue0_SFN5",
   "ue0_SFN6",
   "ue0_SFN7",
+  "ue0_trx_read_ns",
+  "ue0_trx_write_ns",
 };
 
 const char* eurecomFunctionsNames[] = {
@@ -188,6 +190,17 @@ const char* eurecomFunctionsNames[] = {
   "ue_thread_synch",
   "ue_thread_rxtx0",
   "ue_thread_rxtx1",
+  "trx_read_sf9",
+  "trx_write_sf9",
+  "ue_signal_cond_rxtx",
+  "ue_wait_cond_rxtx0",
+  "ue_wait_cond_rxtx1",
+  "ue_lock_mutex_rxtx_for_cond_wait0",
+  "ue_lock_mutex_rxtx_for_cond_wait1",
+  "ue_lock_mutex_rxtx_for_cnt_decrement0",
+  "ue_lock_mutex_rxtx_for_cnt_decrement1",
+  "ue_lock_mutex_rxtx_for_cnt_increment0",
+  "ue_lock_mutex_rxtx_for_cnt_increment1",
 
  /* RRH signals  */ 
   "eNB_tx",
@@ -218,6 +231,11 @@ const char* eurecomFunctionsNames[] = {
   "phy_eNB_slot_fep",
   "phy_procedures_ue_tx",
   "phy_procedures_ue_rx",
+  "phy_procedures_ue_tx_ulsch_uespec",
+  "phy_procedures_ue_tx_pucch",
+  "phy_procedures_ue_tx_ulsch_common",
+  "phy_procedures_ue_tx_prach",
+  "phy_procedures_ue_tx_ulsch_rar",
   "phy_procedures_eNB_lte",
   "phy_procedures_UE_lte",
   "pdsch_thread",
@@ -240,6 +258,10 @@ const char* eurecomFunctionsNames[] = {
   "rx_pdcch",
   "dci_decoding",
   "rx_phich",
+  "pdsch_procedures",
+  "pdsch_procedures_si",
+  "pdsch_procedures_p",
+  "pdsch_procedures_ra",
   "phy_ue_config_sib2",
   "macxface_phy_config_sib1_eNB",
   "macxface_phy_config_sib2_eNB",
@@ -266,6 +288,8 @@ const char* eurecomFunctionsNames[] = {
   "phy_eNB_dlsch_encoding",
   "phy_eNB_dlsch_encoding_w",
   "phy_eNB_dlsch_scrambling",
+  "phy_eNB_beam_precoding",
+  "phy_eNB_ofdm_mod_l",
 
   /* MAC  signals  */
   "macxface_macphy_init",
diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h
index 81a5fb083d98fabf1cdf29583154bd11f6b5096f..0d1c507b749b5b5583c5f40e3957571f843327e8 100644
--- a/openair2/UTIL/LOG/vcd_signal_dumper.h
+++ b/openair2/UTIL/LOG/vcd_signal_dumper.h
@@ -146,6 +146,8 @@ typedef enum {
   VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN5,
   VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN6,
   VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN7,
+  VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS,
+  VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS,
   VCD_SIGNAL_DUMPER_VARIABLES_LAST,
   VCD_SIGNAL_DUMPER_VARIABLES_END = VCD_SIGNAL_DUMPER_VARIABLES_LAST,
 } vcd_signal_dump_variables;
@@ -162,6 +164,17 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH,
   VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0,
   VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX1,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_SF9,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SIGNAL_COND_RXTX,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX0,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX1,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT1,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT1,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT1,
 
   /* RRH signals  */ 
   VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX,
@@ -192,6 +205,11 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_RAR,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_LTE,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD,
@@ -214,6 +232,10 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH,
   VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING,
   VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_CONFIG_SIB1_ENB,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_CONFIG_SIB2_ENB,
@@ -240,6 +262,8 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING,
   VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W,
   VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_OFDM_MODULATION,
 
   /* MAC signals  */
   VCD_SIGNAL_DUMPER_FUNCTIONS_MACPHY_INIT,
diff --git a/openair2/UTIL/OPT/opt.h b/openair2/UTIL/OPT/opt.h
index cc1ab6854c66179f9bd718b0bb4a998f5646f42e..0d2ab89e2a71e3c1d5797e9fd2dc94f813195a9a 100644
--- a/openair2/UTIL/OPT/opt.h
+++ b/openair2/UTIL/OPT/opt.h
@@ -81,7 +81,7 @@ extern char in_path[100];
 */
 
 void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
-               int ueid, int rntiType, int rnti, uint8_t subframe,
+               int ueid, int rntiType, int rnti, uint16_t sysFrame, uint8_t subframe,
                int oob_event, int oob_event_value);
 
 int init_opt(char *path, char *ip, char *port, radio_type_t radio_type_p);
diff --git a/openair2/UTIL/OPT/probe.c b/openair2/UTIL/OPT/probe.c
index 8f02c4345672f99dbee3f0f96082352e59032c82..1c6b8e814bca524fa040d610501b6e9b106d2ed5 100644
--- a/openair2/UTIL/OPT/probe.c
+++ b/openair2/UTIL/OPT/probe.c
@@ -230,7 +230,7 @@ int opt_create_listener_socket(char *ip_address, uint16_t port)
  */
 /* Add framing header to MAC PDU and send. */
 static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
-                      guint16 rnti, guint16 ueid, guint16 subframeNumber,
+                      guint16 rnti, guint16 ueid, guint16 sfnSf,
                       guint8 isPredefinedData, guint8 retx, guint8 crcStatus,
                       guint8 oob_event, guint8 oob_event_value,
                       uint8_t *pdu_buffer, unsigned int pdu_buffer_size)
@@ -278,7 +278,7 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
 
   /* Subframe number */
   frameBuffer[frameOffset++] = MAC_LTE_SUBFRAME_TAG;
-  tmp16 = htons(subframeNumber); // frame counter : this will give an expert info as wireshark expects SF and not F
+  tmp16 = htons(sfnSf); // frame counter : this will give an expert info as wireshark expects SF and not F
   memcpy(frameBuffer+frameOffset, &tmp16, 2);
   frameOffset += 2;
 
@@ -287,7 +287,7 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
   
 #ifdef WIRESHARK_DEV
   frameOffset += 2;
-  tmp16 = htons(subframeNumber); // subframe
+  tmp16 = htons(sfnSf); // subframe
   memcpy(frameBuffer+frameOffset, &tmp16, 2);
   frameOffset += 2;
 #endif
@@ -304,19 +304,25 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
     frameBuffer[frameOffset++] = retx;
   }
 
-#ifdef WIRESHARK_DEV
+//#ifdef WIRESHARK_DEV
 
   /* Relating to out-of-band events */
   /* N.B. dissector will only look to these fields if length is 0... */
   if (pdu_buffer_size==0) {
     switch (oob_event) {
     case ltemac_send_preamble :
-      LOG_D(OPT,"oob event %d %d\n",ltemac_send_preamble );
+      LOG_D(OPT,"oob ltemac_send_preamble event %02x."
+          //"%02x."
+          "%02x.%02x\n",
+          MAC_LTE_OOB_EVENT_TAG,
+          //ltemac_send_preamble,
+          rnti,
+          oob_event_value);
       //frameBuffer[frameOffset++]=0;
       //frameBuffer[frameOffset++]=0;
       //frameBuffer[frameOffset++]=0;
       frameBuffer[frameOffset++] = MAC_LTE_OOB_EVENT_TAG;
-      frameBuffer[frameOffset++]=ltemac_send_preamble;
+      //frameBuffer[frameOffset++]=ltemac_send_preamble;
       frameBuffer[frameOffset++]=rnti; // is the preamble
       frameBuffer[frameOffset++]=oob_event_value;
       break;
@@ -329,12 +335,12 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
 
     case ltemac_sr_failure:
     default:
-      LOG_D(OPT,"not implemeneted yet\n");
+      LOG_W(OPT,"not implemeneted yet\n");
       break;
     }
   }
 
-#endif
+//#endif
   /***************************************/
   /* Now write the MAC PDU               */
   frameBuffer[frameOffset++] = MAC_LTE_PAYLOAD_TAG;
@@ -428,7 +434,7 @@ static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
 
 /* Remote serveraddress (where Wireshark is running) */
 void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
-               int ueid, int rntiType, int rnti, uint8_t subframe, int oob_event,
+               int ueid, int rntiType, int rnti, uint16_t sysFrameNumber, uint8_t subFrameNumber, int oob_event,
                int oob_event_value)
 {
   MAC_Context_Info_t pdu_context;
@@ -441,7 +447,7 @@ void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
 
     SendFrame(radio_type,
               (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK,
-              rntiType, rnti, ueid, subframe,
+              rntiType, rnti, ueid, (sysFrameNumber<<4) + subFrameNumber,
               1, 0, 1,  //guint8 isPredefinedData, guint8 retx, guint8 crcStatus
               oob_event,oob_event_value,
               pdu_buffer, pdu_buffer_size);
@@ -460,8 +466,8 @@ void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
     pdu_context.ueid = ueid;
     pdu_context.isRetx = 0;
     pdu_context.crcStatusOK =1;
-    pdu_context.sysFrameNumber = subframe;
-    pdu_context.subFrameNumber = 0;
+    pdu_context.sysFrameNumber = sysFrameNumber;
+    pdu_context.subFrameNumber = subFrameNumber;
     pdu_context.subframesSinceCaptureStart = subframesSinceCaptureStart++;
     MAC_LTE_PCAP_WritePDU( &pdu_context, pdu_buffer, pdu_buffer_size);
     break;
diff --git a/openair2/UTIL/OTG/otg_tx.c b/openair2/UTIL/OTG/otg_tx.c
index 5a2718c02b06252c1dac08b2452d9edbc3d6c70a..bdf8137cfa42c07159e0a156c9983d9324504ff5 100644
--- a/openair2/UTIL/OTG/otg_tx.c
+++ b/openair2/UTIL/OTG/otg_tx.c
@@ -262,13 +262,14 @@ unsigned char *packet_gen(
   char *header=NULL;
   int header_size = 0;
 
-
+  //LOG_I(OTG,"Src: %d - Dest: %d - before exit\n",src_instance,dst_instance);
   // check if the app is configured
   if (app >= g_otg->application_idx[src_instance][dst_instance]) {
+    //LOG_I(OTG,"Src: %d - Dest: %d - no packet to generate - no application\n",src_instance,dst_instance);
     return NULL;
   }
 
-  LOG_T(OTG,"[src %d] [dst %d ][APP %d] current time  %d\n",src_instance,  dst_instance, app, ctime);
+  //LOG_I(OTG,"[src %d] [dst %d ][APP %d] current time  %d\n",src_instance,  dst_instance, app, ctime);
 
   *pkt_size=0;
   init_packet_gen(src_instance, dst_instance,ctime);
diff --git a/openair3/NAS/COMMON/API/NETWORK/l2_message.h b/openair3/NAS/COMMON/API/NETWORK/l2_message.h
index b6ad3727cc6b4b4d591faea13669fba9f7d52702..39a2d18905358ddf5300b531f15a3dda8b1c3bf4 100644
--- a/openair3/NAS/COMMON/API/NETWORK/l2_message.h
+++ b/openair3/NAS/COMMON/API/NETWORK/l2_message.h
@@ -109,6 +109,14 @@ Description Defines the messages supported by the Access Stratum sublayer
 #define AS_HSDUPA     (1 << NET_ACCESS_HSDUPA)
 #define AS_EUTRAN     (1 << NET_ACCESS_EUTRAN)
 
+/*
+ * NAS->AS -K_eNB refresh request
+ * NAS request AS to refresh its KeNB key
+ */
+typedef struct kenb_refresh_req_s {
+  Byte_t kenb[32];
+} kenb_refresh_req_t;
+
 /*
  * NAS->AS - Cell Information request
  * NAS request AS to search for a suitable cell belonging to the selected
diff --git a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c
index cec2d169774edc2edc704e25a9454ae772f700f3..248540dff3fb8b7481136a3c1b9ba5ca47a81747 100644
--- a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c
+++ b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c
@@ -188,10 +188,11 @@ int decode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
 
     default:
       errorCodeDecoder = TLV_DECODE_UNEXPECTED_IEI;
+      LOG_TRACE(WARNING, "DECODE_UNEXPECTED_IEI %x (4 bits)", ieiDecoded);
       return TLV_DECODE_UNEXPECTED_IEI;
     }
   }
-
+  LOG_TRACE(WARNING, "DECODED %d\n", decoded);
   return decoded;
 }
 
diff --git a/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c b/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c
index fac93c5df3eb878a5a7c7afc40ba459db6c44e2d..3e0bffde2d1afd718288a1bcee40058096549220 100644
--- a/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c
+++ b/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c
@@ -38,7 +38,7 @@ int decode_authentication_request(authentication_request_msg *authentication_req
   CHECK_PDU_POINTER_AND_LENGTH_DECODER(buffer, AUTHENTICATION_REQUEST_MINIMUM_LENGTH, len);
 
   /* Decoding mandatory fields */
-  if ((decoded_result = decode_u8_nas_key_set_identifier(&authentication_request->naskeysetidentifierasme, 0, *(buffer + decoded) >> 4, len - decoded)) < 0)
+  if ((decoded_result = decode_u8_nas_key_set_identifier(&authentication_request->naskeysetidentifierasme, 0, *(buffer + decoded), len - decoded)) < 0)
     return decoded_result;
 
   decoded++;
diff --git a/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c b/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c
index aeec3d4024e6e6c81e8452c4820a07a813ead52e..a1a34f94954ccfed88d36be7b5007e2eff9f972d 100644
--- a/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c
+++ b/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c
@@ -72,6 +72,8 @@ int decode_security_mode_command(security_mode_command_msg *security_mode_comman
       decoded += decoded_result;
       /* Set corresponding mask to 1 in presencemask */
       security_mode_command->presencemask |= SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT;
+      LOG_TRACE(INFO," SECURITY MODE COMMAND: IMEISV_REQUEST: %d \n",security_mode_command->imeisvrequest);
+
       break;
 
     case SECURITY_MODE_COMMAND_REPLAYED_NONCEUE_IEI:
diff --git a/openair3/NAS/COMMON/EMM/MSG/SecurityModeComplete.c b/openair3/NAS/COMMON/EMM/MSG/SecurityModeComplete.c
index f10401d09a9d75d5373eca7a359ab6a8b0226dd7..3258134febff5c6ae8cefb871fa0eb4b9cc88218 100644
--- a/openair3/NAS/COMMON/EMM/MSG/SecurityModeComplete.c
+++ b/openair3/NAS/COMMON/EMM/MSG/SecurityModeComplete.c
@@ -76,8 +76,11 @@ int encode_security_mode_complete(security_mode_complete_msg *security_mode_comp
   /* Checking IEI and pointer */
   CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, SECURITY_MODE_COMPLETE_MINIMUM_LENGTH, len);
 
+  LOG_TRACE(INFO,"SECURITY MODE COMMAND COMPLETE:  presencemask: %d \n",security_mode_complete->presencemask);
+
   if ((security_mode_complete->presencemask & SECURITY_MODE_COMPLETE_IMEISV_PRESENT)
       == SECURITY_MODE_COMPLETE_IMEISV_PRESENT) {
+	  LOG_TRACE(INFO,"SECURITY MODE COMMAND COMPLETE: encode imeisv \n");
     if ((encode_result =
            encode_mobile_identity(&security_mode_complete->imeisv,
                                   SECURITY_MODE_COMPLETE_IMEISV_IEI, buffer + encoded, len -
@@ -87,7 +90,7 @@ int encode_security_mode_complete(security_mode_complete_msg *security_mode_comp
     else
       encoded += encode_result;
   }
-
+  LOG_TRACE(INFO,"SECURITY MODE COMMAND COMPLETE done !!! \n");
   return encoded;
 }
 
diff --git a/openair3/NAS/COMMON/IES/EmergencyNumberList.c b/openair3/NAS/COMMON/IES/EmergencyNumberList.c
index 39b59ef0ca79647e478be37207c564d8a6b417a4..9330fdc312ef0107e29298554021bd03d1ae19db 100644
--- a/openair3/NAS/COMMON/IES/EmergencyNumberList.c
+++ b/openair3/NAS/COMMON/IES/EmergencyNumberList.c
@@ -41,10 +41,24 @@ int decode_emergency_number_list(EmergencyNumberList *emergencynumberlist, uint8
   ielen = *(buffer + decoded);
   decoded++;
   CHECK_LENGTH_DECODER(len - decoded, ielen);
-  emergencynumberlist->lengthofemergency = *(buffer + decoded);
-  decoded++;
-  emergencynumberlist->emergencyservicecategoryvalue = *(buffer + decoded) & 0x1f;
-  decoded++;
+  int information_element_index = 0;
+  while ((decoded < ielen) && (information_element_index < EMERGENCY_NUMBER_LIST_MAX_NUMBER_INFORMATION)) {
+    emergencynumberlist->emergency_number_information[information_element_index].lengthofemergency = *(buffer + decoded);
+    decoded++;
+    emergencynumberlist->emergency_number_information[information_element_index].emergencyservicecategoryvalue = *(buffer + decoded) & 0x1f;
+    decoded++;
+    int remaining_len = emergencynumberlist->emergency_number_information[information_element_index].lengthofemergency - 1;
+    int digit_index = 0;
+    while (remaining_len > 0) {
+    	emergencynumberlist->emergency_number_information[information_element_index].bcd_digits[digit_index++] = *(buffer + decoded);
+        decoded++;
+        remaining_len --;
+    }
+    while (digit_index < EMERGENCY_NUMBER_LIST_MAX_2DIGITS) {
+    	emergencynumberlist->emergency_number_information[information_element_index].bcd_digits[digit_index++] = 0xFF;
+    }
+    information_element_index++;
+  }
 #if defined (NAS_DEBUG)
   dump_emergency_number_list_xml(emergencynumberlist, iei);
 #endif
@@ -67,11 +81,16 @@ int encode_emergency_number_list(EmergencyNumberList *emergencynumberlist, uint8
 
   lenPtr  = (buffer + encoded);
   encoded ++;
-  *(buffer + encoded) = emergencynumberlist->lengthofemergency;
-  encoded++;
-  *(buffer + encoded) = 0x00 |
-                        (emergencynumberlist->emergencyservicecategoryvalue & 0x1f);
-  encoded++;
+  for (  int ie_index = 0; ie_index < emergencynumberlist->num_emergency_elements; ie_index++) {
+	  *(buffer + encoded) = emergencynumberlist->emergency_number_information[ie_index].lengthofemergency;
+	  encoded++;
+	  *(buffer + encoded) = 0x00 |
+	                        (emergencynumberlist->emergency_number_information[ie_index].emergencyservicecategoryvalue & 0x1f);
+	  encoded++;
+	  for (int bcd2_index = 0; bcd2_index < (emergencynumberlist->emergency_number_information[ie_index].lengthofemergency - 1); bcd2_index++) {
+		  *(buffer + encoded) = emergencynumberlist->emergency_number_information[ie_index].bcd_digits[bcd2_index];
+	  }
+  }
   *lenPtr = encoded - 1 - ((iei > 0) ? 1 : 0);
   return encoded;
 }
@@ -83,9 +102,20 @@ void dump_emergency_number_list_xml(EmergencyNumberList *emergencynumberlist, ui
   if (iei > 0)
     /* Don't display IEI if = 0 */
     printf("    <IEI>0x%X</IEI>\n", iei);
-
-  printf("    <Length of emergency>%u</Length of emergency>\n", emergencynumberlist->lengthofemergency);
-  printf("    <Emergency service category value>%u</Emergency service category value>\n", emergencynumberlist->emergencyservicecategoryvalue);
+  for (  int ie_index = 0; ie_index < emergencynumberlist->num_emergency_elements; ie_index++) {
+	  printf("    <Length of emergency>%u</Length of emergency>\n", emergencynumberlist->emergency_number_information[ie_index].lengthofemergency);
+	  printf("    <Emergency service category value>%u</Emergency service category value>\n", emergencynumberlist->emergency_number_information[ie_index].emergencyservicecategoryvalue);
+	  for (int bcd2_index = 0; bcd2_index < (emergencynumberlist->emergency_number_information[ie_index].lengthofemergency - 1); bcd2_index++) {
+		  uint8_t bcd1 = emergencynumberlist->emergency_number_information[ie_index].bcd_digits[bcd2_index] & 0x0f;
+		  uint8_t bcd2 = (emergencynumberlist->emergency_number_information[ie_index].bcd_digits[bcd2_index] & 0xf0) >> 4;
+		  if (bcd1 < 10) {
+		    printf("    <BCD Digit%u>%u</BCD Digit%u>\n", (bcd2_index*2)+1, bcd1, (bcd2_index*2)+1);
+		    if (bcd2 < 10) {
+		    	printf("    <BCD Digit%u>%u</BCD Digit%u>\n", (bcd2_index*2)+2, bcd2, (bcd2_index*2)+2);
+		    }
+		  }
+	  }
+  }
   printf("</Emergency Number List>\n");
 }
 
diff --git a/openair3/NAS/COMMON/IES/EmergencyNumberList.h b/openair3/NAS/COMMON/IES/EmergencyNumberList.h
index d2fd149dc098c9c43b5c6a15df870074f9b8b742..ab47c1ff06766208d0ff18153a05dc7fa6efb599 100644
--- a/openair3/NAS/COMMON/IES/EmergencyNumberList.h
+++ b/openair3/NAS/COMMON/IES/EmergencyNumberList.h
@@ -32,8 +32,14 @@
 #define EMERGENCY_NUMBER_LIST_MAXIMUM_LENGTH 50
 
 typedef struct EmergencyNumberList_tag {
-  uint8_t  lengthofemergency;
-  uint8_t  emergencyservicecategoryvalue:5;
+  uint8_t  num_emergency_elements;
+  struct {
+    uint8_t  lengthofemergency;
+    uint8_t  emergencyservicecategoryvalue:5;
+#define EMERGENCY_NUMBER_LIST_MAX_2DIGITS 6
+    uint8_t  bcd_digits[EMERGENCY_NUMBER_LIST_MAX_2DIGITS]; // length to be fixed
+#define EMERGENCY_NUMBER_LIST_MAX_NUMBER_INFORMATION 2
+  } emergency_number_information[EMERGENCY_NUMBER_LIST_MAX_NUMBER_INFORMATION];
 } EmergencyNumberList;
 
 int encode_emergency_number_list(EmergencyNumberList *emergencynumberlist, uint8_t iei, uint8_t *buffer, uint32_t len);
diff --git a/openair3/NAS/COMMON/IES/EsmMessageContainer.c b/openair3/NAS/COMMON/IES/EsmMessageContainer.c
index 1a7f88d2998c51a6dd9706597bfcc532b6c69af7..a223f36820ee1cd31689fcb7c358801a8afcecc2 100644
--- a/openair3/NAS/COMMON/IES/EsmMessageContainer.c
+++ b/openair3/NAS/COMMON/IES/EsmMessageContainer.c
@@ -28,7 +28,7 @@
 #include "EsmMessageContainer.h"
 #include "nas_log.h"
 
-#define NAS_DEBUG 1
+//#define NAS_DEBUG 1
 
 int decode_esm_message_container(EsmMessageContainer *esmmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len)
 {
diff --git a/openair3/NAS/COMMON/IES/MobileIdentity.c b/openair3/NAS/COMMON/IES/MobileIdentity.c
index 7ab30011ce93e42504ae91b752dccc96c97950bf..4651fa0047dffd5b757a1b16d9d50aef3c067403 100644
--- a/openair3/NAS/COMMON/IES/MobileIdentity.c
+++ b/openair3/NAS/COMMON/IES/MobileIdentity.c
@@ -575,6 +575,8 @@ static int encode_imei_mobile_identity(ImeiMobileIdentity_t *imei, uint8_t *buff
 static int encode_imeisv_mobile_identity(ImeisvMobileIdentity_t *imeisv, uint8_t *buffer)
 {
   uint32_t encoded = 0;
+  LOG_TRACE(INFO,"SECURITY MODE COMMAND COMPLETE: encode_imeisv_mobile_identity \n");
+
   *(buffer + encoded) = 0x00 | (imeisv->digit1 << 4) | (imeisv->oddeven << 3) |
                         (imeisv->typeofidentity);
   encoded++;
@@ -590,12 +592,15 @@ static int encode_imeisv_mobile_identity(ImeisvMobileIdentity_t *imeisv, uint8_t
   encoded++;
   *(buffer + encoded) = 0x00 | (imeisv->digit13 << 4) | imeisv->digit12;
   encoded++;
+  *(buffer + encoded) = 0x00 | (imeisv->digit15 << 4) | imeisv->digit14;
+  encoded++;
+  *(buffer + encoded) = 0x00 | (imeisv->parity << 4) | imeisv->digit16;
 
-  if (imeisv->oddeven != MOBILE_IDENTITY_EVEN) {
-    *(buffer + encoded) = 0x00 | (imeisv->digit15 << 4) | imeisv->digit14;
-  } else {
-    *(buffer + encoded) = 0xf0 | imeisv->digit14;
-  }
+  //if (imeisv->oddeven != MOBILE_IDENTITY_EVEN) {
+  //  *(buffer + encoded) = 0x00 | (imeisv->digit15 << 4) | imeisv->digit14;
+  //} else {
+  //  *(buffer + encoded) = 0xf0 | imeisv->digit14;
+  //}
 
   encoded++;
   return encoded;
diff --git a/openair3/NAS/COMMON/IES/MobileIdentity.h b/openair3/NAS/COMMON/IES/MobileIdentity.h
index 8d1c5cdbe5b1a1f31399ff1687edb630dcab6c78..72abcb9ed47774178e509301717ffde8d5680a2f 100644
--- a/openair3/NAS/COMMON/IES/MobileIdentity.h
+++ b/openair3/NAS/COMMON/IES/MobileIdentity.h
@@ -73,8 +73,63 @@ typedef struct {
   uint8_t  mbmssessionid;
 } TmgiMobileIdentity_t;
 
+typedef struct imeisv_s{
+  uint8_t  digit1:4;
+  uint8_t  oddeven:1;
+  uint8_t  typeofidentity:3;
+  uint8_t  digit2:4;
+  uint8_t  digit3:4;
+  uint8_t  digit4:4;
+  uint8_t  digit5:4;
+  uint8_t  digit6:4;
+  uint8_t  digit7:4;
+  uint8_t  digit8:4;
+  uint8_t  digit9:4;
+  uint8_t  digit10:4;
+  uint8_t  digit11:4;
+  uint8_t  digit12:4;
+  uint8_t  digit13:4;
+  uint8_t  digit14:4;
+  uint8_t  digit15:4;
+  uint8_t  digit16:4;
+#define EVEN_PARITY 0
+#define IMEI_ODD_PARITY  0xf
+       uint8_t parity:4;
+} imeisv_t;
+
+#if 0
+typedef struct imeisv_s {
+   uint8_t length;
+   union {
+     struct {
+       uint8_t tac2:4;
+       uint8_t tac1:4;
+       uint8_t tac4:4;
+       uint8_t tac3:4;
+       uint8_t tac6:4;
+       uint8_t tac5:4;
+       uint8_t tac8:4;
+       uint8_t tac7:4;
+       uint8_t snr2:4;
+       uint8_t snr1:4;
+       uint8_t snr4:4;
+       uint8_t snr3:4;
+       uint8_t snr6:4;
+       uint8_t snr5:4;
+       uint8_t svn2:4;
+       uint8_t svn1:4;
+#define EVEN_PARITY 0
+#define IMEI_ODD_PARITY  0xf
+       uint8_t parity:4;
+     } num;
+#define IMEISV_BCD8_SIZE   9
+     uint8_t value[IMEISV_BCD8_SIZE];
+   } u;
+} imeisv_t;
+#endif
+
 typedef ImsiMobileIdentity_t ImeiMobileIdentity_t;
-typedef ImsiMobileIdentity_t ImeisvMobileIdentity_t;
+typedef imeisv_t             ImeisvMobileIdentity_t;
 typedef ImsiMobileIdentity_t TmsiMobileIdentity_t;
 typedef ImsiMobileIdentity_t NoMobileIdentity_t;
 
diff --git a/openair3/NAS/COMMON/UTIL/TLVDecoder.h b/openair3/NAS/COMMON/UTIL/TLVDecoder.h
index 801ab77c8df58e6ba17b5b2526b5f276b63b2854..37834c5660253a8378bb080dffd6e6634fa12c06 100644
--- a/openair3/NAS/COMMON/UTIL/TLVDecoder.h
+++ b/openair3/NAS/COMMON/UTIL/TLVDecoder.h
@@ -26,7 +26,7 @@
 #include "nas_log.h"
 
 #ifndef NAS_DEBUG
-# define NAS_DEBUG 1
+//# define NAS_DEBUG 1
 #endif
 
 #define DECODE_U8(bUFFER, vALUE, sIZE)    \
diff --git a/openair3/NAS/TOOLS/usim_data.c b/openair3/NAS/TOOLS/usim_data.c
index 3313f474983b4b1e2beeaf9c7501918c2ff6d95f..23eba29bb134cf1fa3ad8a9bacec4f546d23cd96 100644
--- a/openair3/NAS/TOOLS/usim_data.c
+++ b/openair3/NAS/TOOLS/usim_data.c
@@ -220,6 +220,7 @@ int main (int argc, const char* argv[])
     usim_data.imsi.u.num.digit13 = 3;
     usim_data.imsi.u.num.digit14 = 4;
     usim_data.imsi.u.num.digit15 = 0xF;
+    usim_data.usimtestmode = 1; // set usim in test mode in order to get the CMW500 K key
 #endif
     /*
      * Ciphering and Integrity Keys
diff --git a/openair3/NAS/UE/API/USIM/usim_api.c b/openair3/NAS/UE/API/USIM/usim_api.c
index a517799ff7c33eccf721736dc35251fc87cc796a..58ca9aa279e95e66375647e3760bf490f833dded 100644
--- a/openair3/NAS/UE/API/USIM/usim_api.c
+++ b/openair3/NAS/UE/API/USIM/usim_api.c
@@ -72,6 +72,7 @@ Description Implements the API used by the NAS layer to read/write
 #define USIM_API_K_SIZE         16
 //#define USIM_API_K_VALUE        "fec86ba6eb707ed08905757b1bb44b8f"
 #define USIM_API_K_VALUE        "8BAF473F2F8FD09487CCCBD7097C6862"
+#define TEST_USIM_API_K_VALUE   "000102030405060708090a0b0c0d0e0f" // CMW500 K key
 
 static uint8_t _usim_api_k[USIM_API_K_SIZE];
 
@@ -136,7 +137,14 @@ int usim_api_read(usim_data_t* data)
   }
 
   /* initialize the subscriber authentication security key */
-  _usim_api_hex_string_to_hex_value(_usim_api_k, USIM_API_K_VALUE, USIM_API_K_SIZE);
+  if(data->usimtestmode == 0)
+  {
+    _usim_api_hex_string_to_hex_value(_usim_api_k, USIM_API_K_VALUE, USIM_API_K_SIZE);
+  }
+  else
+  {
+    _usim_api_hex_string_to_hex_value(_usim_api_k, TEST_USIM_API_K_VALUE, USIM_API_K_SIZE);
+  }
 
   free(path);
   LOG_FUNC_RETURN (RETURNok);
@@ -181,6 +189,189 @@ int usim_api_write(const usim_data_t* data)
   LOG_FUNC_RETURN (RETURNok);
 }
 
+/****************************************************************************
+ **                                                                        **
+ ** Name:        usim_api_authenticate_test()                              **
+ **                                                                        **
+ ** Description: Performs mutual authentication of the USIM to the network,**
+ **              checking whether authentication token AUTN can be accep-  **
+ **              ted. If so, returns an authentication response RES and    **
+ **              the ciphering and integrity keys.                         **
+ **              In case of synch failure, returns a re-synchronization    **
+ **              token AUTS.                                               **
+ **                                                                        **
+ **              Key Generation for Test USIM based on 34.108              **
+ **                                                                        **
+ **              Authentication and key generating function algorithms are **
+ **              specified in 3GPP TS 35.206.                              **
+ **                                                                        **
+ ** Inputs:      rand_pP:          Random challenge number                    **
+ **              autn_pP:          Authentication token                       **
+ **                             AUTN = (SQN xor AK) || AMF || MAC          **
+ **                                         48          16     64 bits     **
+ **              Others:        Security key                               **
+ **                                                                        **
+ ** Outputs:     auts_pP:          Re-synchronization token                   **
+ **              res_pP:           Authentication response                    **
+ **              ck_pP:            Ciphering key                              **
+ **              ik_pP             Integrity key                              **
+ **                                                                        **
+ **              Return:        RETURNerror, RETURNok                      **
+ **              Others:        None                                       **
+ **                                                                        **
+ ***************************************************************************/
+int usim_api_authenticate_test(const OctetString* rand_pP, const OctetString* autn_pP,
+                               OctetString* auts_pP, OctetString* res_pP,
+                               OctetString* ck_pP, OctetString* ik_pP)
+{
+  LOG_FUNC_IN;
+
+  int rc;
+  int i;
+
+  LOG_TRACE(INFO, "USIM-API  - rand :%s",dump_octet_string(rand_pP));
+  LOG_TRACE(INFO, "USIM-API  - autn :%s",dump_octet_string(autn_pP));
+
+  //step1: XDOUT = RAND xor K
+  //       RES = XDOUT
+  for (i=0; i<USIM_API_K_SIZE; i++)
+  {
+      res_pP->value[i] = rand_pP->value[i] ^ _usim_api_k[i];
+  }
+
+  //step2: res = f2(xdout,n)
+  //       ck  = f3(xdout)
+  //       ik  = f4(xdout)
+  //       ak  = f5(xdout)
+  u8 ak[USIM_API_AK_SIZE];
+  for (i=0; i<15; i++)
+  {
+      ck_pP->value[i] = res_pP->value[i+1];
+  }
+  ck_pP->value[15] = res_pP->value[0];
+
+  for (i=0; i<14; i++)
+  {
+      ik_pP->value[i] = res_pP->value[i+2];
+  }
+  ik_pP->value[14] = res_pP->value[0];
+  ik_pP->value[15] = res_pP->value[1];
+
+  for (i=0; i<USIM_API_AK_SIZE; i++)
+  {
+      ak[i] = res_pP->value[i+3];
+  }
+  LOG_TRACE(INFO, "USIM-API  - res(f2)  :%s",dump_octet_string(res_pP));
+  LOG_TRACE(INFO, "USIM-API  - ck(f3)   :%s",dump_octet_string(ck_pP));
+  LOG_TRACE(INFO, "USIM-API  - ik(f4)   :%s",dump_octet_string(ik_pP));
+  LOG_TRACE(INFO, "USIM-API  - ak(f5)   : %02X%02X%02X%02X%02X%02X",
+            ak[0],ak[1],ak[2],ak[3],ak[4],ak[5]);
+
+  //step3: concatenate SQN with AMP SQN||AMF
+  //       SQN = AUTN xor ak
+  u8 sqn[USIM_API_SQN_SIZE];
+  for (i = 0; i < USIM_API_SQN_SIZE; i++) {
+    sqn[i] = autn_pP->value[i] ^ ak[i];
+  }
+  LOG_TRACE(INFO, "USIM-API  - Retrieved SQN %02X%02X%02X%02X%02X%02X",
+            sqn[0],sqn[1],sqn[2],sqn[3],sqn[4],sqn[5]);
+  LOG_TRACE(INFO, "USIM-API  - Retrieved AMF %02X%02X",
+            autn_pP->value[USIM_API_SQN_SIZE],autn_pP->value[USIM_API_SQN_SIZE+1]);
+
+#define USIM_API_XMAC_SIZE 8
+  u8 cdout[USIM_API_XMAC_SIZE];
+  for (i = 0; i < USIM_API_XMAC_SIZE; i++)
+  {
+    if(i < USIM_API_SQN_SIZE)
+    {
+        cdout[i] = sqn[i];
+    }
+    else
+    {
+        cdout[i] = autn_pP->value[i];
+    }
+  }
+  LOG_TRACE(INFO, "USIM-API  - Retrieved CDOUT %02X%02X%02X%02X%02X%02X%02X%02X",
+          cdout[0],cdout[1],cdout[2],cdout[3],cdout[4],cdout[5],cdout[6],cdout[7]);
+
+  //step4:calculate XMAC from cdout and xdout
+  u8 xmac[USIM_API_XMAC_SIZE];
+  for(i = 0; i < USIM_API_XMAC_SIZE; i++)
+  {
+      xmac[i] = res_pP->value[i] ^ cdout[i];
+  }
+  LOG_TRACE(INFO,
+            "USIM-API  - Computed XMAC %02X%02X%02X%02X%02X%02X%02X%02X",
+            xmac[0],xmac[1],xmac[2],xmac[3],
+            xmac[4],xmac[5],xmac[6],xmac[7]);
+
+  /* Compare the XMAC with the MAC included in AUTN */
+#define USIM_API_AMF_SIZE 2
+
+  if ( memcmp(xmac, &autn_pP->value[USIM_API_SQN_SIZE + USIM_API_AMF_SIZE],
+              USIM_API_XMAC_SIZE) != 0 ) {
+    LOG_TRACE(INFO,
+              "USIM-API  - Comparing the XMAC with the MAC included in AUTN Failed");
+    rc = RETURNerror;
+    //LOG_FUNC_RETURN (RETURNerror);
+  } else {
+    LOG_TRACE(INFO,
+              "USIM-API  - Comparing the XMAC with the MAC included in AUTN Succeeded");
+    /* Verify that the received sequence number SQN is in the correct range */
+    rc = _usim_api_check_sqn(*(uint32_t*)(sqn), sqn[USIM_API_SQN_SIZE - 1]);
+  }
+
+
+  if (rc != RETURNok) {
+    /* Synchronisation failure; compute the AUTS parameter */
+
+    /* Concealed value of the counter SQNms in the USIM:
+     * Conc(SQNMS) = SQNMS ⊕ f5*K(RAND) */
+    f5star(_usim_api_k, rand_pP->value, ak);
+
+
+    u8 sqn_ms[USIM_API_SQNMS_SIZE];
+    memset(sqn_ms, 0, USIM_API_SQNMS_SIZE);
+
+    //#define USIM_API_SQN_MS_SIZE  3
+    printf("_usim_api_data.sqn_ms %p\n",_usim_api_data.sqn_ms);
+    for (i = 0; i < USIM_API_SQNMS_SIZE; i++) {
+      //#warning "LG:BUG HERE TODO"
+      printf("i %d:  ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQNMS_SIZE - i] %d\n",i, ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQNMS_SIZE - i]);
+      sqn_ms[USIM_API_SQNMS_SIZE - i] =
+        ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQNMS_SIZE - i];
+    }
+
+    u8 sqnms[USIM_API_SQNMS_SIZE];
+
+    for (i = 0; i < USIM_API_SQNMS_SIZE; i++) {
+      sqnms[i] = sqn_ms[i] ^ ak[i];
+    }
+
+    LOG_TRACE(DEBUG, "USIM-API  - SQNms %02X%02X%02X%02X%02X%02X",
+              sqnms[0],sqnms[1],sqnms[2],sqnms[3],sqnms[4],sqnms[5]);
+
+    /* Synchronisation message authentication code:
+     * MACS = f1*K(SQNMS || RAND || AMF) */
+#define USIM_API_MACS_SIZE USIM_API_XMAC_SIZE
+    u8 macs[USIM_API_MACS_SIZE];
+    f1star(_usim_api_k, rand_pP->value, sqn_ms,
+           &rand_pP->value[USIM_API_SQN_SIZE], macs);
+    LOG_TRACE(DEBUG, "USIM-API  - MACS %02X%02X%02X%02X%02X%02X%02X%02X",
+              macs[0],macs[1],macs[2],macs[3],
+              macs[4],macs[5],macs[6],macs[7]);
+
+    /* Synchronisation authentication token:
+     * AUTS = Conc(SQNMS) || MACS */
+    memcpy(&auts_pP->value[0], sqnms, USIM_API_SQNMS_SIZE);
+    memcpy(&auts_pP->value[USIM_API_SQNMS_SIZE], macs, USIM_API_MACS_SIZE);
+    auts_pP->length = USIM_API_SQNMS_SIZE + USIM_API_MACS_SIZE;
+    LOG_FUNC_RETURN (RETURNerror);
+  }
+
+  LOG_FUNC_RETURN (RETURNok);
+}
+
 /****************************************************************************
  **                                                                        **
  ** Name:        usim_api_authenticate()                                   **
diff --git a/openair3/NAS/UE/API/USIM/usim_api.h b/openair3/NAS/UE/API/USIM/usim_api.h
index 3667abd4eeebfa195e6e4e7e54d4c51f337171cc..8cfaeb8aed67d14a0ca3cecde85eeba9433ce3d1 100644
--- a/openair3/NAS/UE/API/USIM/usim_api.h
+++ b/openair3/NAS/UE/API/USIM/usim_api.h
@@ -327,6 +327,8 @@ typedef struct {
   usim_epsloci_t epsloci;
   /* Non-Access Stratum configuration       */
   usim_nasconfig_t nasconfig;
+  /* usim test mode */
+  uint8_t usimtestmode;
 } usim_data_t;
 
 /****************************************************************************/
@@ -344,5 +346,8 @@ int usim_api_write(const usim_data_t* data);
 int usim_api_authenticate(const OctetString* rand, const OctetString* autn,
                           OctetString* auts, OctetString* res,
                           OctetString* ck, OctetString* ik);
+int usim_api_authenticate_test(const OctetString* rand, const OctetString* autn,
+                               OctetString* auts, OctetString* res,
+                               OctetString* ck, OctetString* ik);
 
 #endif /* __USIM_API_H__*/
diff --git a/openair3/NAS/UE/EMM/Authentication.c b/openair3/NAS/UE/EMM/Authentication.c
index 7ffab89f89c2dff1ed2b592edc24c78e068941ca..9022acbdac8d1a3cc4e6f9602dacb2572b79a323 100644
--- a/openair3/NAS/UE/EMM/Authentication.c
+++ b/openair3/NAS/UE/EMM/Authentication.c
@@ -79,6 +79,8 @@ extern void *_emm_service_t3417_handler(void *);
 extern void *_emm_detach_t3421_handler(void *);
 extern void *_emm_tau_t3430_handler(void *);
 
+extern uint8_t usim_test;
+
 /****************************************************************************/
 /*******************  L O C A L    D E F I N I T I O N S  *******************/
 /****************************************************************************/
@@ -233,7 +235,14 @@ int emm_proc_authentication_request(int native_ksi, int ksi,
        * of the core network by means of the received AUTN parameter and
        * request the USIM to compute RES, CK and IK for given RAND
        */
-      rc = usim_api_authenticate(rand, autn, &auts, &res, &ck, &ik);
+      if(usim_test == 0)
+      {
+        rc = usim_api_authenticate(rand, autn, &auts, &res, &ck, &ik);
+      }
+      else
+      {
+        rc = usim_api_authenticate_test(rand, autn, &auts, &res, &ck, &ik); // XOR algo for autentication on usim test mode
+      }
     }
 
     if (rc != RETURNok) {
diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c
index 707996b5a752e04e8aa055478de199f7a7056135..85f98c4bd7b03e40e093b37d3c86827f1c21fe82 100644
--- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c
+++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c
@@ -55,6 +55,7 @@ Description Implements the EPS Mobility Management procedures executed
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
 /****************************************************************************/
+extern uint8_t usim_test;
 
 /****************************************************************************/
 /*******************  L O C A L    D E F I N I T I O N S  *******************/
@@ -109,7 +110,14 @@ int EmmDeregisteredNormalService(const emm_reg_t *evt)
     /*
      * Initiate the attach procedure for EPS services
      */
-    rc = emm_proc_attach(EMM_ATTACH_TYPE_EPS);
+    if(usim_test == 0)
+    {
+      rc = emm_proc_attach(EMM_ATTACH_TYPE_EPS);
+    }
+    else
+    {
+      rc = emm_proc_attach(EMM_ATTACH_TYPE_IMSI); // CMW500 IMSI initial attach expected
+    }
     break;
 
   case _EMMREG_ATTACH_REQ:
diff --git a/openair3/NAS/UE/EMM/SAP/emm_asDef.h b/openair3/NAS/UE/EMM/SAP/emm_asDef.h
index bf0e6f6c3765525dbd6ed6f3e77818d6785b7866..69ea979b6361328530af8557330a47ad33d55e67 100644
--- a/openair3/NAS/UE/EMM/SAP/emm_asDef.h
+++ b/openair3/NAS/UE/EMM/SAP/emm_asDef.h
@@ -120,6 +120,7 @@ typedef struct emm_as_security_s {
   uint8_t ucs2;
   uint8_t uia;        /* Replayed UMTS integrity algorithms   */
   uint8_t gea;        /* Replayed GPRS encryption algorithms   */
+  uint8_t imeisv_request;
   uint8_t umts_present;
   uint8_t gprs_present;
 
diff --git a/openair3/NAS/UE/EMM/SAP/emm_recv.c b/openair3/NAS/UE/EMM/SAP/emm_recv.c
index 32e8e1ec30ef8cd2ab725360c4737ff3ca48cc0d..0ad41b09d878862b677cc35da535f103baf1cadf 100644
--- a/openair3/NAS/UE/EMM/SAP/emm_recv.c
+++ b/openair3/NAS/UE/EMM/SAP/emm_recv.c
@@ -137,8 +137,15 @@ int emm_recv_attach_accept(attach_accept_msg *msg, int *emm_cause)
   /*
    * Message checking
    */
-  if (msg->tailist.typeoflist !=
-      TRACKING_AREA_IDENTITY_LIST_ONE_PLMN_CONSECUTIVE_TACS) {
+  // supported cases:
+  // typeoflist = 1 Or
+  // typeoflist = 0 and numberofelements = 1 (ie numberofelements equal to zero see 3gpp 24.301 9.9.3.33.1)
+  LOG_TRACE(DEBUG,"attach accept type of list: %d, number of element: %d\n",msg->tailist.typeoflist, msg->tailist.numberofelements);
+  if (!( (msg->tailist.typeoflist == TRACKING_AREA_IDENTITY_LIST_ONE_PLMN_CONSECUTIVE_TACS) ||
+         ((msg->tailist.typeoflist == 0) && ( msg->tailist.numberofelements == 0))
+       )
+     )
+  {
     /* Only list of TACs belonging to one PLMN with consecutive
      * TAC values is supported */
     *emm_cause = EMM_CAUSE_IE_NOT_IMPLEMENTED;
@@ -465,13 +472,15 @@ int emm_recv_security_mode_command(security_mode_command_msg *msg,
    * Message processing
    */
   /* Execute the security mode control procedure initiated by the network */
+  LOG_TRACE(INFO,"Execute the security mode control procedure initiated by the network:  imeisvrequest %d\n",msg->imeisvrequest);
   rc = emm_proc_security_mode_command(
          msg->naskeysetidentifier.tsc != NAS_KEY_SET_IDENTIFIER_MAPPED,
          msg->naskeysetidentifier.naskeysetidentifier,
          msg->selectednassecurityalgorithms.typeofcipheringalgorithm,
          msg->selectednassecurityalgorithms.typeofintegrityalgorithm,
          msg->replayeduesecuritycapabilities.eea,
-         msg->replayeduesecuritycapabilities.eia);
+         msg->replayeduesecuritycapabilities.eia,
+		 msg->imeisvrequest & 0x7);
 
   LOG_FUNC_RETURN (rc);
 }
diff --git a/openair3/NAS/UE/EMM/SAP/emm_send.c b/openair3/NAS/UE/EMM/SAP/emm_send.c
index 7e13d03c7b101ac40108622a667a4decd676c271..e3fc4fa7f990622aa6a78f922d863e6ca2074669 100644
--- a/openair3/NAS/UE/EMM/SAP/emm_send.c
+++ b/openair3/NAS/UE/EMM/SAP/emm_send.c
@@ -855,6 +855,34 @@ int emm_send_security_mode_complete(const emm_as_security_t *msg,
   /* Mandatory - Message type */
   emm_msg->messagetype = SECURITY_MODE_COMPLETE;
 
+  if(msg->imeisv_request)
+  {
+	  // configure imeisv param
+	  emm_msg->presencemask |= SECURITY_MODE_COMPLETE_IMEISV_PRESENT;
+
+	  // 33 85 76 02 05 26 84 01 F1
+	  emm_msg->imeisv.imeisv.digit1         = 0x3;
+	  emm_msg->imeisv.imeisv.oddeven        = 0x0;
+	  emm_msg->imeisv.imeisv.typeofidentity = 0x3;
+	  emm_msg->imeisv.imeisv.digit2         = 0x5;
+	  emm_msg->imeisv.imeisv.digit3         = 0x7;
+	  emm_msg->imeisv.imeisv.digit4         = 0x4;
+	  emm_msg->imeisv.imeisv.digit5         = 0x7;
+	  emm_msg->imeisv.imeisv.digit6         = 0x3;
+	  emm_msg->imeisv.imeisv.digit7         = 0x0;
+	  emm_msg->imeisv.imeisv.digit8         = 0x4;
+	  emm_msg->imeisv.imeisv.digit9         = 0x0;
+	  emm_msg->imeisv.imeisv.digit10        = 0x0;
+	  emm_msg->imeisv.imeisv.digit11        = 0x7;
+	  emm_msg->imeisv.imeisv.digit12        = 0x0;
+	  emm_msg->imeisv.imeisv.digit13        = 0x5;
+	  emm_msg->imeisv.imeisv.digit14        = 0x3;
+	  emm_msg->imeisv.imeisv.digit15        = 0x0;
+	  emm_msg->imeisv.imeisv.digit16        = 0x0;
+	  emm_msg->imeisv.imeisv.parity         = IMEI_ODD_PARITY;
+
+	  size += SECURITY_MODE_COMPLETE_MAXIMUM_LENGTH;
+  }
   LOG_FUNC_RETURN (size);
 }
 
diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c
index c48c2cbaafb815f34ee862764d0b36acea5d450b..f27eb7b4afa87a25a76e08beb95f4a2aa6607b9c 100644
--- a/openair3/NAS/UE/EMM/SecurityModeControl.c
+++ b/openair3/NAS/UE/EMM/SecurityModeControl.c
@@ -65,6 +65,10 @@ Description Defines the security mode control EMM procedure executed by the
 #include "secu_defs.h"
 #include "msc.h"
 
+#if  defined(NAS_BUILT_IN_UE)
+#include "nas_itti_messaging.h"
+#endif
+
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
 /****************************************************************************/
@@ -142,7 +146,7 @@ static void _security_release(emm_security_context_t *ctx);
  **                                                                        **
  ***************************************************************************/
 int emm_proc_security_mode_command(int native_ksi, int ksi,
-                                   int seea, int seia, int reea, int reia)
+                                   int seea, int seia, int reea, int reia, int imeisv_request)
 {
   LOG_FUNC_IN;
 
@@ -286,7 +290,9 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
 
       _emm_data.security->selected_algorithms.encryption = seea;
       _emm_data.security->selected_algorithms.integrity  = seia;
-
+#if  defined(NAS_BUILT_IN_UE)
+      nas_itti_kenb_refresh_req(_security_data.kenb.value);
+#endif
     }
     /*
      * NAS security mode command not accepted by the UE
@@ -323,6 +329,7 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
   emm_sap.u.emm_as.u.security.guti = _emm_data.guti;
   emm_sap.u.emm_as.u.security.ueid = 0;
   emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_SMC;
+  emm_sap.u.emm_as.u.security.imeisv_request = imeisv_request;
   emm_sap.u.emm_as.u.security.emm_cause = emm_cause;
   /* Setup EPS NAS security data */
   emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
diff --git a/openair3/NAS/UE/EMM/emm_main.c b/openair3/NAS/UE/EMM/emm_main.c
index eb92f849de80900288b0939ce729224a4302f572..2eb4d8fa24d6b18c1d7e8f88d01bbfc00961c2ca 100644
--- a/openair3/NAS/UE/EMM/emm_main.c
+++ b/openair3/NAS/UE/EMM/emm_main.c
@@ -40,6 +40,7 @@ Description Defines the EPS Mobility Management procedure call manager,
 #include "emm_main.h"
 #include "nas_log.h"
 #include "emmData.h"
+#include "MobileIdentity.h"
 
 #include "memory.h"
 #include "usim_api.h"
@@ -52,6 +53,7 @@ Description Defines the EPS Mobility Management procedure call manager,
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
 /****************************************************************************/
+extern uint8_t usim_test;
 
 /****************************************************************************/
 /*******************  L O C A L    D E F I N I T I O N S  *******************/
@@ -159,6 +161,7 @@ void emm_main_initialize(emm_indication_callback_t cb, const char *imei)
   /*
    * Get USIM application data
    */
+  _usim_data.usimtestmode = usim_test;
   if ( usim_api_read(&_usim_data) != RETURNok ) {
     /* The USIM application may not be present or not valid */
     LOG_TRACE(WARNING, "EMM-MAIN  - Failed to read USIM application data");
@@ -917,7 +920,7 @@ static int _emm_main_get_imei(imei_t *imei, const char *imei_str)
   int len = strlen(imei_str);
 
   if (len % 2) {
-    imei->u.num.parity = ODD_PARITY;
+    imei->u.num.parity = IMEI_ODD_PARITY;
   } else {
     imei->u.num.parity = EVEN_PARITY;
   }
diff --git a/openair3/NAS/UE/EMM/emm_proc.h b/openair3/NAS/UE/EMM/emm_proc.h
index e6a3ae0cdd0d85ac093887f9e784bf1ea7590c84..60f71f11c200ebd67ef02b90b5088cfa92dbaead 100644
--- a/openair3/NAS/UE/EMM/emm_proc.h
+++ b/openair3/NAS/UE/EMM/emm_proc.h
@@ -174,7 +174,7 @@ int emm_proc_authentication_delete(void);
  * --------------------------------------------------------------------------
  */
 int emm_proc_security_mode_command(int native_ksi, int ksi, int seea, int seia,
-                                   int reea, int reia);
+                                   int reea, int reia,int imeisv_request);
 
 /*
  *---------------------------------------------------------------------------
diff --git a/openair3/NAS/UE/UEprocess.c b/openair3/NAS/UE/UEprocess.c
index 248633c3a192abfa68bbd0103e95492fcc6d732e..20af58dac67563576cb9c9f425a7bd63987033ec 100644
--- a/openair3/NAS/UE/UEprocess.c
+++ b/openair3/NAS/UE/UEprocess.c
@@ -71,6 +71,8 @@ static void _nas_signal_handler(int signal);
 
 static void _nas_clean(int usr_fd, int net_fd);
 
+uint8_t usim_test = 0;
+
 /****************************************************************************/
 /******************  E X P O R T E D    F U N C T I O N S  ******************/
 /****************************************************************************/
diff --git a/openair3/NAS/UE/nas_itti_messaging.c b/openair3/NAS/UE/nas_itti_messaging.c
index 10bfdf9d6e9623edd5387ad4afbe4035327a56a6..7667ad50a438b95892355a31c86b98b39c5f6e71 100644
--- a/openair3/NAS/UE/nas_itti_messaging.c
+++ b/openair3/NAS/UE/nas_itti_messaging.c
@@ -180,6 +180,39 @@ int nas_itti_protected_msg(const char *buffer, const nas_message_t *msg, const i
 
 extern unsigned char NB_eNB_INST;
 
+int nas_itti_kenb_refresh_req(const Byte_t kenb[32])
+{
+  MessageDef *message_p;
+
+  message_p = itti_alloc_new_message(TASK_NAS_UE, NAS_KENB_REFRESH_REQ);
+
+  memcpy(NAS_KENB_REFRESH_REQ(message_p).kenb, kenb, sizeof(NAS_KENB_REFRESH_REQ(message_p).kenb));
+
+  MSC_LOG_TX_MESSAGE(
+      MSC_NAS_UE,
+      MSC_RRC_UE,
+      NULL,0,
+      "0 NAS_KENB_REFRESH_REQ KeNB "
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x",
+      kenb[0],  kenb[1],  kenb[2],  kenb[3],
+      kenb[4],  kenb[5],  kenb[6],  kenb[7],
+      kenb[8],  kenb[9],  kenb[10], kenb[11],
+      kenb[12], kenb[13], kenb[14], kenb[15],
+      kenb[16], kenb[17], kenb[18], kenb[19],
+      kenb[20], kenb[21], kenb[22], kenb[23],
+      kenb[24], kenb[25], kenb[26], kenb[27],
+      kenb[28], kenb[29], kenb[30], kenb[31]);
+
+  return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + 0 /* TODO to be virtualized */, message_p);
+}
+
 int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat)
 {
   MessageDef *message_p;
diff --git a/openair3/NAS/UE/nas_itti_messaging.h b/openair3/NAS/UE/nas_itti_messaging.h
index dae4f5fb2837a4dc25df98680a59456e1bbaa86a..22c09f109b3be64977db004b3d12579f5ff2b688 100644
--- a/openair3/NAS/UE/nas_itti_messaging.h
+++ b/openair3/NAS/UE/nas_itti_messaging.h
@@ -47,6 +47,9 @@ int nas_itti_protected_msg(
 
 
 # if defined(NAS_BUILT_IN_UE)
+
+int nas_itti_kenb_refresh_req(const Byte_t kenb[32]);
+
 int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat);
 
 int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data_pP, uint32_t lengthP);
diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h
index 98f383cb61b057a51bff618b66e385c5a86de874..2eb0a506be8f840c34ac5de1cb7f7a5ca9763fc3 100644
--- a/targets/ARCH/COMMON/common_lib.h
+++ b/targets/ARCH/COMMON/common_lib.h
@@ -44,8 +44,9 @@
 #define BBU_LOCAL_RADIO_HEAD  0
 #define BBU_REMOTE_RADIO_HEAD 1
 
+#ifndef MAX_CARDS
 #define MAX_CARDS 8
-
+#endif
 
 typedef int64_t openair0_timestamp;
 typedef volatile int64_t openair0_vtimestamp;
diff --git a/targets/ARCH/EXMIMO/DEFS/openair_device.h b/targets/ARCH/EXMIMO/DEFS/openair_device.h
index 4dbd5ec171408d6d6ced690754a6da3cc9f49b41..b22cf1879b6736c1452cd23aa14c19846e95ed84 100644
--- a/targets/ARCH/EXMIMO/DEFS/openair_device.h
+++ b/targets/ARCH/EXMIMO/DEFS/openair_device.h
@@ -24,9 +24,8 @@
 
 
 // Maximum number of concurrently supported cards
-//
-#define MAX_CARDS   8
-#define INIT_ZEROS {0, 0, 0, 0, 0, 0, 0, 0};
+#define MAX_CARDS  16 
+#define INIT_ZEROS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
 
 /** PCIe subsystem configuration Space
diff --git a/targets/ARCH/EXMIMO/DRIVER/eurecom/fileops.c b/targets/ARCH/EXMIMO/DRIVER/eurecom/fileops.c
index 7efdbd5ae83271cb3c67258109d974ce9d3116ea..5002cccc9836730bd89e03e0387a03f716b01b4e 100644
--- a/targets/ARCH/EXMIMO/DRIVER/eurecom/fileops.c
+++ b/targets/ARCH/EXMIMO/DRIVER/eurecom/fileops.c
@@ -271,14 +271,18 @@ int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd
     printk("[openair][IOCTL] : openair_DUMP_CONFIG(%d):  exmimo_pci_kvirt[%d].exmimo_config_ptr = %p (phys %08x)\n",
            (int)arg, (int)arg, exmimo_pci_kvirt[(int)arg].exmimo_config_ptr, p_exmimo_pci_phys[(int)arg]->exmimo_config_ptr);
 
-    /*printk("EXMIMO_CONFIG: freq0 %d Hz, freq1 %d Hz, freqtx0 %d Hz, freqtx1 %d Hz, \nRX gain0 %d dB, RX Gain1 %d dB\n",
+    printk("[openair][IOCTL]: EXMIMO_CONFIG: freq0 %u Hz, freq1 %u Hz, freqtx0 %u Hz, freqtx1 %u Hz, \nRX gain0 %d dB, RX Gain1 %d dB, autocal (%d,%d,%d,%d)\n",
                 exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_rx[0],
                 exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_rx[1],
                 exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_tx[0],
                 exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rf_freq_tx[1],
                 exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rx_gain[0][0],
-                exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rx_gain[1][0]);
-    */
+                exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.rx_gain[1][0],
+                exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.do_autocal[0],
+		exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.do_autocal[1],
+                exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.do_autocal[2],
+                exmimo_pci_kvirt[(int)arg].exmimo_config_ptr->rf.do_autocal[3]);
+    
 
     exmimo_send_pccmd((int)arg, EXMIMO_CONFIG);
 
diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
index 75aa4d26227b3294a285f1d33605f5029c8c138e..16754a84fb3ff37d203eb3fbae12834a08ce0709 100644
--- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
+++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
@@ -63,7 +63,7 @@
 
 exmimo_pci_interface_bot_virtual_t openair0_exmimo_pci[MAX_CARDS]; // contains userspace pointers for each card
 
-char *bigshm_top[MAX_CARDS] = INIT_ZEROS;
+char *bigshm_top[MAX_CARDS];
 
 int openair0_fd;
 int openair0_num_antennas[MAX_CARDS];
@@ -126,7 +126,8 @@ int openair0_open(void)
 
   //printf("bigshm_top_kvirtptr (MAX_CARDS %d): %p  %p  %p  %p\n", MAX_CARDS,bigshm_top_kvirtptr[0], bigshm_top_kvirtptr[1], bigshm_top_kvirtptr[2], bigshm_top_kvirtptr[3]);
 
-
+  for( card=0; card < MAX_CARDS; card++)
+    bigshm_top[card] = NULL;
 
   for( card=0; card < openair0_num_detected_cards; card++) {
     bigshm_top[card] = (char *)mmap( NULL,
@@ -530,6 +531,7 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi
     return(0);
   }
 
+  ret = pthread_mutex_lock(&exm->watchdog_mutex);
 
   switch (ret) {
   case EINVAL:
@@ -558,8 +560,6 @@ int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, voi
     break;
   }
 
-  ret = pthread_mutex_lock(&exm->watchdog_mutex);
-
   ts = exm->ts;
   if (exm->wait_first_read==1) {
     exm->wait_first_read=0;
@@ -731,15 +731,17 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
     printf ("Detected %d number of cards, %d number of antennas.\n", openair0_num_detected_cards, openair0_num_antennas[0]);
   }
 
-  //  p_exmimo_config = openair0_exmimo_pci[0].exmimo_config_ptr;
-  p_exmimo_id     = openair0_exmimo_pci[0].exmimo_id_ptr;
+  for (card=0; card<openair0_num_detected_cards; card++) {
+    //  p_exmimo_config = openair0_exmimo_pci[0].exmimo_config_ptr;
+    p_exmimo_id     = openair0_exmimo_pci[card].exmimo_id_ptr;
 
-  printf("Card %d: ExpressMIMO %d, HW Rev %d, SW Rev 0x%d\n", 0, p_exmimo_id->board_exmimoversion, p_exmimo_id->board_hwrev, p_exmimo_id->board_swrev);
+    printf("Card %d: ExpressMIMO %d, HW Rev %d, SW Rev 0x%d\n", card, p_exmimo_id->board_exmimoversion, p_exmimo_id->board_hwrev, p_exmimo_id->board_swrev);
 
-  // check if the software matches firmware
-  if (p_exmimo_id->board_swrev!=BOARD_SWREV_CNTL2) {
-    printf("Software revision %d and firmware revision %d do not match. Please update either the firmware or the software!\n",BOARD_SWREV_CNTL2,p_exmimo_id->board_swrev);
-    return(-1);
+    // check if the software matches firmware
+    if (p_exmimo_id->board_swrev!=BOARD_SWREV_CNTL2) {
+      printf("Software revision %d and firmware revision %d do not match. Please update either the firmware or the software!\n",BOARD_SWREV_CNTL2,p_exmimo_id->board_swrev);
+      return(-1);
+    }
   }
 
   device->type             = EXMIMO_DEV; 
@@ -850,6 +852,11 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
 #endif
 
     for (ant=0; ant<4; ant++) {
+      p_exmimo_config->rf.rf_freq_rx[ant] = 0;
+      p_exmimo_config->rf.rf_freq_tx[ant] = 0;
+      p_exmimo_config->rf.rf_mode[ant] = 0;
+      p_exmimo_config->rf.rx_gain[ant][0] = 0;
+      p_exmimo_config->rf.tx_gain[ant][0] = 0;
 
       openair0_cfg[card].rxbase[ant] = (int32_t*)openair0_exmimo_pci[card].adc_head[ant];
       openair0_cfg[card].txbase[ant] = (int32_t*)openair0_exmimo_pci[card].dac_head[ant];
@@ -858,7 +865,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
 	ACTIVE_RF += (1<<ant)<<5;
         p_exmimo_config->rf.rf_mode[ant] = RF_MODE_BASE;
         p_exmimo_config->rf.do_autocal[ant] = 1;//openair0_cfg[card].autocal[ant];
-	printf("card %d, antenna %d, autocal %d\n",card,ant,openair0_cfg[card].autocal[ant]);
+	printf("card %d, antenna %d, autocal %d\n",card,ant,p_exmimo_config->rf.do_autocal[ant]);
       }
 
       if (openair0_cfg[card].tx_freq[ant]>0) {
diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_frame.cc b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_frame.cc
index 6973fb2980330985987377ade5773ed27cdedcd8..b8ed0e92e5dc48619bffbdfddd053164798acad9 100644
--- a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_frame.cc
+++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/oarf_get_frame.cc
@@ -171,7 +171,7 @@ DEFUN_DLD (oarf_get_frame, args, nargout,"Get frame")
     printf("Info : Only resampling_factor of channel 0 is taken into account for copying received frame for all the other chains\n");
 
     
-    ComplexMatrix dx (FRAME_LENGTH_COMPLEX_SAMPLES*4, numant*openair0_num_detected_cards);
+    ComplexMatrix dx (FRAME_LENGTH_COMPLEX_SAMPLES*4, MAX_ANTENNAS*openair0_num_detected_cards);
     /*
     // set the tx buffer to 0x00010001 to put switch in rx mode
     for (aa=0; aa<numant; aa++) 
@@ -185,14 +185,14 @@ DEFUN_DLD (oarf_get_frame, args, nargout,"Get frame")
   
     for (j=0; j<openair0_num_detected_cards;j++)
     {
-      for (i=0; i<numant; i++)
+      for (i=0; i<MAX_ANTENNAS; i++)
       {
           //if ( numant == openair0_num_antennas[j] )
               rx_sig[i+(j*MAX_ANTENNAS)] = (short*) openair0_exmimo_pci[ j ].adc_head[ i ];
           //else
           //    rx_sig[i+(j*MAX_ANTENNAS)] = (short*) openair0_exmimo_pci[ i / (int)openair0_num_antennas[0] ].adc_head[i % openair0_num_antennas[0]];
             
-         // printf("Card %i adc_head[%i] = %p \n",j, i, rx_sig[i+(j*MAX_ANTENNAS)]);
+          //  printf("Card %i adc_head[%i] = %p \n",j, i, rx_sig[i+(j*MAX_ANTENNAS)]);
       }
     }
 
@@ -201,8 +201,8 @@ DEFUN_DLD (oarf_get_frame, args, nargout,"Get frame")
         openair0_get_frame(card);
 
   for (j=0; j<openair0_num_detected_cards;j++)
-    for (i=0; i<frame_length_samples[j]; i++)
-        for (aa=0; aa<numant; aa++)
+    for (i=0; i<frame_length_samples[j]; i++) 
+        for (aa=0; aa<MAX_ANTENNAS; aa++) 
             dx(i, aa+j*MAX_ANTENNAS) = Complex( rx_sig[aa+j*MAX_ANTENNAS][i*2], rx_sig[aa+j*MAX_ANTENNAS][i*2+1] );
     
     openair0_close();
diff --git a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/txsig.m b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/txsig.m
index 97fad27531e5bf5dcf91ade4beac5b909f08f9fd..77da351118ac44642a6fa2407e9d85de87b23453 100644
--- a/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/txsig.m
+++ b/targets/ARCH/EXMIMO/USERSPACE/OCTAVE/txsig.m
@@ -38,14 +38,14 @@ rffe_band = B19G_TDD*[1 1 1 1];
 
 oarf_config_exmimo(card, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,eNB_flag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
 %oarf_config_exmimo(1, freq_rx,freq_tx,tdd_config,syncmode,rxgain,txgain,eNB_flag,rf_mode,rf_rxdc,rf_local,rf_vcocal,rffe_rxg_low,rffe_rxg_final,rffe_band,autocal,resampling_factor);
-amp = pow2(14)-1;
+amp = pow2(10)-1;
 n_bit = 16;
 
 length = 307200/pow2(resampling_factor(1));
 
 s = zeros(length,4);
 
-select = 1;
+select = 7;
 
 switch(select)
 
@@ -73,7 +73,8 @@ case 3
 case 4
   pss0_f0=[0,0,0,0,0,0,0,0,0,0,32767,0,-26120,-19785,11971,-30502,-24020,-22288,32117,6492,31311,9658,-16384,-28378,25100,-21063,-7292,-31946,20429,25618,14948,29158,11971,-30502,31311,9658,25100,-21063,-16384,28377,-24020,22287,32117,6492,-7292,31945,20429,25618,-26120,-19785,-16384,-28378,-16384,28377,-26120,-19785,-32402,4883,31311,-9659,32117,6492,-7292,-31946,32767,-1,25100,-21063,-24020,22287,-32402,4883,-32402,4883,-24020,22287,25100,-21063,32767,-1,-7292,-31946,32117,6492,31311,-9659,-32402,4883,-26120,-19785,-16384,28377,-16384,-28378,-26120,-19785,20429,25618,-7292,31945,32117,6492,-24020,22287,-16384,28377,25100,-21063,31311,9658,11971,-30502,14948,29158,20429,25618,-7292,-31946,25100,-21063,-16384,-28378,31311,9658,32117,6492,-24020,-22288,11971,-30502,-26120,-19785,32767,0,0,0,0,0,0,0,0,0,0,0];
 
-  pss0_f = pss0_f0(1:2:length(pss0_f0)) + sqrt(-1)*pss0_f0(2:2:length(pss0_f0));
+  %pss0_f = pss0_f0(1:2:length(pss0_f0)) + sqrt(-1)*pss0_f0(2:2:length(pss0_f0));
+  pss0_f = pss0_f0(1:2:size(pss0_f0,2)) + sqrt(-1)*pss0_f0(2:2:size(pss0_f0,2));
   
   pss0_f = [0 pss0_f(37:72) zeros(1,512-73) pss0_f(1:36)];
   pss0_t = ifft(pss0_f);
@@ -84,10 +85,15 @@ case 4
   pss0_t_fp_re = floor(real(8192*pss0_t/pss0_max)); 
   pss0_t_fp_im = floor(imag(8192*pss0_t/pss0_max)); 
   
+  %keyboard;
   s(38400+(1:length(pss0_t_fp_re)),1) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
   s(38400+(1:length(pss0_t_fp_re)),2) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
   s(38400+(1:length(pss0_t_fp_re)),3) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
   s(38400+(1:length(pss0_t_fp_re)),4) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
+  %s(38400+(1:size(pss0_t_fp_re,2)),1) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
+  %s(38400+(1:size(pss0_t_fp_re,2)),2) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
+  %s(38400+(1:size(pss0_t_fp_re,2)),3) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
+  %s(38400+(1:size(pss0_t_fp_re,2)),4) = 2*floor(pss0_t_fp_re) + 2*sqrt(-1)*floor(pss0_t_fp_im);
 
 case 5
   x=1:length;
@@ -108,7 +114,9 @@ case 6
   
   s(:,1) = OFDM_TX_FRAME(num_carriers,num_zeros,prefix_length,num_symbols_frame,preamble_length);
   s(:,1) = floor(amp*(s(:,1)./max([real(s(:,1)); imag(s(:,1))])));
-  
+
+case 7
+  s(:,1) = floor(txs0);
 
 otherwise 
   error('unknown case')
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm7.exmimo2.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm7.exmimo2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..6209fbe150c06020ece001df690ac751edeb3bb2
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band38.tm7.exmimo2.conf
@@ -0,0 +1,172 @@
+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";
+
+       ////////// Physical parameters:
+
+    component_carriers = (
+      {
+        frame_type					      = "TDD";
+        tdd_config 					      = 3;
+        tdd_config_s            			      = 0;
+        prefix_type             			      = "NORMAL";
+        eutra_band              			      = 38;
+        downlink_frequency      			      = 2580000000L;
+        uplink_frequency_offset 			      = 0; //-120000000;
+        Nid_cell					      = 0;
+        N_RB_DL                 			      = 25;
+        Nid_cell_mbsfn          			      = 0;
+        nb_antenna_ports          			      = 1;
+        nb_antennas_tx          			      = 3;
+        nb_antennas_rx          			      = 3;
+        tx_gain                                            = 10; //25;
+        rx_gain                                            = 10; //20;
+        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 			      = -26;
+        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                                       = 0;
+        phich_duration                                     = "NORMAL";
+        phich_resource                                     = "ONESIXTH";
+        srs_enable                                         = "DISABLE";
+        /*  srs_BandwidthConfig                                =;
+        srs_SubframeConfig                                 =;
+        srs_ackNackST                                      =;
+        srs_MaxUpPts                                       =;*/
+
+        pusch_p0_Nominal                                   = -85;
+        pusch_alpha                                        = "AL1";
+        pucch_p0_Nominal                                   = -108;
+        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                              = 2;
+        rach_preambleInitialReceivedTargetPower            = -100;
+        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				      = 7;
+      }
+    );
+
+
+    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.12.70";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+      ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+      ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.212/24";
+
+      ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+      ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.212/24";
+      ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+
+    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                         ="debug";
+      rrc_log_verbosity                     ="medium";
+   };
+  }
+);
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band4.exmimo2.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band4.exmimo2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..bf7861f66d305b51b1f5a3eafe902ef4e9a8ced7
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band4.exmimo2.conf
@@ -0,0 +1,147 @@
+Active_eNBs = ( "eNB_Eurecom_LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    # real_time choice in {hard, rt-preempt, no}
+    real_time       =  "no";
+    ////////// 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 =  "94";
+    
+       ////////// Physical parameters:
+  
+    component_carriers = (
+    		       	 {
+  			   frame_type					      = "FDD";	
+                           tdd_config 					      = 3;
+                           tdd_config_s            			      = 0;
+ 			   prefix_type             			      = "NORMAL";
+  			   eutra_band              			      = 4;
+                           downlink_frequency      			      = 2112500000L;
+                           uplink_frequency_offset 			      = -400000000;
+  
+  			   Nid_cell					      = 0;
+                           N_RB_DL                 			      = 25;
+                           Nid_cell_mbsfn          			      = 0;
+                           nb_antennas_tx          			      = 1;
+                           nb_antennas_rx          			      = 1;
+			   nb_antenna_ports				      = 1;
+			   tx_gain					      = 20;
+			   rx_gain			    		      = 20;
+                           prach_root              			      = 22;
+                           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 			      = -25;
+                           pdsch_p_b                  			      = 0;
+                           pusch_n_SB                 			      = 1; 
+                           pusch_enable64QAM          			      = "DISABLE";
+			   pusch_hoppingMode                                  = "interSubFrame";
+			   pusch_hoppingOffset                                = 1;
+     	                   pusch_groupHoppingEnabled  			      = "ENABLE";
+	                   pusch_groupAssignment      			      = 0;
+	                   pusch_sequenceHoppingEnabled		   	      = "DISABLE";
+	                   pusch_nDMRS1                                       = 0;
+	                   phich_duration                                     = "NORMAL";
+	                   phich_resource                                     = "ONESIXTH";
+	                   srs_enable                                         = "DISABLE";
+	               /*  srs_BandwidthConfig                                =;
+	                   srs_SubframeConfig                                 =;
+	                   srs_ackNackST                                      =;
+	                   srs_MaxUpPts                                       =;*/  
+
+	                   pusch_p0_Nominal                                   = -85; 
+	                   pusch_alpha                                        = "AL1";
+	                   pucch_p0_Nominal                                   = -96;
+	                   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                              = 2;
+	                   rach_preambleInitialReceivedTargetPower            = -100;
+                           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			      = 20000; //10000;
+			   ue_TimersAndConstants_n310			      = 20;
+			   ue_TimersAndConstants_n311			      = 1;
+
+			   ue_TransmissionMode 				      = 1;
+
+			 }
+			 );
+    
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.12.70";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES : 
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.212/24";
+
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.212/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+    
+    log_config : 
+    {
+	global_log_level                      ="info";
+    	global_log_verbosity                  ="high";
+	hw_log_level                          ="info"; 
+    	hw_log_verbosity                      ="high";
+	phy_log_level                         ="info"; 
+    	phy_log_verbosity                     ="high";
+	mac_log_level                         ="debug"; 
+    	mac_log_verbosity                     ="high";
+	rlc_log_level                         ="info"; 
+    	rlc_log_verbosity                     ="high";
+	pdcp_log_level                        ="info"; 
+    	pdcp_log_verbosity                    ="high";
+	rrc_log_level                         ="info"; 
+    	rrc_log_verbosity                     ="high";
+   };	
+   
+  }
+);
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band5.flexran.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band5.flexran.50PRB.usrpb210.conf
new file mode 100644
index 0000000000000000000000000000000000000000..2e39b934e43841c3ba0f922d791921cb0602eaf1
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band5.flexran.50PRB.usrpb210.conf
@@ -0,0 +1,182 @@
+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 =  "95";
+
+       ////////// Physical parameters:
+
+    component_carriers = (
+      {
+        node_function                                         = "eNodeB_3GPP";
+	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              			      = 5;
+        downlink_frequency      			      = 879000000L;
+        uplink_frequency_offset 			      = -45000000;
+        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                                            = 115;
+        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 			      = -26;
+        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                                   = -90;
+        pusch_alpha                                        = "AL1";
+        pucch_p0_Nominal                                   = -108;
+        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;
+      }
+    );
+
+    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.100.101";
+                              ipv6       = "192:168:100::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.100.106/24";
+
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.100.106/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+
+    NETWORK_CONTROLLER :
+    {
+        FLEXRAN_AGENT_INTERFACE_NAME            = "eth1";
+        FLEXRAN_AGENT_IPV4_ADDRESS              = "10.0.2.5/30";
+        FLEXRAN_AGENT_PORT                      = 2210;
+        FLEXRAN_AGENT_CACHE                     = "/mnt/oai_agent_cache";
+    };
+
+    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.band5.flexran.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band5.flexran.usrpb210.conf
new file mode 100644
index 0000000000000000000000000000000000000000..66e7ef433d4932e8b5be2a3b0166cba4514912e2
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band5.flexran.usrpb210.conf
@@ -0,0 +1,182 @@
+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 =  "95";
+
+       ////////// Physical parameters:
+
+    component_carriers = (
+      {
+        node_function                                         = "eNodeB_3GPP";
+	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              			      = 5;
+        downlink_frequency      			      = 879000000L;
+        uplink_frequency_offset 			      = -45000000;
+        Nid_cell					      = 0;
+        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;
+        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 			      = -26;
+        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                                   = -90;
+        pusch_alpha                                        = "AL1";
+        pucch_p0_Nominal                                   = -108;
+        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;
+      }
+    );
+
+    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.100.101";
+                              ipv6       = "192:168:100::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.100.106/24";
+
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.100.106/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+
+    NETWORK_CONTROLLER :
+    {
+        FLEXRAN_AGENT_INTERFACE_NAME            = "eth1";
+        FLEXRAN_AGENT_IPV4_ADDRESS              = "10.0.2.5/30";
+        FLEXRAN_AGENT_PORT                      = 2210;
+        FLEXRAN_AGENT_CACHE                     = "/mnt/oai_agent_cache";
+    };
+
+    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.exmimo2.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.exmimo2.conf
index c338656679ef925ed7d92f0578bbe55c3fd4e885..c190020e082e2b7b9de4ed8d2adcf269f0b75a12 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.exmimo2.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.exmimo2.conf
@@ -51,7 +51,7 @@ eNBs =
                            pucch_nCS_AN            			      = 0;
                            pucch_n1_AN             			      = 32;
                            pdsch_referenceSignalPower 			      = -24;
-                           pdsch_p_b                  			      = 0;
+                           pdsch_p_b                  			      = 1;
                            pusch_n_SB                 			      = 1; 
                            pusch_enable64QAM          			      = "DISABLE";
 			   pusch_hoppingMode                                  = "interSubFrame";
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.flexran.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.flexran.50PRB.usrpb210.conf
new file mode 100644
index 0000000000000000000000000000000000000000..7e68b5d84b73ec285c87ea405e14c78926d99a0b
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.flexran.50PRB.usrpb210.conf
@@ -0,0 +1,182 @@
+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 =  "95";
+
+       ////////// Physical parameters:
+
+    component_carriers = (
+      {
+        node_function                                         = "eNodeB_3GPP";
+	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      			      = 2660000000L;
+        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;
+        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                                   = -100;
+        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            = -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.100.101";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.100.106/24";
+
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.100.106/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+
+    NETWORK_CONTROLLER :
+    {
+        FLEXRAN_AGENT_INTERFACE_NAME            = "eth1";
+        FLEXRAN_AGENT_IPV4_ADDRESS              = "10.0.2.5/30";
+        FLEXRAN_AGENT_PORT                      = 2210;
+        FLEXRAN_AGENT_CACHE                     = "/mnt/oai_agent_cache";
+    };
+
+    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.flexran.oaisim.local_no_mme.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.flexran.oaisim.local_no_mme.conf
new file mode 100644
index 0000000000000000000000000000000000000000..ca36fab45578ff31fd382ad0f30fdb29503220ad
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.flexran.oaisim.local_no_mme.conf
@@ -0,0 +1,160 @@
+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 =  "10";
+
+       ////////// Physical parameters:
+
+    component_carriers = (
+      {
+        node_function                                         = "eNodeB_3GPP";
+	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      			      = 2680000000L;
+        uplink_frequency_offset 			      = -120000000;
+        Nid_cell					              = 0;
+        N_RB_DL                 			      = 25;
+        Nid_cell_mbsfn          			      = 0;
+	nb_antenna_ports				      = 2;
+        nb_antennas_tx          			      = 2;
+        nb_antennas_rx          			      = 2;
+        tx_gain                                   = 25;
+        rx_gain                                   = 20;
+        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 			      = 0;
+        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                              = 0;
+        phich_duration                            = "NORMAL";
+        phich_resource                            = "ONESIXTH";
+        srs_enable                                = "DISABLE";
+        /*  srs_BandwidthConfig                   =;
+        srs_SubframeConfig                        =;
+        srs_ackNackST                             =;
+        srs_MaxUpPts                              =;*/
+
+        pusch_p0_Nominal                          = -108;
+        pusch_alpha                               = "AL1";
+        pucch_p0_Nominal                          = -108;
+        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                     = 2;
+        rach_preambleInitialReceivedTargetPower   = -100;
+        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 				      = 2;
+      }
+    );
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "0.0.0.0";
+                              ipv6       = "0::0";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "none";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "0.0.0.0/24";
+
+        ENB_INTERFACE_NAME_FOR_S1U               = "none";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "0.0.0.0/24";
+        ENB_PORT_FOR_S1U                         = 2153; # Spec 2152
+    };
+
+    NETWORK_CONTROLLER :
+    {
+        ENB_AGENT_INTERFACE_NAME            = "eth1";
+        ENB_AGENT_IPV4_ADDRESS              = "10.0.2.5/30";
+        ENB_AGENT_PORT                      = 2210;
+        ENB_AGENT_CACHE                     = "/mnt/oai_agent_cache";
+    };
+
+    log_config :
+    {
+      global_log_level                      ="trace";
+      global_log_verbosity                  ="medium";
+      hw_log_level                          ="info";
+      hw_log_verbosity                      ="medium";
+      phy_log_level                         ="trace";
+      phy_log_verbosity                     ="medium";
+      mac_log_level                         ="trace";
+      mac_log_verbosity                     ="medium";
+      rlc_log_level                         ="trace";
+      rlc_log_verbosity                     ="medium";
+      pdcp_log_level                        ="trace";
+      pdcp_log_verbosity                    ="medium";
+      rrc_log_level                         ="trace";
+      rrc_log_verbosity                     ="medium";
+      gtpu_log_level                        ="debug";
+      gtpu_log_verbosity                    ="medium";
+      udp_log_level                         ="debug";
+      udp_log_verbosity                     ="medium";
+      osa_log_level                         ="debug";
+      osa_log_verbosity                     ="low";
+   };
+
+  }
+);
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.flexran.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.flexran.usrpb210.conf
new file mode 100644
index 0000000000000000000000000000000000000000..4ee429f45e907b8db78414c1bf5e0cadca5b3a4c
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.flexran.usrpb210.conf
@@ -0,0 +1,182 @@
+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 =  "95";
+
+       ////////// Physical parameters:
+
+    component_carriers = (
+      {
+        node_function                                         = "eNodeB_3GPP";
+	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      			      = 2660000000L;
+        uplink_frequency_offset 			      = -120000000;
+        Nid_cell					      = 0;
+        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                                            = 125;
+        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 			      = -24;
+        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                                   = -103;
+        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            = -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.100.101";
+                              ipv6       = "192:168:100::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.100.106/24";
+
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.100.106/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+
+    NETWORK_CONTROLLER :
+    {
+        FLEXRAN_AGENT_INTERFACE_NAME            = "eth1";
+        FLEXRAN_AGENT_IPV4_ADDRESS              = "10.0.2.5/30";
+        FLEXRAN_AGENT_PORT                      = 2210;
+        FLEXRAN_AGENT_CACHE                     = "/mnt/oai_agent_cache";
+    };
+
+    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.exmimo2.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf
index a2234cf5156178f1181fc3e819781950a54a7be3..84e947eecc651f6aae2a88f538e5c16281f0c279 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf
@@ -160,13 +160,13 @@ eNBs =
       global_log_verbosity                  ="medium";
       hw_log_level                          ="info";
       hw_log_verbosity                      ="medium";
-      phy_log_level                         ="warn";
+      phy_log_level                         ="debug";
       phy_log_verbosity                     ="medium";
-      mac_log_level                         ="warn";
+      mac_log_level                         ="debug";
       mac_log_verbosity                     ="medium";
-      rlc_log_level                         ="warn";
+      rlc_log_level                         ="info";
       rlc_log_verbosity                     ="medium";
-      pdcp_log_level                        ="warn";
+      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.generic.oaisim.local_no_mme.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf
index ef7c1cc19c35ba05b9d21f90c2ca20751b54a0b0..a79cb2cae6301060a579ffc143defc2bb61d7d60 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.generic.oaisim.local_no_mme.conf
@@ -62,11 +62,11 @@ eNBs =
         pusch_nDMRS1                              = 0;
         phich_duration                            = "NORMAL";
         phich_resource                            = "ONESIXTH";
-        srs_enable                                = "DISABLE";
-        /*  srs_BandwidthConfig                   =;
-        srs_SubframeConfig                        =;
-        srs_ackNackST                             =;
-        srs_MaxUpPts                              =;*/
+        srs_enable                                = "ENABLE";
+        srs_BandwidthConfig                       =2;
+        srs_SubframeConfig                        =13;
+        srs_ackNackST                             ="DISABLE";
+        srs_MaxUpPts                              ="DISABLE";
 
         pusch_p0_Nominal                          = -108;
         pusch_alpha                               = "AL1";
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf
index 01cd014afc143fb80b8e88636ee341bee40beffa..5ef5a4f50b6e653a75f1c817cc6eeba3804d9d97 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf
@@ -68,9 +68,9 @@ eNBs =
         srs_ackNackST                                      =;
         srs_MaxUpPts                                       =;*/
 
-        pusch_p0_Nominal                                   = -96;
+        pusch_p0_Nominal                                   = -90;
         pusch_alpha                                        = "AL1";
-        pucch_p0_Nominal                                   = -103;
+        pucch_p0_Nominal                                   = -96;
         msg3_delta_Preamble                                = 6;
         pucch_deltaF_Format1                               = "deltaF2";
         pucch_deltaF_Format1b                              = "deltaF3";
@@ -137,7 +137,7 @@ eNBs =
 
     ////////// MME parameters:
 
-    mme_ip_address      = ( { ipv4       = "127.0.0.3";
+    mme_ip_address      = ( { ipv4       = "192.168.12.70";
                               ipv6       = "192:168:30::17";
                               active     = "yes";
                               preference = "ipv4";
@@ -147,10 +147,10 @@ eNBs =
     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               = "lo";
-        ENB_IPV4_ADDRESS_FOR_S1U                 = "127.0.0.4/24";
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth1";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.147/24";
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth1";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.147/24";
         ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
     };
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm7.exmimo2.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm7.exmimo2.conf
new file mode 100644
index 0000000000000000000000000000000000000000..52a8d8ee502c1d878d844b98b2c226300ed25354
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm7.exmimo2.conf
@@ -0,0 +1,182 @@
+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";
+
+       ////////// Physical parameters:
+
+    component_carriers = (
+        {
+        node_function                                         = "eNodeB_3GPP";
+        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      			      = 2680000000L;
+        uplink_frequency_offset 			      = -120000000;
+        Nid_cell					      = 0;
+        N_RB_DL                 			      = 25;
+        Nid_cell_mbsfn          			      = 0;
+        nb_antenna_ports          			      = 1;
+        nb_antennas_tx          			      = 1;
+        nb_antennas_rx          			      = 1;
+        tx_gain                                            = 25;
+        rx_gain                                            = 20;
+        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 			      = -26;
+        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                                       = 0;
+        phich_duration                                     = "NORMAL";
+        phich_resource                                     = "ONESIXTH";
+        srs_enable                                         = "DISABLE";
+        /*  srs_BandwidthConfig                                =;
+        srs_SubframeConfig                                 =;
+        srs_ackNackST                                      =;
+        srs_MaxUpPts                                       =;*/
+
+        pusch_p0_Nominal                                   = -80; /*-85;*/
+        pusch_alpha                                        = "AL1";
+        pucch_p0_Nominal                                   = -108; /* -108 */
+        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                              = 2;
+        rach_preambleInitialReceivedTargetPower            = -100;
+        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				      = 7;
+        }
+    );
+
+
+    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.12.171";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth2";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.80/24";
+
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth2";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.80/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+
+    log_config :
+    {
+      global_log_level                      ="info";
+      global_log_verbosity                  ="medium";
+      hw_log_level                          ="info";
+      hw_log_verbosity                      ="medium";
+      phy_log_level                         ="debug";
+      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";
+      gtpu_log_level                         ="error";
+      gtpu_log_verbosity                     ="medium";
+      udp_log_level                         ="error";
+      udp_log_verbosity                     ="medium";
+      osa_log_level                         ="warn";
+      osa_log_verbosity                     ="low";
+   };
+
+  }
+);
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.usrpb210.conf
index 7941441d1da3d46964b4306643a07929770f062c..540edcd5b91c5e5f25c3bdf5e6b13a7a1f4fcfa6 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.usrpb210.conf
@@ -7,125 +7,126 @@ 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 =  "94";
-    
+
        ////////// Physical parameters:
-  
+
     component_carriers = (
-    		       	 {
-  			   frame_type					      = "FDD";	
-                           tdd_config 					      = 3;
-                           tdd_config_s            			      = 0;
- 			   prefix_type             			      = "NORMAL";
-  			   eutra_band              			      = 7;
-                           downlink_frequency      			      = 2680000000L;
-                           uplink_frequency_offset 			      = -120000000;
-  			   Nid_cell					      = 0;
-                           N_RB_DL                 			      = 25;
-                           Nid_cell_mbsfn          			      = 0;
-			   nb_antenna_ports				      = 2;
-                           nb_antennas_tx          			      = 2;
-                           nb_antennas_rx          			      = 2; 
-			   tx_gain                                            = 90;
-			   rx_gain                                            = 125;
-                           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 			      = -26;
-                           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                                   = -90; 
-	                   pusch_alpha                                        = "AL1";
-	                   pucch_p0_Nominal                                   = -96;
-	                   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	   			      = 2;
-
-			 }
-			 );
+      {
+        node_function                                         = "eNodeB_3GPP";
+	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      			      = 2660000000L;
+        uplink_frequency_offset 			      = -120000000;
+        Nid_cell					      = 0;
+        N_RB_DL                 			      = 25;
+        Nid_cell_mbsfn          			      = 0;
+        nb_antenna_ports          			      = 2;
+        nb_antennas_tx          			      = 2;
+        nb_antennas_rx          			      = 2;
+        tx_gain                                            = 90;
+        rx_gain                                            = 125;
+        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 			      = -24;
+        pdsch_p_b                  			      = 1;
+        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                                   = -90;
+        pusch_alpha                                        = "AL1";
+        pucch_p0_Nominal                                   = -96;
+        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            = -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				      = 2;
+      }
+    );
 
     srb1_parameters :
     {
-        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] 
+        # 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 :
     {
@@ -133,42 +134,41 @@ eNBs =
         SCTP_INSTREAMS  = 2;
         SCTP_OUTSTREAMS = 2;
     };
-    
+
     ////////// MME parameters:
-    mme_ip_address      = ( { ipv4       = "192.168.12.171";
+    mme_ip_address      = ( { ipv4       = "192.168.12.70";
                               ipv6       = "192:168:30::17";
                               active     = "yes";
                               preference = "ipv4";
                             }
                           );
 
-    NETWORK_INTERFACES : 
+    NETWORK_INTERFACES :
     {
-        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
-        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.150/24";
 
-        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
-        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.150/24";
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth1";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.147/24";
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth1";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.147/24";
         ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
     };
-    
-    log_config : 
+
+    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";
-   };	
-   
+      global_log_level                      ="info";
+      global_log_verbosity                  ="medium";
+      hw_log_level                          ="info";
+      hw_log_verbosity                      ="medium";
+      phy_log_level                         ="debug";
+      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/rcc.band7.tm1.if4p5.25PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.conf
index 3e404e5dc6965fc16a3c18cd373ad7f9a7a5aa93..5bdfcc7a12faba672a4b21de8f0aa229bfc0c847 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if4p5.25PRB.conf
@@ -31,7 +31,7 @@ eNBs =
       tdd_config_s            			      = 0;
       prefix_type             			      = "NORMAL";
       eutra_band              			      = 7;
-      downlink_frequency      			      = 2660000000L;
+      downlink_frequency      			      = 2685000000L;
       uplink_frequency_offset 			      = -120000000;
       Nid_cell					      = 0;
       N_RB_DL                 			      = 25;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.25PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.25PRB.conf
index 6987bebda9f7b9254c25f38be57b68820776e618..e8e0e6dadbd966de2804a9bade331d7be38f0563 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.25PRB.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band7.tm1.if5.25PRB.conf
@@ -31,7 +31,7 @@ eNBs =
       tdd_config_s            			      = 0;
       prefix_type             			      = "NORMAL";
       eutra_band              			      = 7;
-      downlink_frequency      			      = 2660000000L;
+      downlink_frequency      			      = 2685000000L;
       uplink_frequency_offset 			      = -120000000;
       Nid_cell					      = 0;
       N_RB_DL                 			      = 25;
@@ -68,9 +68,9 @@ eNBs =
       srs_ackNackST                                      =;
       srs_MaxUpPts                                       =;*/
 
-      pusch_p0_Nominal                                   = -90;
+      pusch_p0_Nominal                                   = -96;
       pusch_alpha                                        = "AL1";
-      pucch_p0_Nominal                                   = -96;
+      pucch_p0_Nominal                                   = -104;
       msg3_delta_Preamble                                = 6;
       pucch_deltaF_Format1                               = "deltaF2";
       pucch_deltaF_Format1b                              = "deltaF3";
@@ -86,7 +86,7 @@ eNBs =
       rach_messagePowerOffsetGroupB                      = ;
       */
       rach_powerRampingStep                              = 4;
-      rach_preambleInitialReceivedTargetPower            = -108;
+      rach_preambleInitialReceivedTargetPower            = -104;
       rach_preambleTransMax                              = 10;
       rach_raResponseWindowSize                          = 10;
       rach_macContentionResolutionTimer                  = 48;
diff --git a/targets/PROJECTS/TDDREC/s_init_params.m b/targets/PROJECTS/TDDREC/s_init_params.m
index 9683ed2d1747703901fba28e828c6f1b5a6cd793..be51524755af39c66fe26aedff74c2e3de3943cb 100644
--- a/targets/PROJECTS/TDDREC/s_init_params.m
+++ b/targets/PROJECTS/TDDREC/s_init_params.m
@@ -1,6 +1,7 @@
 clear all
 close all
 addpath([getenv('OPENAIR_TARGETS') '/ARCH/EXMIMO/USERSPACE/OCTAVE']);
+addpath([getenv('OPENAIR_DIR') '/cmake_targets/lte_build_oai/build']);
 
 %% -------- ExpressMIMO2 configuration --------
 limeparms;
diff --git a/targets/RT/USER/Makefile b/targets/RT/USER/Makefile
index 621f30c5f41268f8009ee53646d652dcd3628719..8c413d4e2e254048621c62d66f5d05634dcca154 100644
--- a/targets/RT/USER/Makefile
+++ b/targets/RT/USER/Makefile
@@ -193,7 +193,7 @@ CFLAGS += -DHARD_RT
 endif
 
 ifeq ($(EMOS),1)
-CFLAGS += -D_FILE_OFFSET_BITS=64 -DEMOS #-DEMOS_CHANNEL
+CFLAGS += -D_FILE_OFFSET_BITS=64 #-DEMOS -DEMOS_CHANNEL
 LDFLAGS += -lgps
 endif
 
@@ -320,6 +320,7 @@ drivers:
 #	cd $(OPENAIR2_DIR)/NAS/DRIVER/MESH/RB_TOOL && make clean && make
 	cd $(OPENAIR_TARGETS)/ARCH/EXMIMO/DRIVER/eurecom && make clean && make 
 	cd $(OPENAIR_TARGETS)/ARCH/EXMIMO/USERSPACE/OAI_FW_INIT && make clean && make 
+	cp $(OPENAIR_TARGETS)/ARCH/EXMIMO/USERSPACE/OAI_FW_INIT/updatefw $(OPENAIR_TARGETS)/bin/.
 
 run: condtest
 	rtai-load condtest --verbose
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 49f820a8b4e548b7f4d84afa75df10203b68e0e5..9f330a1be680157c605d03b3d8d701c298ac387e 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -128,6 +128,8 @@ extern pthread_cond_t sync_cond;
 extern pthread_mutex_t sync_mutex;
 extern int sync_var;
 
+extern transmission_mode;
+
 //pthread_t                       main_eNB_thread;
 
 time_stats_t softmodem_stats_mt; // main thread
@@ -273,28 +275,45 @@ static inline void wait_sync(char *thread_name) {
 
 }
 
-void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
-     
-  unsigned int aa,slot_offset, slot_offset_F;
-  int dummy_tx_b[7680*4] __attribute__((aligned(32)));
-  int i,j, tx_offset;
-  int slot_sizeF = (phy_vars_eNB->frame_parms.ofdm_symbol_size)*
-                   ((phy_vars_eNB->frame_parms.Ncp==1) ? 6 : 7);
-  int len,len2;
-  int16_t *txdata;
-//  int CC_id = phy_vars_eNB->proc.CC_id;
 
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 );
+void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
+{
 
-  // compute subframe modulo-2
-  slot_offset_F = ((subframe&1)<<1)*slot_sizeF;
+  unsigned int aa,slot_offset;
+  //int dummy_tx_b[7680*4] __attribute__((aligned(32)));
+  int i, tx_offset;
+  //int slot_sizeF = (phy_vars_eNB->frame_parms.ofdm_symbol_size)* ((phy_vars_eNB->frame_parms.Ncp==1) ? 6 : 7);
+  int len;
+  //int slot_offset_F = (subframe<<1)*slot_sizeF;
 
   slot_offset = subframe*phy_vars_eNB->frame_parms.samples_per_tti;
 
+  
   if ((subframe_select(&phy_vars_eNB->frame_parms,subframe)==SF_DL)||
       ((subframe_select(&phy_vars_eNB->frame_parms,subframe)==SF_S))) {
     //    LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);
 
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_OFDM_MODULATION,1);
+
+    do_OFDM_mod_symbol(&phy_vars_eNB->common_vars,
+                  0,
+                  subframe<<1,
+                  &phy_vars_eNB->frame_parms,
+		  phy_vars_eNB->do_precoding);
+ 
+    // if S-subframe generate first slot only 
+    if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL) {
+      do_OFDM_mod_symbol(&phy_vars_eNB->common_vars,
+                    0,
+                    1+(subframe<<1),
+                    &phy_vars_eNB->frame_parms,
+                    phy_vars_eNB->do_precoding);
+    }
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_OFDM_MODULATION,0);
+    
+
+/*
     for (aa=0; aa<phy_vars_eNB->frame_parms.nb_antennas_tx; aa++) {
       if (phy_vars_eNB->frame_parms.Ncp == EXTENDED) {
         PHY_ofdm_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F],
@@ -316,13 +335,15 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
                           7,
                           &(phy_vars_eNB->frame_parms));
 	// if S-subframe generate first slot only
-	if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL) 
+	if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_DL)
 	  normal_prefix_mod(&phy_vars_eNB->common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF],
 			    dummy_tx_b+(phy_vars_eNB->frame_parms.samples_per_tti>>1),
 			    7,
 			    &(phy_vars_eNB->frame_parms));
       }
+    } */
 
+    for (aa=0; aa<phy_vars_eNB->frame_parms.nb_antennas_tx; aa++) {
       // if S-subframe generate first slot only
       if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_S)
 	len = phy_vars_eNB->frame_parms.samples_per_tti>>1;
@@ -335,55 +356,36 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
 	dummy_tx_b[i+2] = 0xff00;
 	dummy_tx_b[i+3] = 0xff000000;
 	}*/
-      
-      if (slot_offset+time_offset[aa]<0) {
-	txdata = (int16_t*)&phy_vars_eNB->common_vars.txdata[0][aa][(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)+tx_offset];
-        len2 = -(slot_offset+time_offset[aa]);
-	len2 = (len2>len) ? len : len2;
-	for (i=0; i<(len2<<1); i++) {
-	  txdata[i] = ((int16_t*)dummy_tx_b)[i]<<openair0_cfg[0].iq_txshift;
-	}
-	if (len2<len) {
-	  txdata = (int16_t*)&phy_vars_eNB->common_vars.txdata[0][aa][0];
-	  for (j=0; i<(len<<1); i++,j++) {
-	    txdata[j++] = ((int16_t*)dummy_tx_b)[i]<<openair0_cfg[0].iq_txshift;
-	  }
-	}
-      }  
-      else if ((slot_offset+time_offset[aa]+len)>(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti)) {
-	tx_offset = (int)slot_offset+time_offset[aa];
-	txdata = (int16_t*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset];
-	len2 = -tx_offset+LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
-	for (i=0; i<(len2<<1); i++) {
-	  txdata[i] = ((int16_t*)dummy_tx_b)[i]<<openair0_cfg[0].iq_txshift;
-	}
-	txdata = (int16_t*)&phy_vars_eNB->common_vars.txdata[0][aa][0];
-	for (j=0; i<(len<<1); i++,j++) {
-	  txdata[j++] = ((int16_t*)dummy_tx_b)[i]<<openair0_cfg[0].iq_txshift;
-	}
-      }
-      else {
-	tx_offset = (int)slot_offset+time_offset[aa];
-	txdata = (int16_t*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset];
+      for (i=0; i<len; i++) {
+        tx_offset = (int)slot_offset+time_offset[aa]+i;
 
-	for (i=0; i<(len<<1); i++) {
-	  txdata[i] = ((int16_t*)dummy_tx_b)[i]<<openair0_cfg[0].iq_txshift;
-	}
-      }
-      
+	
+        if (tx_offset<0)
+          tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
+
+        if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti))
+          tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
+
+/*	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<<openair0_cfg[0].iq_txshift;
+	
+	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<<openair0_cfg[0].iq_txshift; */
+
+	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[0] = ((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[0]<<openair0_cfg[0].iq_txshift;
+	
+	((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[1] = ((short*)&phy_vars_eNB->common_vars.txdata[0][aa][tx_offset])[1]<<openair0_cfg[0].iq_txshift;
+     }
      // if S-subframe switch to RX in second subframe
-      /*
      if (subframe_select(&phy_vars_eNB->frame_parms,subframe) == SF_S) {
        for (i=0; i<len; i++) {
 	 phy_vars_eNB->common_vars.txdata[0][aa][tx_offset++] = 0x00010001;
        }
      }
-      */
+
      if ((((phy_vars_eNB->frame_parms.tdd_config==0) ||
-	   (phy_vars_eNB->frame_parms.tdd_config==1) ||
-	   (phy_vars_eNB->frame_parms.tdd_config==2) ||
-	   (phy_vars_eNB->frame_parms.tdd_config==6)) && 
-	   (subframe==0)) || (subframe==5)) {
+	  (phy_vars_eNB->frame_parms.tdd_config==1) ||
+	  (phy_vars_eNB->frame_parms.tdd_config==2) ||
+	  (phy_vars_eNB->frame_parms.tdd_config==6)) && 
+	  (subframe==0)) || (subframe==5)) {
        // turn on tx switch N_TA_offset before
        //LOG_D(HW,"subframe %d, time to switch to tx (N_TA_offset %d, slot_offset %d) \n",subframe,phy_vars_eNB->N_TA_offset,slot_offset);
        for (i=0; i<phy_vars_eNB->N_TA_offset; i++) {
@@ -391,17 +393,17 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
          if (tx_offset<0)
            tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
 	 
-         if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti))
-           tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
+	 if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti))
+	   tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->frame_parms.samples_per_tti;
 	 
-         phy_vars_eNB->common_vars.txdata[0][aa][tx_offset] = 0x00000000;
+	 phy_vars_eNB->common_vars.txdata[0][aa][tx_offset] = 0x00000000;
        }
      }
     }
   }
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 );
 }
 
+
 void tx_fh_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, proc->timestamp_tx&0xffffffff );
   send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL);
@@ -471,15 +473,16 @@ void proc_tx_full(PHY_VARS_eNB *eNB,
   if (eNB->tx_fh) eNB->tx_fh(eNB,proc);
 
   /*
-   if (proc->frame_tx>1000) {
-     write_output("/tmp/txsig0.m","txs0", &eNB->common_vars.txdata[eNB->Mod_id][0][0], eNB->frame_parms.samples_per_tti*10,1,1);
-     write_output("/tmp/txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB->Mod_id][0][0],eNB->frame_parms.symbols_per_tti*eNB->frame_parms.ofdm_symbol_size*10,1,1);
-     write_output("/tmp/txsig1.m","txs1", &eNB->common_vars.txdata[eNB->Mod_id][1][0], eNB->frame_parms.samples_per_tti*10,1,1);
-     write_output("/tmp/txsigF1.m","txsF1", &eNB->common_vars.txdataF[eNB->Mod_id][1][0],eNB->frame_parms.symbols_per_tti*eNB->frame_parms.ofdm_symbol_size*10,1,1);
-     //if (transmission_mode == 7) write_output("/tmp/txsigF5.m","txsF5", &eNB->common_vars.txdataF[eNB->Mod_id][5][0],eNB->frame_parms.symbols_per_tti*eNB->frame_parms.ofdm_symbol_size*10,1,1);
-     exit_fun("");
-   }
-   */
+  if (proc->frame_tx>1000) {
+    write_output("/tmp/txsig0.m","txs0", &eNB->common_vars.txdata[eNB->Mod_id][0][0], eNB->frame_parms.samples_per_tti*10,1,1);
+    write_output("/tmp/txsigF0.m","txsF0", &eNB->common_vars.txdataF[eNB->Mod_id][0][0],eNB->frame_parms.symbols_per_tti*eNB->frame_parms.ofdm_symbol_size*10,1,1);
+    write_output("/tmp/txsig1.m","txs1", &eNB->common_vars.txdata[eNB->Mod_id][1][0], eNB->frame_parms.samples_per_tti*10,1,1);
+    write_output("/tmp/txsigF1.m","txsF1", &eNB->common_vars.txdataF[eNB->Mod_id][1][0],eNB->frame_parms.symbols_per_tti*eNB->frame_parms.ofdm_symbol_size*10,1,1);
+    if (transmission_mode == 7) 
+      write_output("/tmp/txsigF5.m","txsF5", &eNB->common_vars.txdataF[eNB->Mod_id][5][0],eNB->frame_parms.symbols_per_tti*eNB->frame_parms.ofdm_symbol_size*10,1,1);
+    exit_fun("");
+  }
+  */
 }
 
 void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB,
@@ -644,7 +647,7 @@ static void wait_system_ready (char *message, volatile int *start_flag) {
 #endif
 
 
-// asynchronous UL with IF4p5 (RCC,RAU,eNodeB_BBU)
+// asynchronous UL with IF5 (RCC,RAU,eNodeB_BBU)
 void fh_if5_asynch_UL(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
 
   eNB_proc_t *proc       = &eNB->proc;
@@ -990,6 +993,8 @@ void rx_fh_if5(PHY_VARS_eNB *eNB,int *frame, int *subframe) {
     *subframe = proc->subframe_rx;        
   }      
 
+
+
   proc->timestamp_tx = proc->timestamp_rx +  (4*fp->samples_per_tti);
   
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
@@ -1748,8 +1753,8 @@ void kill_eNB_proc(int inst) {
    antennas are mapped to successive RF chains on the same card. */
 int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg) {
 
-  int i, CC_id;
-  int j;
+  int i,j; 
+  int CC_id,card,ant;
 
   //uint16_t N_TA_offset = 0;
 
@@ -1780,10 +1785,12 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
     // replace RX signal buffers with mmaped HW versions
       
       for (i=0; i<frame_parms->nb_antennas_rx; i++) {
-	printf("Mapping eNB CC_id %d, rx_ant %d\n",CC_id,i);
+	card = i/4;
+	ant = i%4;
+	printf("Mapping eNB CC_id %d, rx_ant %d, on card %d, chain %d\n",CC_id,i,phy_vars_eNB[CC_id]->rf_map.card+card, phy_vars_eNB[CC_id]->rf_map.chain+ant);
 	free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
-	phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = openair0_cfg[CC_id].rxbase[i];
-
+	phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card+card].rxbase[phy_vars_eNB[CC_id]->rf_map.chain+ant];
+	
 	printf("rxdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
 	for (j=0; j<16; j++) {
 	  printf("rxbuffer %d: %x\n",j,phy_vars_eNB[CC_id]->common_vars.rxdata[0][i][j]);
@@ -1792,9 +1799,11 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
       }
       
       for (i=0; i<frame_parms->nb_antennas_tx; i++) {
-	printf("Mapping eNB CC_id %d, tx_ant %d\n",CC_id,i);
+	card = i/4;
+	ant = i%4;
+	printf("Mapping eNB CC_id %d, tx_ant %d, on card %d, chain %d\n",CC_id,i,phy_vars_eNB[CC_id]->rf_map.card+card, phy_vars_eNB[CC_id]->rf_map.chain+ant);
 	free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
-	phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = openair0_cfg[CC_id].txbase[i];//(int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i];
+	phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card+card].txbase[phy_vars_eNB[CC_id]->rf_map.chain+ant];
 	
 	printf("txdata[%d] @ %p\n",i,phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
 	
@@ -1897,6 +1906,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
       switch (node_function[CC_id]) {
       case NGFI_RRU_IF5:
 	eNB->do_prach             = NULL;
+	eNB->do_precoding         = 0;
 	eNB->fep                  = eNB_fep_rru_if5;
 	eNB->td                   = NULL;
 	eNB->te                   = NULL;
@@ -1922,6 +1932,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
         }
 	break;
       case NGFI_RRU_IF4p5:
+	eNB->do_precoding         = 0;
 	eNB->do_prach             = do_prach;
 	eNB->fep                  = eNB_fep_full;//(single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full;
 	eNB->td                   = NULL;
@@ -1952,6 +1963,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
 
 	break;
       case eNodeB_3GPP:
+	eNB->do_precoding         = 1;
 	eNB->do_prach             = do_prach;
 	eNB->fep                  = eNB_fep_full;//(single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full;
 	eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
@@ -1972,6 +1984,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
 	eNB->ifdevice.host_type   = BBU_HOST;
 	break;
       case eNodeB_3GPP_BBU:
+	eNB->do_precoding   = 1;
 	eNB->do_prach       = do_prach;
 	eNB->fep            = eNB_fep_full;//(single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full;
 	eNB->td             = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
@@ -2004,6 +2017,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
         }
 	break;
       case NGFI_RCC_IF4p5:
+	eNB->do_precoding         = 0;
 	eNB->do_prach             = do_prach;
 	eNB->fep                  = NULL;
 	eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
@@ -2027,6 +2041,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
 
 	break;
       case NGFI_RAU_IF4p5:
+	eNB->do_precoding   = 0;
 	eNB->do_prach       = do_prach;
 	eNB->fep            = NULL;
 
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 453b5934d651c20003b8969dbc1b277217798bf3..4142a05e35e84f590031dc4ef85676e79bd31d3d 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -207,6 +207,7 @@ char   rf_config_file[1024];
 
 int chain_offset=0;
 int phy_test = 0;
+uint8_t usim_test = 0;
 
 
 char ref[128] = "internal";
@@ -237,7 +238,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);
-//int transmission_mode=1;
+int transmission_mode=1;
 
 int16_t           glog_level         = LOG_INFO;
 int16_t           glog_verbosity     = LOG_MED;
@@ -382,6 +383,7 @@ void help (void) {
   printf("  --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n");
   printf("  --mmapped-dma sets flag for improved EXMIMO UE performance\n");  
   printf("  --external-clock tells hardware to use an external clock reference\n");
+  printf("  --usim-test use XOR autentication algo in case of test usim mode\n"); 
   printf("  --single-thread-disable. Disables single-thread mode in lte-softmodem\n"); 
   printf("  -C Set the downlink frequency for all component carriers\n");
   printf("  -d Enable soft scope and L1 and L2 stats (Xforms)\n");
@@ -689,6 +691,7 @@ static void get_options (int argc, char **argv)
     LONG_OPTION_DUMP_FRAME,
     LONG_OPTION_LOOPMEMORY,
     LONG_OPTION_PHYTEST,
+    LONG_OPTION_USIMTEST,
     LONG_OPTION_MMAPPED_DMA,
     LONG_OPTION_EXTERNAL_CLOCK,
     LONG_OPTION_WAIT_FOR_SYNC,
@@ -717,6 +720,7 @@ static void get_options (int argc, char **argv)
     {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
     {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
     {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
+    {"usim-test", no_argument, NULL, LONG_OPTION_USIMTEST},
     {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA},
     {"external-clock", no_argument, NULL, LONG_OPTION_EXTERNAL_CLOCK},
     {"wait-for-sync", no_argument, NULL, LONG_OPTION_WAIT_FOR_SYNC},
@@ -818,6 +822,9 @@ static void get_options (int argc, char **argv)
       phy_test = 1;
       break;
 
+    case LONG_OPTION_USIMTEST:
+        usim_test = 1;
+      break;
     case LONG_OPTION_MMAPPED_DMA:
       mmapped_dma = 1;
       break;
@@ -1137,13 +1144,13 @@ static void get_options (int argc, char **argv)
         frame_parms[CC_id]->N_RB_DL             =  enb_properties->properties[i]->N_RB_DL[CC_id];
         frame_parms[CC_id]->N_RB_UL             =  enb_properties->properties[i]->N_RB_DL[CC_id];
         frame_parms[CC_id]->nb_antennas_tx      =  enb_properties->properties[i]->nb_antennas_tx[CC_id];
-        frame_parms[CC_id]->nb_antennas_tx_eNB  =  enb_properties->properties[i]->nb_antenna_ports[CC_id];
+        frame_parms[CC_id]->nb_antenna_ports_eNB  =  enb_properties->properties[i]->nb_antenna_ports[CC_id];
         frame_parms[CC_id]->nb_antennas_rx      =  enb_properties->properties[i]->nb_antennas_rx[CC_id];
 
 	frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = enb_properties->properties[i]->prach_config_index[CC_id];
 	frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset  = enb_properties->properties[i]->prach_freq_offset[CC_id];
 
-	frame_parms[CC_id]->mode1_flag         = (frame_parms[CC_id]->nb_antennas_tx_eNB == 1) ? 1 : 0;
+	frame_parms[CC_id]->mode1_flag         = (frame_parms[CC_id]->nb_antenna_ports_eNB == 1) ? 1 : 0;
 	frame_parms[CC_id]->threequarter_fs    = threequarter_fs;
 
         //} // j
@@ -1205,8 +1212,13 @@ static void get_options (int argc, char **argv)
         printf("Downlink frequency/ uplink offset of CC_id %d set to %ju/%d\n", CC_id,
                enb_properties->properties[i]->downlink_frequency[CC_id],
                enb_properties->properties[i]->uplink_frequency_offset[CC_id]);
+
       } // CC_id
     }// i
+
+    //this is needed for phy-test option
+    transmission_mode = enb_properties->properties[0]->ue_TransmissionMode[0]+1;
+
   } else if (UE_flag == 1) {
     if (conf_config_file_name != NULL) {
       
@@ -1241,7 +1253,7 @@ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
     frame_parms[CC_id]->Ncp_UL              = NORMAL;
     frame_parms[CC_id]->Nid_cell            = 0;
     frame_parms[CC_id]->num_MBSFN_config    = 0;
-    frame_parms[CC_id]->nb_antennas_tx_eNB  = 1;
+    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
     frame_parms[CC_id]->nb_antennas_tx      = 1;
     frame_parms[CC_id]->nb_antennas_rx      = 1;
 
@@ -1376,7 +1388,7 @@ void init_openair0() {
 
 int main( int argc, char **argv )
 {
-  int i,aa;
+  int i,j,k,aa,re;
 #if defined (XFORMS)
   void *status;
 #endif
@@ -1537,7 +1549,7 @@ int main( int argc, char **argv )
     if (UE_flag==1) {
       frame_parms[CC_id]->nb_antennas_tx     = 1;
       frame_parms[CC_id]->nb_antennas_rx     = 1;
-      frame_parms[CC_id]->nb_antennas_tx_eNB = 1; //initial value overwritten by initial sync later
+      frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
     }
 
     init_ul_hopping(frame_parms[CC_id]);
@@ -1627,7 +1639,18 @@ int main( int argc, char **argv )
       PHY_vars_eNB_g[0][CC_id]->target_ue_dl_mcs=target_dl_mcs;
       PHY_vars_eNB_g[0][CC_id]->ue_ul_nb_rb=6;
       PHY_vars_eNB_g[0][CC_id]->target_ue_ul_mcs=target_ul_mcs;
-      
+      // initialization for phy-test
+      for (k=0;k<NUMBER_OF_UE_MAX;k++) {
+	PHY_vars_eNB_g[0][CC_id]->transmission_mode[k] = transmission_mode;
+	if (transmission_mode==7) 
+	  lte_gold_ue_spec_port5(PHY_vars_eNB_g[0][CC_id]->lte_gold_uespec_port5_table[k],frame_parms[CC_id]->Nid_cell,0x1235+k);
+      }
+      if ((transmission_mode==1) || (transmission_mode==7)) {
+	  for (j=0; j<frame_parms[CC_id]->nb_antennas_tx; j++) 
+	    for (re=0; re<frame_parms[CC_id]->ofdm_symbol_size; re++) 
+	      PHY_vars_eNB_g[0][CC_id]->common_vars.beam_weights[0][0][j][re] = 0x00007fff/frame_parms[CC_id]->nb_antennas_tx; 
+      }
+
       if (phy_test==1) PHY_vars_eNB_g[0][CC_id]->mac_enabled = 0;
       else PHY_vars_eNB_g[0][CC_id]->mac_enabled = 1;
       
@@ -1649,18 +1672,7 @@ int main( int argc, char **argv )
     
       
       PHY_vars_eNB_g[0][CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0];
-      
-      if (frame_parms[CC_id]->frame_type==FDD) {
-	PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
-      }
-      else {
-	if (frame_parms[CC_id]->N_RB_DL == 100)
-	  PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624;
-	else if (frame_parms[CC_id]->N_RB_DL == 50)
-	  PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/2;
-	else if (frame_parms[CC_id]->N_RB_DL == 25)
-	  PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/4;
-      }
+      PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
     }
   
 
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index f4b8e0ab3a0f289b42d638e211d27b8275cabce4..5ab6b7cddf0491e6f5fe03b70101d4781e4707a7 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -433,7 +433,14 @@ static void *UE_thread_synch(void *arg)
       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\n", hw_slot_offset );
+        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 );
+
 	if (UE->UE_scan_carrier == 1) {
 
 	  UE->UE_scan_carrier = 0;
@@ -710,12 +717,22 @@ static void *UE_thread_rxn_txnp4(void *arg)
   while (sync_var<0)
     pthread_cond_wait(&sync_cond, &sync_mutex);
 
+#define THREAD_NAME_LEN 16
+  char threadname[THREAD_NAME_LEN];
+  ret = pthread_getname_np(proc->pthread_rxtx, threadname, THREAD_NAME_LEN);
+  if (ret != 0)
+  {
+   perror("pthread_getname_np : ");
+   exit_fun("Error getting thread name");
+  }
+
   pthread_mutex_unlock(&sync_mutex);
   printf("unlocked sync_mutex, waiting (UE_thread_rxtx)\n");
 
-  printf("Starting UE RXN_TXNP4 thread\n");
+  printf("Starting UE RXN_TXNP4 thread (%s)\n", threadname);
 
   while (!oai_exit) {
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0+(proc->subframe_rx&1), 1 );
     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");
@@ -723,15 +740,18 @@ static void *UE_thread_rxn_txnp4(void *arg)
     }
 
     while (proc->instance_cnt_rxtx < 0) {
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX0+(proc->subframe_rx&1), 1 );
       // most of the time, the thread is waiting here
       pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
     }
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX0+(proc->subframe_rx&1), 0 );
 
     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");
       return &UE_thread_rxtx_retval;
     }
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0+(proc->subframe_rx&1), 0 );
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->subframe_rx&1), 1 );
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_UE+(proc->subframe_rx&1), proc->subframe_rx );
@@ -739,21 +759,40 @@ static void *UE_thread_rxn_txnp4(void *arg)
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE+(proc->subframe_rx&1), proc->frame_rx );
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE+(proc->subframe_tx&1), proc->frame_tx );
 
-    if ((subframe_select( &UE->frame_parms, proc->subframe_rx) == SF_DL) ||
-	(UE->frame_parms.frame_type == FDD) ||
-	(subframe_select( &UE->frame_parms, proc->subframe_rx ) == SF_S)) {
+    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_RX( UE, proc, 0, 0, UE->mode, no_relay, NULL );
     }
     
     if (UE->mac_enabled==1) {
 
       ret = mac_xface->ue_scheduler(UE->Mod_id,
-				    proc->frame_tx,
-				    proc->subframe_rx,
-				    subframe_select(&UE->frame_parms,proc->subframe_tx),
-				    0,
-				    0/*FIXME CC_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_LOST) {
 	LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, returning to PRACH\n",
@@ -771,17 +810,25 @@ static void *UE_thread_rxn_txnp4(void *arg)
     }
 
     if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
-	(UE->frame_parms.frame_type == FDD) ||
-	(subframe_select( &UE->frame_parms, proc->subframe_tx ) == SF_S)) {
+	(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);
+      }
+    }
+
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->subframe_rx&1), 0 );
 
     
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0+(proc->subframe_rx&1), 1 );
     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");
@@ -796,6 +843,7 @@ static void *UE_thread_rxn_txnp4(void *arg)
       exit_fun("noting to add");
       return &UE_thread_rxtx_retval;
     }
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0+(proc->subframe_rx&1), 0 );
   }
   
   // thread finished
@@ -918,10 +966,11 @@ void *UE_thread(void *arg) {
 					   rxp,
 					   UE->frame_parms.samples_per_tti*10,
 					   UE->frame_parms.nb_antennas_rx);
-
+	  
 	  
 	  if (rxs!=UE->frame_parms.samples_per_tti*10) {
-	    exit_fun("problem in rx");
+	    LOG_E(PHY, "problem in rx 1! want #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti*10, rxs);
+	    exit_fun("problem in rx 1");
 	    return &UE_thread_retval;
 	  }
 	}
@@ -954,7 +1003,8 @@ void *UE_thread(void *arg) {
 					     UE->frame_parms.nb_antennas_rx);
 
 	    if (rxs!=UE->frame_parms.samples_per_tti){
-	      exit_fun("problem in rx");
+	      LOG_E(PHY, "problem in rx 2! want #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti, rxs);
+	      exit_fun("problem in rx 2");
 	      return &UE_thread_retval;
 	    }
 
@@ -976,7 +1026,8 @@ void *UE_thread(void *arg) {
 					     UE->rx_offset,
 					     UE->frame_parms.nb_antennas_rx);
 	    if (rxs != UE->rx_offset) {
-	      exit_fun("problem in rx");
+	      LOG_E(PHY, "problem in rx 3! want #samples=%d but got only %d!\n", UE->rx_offset, rxs);
+	      exit_fun("problem in rx 3!");
 	      return &UE_thread_retval;
 	    }
 	  }
@@ -990,6 +1041,11 @@ void *UE_thread(void *arg) {
 					   (void**)rxdata,
 					   UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
 					   UE->frame_parms.nb_antennas_rx);
+    if (rxs != (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0)) {
+      LOG_E(PHY, "problem in rx 4! want #samples=%d but got only %d!\n", UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, rxs);
+      exit_fun("problem in rx 4!");
+      return &UE_thread_retval;
+    }
 	  slot_fep(UE,
 		   0,
 		   0,
@@ -1006,27 +1062,34 @@ void *UE_thread(void *arg) {
 
       }// start_rx_stream==0
       else {
-	UE->proc.proc_rxtx[0].frame_rx++;
-	UE->proc.proc_rxtx[1].frame_rx++;
+	//UE->proc.proc_rxtx[0].frame_rx++;
+	//UE->proc.proc_rxtx[1].frame_rx++;
 	
 	for (int sf=0;sf<10;sf++) {
 	  for (i=0; i<UE->frame_parms.nb_antennas_rx; i++) 
 	    rxp[i] = (void*)&rxdata[i][UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0+(sf*UE->frame_parms.samples_per_tti)];
 	  // grab signal for subframe
-	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
 	  if (UE->mode != loop_through_memory) {
 	    if (sf<9) {
+	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
 	      rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
 					       &timestamp,
 					       rxp,
 					       UE->frame_parms.samples_per_tti,
 					       UE->frame_parms.nb_antennas_rx);
-	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
-	      // prepare tx buffer pointers
+	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
+	      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS, rxs );
+	      if (rxs != UE->frame_parms.samples_per_tti) {
+	        LOG_E(PHY, "problem in rx 5! want #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti, rxs);
+	        exit_fun("problem in rx 5!");
+	        return &UE_thread_retval;
+	      }
 	      
+	      // prepare tx buffer pointers
 	      for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
 		txp[i] = (void*)&UE->common_vars.txdata[i][((sf+2)%10)*UE->frame_parms.samples_per_tti];
 	      
+	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
 	      txs = UE->rfdevice.trx_write_func(&UE->rfdevice,
 						timestamp+
 						(2*UE->frame_parms.samples_per_tti) -
@@ -1036,27 +1099,34 @@ void *UE_thread(void *arg) {
 						UE->frame_parms.samples_per_tti,
 						UE->frame_parms.nb_antennas_tx,
 						1);
-              if (txs !=  UE->frame_parms.samples_per_tti) {
-                 LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, UE->frame_parms.samples_per_tti);
-                 exit_fun( "problem transmitting samples" );
-              }
-
 	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
-
+	      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS, rxs );
+        if (txs !=  UE->frame_parms.samples_per_tti) {
+           LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, UE->frame_parms.samples_per_tti);
+           exit_fun( "problem transmitting samples" );
+        }
 	    }
 	    
 	    else {
+	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9, 1 );
 	      rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
 					       &timestamp,
 					       rxp,
 					       UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0,
 					       UE->frame_parms.nb_antennas_rx);
-	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
+	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9, 0 );
+	      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS, rxs );
+        if (rxs != (UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0)) {
+          LOG_E(PHY, "problem in rx 6! want #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0, rxs);
+          exit_fun("problem in rx 6!");
+          return &UE_thread_retval;
+        }
+
 	      // prepare tx buffer pointers
-	      
 	      for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
 		txp[i] = (void*)&UE->common_vars.txdata[i][((sf+2)%10)*UE->frame_parms.samples_per_tti];
 	      
+	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_SF9, 1 );
 	      txs = UE->rfdevice.trx_write_func(&UE->rfdevice,
 						timestamp+
 						(2*UE->frame_parms.samples_per_tti) -
@@ -1066,25 +1136,34 @@ void *UE_thread(void *arg) {
 						UE->frame_parms.samples_per_tti - rx_off_diff,
 						UE->frame_parms.nb_antennas_tx,
 						1);
+	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_SF9, 0 );
+	      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS, rxs );
               if (txs !=  UE->frame_parms.samples_per_tti - rx_off_diff) {
                  LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, UE->frame_parms.samples_per_tti-rx_off_diff);
                  exit_fun( "problem transmitting samples" );
               }
-	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
 
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9, 1 );
 	      // read in first symbol of next frame and adjust for timing drift
 	      rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
 					       &timestamp1,
 					       (void**)rxdata,
-					       UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 - rx_off_diff,
+					       UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0 - rx_off_diff,
 					       UE->frame_parms.nb_antennas_rx);
-	      rx_off_diff = 0;
+	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9, 0 );
+	      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS, rxs );
+        if (rxs != (UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0 - rx_off_diff)) {
+          LOG_E(PHY, "problem in rx 7! want #samples=%d but got only %d! rx_off_diff=%d\n", UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 - rx_off_diff, rxs, rx_off_diff);
+          exit_fun("problem in rx 7!");
+          return &UE_thread_retval;
+        }
+        rx_off_diff = 0;
 	    }
 	  }
-	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
 	  // operate on thread sf mod 2
 	  UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[sf&1];
 
+	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0+(proc->subframe_rx&1), 1 );
 	  // lock mutex
 	  if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
 	    LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" );
@@ -1093,6 +1172,11 @@ void *UE_thread(void *arg) {
 	  }
 	  // increment instance count and change proc subframe/frame variables
 	  int instance_cnt_rxtx = ++proc->instance_cnt_rxtx;
+	  if(sf == 0)
+	  {
+	     UE->proc.proc_rxtx[0].frame_rx++;
+	     UE->proc.proc_rxtx[1].frame_rx++;
+	  }
 	  proc->subframe_rx=sf;
 	  proc->subframe_tx=(sf+4)%10;
 	  proc->frame_tx = proc->frame_rx + ((proc->subframe_rx>5)?1:0);
@@ -1109,14 +1193,20 @@ void *UE_thread(void *arg) {
 	    exit_fun("nothing to add");
 	    return &UE_thread_retval;
 	  }
+	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0+(proc->subframe_rx&1), 0 );
 
 
 	  if (instance_cnt_rxtx == 0) {
+	    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SIGNAL_COND_RXTX, 1 );
 	    if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
 	      LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n" );
 	      exit_fun("nothing to add");
 	      return &UE_thread_retval;
 	    }
+	    LOG_D(PHY, "firing up rxtx_thread[%d] at subframe %d\n", sf&1, sf);
+
+	    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SIGNAL_COND_RXTX, 0 );
+
 	  } else {
 	    LOG_E( PHY, "[SCHED][UE] UE RX thread busy (IC %d)!!\n", instance_cnt_rxtx);
 	    if (instance_cnt_rxtx > 2) {
diff --git a/targets/SIMU/USER/init_lte.c b/targets/SIMU/USER/init_lte.c
index 7071702c282649c3e95d4cac18001fd0345ad773..b75431cdc6c7b1ec4da08d39555b30cec9fefb13 100644
--- a/targets/SIMU/USER/init_lte.c
+++ b/targets/SIMU/USER/init_lte.c
@@ -45,7 +45,7 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms,
                            uint8_t abstraction_flag)
 {
 
-  int i,j;
+  int i,j,layer,aa,re;
   PHY_VARS_eNB* PHY_vars_eNB = malloc(sizeof(PHY_VARS_eNB));
   memset(PHY_vars_eNB,0,sizeof(PHY_VARS_eNB));
   PHY_vars_eNB->Mod_id=eNB_id;
@@ -71,8 +71,7 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms,
   for (i=0; i<NUMBER_OF_UE_MAX; i++) {
     LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH, UE %d\n",i);
     for (j=0; j<2; j++) {
-      PHY_vars_eNB->dlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL,abstraction_flag);
-      
+      PHY_vars_eNB->dlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL,abstraction_flag,frame_parms);
       if (!PHY_vars_eNB->dlsch[i][j]) {
 	LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i);
 	exit(-1);
@@ -92,7 +91,7 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms,
     
     // this is the transmission mode for the signalling channels
     // this will be overwritten with the real transmission mode by the RRC once the UE is connected
-    PHY_vars_eNB->transmission_mode[i] = frame_parms->nb_antennas_tx_eNB==1 ? 1 : 2;
+    PHY_vars_eNB->transmission_mode[i] = frame_parms->nb_antenna_ports_eNB==1 ? 1 : 2;
 #ifdef LOCALIZATION
     PHY_vars_eNB->ulsch[1+i]->aggregation_period_ms = 5000; // 5000 milliseconds // could be given as an argument (TBD))
     struct timeval ts;
@@ -123,12 +122,11 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms,
     LOG_E(PHY,"Can't get eNB ulsch structures\n");
     exit(-1);
   }
-  
-  PHY_vars_eNB->dlsch_SI  = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, abstraction_flag);
+  PHY_vars_eNB->dlsch_SI  = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, abstraction_flag, frame_parms);
   LOG_D(PHY,"eNB %d : SI %p\n",eNB_id,PHY_vars_eNB->dlsch_SI);
-  PHY_vars_eNB->dlsch_ra  = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, abstraction_flag);
+  PHY_vars_eNB->dlsch_ra  = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, abstraction_flag, frame_parms);
   LOG_D(PHY,"eNB %d : RA %p\n",eNB_id,PHY_vars_eNB->dlsch_ra);
-  PHY_vars_eNB->dlsch_MCH = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, 0);
+  PHY_vars_eNB->dlsch_MCH = new_eNB_dlsch(1,8,NSOFT,frame_parms->N_RB_DL, 0, frame_parms);
   LOG_D(PHY,"eNB %d : MCH %p\n",eNB_id,PHY_vars_eNB->dlsch_MCH);
   
   
@@ -186,7 +184,7 @@ PHY_VARS_UE* init_lte_UE(LTE_DL_FRAME_PARMS *frame_parms,
     PHY_vars_UE->dlsch_SI[i]  = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag);
     PHY_vars_UE->dlsch_ra[i]  = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag);
 
-    PHY_vars_UE->transmission_mode[i] = frame_parms->nb_antennas_tx_eNB==1 ? 1 : 2;
+    PHY_vars_UE->transmission_mode[i] = frame_parms->nb_antenna_ports_eNB==1 ? 1 : 2;
   }
 
   PHY_vars_UE->frame_parms.pucch_config_common.deltaPUCCH_Shift = 1;
@@ -256,8 +254,8 @@ void init_lte_vars(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs],
     (frame_parms[CC_id])->nushift            = (Nid_cell%6);
     (frame_parms[CC_id])->nb_antennas_tx     = nb_antennas_tx;
     (frame_parms[CC_id])->nb_antennas_rx     = nb_antennas_rx;
-    (frame_parms[CC_id])->nb_antennas_tx_eNB = nb_antenna_ports;
-    (frame_parms[CC_id])->mode1_flag          = (frame_parms[CC_id])->nb_antennas_tx_eNB==1 ? 1 : 0;
+    (frame_parms[CC_id])->nb_antenna_ports_eNB = nb_antenna_ports;
+    (frame_parms[CC_id])->mode1_flag           = (frame_parms[CC_id])->nb_antenna_ports_eNB==1 ? 1 : 0;
 
     init_frame_parms(frame_parms[CC_id],1);
 
@@ -294,8 +292,6 @@ void init_lte_vars(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs],
     for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
       (frame_parms[CC_id])->nb_antennas_tx     = 1;
       (frame_parms[CC_id])->nb_antennas_rx     = nb_antennas_rx_ue;
-
-
       PHY_vars_UE_g[UE_id][CC_id] = init_lte_UE(frame_parms[CC_id], UE_id,abstraction_flag);
       PHY_vars_UE_g[UE_id][CC_id]->Mod_id=UE_id;
       PHY_vars_UE_g[UE_id][CC_id]->CC_id=CC_id;
diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c
index 79cd2fcc38212dacd6e4688313273626a0c6745d..3a06a627803f3bd3d1d92fdbbb259ca6b5960f55 100644
--- a/targets/SIMU/USER/oaisim.c
+++ b/targets/SIMU/USER/oaisim.c
@@ -75,6 +75,11 @@ uint8_t config_smbv = 0;
 char smbv_ip[16];
 #endif
 
+#if defined(FLEXRAN_AGENT_SB_IF)
+#   include "flexran_agent.h"
+#endif
+
+
 #include "oaisim_functions.h"
 
 #include "oaisim.h"
@@ -122,6 +127,8 @@ char smbv_ip[16];
 //#define K                      2             /* averaging coefficient */
 //#define TARGET_SF_TIME_NS      1000000       /* 1ms = 1000000 ns */
 
+uint8_t usim_test = 0;
+
 frame_t frame = 0;
 char stats_buffer[16384];
 channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs];
@@ -495,7 +502,6 @@ l2l1_task (void *args_p)
     xargv[0] = xname;
     fl_initialize (&xargc, xargv, NULL, 0, 0);
     eNB_inst = 0;
-    
     for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) {
       for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
 	// DL scope at UEs
@@ -875,6 +881,7 @@ l2l1_task (void *args_p)
                   update_otg_UE (UE_inst, oai_emulation.info.time_ms);
 
                   //Access layer
+		  //		  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE_inst, ENB_FLAG_NO, NOT_A_RNTI, frame, next_slot>>1, 0);
 		  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE_inst, 0, ENB_FLAG_NO, NOT_A_RNTI, frame % MAX_FRAME_NUMBER, next_slot);
                   pdcp_run (&ctxt);
 #endif
@@ -883,7 +890,7 @@ l2l1_task (void *args_p)
                        CC_id++) {
                     phy_procedures_UE_lte (
                       PHY_vars_UE_g[UE_inst][CC_id],
-                      0, abstraction_flag,
+		      0, abstraction_flag,
                       normal_txrx, no_relay,
                       NULL);
                   }
@@ -1296,6 +1303,10 @@ main (int argc, char **argv)
   smbv_write_config_from_frame_parms(smbv_fname, &PHY_vars_eNB_g[0][0]->frame_parms);
 #endif
 
+  /* #if defined (FLEXRAN_AGENT_SB_IF)
+  flexran_agent_start();
+  #endif */ 
+
   // add events to future event list: Currently not used
   //oai_emulation.info.oeh_enabled = 1;
   if (oai_emulation.info.oeh_enabled == 1)
diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c
index 10b6a10ca594dab984c852eccc2d4d5dac9cb121..130a3393905e0325aa60d3ba1612c1772d6ed9aa 100644
--- a/targets/SIMU/USER/oaisim_functions.c
+++ b/targets/SIMU/USER/oaisim_functions.c
@@ -720,7 +720,7 @@ void get_simulation_options(int argc, char *argv[])
       oai_emulation.info.transmission_mode[0] = atoi (optarg);
 
       if ((oai_emulation.info.transmission_mode[0] != 1) &&  (oai_emulation.info.transmission_mode[0] != 2) && (oai_emulation.info.transmission_mode[0] != 3)
-          && (oai_emulation.info.transmission_mode[0] != 5) && (oai_emulation.info.transmission_mode[0] != 6)) {
+          && (oai_emulation.info.transmission_mode[0] != 5) && (oai_emulation.info.transmission_mode[0] != 6) && (oai_emulation.info.transmission_mode[0] !=7)) {
         printf("Unsupported transmission mode %d\n",oai_emulation.info.transmission_mode[0]);
         exit(-1);
       }
@@ -1194,12 +1194,12 @@ void init_openair1(void)
         PHY_vars_eNB_g[eNB_id][CC_id]->pusch_config_dedicated[UE_id].betaOffset_ACK_Index = beta_ACK;
         PHY_vars_eNB_g[eNB_id][CC_id]->pusch_config_dedicated[UE_id].betaOffset_RI_Index  = beta_RI;
         PHY_vars_eNB_g[eNB_id][CC_id]->pusch_config_dedicated[UE_id].betaOffset_CQI_Index = beta_CQI;
-        PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antennas_tx_eNB>1) ? 1 : 0; // rho_A = rho_B
+        PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antenna_ports_eNB>1) ? 1 : 0; // rho_A = rho_B
 
         PHY_vars_UE_g[UE_id][CC_id]->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index = beta_ACK;
         PHY_vars_UE_g[UE_id][CC_id]->pusch_config_dedicated[eNB_id].betaOffset_RI_Index  = beta_RI;
         PHY_vars_UE_g[UE_id][CC_id]->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index = beta_CQI;
-        PHY_vars_UE_g[UE_id][CC_id]->frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antennas_tx_eNB>1) ? 1 : 0; // rho_A = rho_B
+        PHY_vars_UE_g[UE_id][CC_id]->frame_parms.pdsch_config_common.p_b = (frame_parms[CC_id]->nb_antenna_ports_eNB>1) ? 1 : 0; // rho_A = rho_B
       }
     }
   }
@@ -1276,7 +1276,7 @@ void init_openair1(void)
   for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {
     for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
       
-      PHY_vars_UE_g[UE_id][CC_id]->tx_power_max_dBm=23;
+      PHY_vars_UE_g[UE_id][CC_id]->tx_power_max_dBm=10;
       
       PHY_vars_UE_g[UE_id][CC_id]->rx_total_gain_dB=100;
 
@@ -1518,7 +1518,7 @@ void update_ocm()
           //calc_path_loss (enb_data[eNB_id], ue_data[UE_id], eNB2UE[eNB_id][UE_id], oai_emulation.environment_system_config,0);
           UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB;
           //    if (frame % 50 == 0)
-          LOG_I(OCM,"Path loss (CCid %d) between eNB %d at (%f,%f) and UE %d at (%f,%f) is %f, angle %f\n",
+          LOG_D(OCM,"Path loss (CCid %d) between eNB %d at (%f,%f) and UE %d at (%f,%f) is %f, angle %f\n",
                 CC_id,eNB_id,enb_data[eNB_id]->x,enb_data[eNB_id]->y,UE_id,ue_data[UE_id]->x,ue_data[UE_id]->y,
                 eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB, eNB2UE[eNB_id][UE_id][CC_id]->aoa);
           //double dx, dy, distance;
@@ -1577,13 +1577,11 @@ void update_otg_eNB(module_id_t enb_module_idP, unsigned int ctime)
       // generate traffic if the ue is rrc reconfigured state
       //if ((rrc_state=mac_eNB_get_rrc_status(enb_module_idP, dst_id)) > 2 /*RRC_CONNECTED*/ ) {
       if (mac_eNB_get_rrc_status(enb_module_idP, oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_idP][dst_id]) > 2 ){ 
-	
 	if_times += 1;
 	
         for (app_id=0; app_id<MAX_NUM_APPLICATION; app_id++) {
           otg_pkt = malloc (sizeof(Packet_otg_elt_t));
 
-
           (otg_pkt->otg_pkt).sdu_buffer = (uint8_t*) packet_gen(enb_module_idP, dst_id + NB_eNB_INST, app_id, ctime, &((otg_pkt->otg_pkt).sdu_buffer_size));
 
           if ((otg_pkt->otg_pkt).sdu_buffer != NULL) {
@@ -1710,6 +1708,7 @@ void update_otg_UE(module_id_t ue_mod_idP, unsigned int ctime)
 {
 #if defined(USER_MODE) && defined(OAI_EMU)
 
+  int app_id;
   if (oai_emulation.info.otg_enabled ==1 ) {
     module_id_t dst_id, src_id; //dst_id = eNB_index
     module_id_t module_id = ue_mod_idP+NB_eNB_INST;
@@ -1719,31 +1718,33 @@ void update_otg_UE(module_id_t ue_mod_idP, unsigned int ctime)
     for (dst_id=0; dst_id<NB_SIG_CNX_UE; dst_id++) {
       // only consider the first attached eNB
       if (mac_UE_get_rrc_status(ue_mod_idP, dst_id ) > 2 /*RRC_CONNECTED*/) {
-        Packet_otg_elt_t *otg_pkt = malloc (sizeof(Packet_otg_elt_t));
-
-        if (otg_pkt!=NULL)
-          memset(otg_pkt,0,sizeof(Packet_otg_elt_t));
-        else {
-          LOG_E(OTG,"not enough memory\n");
-          exit(-1);
-        }// Manage to add this packet to the tail of your list
-
-        (otg_pkt->otg_pkt).sdu_buffer = (uint8_t*) packet_gen(src_id, dst_id, 0, ctime, &((otg_pkt->otg_pkt).sdu_buffer_size));
-
-        if ((otg_pkt->otg_pkt).sdu_buffer != NULL) {
-          (otg_pkt->otg_pkt).rb_id     = DTCH-2;
-          (otg_pkt->otg_pkt).module_id = module_id;
-          (otg_pkt->otg_pkt).dst_id    = dst_id;
-          (otg_pkt->otg_pkt).is_ue     = 1;
-          //Adding the packet to the OTG-PDCP buffer
-          (otg_pkt->otg_pkt).mode      = PDCP_TRANSMISSION_MODE_DATA;
-          pkt_list_add_tail_eurecom(otg_pkt, &(otg_pdcp_buffer[module_id]));
-          LOG_I(EMU, "[UE %d] ADD pkt to OTG buffer with size %d for dst %d on rb_id %d \n",
-                (otg_pkt->otg_pkt).module_id, otg_pkt->otg_pkt.sdu_buffer_size, (otg_pkt->otg_pkt).dst_id,(otg_pkt->otg_pkt).rb_id);
-        } else {
-          free(otg_pkt);
-          otg_pkt=NULL;
-        }
+        for (app_id=0; app_id<MAX_NUM_APPLICATION; app_id++) {
+	  Packet_otg_elt_t *otg_pkt = malloc (sizeof(Packet_otg_elt_t));
+	  
+	  if (otg_pkt!=NULL)
+	    memset(otg_pkt,0,sizeof(Packet_otg_elt_t));
+	  else {
+	    LOG_E(OTG,"not enough memory\n");
+	    exit(-1);
+	  }// Manage to add this packet to the tail of your list
+	  
+	  (otg_pkt->otg_pkt).sdu_buffer = (uint8_t*) packet_gen(src_id, dst_id, app_id, ctime, &((otg_pkt->otg_pkt).sdu_buffer_size));
+	  
+	  if ((otg_pkt->otg_pkt).sdu_buffer != NULL) {
+	    (otg_pkt->otg_pkt).rb_id     = DTCH-2;
+	    (otg_pkt->otg_pkt).module_id = module_id;
+	    (otg_pkt->otg_pkt).dst_id    = dst_id;
+	    (otg_pkt->otg_pkt).is_ue     = 1;
+	    //Adding the packet to the OTG-PDCP buffer
+	    (otg_pkt->otg_pkt).mode      = PDCP_TRANSMISSION_MODE_DATA;
+	    pkt_list_add_tail_eurecom(otg_pkt, &(otg_pdcp_buffer[module_id]));
+	    LOG_I(EMU, "[UE %d] ADD pkt to OTG buffer with size %d for dst %d on rb_id %d \n",
+		  (otg_pkt->otg_pkt).module_id, otg_pkt->otg_pkt.sdu_buffer_size, (otg_pkt->otg_pkt).dst_id,(otg_pkt->otg_pkt).rb_id);
+	  } else {
+	    free(otg_pkt);
+	    otg_pkt=NULL;
+	  }
+	}
       }
     }
   }
diff --git a/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c b/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c
index 0c1500fd5e3aa2ca4bad398ca97f566ba293f0c5..dc395281dce2d69febc4e5f7e86f6fbcb538a2d0 100644
--- a/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c
+++ b/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c
@@ -188,9 +188,9 @@ void pdcp_rlc_test_exchange_pdus(rlc_um_entity_t *um_txP,
   memset(&mac_rlc_status_resp_tx, 0, sizeof(struct mac_status_resp));
   memset(&mac_rlc_status_resp_rx, 0, sizeof(struct mac_status_resp));
 
-  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, bytes_txP, tx_status);
+  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, bytes_txP, tx_status, ENB_FLAG_YES);
   data_request_tx        = rlc_um_mac_data_request(um_txP);
-  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, bytes_rxP, tx_status);
+  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, bytes_rxP, tx_status, ENB_FLAG_YES);
   data_request_rx        = rlc_um_mac_data_request(um_rxP);