diff --git a/ci-scripts/buildOnVM.sh b/ci-scripts/buildOnVM.sh
index ef2637965fe383dba5134b63760a97837caf3ea4..72fa29aa393935a4c85beb949ff1d2a21cda21a2 100755
--- a/ci-scripts/buildOnVM.sh
+++ b/ci-scripts/buildOnVM.sh
@@ -68,11 +68,12 @@ function build_on_vm {
     then
         echo "VM_MEMORY           = $VM_MEMORY MBytes"
         echo "VM_CPU              = $VM_CPU"
+        echo "VM_DISK             = $VM_DISK GBytes"
         echo "############################################################"
         echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base"
         echo "############################################################"
         acquire_vm_create_lock
-        uvt-kvm create $VM_NAME release=$VM_OSREL --memory $VM_MEMORY --cpu $VM_CPU --disk 10 --unsafe-caching --template ci-scripts/template-host.xml
+        uvt-kvm create $VM_NAME release=$VM_OSREL --memory $VM_MEMORY --cpu $VM_CPU --disk $VM_DISK --unsafe-caching --template ci-scripts/template-host.xml
         echo "Waiting for VM to be started"
         uvt-kvm wait $VM_NAME --insecure
 
diff --git a/ci-scripts/createVM.sh b/ci-scripts/createVM.sh
index b1d234639243733a675db231e7a957a336566df0..237a1a5d5e4521197c51a2f69433a38340f1c6e3 100755
--- a/ci-scripts/createVM.sh
+++ b/ci-scripts/createVM.sh
@@ -85,12 +85,13 @@ function create_vm {
     echo "VM_NAME             = $VM_NAME"
     echo "VM_MEMORY           = $VM_MEMORY MBytes"
     echo "VM_CPU              = $VM_CPU"
+    echo "VM_DISK             = $VM_DISK GBytes"
 
     echo "############################################################"
     echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base"
     echo "############################################################"
     acquire_vm_create_lock
-    uvt-kvm create $VM_NAME release=$VM_OSREL --memory $VM_MEMORY --cpu $VM_CPU --disk 10 --unsafe-caching --template ci-scripts/template-host.xml
+    uvt-kvm create $VM_NAME release=$VM_OSREL --memory $VM_MEMORY --cpu $VM_CPU --disk $VM_DISK --unsafe-caching --template ci-scripts/template-host.xml
     echo "Waiting for VM to be started"
     uvt-kvm wait $VM_NAME --insecure
 
diff --git a/ci-scripts/oai-ci-vm-tool b/ci-scripts/oai-ci-vm-tool
index ce40134cec7f089939fe4871b8a299d12f71e237..fb9dc9ad7638f796a8f79e2cd205de2722022570 100755
--- a/ci-scripts/oai-ci-vm-tool
+++ b/ci-scripts/oai-ci-vm-tool
@@ -52,7 +52,7 @@ function variant_usage {
         if [ "$1" = "full" ]
         then        
             printf  "               VM_NAME=%-15s          ARCHIVES_LOC=%-15s\n" "$VM_NAME" "$ARCHIVES_LOC"
-            printf  "               VM_MEMORY=%-15s        VM_CPU=%-15s\n" "$VM_MEMORY" "$VM_CPU"       
+            printf  "               VM_MEMORY=%-15s        VM_CPU=%-15s           VM_DISK=%-15s\n" "$VM_MEMORY" "$VM_CPU" "$VM_DISK"
             printf  "               NB_PATTERN_FILES=%-15s BUILD_OPTIONS=%-15s\n" "$NB_PATTERN_FILES" "\"$BUILD_OPTIONS\""
             printf  "               LOG_PATTERN=%-15s      EXPERIMENTAL=%-15s\n\n\n" "$LOG_PATTERN"  "$EXPERIMENTAL"
         fi
@@ -185,6 +185,7 @@ function variant__v3__phy_sim {
     NB_PATTERN_FILES=12
     BUILD_OPTIONS="--phy_simulators"
     VM_MEMORY=8192
+    VM_DISK=20
     RUN_OPTIONS="./run_exec_autotests.bash -g \"01510* 015111\" -q -np -b"
 }
 
@@ -272,6 +273,7 @@ function check_set_variant {
             ARCHIVES_LOC=${VARIANTS_LONG[$i]//"-"/"_"}  
             VM_MEMORY=2048
             VM_CPU=4
+            VM_DISK=10
             EXPERIMENTAL=""
             NBARGS=$[$NBARGS+$VARIANT_OPTID]   
             variant__${VARIANTS_SHORT[$i]}__${VARIANTS_LONG[$i]//"-"/"_"}
@@ -494,6 +496,7 @@ AUTHORIZED_VAR=("VM_OSREL RUN_EXPERIMENTAL OPTIONAL_APTCACHER TESTPLATFORM_OWNER
 # -V<xx> option.
 VM_NAME=""
 VM_MEMORY=0
+VM_DISK=0
 VM_CPU=0
 ARCHIVES_LOC=""
 LOG_PATTERN=""
diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh
index 9e69145a8f6ad90dc8bd35d20dd6c69c5184b087..ded67443bc8089a0d08cd31ef3c85903df190a9b 100755
--- a/ci-scripts/runTestOnVM.sh
+++ b/ci-scripts/runTestOnVM.sh
@@ -1149,6 +1149,11 @@ function run_test_on_vm {
         echo "cp /home/ubuntu/bc-install.txt log" >> $VM_CMDS
         echo "cd log" >> $VM_CMDS
         echo "zip -r -qq tmp.zip *.* 0*" >> $VM_CMDS
+        echo "echo \"############################################################\"" >> $VM_CMDS
+        echo "echo \"Evaluating remaining memory on disk!\"" >> $VM_CMDS
+        echo "echo \"############################################################\"" >> $VM_CMDS
+        echo "echo \"df -h\"" >> $VM_CMDS
+        echo "df -h" >> $VM_CMDS
 
         ssh -T -o StrictHostKeyChecking=no ubuntu@$VM_IP_ADDR < $VM_CMDS
 
diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 273aad0c20732e98b2ee70901d58184be170eb48..a0620d834548f6ec1ca75fef73cfd9ba9a3352c6 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1473,15 +1473,8 @@ set(RRC_DIR ${OPENAIR2_DIR}/RRC/LTE)
 set(NR_RRC_DIR ${OPENAIR2_DIR}/RRC/NR)
 set(NR_UE_RRC_DIR ${OPENAIR2_DIR}/RRC/NR_UE)
 set(PDCP_DIR  ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0)
-set(L2_SRC
-  ${OPENAIR2_DIR}/LAYER2/openair2_proc.c
-  ${PDCP_DIR}/pdcp.c
-  ${PDCP_DIR}/pdcp_fifo.c
-  ${PDCP_DIR}/pdcp_sequence_manager.c
-  ${PDCP_DIR}/pdcp_primitives.c
-  ${PDCP_DIR}/pdcp_util.c
-  ${PDCP_DIR}/pdcp_security.c
-  ${PDCP_DIR}/pdcp_netlink.c
+
+set(LTE_RLC_SRC
   ${RLC_AM_DIR}/rlc_am.c
   ${RLC_AM_DIR}/rlc_am_init.c
   ${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c
@@ -1509,6 +1502,29 @@ set(L2_SRC
   ${RLC_DIR}/rlc.c
   ${RLC_DIR}/rlc_rrc.c
   ${RLC_DIR}/rlc_mpls.c
+  )
+
+set(NR_RLC_SRC
+  ${OPENAIR2_DIR}/LAYER2/nr_rlc/asn1_utils.c
+  ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity.c
+  ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity_am.c
+  ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity_tm.c
+  ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity_um.c
+  ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_oai_api.c
+  ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_pdu.c
+  ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_sdu.c
+  ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_ue_manager.c
+  )
+
+set(L2_SRC
+  ${OPENAIR2_DIR}/LAYER2/openair2_proc.c
+  ${PDCP_DIR}/pdcp.c
+  ${PDCP_DIR}/pdcp_fifo.c
+  ${PDCP_DIR}/pdcp_sequence_manager.c
+  ${PDCP_DIR}/pdcp_primitives.c
+  ${PDCP_DIR}/pdcp_util.c
+  ${PDCP_DIR}/pdcp_security.c
+  ${PDCP_DIR}/pdcp_netlink.c
 #  ${RRC_DIR}/rrc_UE.c
   ${RRC_DIR}/rrc_eNB.c
   ${RRC_DIR}/rrc_eNB_S1AP.c
@@ -1519,7 +1535,12 @@ set(L2_SRC
   ${RRC_DIR}/L2_interface_ue.c
   )
 
+set(L2_LTE_SRC
+  ${LTE_RLC_SRC}
+  )
+
 set(L2_NR_SRC
+  ${NR_RLC_SRC}
   ${NR_RRC_DIR}/rrc_gNB.c
   ${NR_RRC_DIR}/nr_rrc_common.c
   ${NR_RRC_DIR}/L2_nr_interface.c
@@ -1534,40 +1555,13 @@ set(L2_SRC_UE
   ${PDCP_DIR}/pdcp_util.c
   ${PDCP_DIR}/pdcp_security.c
   ${PDCP_DIR}/pdcp_netlink.c
-  ${RLC_AM_DIR}/rlc_am.c
-  ${RLC_AM_DIR}/rlc_am_init.c
-  ${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c
-  ${RLC_AM_DIR}/rlc_am_timer_reordering.c
-  ${RLC_AM_DIR}/rlc_am_timer_status_prohibit.c
-  ${RLC_AM_DIR}/rlc_am_segment.c
-  ${RLC_AM_DIR}/rlc_am_segments_holes.c
-  ${RLC_AM_DIR}/rlc_am_in_sdu.c
-  ${RLC_AM_DIR}/rlc_am_receiver.c
-  ${RLC_AM_DIR}/rlc_am_retransmit.c
-  ${RLC_AM_DIR}/rlc_am_windows.c
-  ${RLC_AM_DIR}/rlc_am_rx_list.c
-  ${RLC_AM_DIR}/rlc_am_reassembly.c
-  ${RLC_AM_DIR}/rlc_am_status_report.c
-  ${RLC_TM_DIR}/rlc_tm.c
-  ${RLC_TM_DIR}/rlc_tm_init.c
-  ${RLC_UM_DIR}/rlc_um.c
-  ${RLC_UM_DIR}/rlc_um_fsm.c
-  ${RLC_UM_DIR}/rlc_um_control_primitives.c
-  ${RLC_UM_DIR}/rlc_um_segment.c
-  ${RLC_UM_DIR}/rlc_um_reassembly.c
-  ${RLC_UM_DIR}/rlc_um_receiver.c
-  ${RLC_UM_DIR}/rlc_um_dar.c
-  ${RLC_DIR}/rlc_mac.c
-  ${RLC_DIR}/rlc.c
-  ${RLC_DIR}/rlc_rrc.c
-  ${RLC_DIR}/rlc_mpls.c
   ${RRC_DIR}/rrc_UE.c
   ${RRC_DIR}/rrc_common.c
   ${RRC_DIR}/L2_interface_common.c
   ${RRC_DIR}/L2_interface_ue.c
   )
   
-  set(LTE_NR_L2_SRC_UE
+set(LTE_NR_L2_SRC_UE
   ${PDCP_DIR}/pdcp.c
   ${PDCP_DIR}/pdcp_fifo.c
   ${PDCP_DIR}/pdcp_sequence_manager.c
@@ -1575,37 +1569,11 @@ set(L2_SRC_UE
   ${PDCP_DIR}/pdcp_util.c
   ${PDCP_DIR}/pdcp_security.c
   ${PDCP_DIR}/pdcp_netlink.c
-  ${RLC_AM_DIR}/rlc_am.c
-  ${RLC_AM_DIR}/rlc_am_init.c
-  ${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c
-  ${RLC_AM_DIR}/rlc_am_timer_reordering.c
-  ${RLC_AM_DIR}/rlc_am_timer_status_prohibit.c
-  ${RLC_AM_DIR}/rlc_am_segment.c
-  ${RLC_AM_DIR}/rlc_am_segments_holes.c
-  ${RLC_AM_DIR}/rlc_am_in_sdu.c
-  ${RLC_AM_DIR}/rlc_am_receiver.c
-  ${RLC_AM_DIR}/rlc_am_retransmit.c
-  ${RLC_AM_DIR}/rlc_am_windows.c
-  ${RLC_AM_DIR}/rlc_am_rx_list.c
-  ${RLC_AM_DIR}/rlc_am_reassembly.c
-  ${RLC_AM_DIR}/rlc_am_status_report.c
-  ${RLC_TM_DIR}/rlc_tm.c
-  ${RLC_TM_DIR}/rlc_tm_init.c
-  ${RLC_UM_DIR}/rlc_um.c
-  ${RLC_UM_DIR}/rlc_um_fsm.c
-  ${RLC_UM_DIR}/rlc_um_control_primitives.c
-  ${RLC_UM_DIR}/rlc_um_segment.c
-  ${RLC_UM_DIR}/rlc_um_reassembly.c
-  ${RLC_UM_DIR}/rlc_um_receiver.c
-  ${RLC_UM_DIR}/rlc_um_dar.c
-  ${RLC_DIR}/rlc_mac.c
-  ${RLC_DIR}/rlc.c
-  ${RLC_DIR}/rlc_rrc.c
-  ${RLC_DIR}/rlc_mpls.c
-  ${RRC_DIR}/L2_interface_common.c  
+  ${LTE_RLC_SRC}
   )
 
 set(NR_L2_SRC_UE
+  ${NR_RLC_SRC}
   ${NR_UE_RRC_DIR}/L2_interface_ue.c
   ${NR_UE_RRC_DIR}/main_ue.c
   ${NR_UE_RRC_DIR}/rrc_UE.c
@@ -1693,6 +1661,10 @@ add_library(MAC_UE_NR
   ${MAC_NR_SRC_UE}
   )
 
+add_library(L2_LTE
+  ${L2_LTE_SRC}
+  )
+
 add_library(L2_NR
   ${L2_NR_SRC}
   ${MAC_NR_SRC}
@@ -2345,7 +2317,7 @@ add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag)
 target_link_libraries (lte-softmodem
   -Wl,--start-group
   RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP X2AP_LIB X2AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB 
-  PHY_COMMON PHY PHY_RU LFDS L2 NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7
+  PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7
   ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB}
   -Wl,--end-group z dl)
   
@@ -2417,7 +2389,7 @@ endif()
 target_link_libraries (lte-uesoftmodem
   -Wl,--start-group
   RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB F1AP F1AP_LIB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON 
-  PHY_UE PHY_RU LFDS L2_UE SIMU ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
+  PHY_UE PHY_RU LFDS L2_UE L2_LTE SIMU ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
   NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
   -Wl,--end-group z dl)
 
@@ -2745,7 +2717,7 @@ if (${T_TRACER})
         SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB
         SCHED_NR_UE_LIB NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB
         NFAPI_USER_LIB PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_UE PHY_RU PHY_MEX
-        L2 L2_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_NR MAC_UE_NR CN_UTILS GTPV1U
+        L2 L2_LTE L2_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_NR MAC_UE_NR CN_UTILS GTPV1U
         SCTP_CLIENT UDP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU SIMU_ETH OPENAIR0_LIB)
     if (TARGET ${i})
       add_dependencies(${i} generate_T)
diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml
index a407171d01dc455664f7fccd4f0e57aabcd5d8a8..6795f2d1fa490eaeae21477fa55059e105c82fa2 100644
--- a/cmake_targets/autotests/test_case_list.xml
+++ b/cmake_targets/autotests/test_case_list.xml
@@ -1088,7 +1088,7 @@
                                  (Test7: 106 PRB 51 PDSCH-Offset),
                                  (Test8: 217 PRB 100 PDSCH-PRBs),
                                  (Test9: 217 PRB 80 PDSCH-Offset),
-                                 (Test10: 217 PRB 100 PDSCH-PRBs 80 PDSCH-Offset),
+                                 (Test10: 217 PRB 100 PDSCH-PRBs 110 PDSCH-Offset),
                                  (Test11: 106 PRBs 50 PDSCH-PRBs MCS Index 28</desc>
       <pre_compile_prog></pre_compile_prog>
       <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog>
@@ -1105,7 +1105,7 @@
                   -n100 -R106 -a51
                   -n100 -R217 -b100
                   -n100 -R217 -a80
-                  -n100 -R217 -a80 -b100
+                  -n100 -R217 -a110 -b100
                   -n100 -e28</main_exec_args>
       <tags>nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7
       nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11</tags>
diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c
index e14f28f8297383bfd22573d2b75f47f3c3f88705..56c3c0951fd493758c171e81ac62920297af03f7 100644
--- a/common/config/config_userapi.c
+++ b/common/config/config_userapi.c
@@ -81,7 +81,7 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) {
   }
 
   if (*ptr == NULL) {
-    *ptr = malloc(length);
+    *ptr = malloc(length>40?length:40); // LTS: dummy fix, waiting Francois full fix in 4G branch
 
     if ( *ptr != NULL) {
       memset(*ptr,0,length);
diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c
index 6bad041641cf626440d049af9662104ee9f471b9..7f177b90cee51c7c516ebe436fac181ff02d210c 100644
--- a/common/utils/LOG/log.c
+++ b/common/utils/LOG/log.c
@@ -324,7 +324,9 @@ void  log_getconfig(log_t *g_log)
 
   config_get( logparams_debug,(sizeof(log_maskmap)/sizeof(mapping)) - 1,CONFIG_STRING_LOG_PREFIX);
   config_get( logparams_dump,(sizeof(log_maskmap)/sizeof(mapping)) - 1,CONFIG_STRING_LOG_PREFIX);
-  config_check_unknown_cmdlineopt(CONFIG_STRING_LOG_PREFIX);
+
+  if (config_check_unknown_cmdlineopt(CONFIG_STRING_LOG_PREFIX) > 0)
+    exit(1);
 
   /* set the debug mask according to the debug parameters values */
   for (int i=0; log_maskmap[i].name != NULL ; i++) {
diff --git a/common/utils/LOG/vcd_signal_dumper.c b/common/utils/LOG/vcd_signal_dumper.c
index 7ea15cf9dbe13897c7d0e245d9628fc37c330d18..63c5336bd88fc25751b623106a1417525f631588 100644
--- a/common/utils/LOG/vcd_signal_dumper.c
+++ b/common/utils/LOG/vcd_signal_dumper.c
@@ -247,7 +247,8 @@ const char* eurecomVariablesNames[] = {
   "slot_number_TX0_gNB",
   "slot_number_TX1_gNB",
   "slot_number_RX0_gNB",
-  "slot_number_RX1_gNB"
+  "slot_number_RX1_gNB",
+  "ru_tx_ofdm_mask"
 };
 
 const char* eurecomFunctionsNames[] = {
@@ -328,6 +329,13 @@ const char* eurecomFunctionsNames[] = {
   "phy_procedures_ru_feptx_ofdm7",
   "phy_procedures_ru_feptx_ofdm8",
   "phy_procedures_ru_feptx_ofdm9",
+  "phy_procedures_ru_feptx_ofdm10",
+  "phy_procedures_ru_feptx_ofdm11",
+  "phy_procedures_ru_feptx_ofdm12",
+  "phy_procedures_ru_feptx_ofdm13",
+  "phy_procedures_ru_feptx_ofdm14",
+  "phy_procedures_ru_feptx_ofdm15",
+  "phy_procedures_ru_feptx_ofdm16",
   "phy_procedures_ru_feptx_prec0",
   "phy_procedures_ru_feptx_prec1",
   "phy_procedures_ru_feptx_prec2",
@@ -502,6 +510,7 @@ const char* eurecomFunctionsNames[] = {
   "pdcch_interleaving",
   "pdcch_tx",
   /*NR softmodem signal*/
+  "wakeup_txfh",
   "gNB_thread_rxtx0",
   "gNB_thread_rxtx1"
 };
diff --git a/common/utils/LOG/vcd_signal_dumper.h b/common/utils/LOG/vcd_signal_dumper.h
index a7c4c10fe31a6dc88859dfc450683d07151f6761..3a6fb6d6abb9f932b700efa1acb747ef6fd5a1ad 100644
--- a/common/utils/LOG/vcd_signal_dumper.h
+++ b/common/utils/LOG/vcd_signal_dumper.h
@@ -225,6 +225,7 @@ typedef enum {
   VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,
   VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,
   VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX1_GNB,
+  VCD_SIGNAL_DUMPER_VARIABLES_RU_TX_OFDM_MASK,
 
 
   VCD_SIGNAL_DUMPER_VARIABLES_END
@@ -309,6 +310,13 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM7,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM8,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM9,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM10,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM11,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM12,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM13,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM14,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM15,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM16,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC1,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC2,
@@ -494,6 +502,7 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_TX,
 
   /*NR softmodem signal*/
+  VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH,
   VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0,
   VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1,
 
diff --git a/common/utils/T/T_defs.h b/common/utils/T/T_defs.h
index 4f2b10c3ae152d08a2eedebcd65e0d54cf28c467..ab275d4d62d9cd7f03474e0a0521881b963adecb 100644
--- a/common/utils/T/T_defs.h
+++ b/common/utils/T/T_defs.h
@@ -73,10 +73,10 @@ typedef struct {
 } T_cache_t;
 
 /* number of VCD functions (to be kept up to date! see in T_messages.txt) */
-#define VCD_NUM_FUNCTIONS (237)//(232)
+#define VCD_NUM_FUNCTIONS (245)
 
 /* number of VCD variables (to be kept up to date! see in T_messages.txt) */
-#define VCD_NUM_VARIABLES (185)
+#define VCD_NUM_VARIABLES (186)
 
 /* first VCD function (to be kept up to date! see in T_messages.txt) */
 #define VCD_FIRST_FUNCTION    ((uintptr_t)T_VCD_FUNCTION_RT_SLEEP)
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 0b10b6e25ece1fd6199919df2cd012df24804a20..407bb66be17416fccb5345f58198da518fdf4357 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -2050,6 +2050,11 @@ ID = VCD_VARIABLE_SLOT_NUMBER_RX1_GNB
     GROUP = ALL:VCD:ENB:VCD_VARIABLE
     FORMAT = ulong,value
     VCD_NAME = slot_number_RX1_gNB
+ID = VCD_VARIABLE_RU_TX_OFDM_MASK
+    DESC = VCD variable RU_TX_OFDM_MASK
+    GROUP = ALL:VCD:ENB:VCD_VARIABLE
+    FORMAT = ulong,value
+    VCD_NAME = ru_tx_ofdm_mask
 
 #functions
 
@@ -2418,6 +2423,41 @@ ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM9
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
     VCD_NAME = phy_procedures_ru_feptx_ofdm9
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM10
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM10
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm10
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM11
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM11
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm11
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM12
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM12
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm12
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM13
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM13
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm13
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM14
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM14
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm14
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM15
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM15
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm15
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM16
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM16
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm16
 ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_PREC
     DESC = VCD function PHY_PROCEDURES_RU_FEPTX_PREC
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
@@ -3230,6 +3270,11 @@ ID = VCD_FUNCTION_PDCCH_TX
     VCD_NAME = pdcch_tx
 
   #function for gNB
+ID = VCD_FUNCTION_WAKEUP_TXFH
+    DESC = VCD function WAKEUP_TXFH
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = wakeup_txfh
 ID = VCD_FUNCTION_gNB_PROC_RXTX0
     DESC = VCD function gNB_PROC_RXTX0
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
diff --git a/common/utils/hashtable/hashtable.c b/common/utils/hashtable/hashtable.c
index 50c2ec83245bd5dc5d7ce69e89103c5c96c1f2a1..e9641f8e0c06141eeeacd8442dbc518897b2e141 100644
--- a/common/utils/hashtable/hashtable.c
+++ b/common/utils/hashtable/hashtable.c
@@ -162,34 +162,6 @@ hashtable_rc_t hashtable_is_key_exists (const hash_table_t *const hashtblP, cons
   return HASH_TABLE_KEY_NOT_EXISTS;
 }
 //-------------------------------------------------------------------------------------------------------------------------------
-hashtable_rc_t hashtable_apply_funct_on_elements (hash_table_t *const hashtblP, void functP(hash_key_t keyP, void *dataP, void *parameterP), void *parameterP)
-//-------------------------------------------------------------------------------------------------------------------------------
-{
-  hash_node_t  *node         = NULL;
-  unsigned int  i            = 0;
-  unsigned int  num_elements = 0;
-
-  if (hashtblP == NULL) {
-    return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
-  }
-
-  while ((num_elements < hashtblP->num_elements) && (i < hashtblP->size)) {
-    if (hashtblP->nodes[i] != NULL) {
-      node=hashtblP->nodes[i];
-
-      while(node) {
-        num_elements += 1;
-        functP(node->key, node->data, parameterP);
-        node=node->next;
-      }
-    }
-
-    i += 1;
-  }
-
-  return HASH_TABLE_OK;
-}
-//-------------------------------------------------------------------------------------------------------------------------------
 hashtable_rc_t hashtable_dump_content (const hash_table_t *const hashtblP, char *const buffer_pP, int *const remaining_bytes_in_buffer_pP )
 //-------------------------------------------------------------------------------------------------------------------------------
 {
@@ -266,7 +238,6 @@ hashtable_rc_t hashtable_insert(hash_table_t *const hashtblP, const hash_key_t k
   }
 
   hashtblP->nodes[hash]=node;
-  hashtblP->num_elements += 1;
   return HASH_TABLE_OK;
 }
 //-------------------------------------------------------------------------------------------------------------------------------
@@ -295,7 +266,6 @@ hashtable_rc_t hashtable_remove(hash_table_t *const hashtblP, const hash_key_t k
       }
 
       free(node);
-      hashtblP->num_elements -= 1;
       return HASH_TABLE_OK;
     }
 
@@ -335,47 +305,3 @@ hashtable_rc_t hashtable_get(const hash_table_t *const hashtblP, const hash_key_
   *dataP = NULL;
   return HASH_TABLE_KEY_NOT_EXISTS;
 }
-//-------------------------------------------------------------------------------------------------------------------------------
-/*
- * Resizing
- * The number of elements in a hash table is not always known when creating the table.
- * If the number of elements grows too large, it will seriously reduce the performance of most hash table operations.
- * If the number of elements are reduced, the hash table will waste memory. That is why we provide a function for resizing the table.
- * Resizing a hash table is not as easy as a realloc(). All hash values must be recalculated and each element must be inserted into its new position.
- * We create a temporary hash_table_t object (newtbl) to be used while building the new hashes.
- * This allows us to reuse hashtable_insert() and hashtable_remove(), when moving the elements to the new table.
- * After that, we can just free the old table and copy the elements from newtbl to hashtbl.
- */
-
-hashtable_rc_t hashtable_resize(hash_table_t *const hashtblP, const hash_size_t sizeP) {
-  hash_table_t       newtbl;
-  hash_size_t        n;
-  hash_node_t       *node,*next;
-
-  if (hashtblP == NULL) {
-    return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
-  }
-
-  newtbl.size     = sizeP;
-  newtbl.hashfunc = hashtblP->hashfunc;
-  newtbl.num_elements = 0;
-
-  if(!(newtbl.nodes=calloc(sizeP, sizeof(hash_node_t *)))) return -1;
-
-  for(n=0; n<hashtblP->size; ++n) {
-    for(node=hashtblP->nodes[n]; node; node=next) {
-      next = node->next;
-      hashtable_insert(&newtbl, node->key, node->data);
-      // Lionel GAUTHIER: BAD CODE TO BE REWRITTEN
-      hashtable_remove(hashtblP, node->key);
-    }
-  }
-
-  free(hashtblP->nodes);
-  hashtblP->size=newtbl.size;
-  hashtblP->nodes=newtbl.nodes;
-  return HASH_TABLE_OK;
-}
-
-
-
diff --git a/common/utils/hashtable/hashtable.h b/common/utils/hashtable/hashtable.h
index 3f770684fae9996f8973b4268f106a6526dafd0b..09f8623ce23af44ac608ed1f9e95102f2653e093 100644
--- a/common/utils/hashtable/hashtable.h
+++ b/common/utils/hashtable/hashtable.h
@@ -49,7 +49,6 @@ typedef struct hash_node_s {
 
 typedef struct hash_table_s {
   hash_size_t         size;
-  hash_size_t         num_elements;
   struct hash_node_s **nodes;
   hash_size_t       (*hashfunc)(const hash_key_t);
   void              (*freefunc)(void *);
@@ -60,12 +59,10 @@ void            hash_free_int_func(void *memoryP);
 hash_table_t   *hashtable_create (const hash_size_t   size, hash_size_t (*hashfunc)(const hash_key_t ), void (*freefunc)(void *));
 hashtable_rc_t  hashtable_destroy(hash_table_t **hashtbl);
 hashtable_rc_t  hashtable_is_key_exists (const hash_table_t *const hashtbl, const uint64_t key);
-hashtable_rc_t  hashtable_apply_funct_on_elements (hash_table_t *const hashtblP, void funct(hash_key_t keyP, void *dataP, void *parameterP), void *parameterP);
 hashtable_rc_t  hashtable_dump_content (const hash_table_t *const hashtblP, char *const buffer_pP, int *const remaining_bytes_in_buffer_pP );
 hashtable_rc_t  hashtable_insert (hash_table_t *const hashtbl, const hash_key_t key, void *data);
 hashtable_rc_t  hashtable_remove (hash_table_t *const hashtbl, const hash_key_t key);
 hashtable_rc_t  hashtable_get    (const hash_table_t *const hashtbl, const hash_key_t key, void **dataP);
-hashtable_rc_t  hashtable_resize (hash_table_t *const hashtbl, const hash_size_t size);
 
 
 
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index b4bf5efe81e834ad77228041d9fe98b6281be239..cb1d45adc2d3667ab337f345195f0ce7a237e638 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -290,6 +290,8 @@ static void *gNB_L1_thread_tx(void *param) {
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,slot_tx);
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,frame_tx);
     phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 1 );
     pthread_mutex_lock( &L1_proc_tx->mutex );
     L1_proc_tx->instance_cnt = -1;
 
@@ -301,6 +303,7 @@ static void *gNB_L1_thread_tx(void *param) {
     pthread_mutex_unlock(&L1_proc_tx->mutex);
 
     wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 0 );
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
   }
 
@@ -420,10 +423,10 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
 
 // note this  should depend on the numerology used by the TX L1 thread, set here for 500us slot time
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1);
-  waitret=timedwait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh",1000000); 
+  waitret=wait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh"); 
+  AssertFatal(release_thread(&proc->mutex_RUs_tx,&proc->instance_cnt_RUs,"wakeup_txfh")==0, "error releaseing gNB lock on RUs\n"); 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0);
 
-  AssertFatal(release_thread(&proc->mutex_RUs_tx,&proc->instance_cnt_RUs,"wakeup_txfh")==0, "error releaseing gNB lock on RUs\n"); 
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
 
   if (waitret == ETIMEDOUT) {
@@ -448,7 +451,7 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
     ru      = gNB->RU_list[i];
     ru_proc = &ru->proc;
     
-    AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret);
+    //AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret);
 
     if (ru_proc->instance_cnt_gNBs == 0) {
       VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1);
@@ -456,7 +459,7 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
       AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
       gNB->proc.RU_mask_tx = 0;
       AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
-      AssertFatal((ret=pthread_mutex_unlock( &ru_proc->mutex_gNBs ))==0,"mutex_unlock return %d\n",ret);
+      //AssertFatal((ret=pthread_mutex_unlock( &ru_proc->mutex_gNBs ))==0,"mutex_unlock return %d\n",ret);
 
       VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0);
       return(-1);
@@ -522,6 +525,8 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
   RU_proc_t *ru_proc=&ru->proc;
   int ret;
   int i;
+  struct timespec abstime;
+  int time_ns = 50000;
   
   AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret);
   for (i=0;i<gNB->num_RU;i++) {
@@ -542,14 +547,22 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
     AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret);
   }
 
+  clock_gettime(CLOCK_REALTIME, &abstime);
+  abstime.tv_nsec = abstime.tv_nsec + time_ns;
+
+  if (abstime.tv_nsec >= 1000*1000*1000) {
+    abstime.tv_nsec -= 1000*1000*1000;
+    abstime.tv_sec  += 1;
+  }
 
   // wake up TX for subframe n+sl_ahead
   // lock the TX mutex and make sure the thread is ready
-  AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex)) == 0,"mutex_lock returns %d\n", ret);
+  AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
 
   if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
    AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
    LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); 
+   return(-1);
   }
  
   ++L1_proc->instance_cnt;
diff --git a/executables/nr-ru.c b/executables/nr-ru.c
index 1abcd3b7a159669598ce48ec4f165f2fd3fe1dbf..b402110c4bb4cd08f0f33e7a4999cfdaf30fb9f9 100644
--- a/executables/nr-ru.c
+++ b/executables/nr-ru.c
@@ -91,7 +91,8 @@ unsigned short config_frames[4] = {2,9,11,13};
 /* these variables have to be defined before including ENB_APP/enb_paramdef.h and GNB_APP/gnb_paramdef.h */
 static int DEFBANDS[] = {7};
 static int DEFENBS[] = {0};
-
+static int DEFBFW[] = {0x00007fff};
+ 
 //static int DEFNRBANDS[] = {7};
 //static int DEFGNBS[] = {0};
 
@@ -677,9 +678,6 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
   proc->frame_rx     = (proc->timestamp_rx / (fp->samples_per_slot*fp->slots_per_frame))&1023;
   proc->tti_rx       = (proc->timestamp_rx / fp->samples_per_slot)%fp->slots_per_frame;
   // synchronize first reception to frame 0 subframe 0
-  proc->timestamp_tx = proc->timestamp_rx+(sl_ahead*fp->samples_per_slot);
-  proc->tti_tx  = (proc->tti_rx+sl_ahead)%fp->slots_per_frame;
-  proc->frame_tx     = (proc->tti_rx>(fp->slots_per_frame-1-sl_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
   LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n",
         ru->idx,
         0,
@@ -764,18 +762,22 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame );
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot );
 
-    for (i=0; i<ru->nb_tx; i++)
+    for (i=0; i<ru->nb_tx; i++){
       txp[i] = (void *)&ru->common.txdata[i][(slot*fp->samples_per_slot)-sf_extension];
+    }
+
 
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
     // prepare tx buffer pointers
+    start_meas(&ru->tx_fhaul);
     txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
                                       timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
                                       txp,
                                       siglen+sf_extension,
                                       ru->nb_tx,
                                       flags);
+    stop_meas(&ru->tx_fhaul);
     LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
           (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot);
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
@@ -784,6 +786,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
 }
 
 
+
 /*!
  * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU.
  * This handles the RX FH for an asynchronous RRU/UE
@@ -872,7 +875,7 @@ static void *ru_thread_prach( void *param ) {
                 0,0
           );
     }
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 ); */
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ 
     if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
   }
 
@@ -1209,14 +1212,20 @@ static void *ru_stats_thread(void *param) {
     sleep(1);
 
     if (opp_enabled == 1) {
+
       if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL);
 
-      if (ru->feptx_ofdm) print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
+      if (ru->feptx_ofdm){
+        print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL);
+        print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL);
+        print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
+        print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL);
+      }
 
       if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);
 
-      if (ru->fh_north_out) {
         print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
+      if (ru->fh_north_out) {
         print_meas(&ru->compression,"compression",NULL,NULL);
         print_meas(&ru->transport,"transport",NULL,NULL);
       }
@@ -1273,7 +1282,7 @@ static void *ru_thread_tx( void *param ) {
     // do TX front-end processing if needed (precoding and/or IDFTs)
     if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx);
 
-    // do OFDM if needed
+    // do OFDM with/without TX front-end processing  if needed
     if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx);
 
     if(!emulate_rf) {
@@ -1284,8 +1293,17 @@ static void *ru_thread_tx( void *param ) {
     } else {
       if(proc->frame_tx == print_frame) {
         for (i=0; i<ru->nb_tx; i++) {
-          sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
-          LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
+
+          if(proc->tti_tx == 0) {
+            sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_tx);
+            LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
+
+            sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
+            LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
+
+            sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
+            LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
+          }
 
           if(proc->tti_tx == 9) {
             sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
@@ -1338,14 +1356,14 @@ static void *ru_thread_tx( void *param ) {
         ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx);
         AssertFatal(ret == 0,"mutex_lock returns %d\n",ret);
         // the thread can now be woken up
-        if (L1_proc->instance_cnt_RUs==-1) {
-           AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
+        //if (L1_proc->instance_cnt_RUs == -1) {
+          L1_proc->instance_cnt_RUs = 0;
+          AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
                        "ERROR pthread_cond_signal for gNB_L1_thread\n");
-        } //else AssertFatal(1==0,"gNB TX thread is not ready\n");
-        L1_proc->instance_cnt_RUs = 0;
-        VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
+        //} //else AssertFatal(1==0,"gNB TX thread is not ready\n");
         ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx);
         AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
+        VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
       }
     }
   }
@@ -1507,7 +1525,7 @@ static void *ru_thread( void *param ) {
       // do TX front-end processing if needed (precoding and/or IDFTs)
       if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx);
 
-      // do OFDM if needed
+      // do OFDM with/without TX front-end processing  if needed
       if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx);
 
       if(!emulate_rf) {
@@ -1646,6 +1664,7 @@ int stop_rf(RU_t *ru) {
   return 0;
 }
 
+
 void init_RU_proc(RU_t *ru) {
   int i=0;
   RU_proc_t *proc;
@@ -1668,6 +1687,7 @@ void init_RU_proc(RU_t *ru) {
   proc->frame_offset             = 0;
   proc->num_slaves               = 0;
   proc->frame_tx_unwrap          = 0;
+  proc->feptx_mask               = 0;
 
   for (i=0; i<10; i++) proc->symbol_mask[i]=0;
 
@@ -2025,9 +2045,9 @@ void set_function_spec_param(RU_t *ru) {
         malloc_IF4p5_buffer(ru);
       } else if (ru->function == gNodeB_3GPP) {
         ru->do_prach             = 0;                       // no prach processing in RU
-        ru->feprx                = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full;     // RX DFTs
-        ru->feptx_ofdm           = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft and precoding
-        ru->feptx_prec           = NULL;              // this is fep with idft and precoding
+        ru->feprx                = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread   : nr_fep_full;                // RX DFTs
+        ru->feptx_ofdm           = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm;              // this is fep with idft and precoding
+        ru->feptx_prec           = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL                  : nr_feptx_prec;           // this is fep with idft and precoding
         ru->fh_north_in          = NULL;                    // no incoming fronthaul from north
         ru->fh_north_out         = NULL;                    // no outgoing fronthaul to north
         ru->nr_start_if          = NULL;                    // no if interface
@@ -2055,8 +2075,8 @@ void set_function_spec_param(RU_t *ru) {
 
     case REMOTE_IF5: // the remote unit is IF5 RRU
       ru->do_prach               = 0;
-      ru->feprx                  = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full;     // this is frequency-shift + DFTs
-      ru->feptx_prec             = feptx_prec;          // need to do transmit Precoding + IDFTs
+      ru->feprx                  = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread   : nr_fep_full;     // this is frequency-shift + DFTs
+      ru->feptx_prec             = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL                  : nr_feptx_prec;          // need to do transmit Precoding + IDFTs
       ru->feptx_ofdm             = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // need to do transmit Precoding + IDFTs
       ru->fh_south_in            = fh_if5_south_in;     // synchronous IF5 reception
       ru->fh_south_out           = fh_if5_south_out;    // synchronous IF5 transmission
@@ -2080,7 +2100,7 @@ void set_function_spec_param(RU_t *ru) {
     case REMOTE_IF4p5:
       ru->do_prach               = 0;
       ru->feprx                  = NULL;                // DFTs
-      ru->feptx_prec             = feptx_prec;          // Precoding operation
+      ru->feptx_prec             = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec;          // Precoding operation
       ru->feptx_ofdm             = NULL;                // no OFDM mod
       ru->fh_south_in            = fh_if4p5_south_in;   // synchronous IF4p5 reception
       ru->fh_south_out           = fh_if4p5_south_out;  // synchronous IF4p5 transmission
@@ -2334,6 +2354,14 @@ void RCconfig_RU(void)
       RC.ru[j]->nb_rx                             = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr);
       RC.ru[j]->att_tx                            = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr);
       RC.ru[j]->att_rx                            = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr);
+
+      if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) {
+        RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt;
+        for (i=0; i<RC.ru[j]->num_gNB; i++)  {
+          RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t));
+          for (int b=0; b<RC.ru[j]->nb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b];
+        }
+      }
     }// j=0..num_rus
   } else {
     RC.nb_RU = 0;
diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c
index 931e2c1cd4ca05329c61decaaf3080c88242e529..0a638f72655a2a6634b6d073e3c5ad61bd7fbe08 100644
--- a/executables/nr-softmodem.c
+++ b/executables/nr-softmodem.c
@@ -924,6 +924,10 @@ init_opt();
 #  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
 #endif
   LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
+
+  if(IS_SOFTMODEM_NOS1)
+	  init_pdcp();
+
 #if defined(ENABLE_ITTI)
 
   if (RC.nb_nr_inst > 0)  {
@@ -942,9 +946,6 @@ init_opt();
     flexran_agent_start(i);
   }
 
-  if(IS_SOFTMODEM_NOS1)
-	  init_pdcp();
-
   // init UE_PF_PO and mutex lock
   pthread_mutex_init(&ue_pf_po_mutex, NULL);
   memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index fcbd659bbea7832b5b8f75c5394058fb5530a5f3..24288d76d38fe476325e77a886ea0d9b8a261ff2 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -419,7 +419,7 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
 	  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO,
                                    0x1234, proc->frame_rx,
                                    proc->nr_tti_rx, 0);
-	  //pdcp_run(&ctxt);
+	  pdcp_run(&ctxt);
           pdcp_fifo_flush_sdus(&ctxt);
   }
   }
diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c
index d8a916d13fba1c7fd61d2dc36ba0acefe8679aae..7e2ffebb35bde1b4324174f2dcc64d3c547374cf 100644
--- a/executables/nr-uesoftmodem.c
+++ b/executables/nr-uesoftmodem.c
@@ -664,7 +664,7 @@ int main( int argc, char **argv ) {
   logInit();
   // get options and fill parameters from configuration file
   get_options (); //Command-line options, enb_properties
-  //get_common_options();
+  get_common_options();
 #if T_TRACER
   T_Config_Init();
 #endif
diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c
index 206fcf3b6f3a65e2eab8d7748e3bcd9ec51d1a1b..e8828d805c9c5d5b96b7498b81deb1f15d3c4c60 100644
--- a/openair1/PHY/INIT/nr_init_ru.c
+++ b/openair1/PHY/INIT/nr_init_ru.c
@@ -74,6 +74,10 @@ int nr_phy_init_RU(RU_t *ru) {
     }
   
 
+    // allocate precoding input buffers (TX)
+    ru->common.txdataF = (int32_t **)malloc16(15*sizeof(int32_t*));
+    for(i=0; i< 15; ++i)  ru->common.txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t)); // [hna] samples_per_frame without CP
+
     // allocate IFFT input buffers (TX)
     ru->common.txdataF_BF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*));
     LOG_I(PHY,"[INIT] common.txdata_BF= %p (%lu bytes)\n",ru->common.txdataF_BF,
@@ -105,37 +109,33 @@ int nr_phy_init_RU(RU_t *ru) {
 		RC.nb_nr_L1_inst,NUMBER_OF_gNB_MAX);
 
     LOG_E(PHY,"[INIT] %s() RC.nb_nr_L1_inst:%d \n", __FUNCTION__, RC.nb_nr_L1_inst);
-
-    for (i=0; i<RC.nb_nr_L1_inst; i++) {
-      for (p=0;p<15;p++) {
-	if (p == 0|| p==5) {
-	  ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*));
-	  for (j=0; j<ru->nb_tx; j++) {
-	    ru->beam_weights[i][p][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 (((p<4) && (p==j)) || ((p==4) && (j==0))) {
-	      for (re=0; re<fp->ofdm_symbol_size; re++) 
-              {
-		ru->beam_weights[i][p][j][re] = 0x00007fff; 
-
-                //LOG_D(PHY,"[INIT] lte_common_vars->beam_weights[%d][%d][%d][%d] = %d\n", i,p,j,re,ru->beam_weights[i][p][j][re]);
-              }
-	    }
-	    else if (p>4) {
-	      for (re=0; re<fp->ofdm_symbol_size; re++) 
-              {
-		ru->beam_weights[i][p][j][re] = 0x00007fff/ru->nb_tx; 
-                //LOG_D(PHY,"[INIT] lte_common_vars->beam_weights[%d][%d][%d][%d] = %d\n", i,p,j,re,ru->beam_weights[i][p][j][re]);
-              }
-	    }  
-	    //LOG_D(PHY,"[INIT] lte_common_vars->beam_weights[%d][%d] = %p (%lu bytes)\n", i,j,ru->beam_weights[i][p][j], fp->ofdm_symbol_size*sizeof(int32_t)); 
-	  } // for (j=0
-	} // if (p<ru
-      } // for p
-    } //for i
+    
+    int beam_count = 0;
+    if (ru->nb_tx>1) {
+      for (p=0;p<fp->Lmax;p++) {
+        if ((fp->L_ssb >> p) & 0x01)
+          beam_count++;
+      }
+      AssertFatal(ru->nb_bfw==(beam_count*ru->nb_tx),"Number of beam weights from config file is %d while the expected number is %d",ru->nb_bfw,(beam_count*ru->nb_tx));
+    
+      int l_ind = 0;
+      for (i=0; i<RC.nb_nr_L1_inst; i++) {
+        for (p=0;p<fp->Lmax;p++) {
+          if ((fp->L_ssb >> p) & 0x01)  {
+	    ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*));
+	    for (j=0; j<ru->nb_tx; j++) {
+	      ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t));
+              for (re=0; re<fp->ofdm_symbol_size; re++) 
+		ru->beam_weights[i][p][j][re] = ru->bw_list[i][l_ind];
+              //printf("Beam Weight %08x for beam %d and tx %d\n",ru->bw_list[i][l_ind],p,j);
+              l_ind++; 
+  	    } // for j
+	  } // for p
+        }
+      } //for i
+    }
   } // !=IF5
+
   ru->common.sync_corr = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_subframe_wCP );
 
   return(0);
@@ -162,6 +162,10 @@ void nr_phy_free_RU(RU_t *ru)
     for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdata_7_5kHz[i]);
     free_and_zero(ru->common.rxdata_7_5kHz);
 
+    // free beamforming input buffers (TX)
+    for (i = 0; i < 15; i++) free_and_zero(ru->common.txdataF[i]);
+    free_and_zero(ru->common.txdataF);
+
     // free IFFT input buffers (TX)
     for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdataF_BF[i]);
     free_and_zero(ru->common.txdataF_BF);
@@ -179,10 +183,8 @@ void nr_phy_free_RU(RU_t *ru)
 
     for (i = 0; i < RC.nb_nr_L1_inst; i++) {
       for (p = 0; p < 15; p++) {
-	if (p == 0 || p == 5) {
 	  for (j=0; j<ru->nb_tx; j++) free_and_zero(ru->beam_weights[i][p][j]);
 	  free_and_zero(ru->beam_weights[i][p]);
-	}
       }
     }
   }
diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c
index 6a13ac88a3eef98adc2514082d38d9d9da941bc9..a5475a1555535a7291978f66c1411566a8cebb34 100644
--- a/openair1/PHY/INIT/nr_parms.c
+++ b/openair1/PHY/INIT/nr_parms.c
@@ -93,7 +93,7 @@ int nr_is_ssb_slot(nfapi_nr_config_request_t *cfg, int slot, int frame)
   p = cfg->sch_config.ssb_periodicity.value;
   n_hf = cfg->sch_config.half_frame_index.value;
 
-  // checking if the ssb is transmitted in given frame according to periodicity
+  // if SSB periodicity is 5ms, they are transmitted in both half frames
   if ( (p>10) && (frame%(p/10)) )  
     return 0;
   else {
@@ -101,15 +101,15 @@ int nr_is_ssb_slot(nfapi_nr_config_request_t *cfg, int slot, int frame)
     // if SSB periodicity is 5ms, they are transmitted in both half frames
     if ( p == 5) {
       if (slot<hf_slots) 
-        n_hf=0;
-      else
-        n_hf=1;
-    }
+      n_hf=0;
+    else
+      n_hf=1;
+  }
 
-    // to set a effective slot number between 0 to hf_slots-1 in the half frame where the SSB is supposed to be
+  // to set a effective slot number between 0 to 9 in the half frame where the SSB is supposed to be
     rel_slot = (n_hf)? (slot-hf_slots) : slot;
 
-    // there are two potential SSB per slot
+
     return ( ((ssb_map >> rel_slot*2) & 0x01) || ((ssb_map >> (1+rel_slot*2)) & 0x01) ); 
   }
 }
@@ -273,15 +273,18 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp,
   fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2;
 
   // definition of Lmax according to ts 38.213 section 4.1
-  if (fp->dl_CarrierFreq < 6e9){
-	if(fp->frame_type && (fp->ssb_type==2))
-		fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8;
-	else
-		fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8;
-  }  
-  else
+  if (fp->dl_CarrierFreq < 6e9) {
+    if(fp->frame_type && (fp->ssb_type==2))
+      fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8;
+    else
+      fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8;
+  } else {
     fp->Lmax = 64;
+  }
 
+  fp->N_ssb = 0;
+  for (int p=0; p<fp->Lmax; p++)
+    fp->N_ssb += ((fp->L_ssb >> p) & 0x01);
 
   return 0;
 }
diff --git a/openair1/PHY/MODULATION/beamforming.c b/openair1/PHY/MODULATION/beamforming.c
index ab3271c61c87eed1046b6e2e2725f68d92e2605f..79e220ac37d2ecb8a7ef8873b4355e87c54da666 100644
--- a/openair1/PHY/MODULATION/beamforming.c
+++ b/openair1/PHY/MODULATION/beamforming.c
@@ -50,6 +50,7 @@
 #include "PHY/CODING/lte_interleaver_inline.h"
 #include "PHY/LTE_TRANSPORT/transport_eNB.h"
 #include "modulation_eNB.h"
+#include "nr_modulation.h"
 #include "common/utils/LOG/vcd_signal_dumper.h"
 
 int beam_precoding(int32_t **txdataF,
@@ -135,3 +136,33 @@ int beam_precoding_one_eNB(int32_t **txdataF,
   }
   return 0;
 }
+
+
+int nr_beam_precoding(int32_t **txdataF,
+	              int32_t **txdataF_BF,
+                      NR_DL_FRAME_PARMS *frame_parms,
+	              int32_t ***beam_weights,
+                      int slot,
+                      int symbol,
+                      int aa,
+                      int nb_antenna_ports)
+{
+
+
+  uint8_t p;
+
+  // clear txdata_BF[aa][re] for each call of ue_spec_beamforming
+  memset(&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size],0,sizeof(int32_t)*(frame_parms->ofdm_symbol_size));
+
+  for (p=0; p<nb_antenna_ports; p++) {
+    if ((frame_parms->L_ssb >> p) & 0x01)  {
+      multadd_cpx_vector((int16_t*)&txdataF[p][symbol*frame_parms->ofdm_symbol_size],
+			 (int16_t*)beam_weights[p][aa], 
+			 (int16_t*)&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size], 
+			 0, 
+			 frame_parms->ofdm_symbol_size, 
+			 15);
+    }
+  }
+  return 0;
+}
diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h
index 8a6abd5de5a93d5ee650528552c446d89294a201..706b4dc113bbb23b9a7390c820614ee72034cf6c 100644
--- a/openair1/PHY/MODULATION/nr_modulation.h
+++ b/openair1/PHY/MODULATION/nr_modulation.h
@@ -93,4 +93,14 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms,
 */
 void nr_dft(int32_t *z,int32_t *d, uint32_t Msc_PUSCH);
 
+int nr_beam_precoding(int32_t **txdataF,
+	              int32_t **txdataF_BF,
+                      NR_DL_FRAME_PARMS *frame_parms,
+	              int32_t ***beam_weights,
+                      int slot,
+                      int symbol,
+                      int aa,
+                      int nb_antenna_ports
+);
+
 #endif
diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c
index b23fd2e2bfb8c9e53c12f43dba024e8756497e61..cbeeca13278f6147c0ce2657f95da5faef7e490d 100644
--- a/openair1/PHY/MODULATION/ofdm_mod.c
+++ b/openair1/PHY/MODULATION/ofdm_mod.c
@@ -86,6 +86,8 @@ void PHY_ofdm_mod(int *input,                       /// pointer to complex input
                  )
 {
 
+  if(nb_symbols == 0) return;
+
   short temp[4096*4] __attribute__((aligned(32)));
   unsigned short i,j;
   short k;
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
index 89321f637ba857beee15a541b44b2a27f4c0c9f2..16fc94a59fe3380db2a3d5c55492b97137091410 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
@@ -45,7 +45,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
   int16_t *fl,*fm,*fr,*fml,*fmr,*fmm,*fdcl,*fdcr,*fdclh,*fdcrh;
   int ch_offset,symbol_offset, length_dmrs, UE_id = 0;
   unsigned short n_idDMRS[2] = {0,1}; //to update from pusch config
-  int32_t temp_in_ifft_0[8192*2] __attribute__((aligned(16)));
+  int32_t temp_in_ifft_0[8192*2] __attribute__((aligned(32)));
   int32_t **ul_ch_estimates_time =  gNB->pusch_vars[UE_id]->ul_ch_estimates_time;
 
 #ifdef DEBUG_CH
@@ -267,7 +267,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
 
 
     // check if PRB crosses DC and improve estimates around DC
-    if ((bwp_start_subcarrier >= gNB->frame_parms.ofdm_symbol_size/2) && (bwp_start_subcarrier+nb_rb_pusch*12 >= gNB->frame_parms.ofdm_symbol_size)) {
+    if ((bwp_start_subcarrier < gNB->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pusch*12 >= gNB->frame_parms.ofdm_symbol_size)) {
       ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset];
       uint16_t idxDC = 2*(gNB->frame_parms.ofdm_symbol_size - bwp_start_subcarrier);
       uint16_t idxPil = idxDC/2;
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
index 665e9a690cfad491357cc4483347ca785275d8d9..7502d5d4a49d1a38439c75ae07447fec9cd93e9d 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
@@ -90,6 +90,7 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch,
   uint8_t Qm = rel15->modulation_order;
   uint32_t encoded_length = nb_symbols*Qm;
 
+
   /// CRC, coding, interleaving and rate matching
   AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n");
   start_meas(dlsch_encoding_stats);
@@ -206,7 +207,6 @@ for (int i=0; i<n_dmrs>>4; i++) {
  printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_symbols %d)\n",
 	start_sc, rel15->start_symbol, rel15->n_prb, rel15->nb_symbols);
 #endif
-
   for (int ap=0; ap<rel15->nb_layers; ap++) {
 
     // DMRS params for this ap
@@ -221,6 +221,7 @@ ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol);
 #endif
     uint8_t k_prime=0;
     uint16_t m=0, n=0, dmrs_idx=0, k=0;
+    int txdataF_offset = (slot%2)*frame_parms->samples_per_slot_wCP;
     if (dmrs_type == NFAPI_NR_DMRS_TYPE1) // another if condition to be included to check pdsch config type (reference of k)
       dmrs_idx = rel15->start_prb*6;
     else
@@ -230,12 +231,12 @@ ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol);
       k = start_sc;
       for (int i=0; i<rel15->n_prb*NR_NB_SC_PER_RB; i++) {
         if ((l == dmrs_symbol) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_type))%(frame_parms->ofdm_symbol_size)))) {
-          ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15;
-          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
+          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15;
+          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
 #ifdef DEBUG_DLSCH_MAPPING
 printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n",
-dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1],
-((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1]);
+dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
+((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
 #endif
           dmrs_idx++;
           k_prime++;
@@ -245,12 +246,12 @@ dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_
 
         else {
 
-          ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * tx_layers[ap][m<<1]) >> 15;
-          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15;
+          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15;
+          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15;
 #ifdef DEBUG_DLSCH_MAPPING
 printf("m %d\t l %d \t k %d \t txdataF: %d %d\n",
-m, l, k, ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1],
-((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1]);
+m, l, k, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
+((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
 #endif
           m++;
         }
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
index 4942ffe2f467eb2d22079b012ff8f9cd504bf858..dc7489ea512c9d3b988dc707961032d9eda60314 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
@@ -79,4 +79,4 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB,
                          int slot_rx,
                          int UE_id,
                          uint8_t harq_pid);
-
+int16_t find_nr_ulsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
index 6e991faf37246a3a72bd4501fe5513b4086faf25..db0c601b2535317f7c82d43e2ee13369e5ef0439 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
@@ -48,7 +48,7 @@
 #include "common/utils/LOG/log.h"
 #include <syscall.h>
 //#define DEBUG_ULSCH_DECODING
-#define gNB_DEBUG_TRACE
+//#define gNB_DEBUG_TRACE
 
 #define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
 //#define PRINT_CRC_CHECK
@@ -311,7 +311,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
 
   int16_t  z [68*384];
   int8_t   l [68*384];
-  uint8_t  kc;
+  uint8_t  kc=255;
   uint8_t  Ilbrm        = 0;
   uint32_t Tbslbrm     = 950984;
   double   Coderate    = 0.0;
@@ -568,6 +568,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
         pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
       }
 
+      AssertFatal(kc!=255,"");
       for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++) {
         pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
       }
diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
index 752d06fb21c766152a35a86110f0557a44bb61de..aaa304ec6373c1c194e41ddbc5a2fc735be928b4 100644
--- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
+++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
@@ -205,10 +205,10 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
   unsigned int pilot_cnt;
   int16_t ch[2],*pil,*rxF,*dl_ch,*fl,*fm,*fr;
   int ch_offset,symbol_offset;
-  int slot_pbch;
-  fapi_nr_pbch_config_t *pbch_config = &ue->nrUE_config.pbch_config;
+  //int slot_pbch;
+  //fapi_nr_pbch_config_t *pbch_config = &ue->nrUE_config.pbch_config;
   // initialized to 5ms in nr_init_ue for scenarios where UE is not configured (otherwise acquired by cell configuration from gNB or LTE)
-  uint8_t ssb_periodicity = 10;// ue->ssb_periodicity;
+  //uint8_t ssb_periodicity = 10;// ue->ssb_periodicity;
 
   //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1];
 
@@ -874,7 +874,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
     //}
     
     // check if PRB crosses DC and improve estimates around DC
-    if ((bwp_start_subcarrier >= ue->frame_parms.ofdm_symbol_size/2) && (bwp_start_subcarrier+nb_rb_pdsch*12 >= ue->frame_parms.ofdm_symbol_size)) {
+    if ((bwp_start_subcarrier < ue->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pdsch*12 >= ue->frame_parms.ofdm_symbol_size)) {
       dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset];
       uint16_t idxDC = 2*(ue->frame_parms.ofdm_symbol_size - bwp_start_subcarrier);
       uint16_t idxPil = idxDC/2;
diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
index de88858c2da60ea4cf2365fe30d2651b5ddb2b63..3c6784be7e8f142a322bb7914406b434cd1a734a 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
@@ -50,6 +50,15 @@
 //#define NR_LTE_PDCCH_DCI_SWITCH
 #define NR_PDCCH_DCI_RUN              // activates new nr functions
 //#define NR_PDCCH_DCI_DEBUG            // activates NR_PDCCH_DCI_DEBUG logs
+#ifdef NR_PDCCH_DCI_DEBUG
+#define LOG_DNL(a, ...) printf("\n\t\t<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ )
+#define LOG_DD(a, ...) printf("\t<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ )
+#define LOG_DDD(a, ...) printf("\t\t<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ )
+#else
+#define LOG_DNL(a...)
+#define LOG_DD(a...)
+#define LOG_DDD(a...)
+#endif
 #define NR_NBR_CORESET_ACT_BWP 3      // The number of CoreSets per BWP is limited to 3 (including initial CORESET: ControlResourceId 0)
 #define NR_NBR_SEARCHSPACE_ACT_BWP 10 // The number of SearSpaces per BWP is limited to 10 (including initial SEARCHSPACE: SearchSpaceId 0)
 #define PDCCH_TEST_POLAR_TEMP_FIX
@@ -134,9 +143,7 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
 
       if (coreset_interleaved==0) f_bundle_j=bundle_j;
 
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\n\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping_deinterleaving)-> [r=%d,c=%d] bundle_j(%d) interleaved at f_bundle_j(%d)\n",r,c,bundle_j,f_bundle_j);
-#endif
+      LOG_DNL("[r=%d,c=%d] bundle_j(%d) interleaved at f_bundle_j(%d)\n",r,c,bundle_j,f_bundle_j);
     }
 
     f_reg = (f_bundle_j*reg_bundle_size_L)+(reg%reg_bundle_size_L);
@@ -145,11 +152,9 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
 
     for (int i=0; i<9; i++) {
       z[index_z + i] = llr[index_llr + i];
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping_deinterleaving)-> [reg=%d,bundle_j=%d] z[%d]=(%d,%d) <-> \t[f_reg=%d,fbundle_j=%d] llr[%d]=(%d,%d) \n",
+      LOG_DDD("[reg=%d,bundle_j=%d] z[%d]=(%d,%d) <-> \t[f_reg=%d,fbundle_j=%d] llr[%d]=(%d,%d) \n",
              reg,bundle_j,(index_z + i),*(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i]),
              f_reg,f_bundle_j,(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i]));
-#endif
     }
 
     if ((reg%reg_bundle_size_L) == 0) r++;
@@ -167,13 +172,11 @@ int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp,
   pdcch_llrp = &pdcch_llr[2 * symbol * coreset_nbr_rb * 9];
 
   if (!pdcch_llrp) {
-    printf("pdcch_qpsk_llr: llr is null, symbol %d\n", symbol);
+    LOG_E(PHY,"pdcch_qpsk_llr: llr is null, symbol %d\n", symbol);
     return (-1);
   }
 
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_llr)-> llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llrp-pdcch_llr);
-#endif
+  LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llrp-pdcch_llr);
 
   //for (i = 0; i < (frame_parms->N_RB_DL * ((symbol == 0) ? 16 : 24)); i++) {
   for (i = 0; i < (coreset_nbr_rb * ((symbol == 0) ? 18 : 18)); i++) {
@@ -184,9 +187,7 @@ int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp,
     else
       *pdcch_llrp = (*rxF);
 
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_llr)-> llr logs: rb=%d i=%d *rxF:%d => *pdcch_llrp:%d\n",i/18,i,*rxF,*pdcch_llrp);
-#endif
+    LOG_DDD("llr logs: rb=%d i=%d *rxF:%d => *pdcch_llrp:%d\n",i/18,i,*rxF,*pdcch_llrp);
     rxF++;
     pdcch_llrp++;
   }
@@ -207,7 +208,7 @@ int32_t pdcch_llr(NR_DL_FRAME_PARMS *frame_parms,
   pdcch_llr8 = &pdcch_llr[2*symbol*frame_parms->N_RB_DL*12];
 
   if (!pdcch_llr8) {
-    printf("pdcch_qpsk_llr: llr is null, symbol %d\n",symbol);
+    LOG_E(PHY,"pdcch_qpsk_llr: llr is null, symbol %d\n",symbol);
     return(-1);
   }
 
@@ -330,43 +331,33 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF,
   //uint8_t rb_count_bit;
   uint8_t i, j, aarx, bitcnt_coreset_freq_dom=0;
   int32_t *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext;
-#ifdef NR_PDCCH_DCI_DEBUG
-  int nushiftmod3 = frame_parms->nushift % 3;
-#endif
 
-#if defined(DEBUG_DCI_DECODING) || defined(NR_PDCCH_DCI_DEBUG)
-  uint8_t symbol_mod = (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol;
-#endif
   c_rb = n_BWP_start; // c_rb is the common resource block: RB within the BWP
 #ifdef DEBUG_DCI_DECODING
+  uint8_t symbol_mod = (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol;
   LOG_I(PHY, "extract_rbs_single: symbol_mod %d\n",symbol_mod);
 #endif
 
   for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
     if (high_speed_flag == 1) {
       dl_ch0 = &dl_ch_estimates[aarx][(symbol * (frame_parms->ofdm_symbol_size))];
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0 = &dl_ch_estimates[aarx = (%d)][ (symbol * (frame_parms->ofdm_symbol_size (%d))) = (%d)]\n",
+      LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][ (symbol * (frame_parms->ofdm_symbol_size (%d))) = (%d)]\n",
              aarx,frame_parms->ofdm_symbol_size,(symbol * (frame_parms->ofdm_symbol_size)));
-#endif
     } else {
       dl_ch0 = &dl_ch_estimates[aarx][0];
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n",aarx);
-#endif
+      LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n",aarx);
     }
 
     dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)];
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n",
+    LOG_DDD("dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n",
            aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS));
-#endif
     rxF_ext = &rxdataF_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)];
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n",
+    LOG_DDD("rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n",
            aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS));
-    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> (for symbol=%d, aarx=%d), symbol_mod=%d, nushiftmod3=%d \n",symbol,aarx,symbol_mod,nushiftmod3);
-#endif
+    LOG_DDD("(for symbol=%d, aarx=%d), symbol_mod=%d, nushiftmod3=%d \n",
+    symbol,aarx,
+    (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol,
+    frame_parms->nushift % 3);
     /*
      * The following for loop handles treatment of PDCCH contained in table rxdataF (in frequency domain)
      * In NR the PDCCH IQ symbols are contained within RBs in the CORESET defined by higher layers which is located within the BWP
@@ -384,9 +375,7 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF,
      * then the IQ symbol is going to be found at the position 0+c_rb-N_RB_DL/2 in rxdataF and
      * we have to point the pointer at (1+c_rb-N_RB_DL/2) in rxdataF
      */
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> n_BWP_start=%d, coreset_nbr_rb=%d\n",n_BWP_start,coreset_nbr_rb);
-#endif
+    LOG_DDD("n_BWP_start=%d, coreset_nbr_rb=%d\n",n_BWP_start,coreset_nbr_rb);
 
     for (c_rb = n_BWP_start; c_rb < (n_BWP_start + coreset_nbr_rb + (BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN * offset_discontiguous)); c_rb++) {
       //c_rb_tmp = 0;
@@ -399,40 +388,32 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF,
           //c_rb_tmp = c_rb_tmp + 6;
           c_rb = c_rb + BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN;
           offset_discontiguous ++;
-#ifdef NR_PDCCH_DCI_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> we entered here as coreset_freq_dom=%lx (bit %d) is 0, coreset_freq_domain is discontiguous\n",coreset_freq_dom,
+          LOG_DDD("we entered here as coreset_freq_dom=%lx (bit %d) is 0, coreset_freq_domain is discontiguous\n",coreset_freq_dom,
                  (46 - bitcnt_coreset_freq_dom));
-#endif
         }
       }
 
       //c_rb = c_rb + c_rb_tmp;
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> c_rb=%d\n",c_rb);
-#endif
+      LOG_DDD("c_rb=%d\n",c_rb);
       rxF=NULL;
 
       // first we set initial conditions for pointer to rxdataF depending on the situation of the first RB within the CORESET (c_rb = n_BWP_start)
       if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) {
         //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): even case
         rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))];
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is lower than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
+        LOG_DDD("in even case c_rb (%d) is lower than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
                c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))));
-#endif
       }
 
       if ((c_rb >= (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) {
         // number of RBs is even  and c_rb is higher than half system bandwidth (we don't skip DC)
         // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF
         rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
+        LOG_DDD("in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
                c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))));
-#endif
         //rxF = &rxdataF[aarx][(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol
         //#ifdef NR_PDCCH_DCI_DEBUG
-        //  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
+        //  LOG_DDD("in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
         //         c_rb,aarx,(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))));
         //#endif
       }
@@ -440,30 +421,24 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF,
       if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) {
         //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): odd case
         rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))];
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is lower or equal than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
+        LOG_DDD("in odd case c_rb (%d) is lower or equal than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
                c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))));
-#endif
       }
 
       if ((c_rb > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) {
         // number of RBs is odd  and   c_rb is higher than half system bandwidth + 1
         // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF just after the first IQ symbols of the RB containing DC
         rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - frame_parms->N_RB_DL) - 5 + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
+        LOG_DDD("in odd case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - frame_parms->N_RB_DL) - 5 + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
                c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size))));
-#endif
       }
 
       if ((c_rb == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // treatment of RB containing the DC
         // if odd number RBs in system bandwidth and first RB to be treated is higher than middle system bandwidth (around DC)
         // we have to treat the RB in two parts: first part from i=0 to 5, the data is at the end of rxdataF (pointing at the end of the table)
         rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))];
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL + 1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
+        LOG_DDD("in odd case c_rb (%d) is half N_RB_DL + 1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n",
                c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))));
-#endif
         /*if (symbol_mod > 300) { // this if is going to be removed as DM-RS signals are present in all symbols of PDCCH
           for (i = 0; i < 6; i++) {
         dl_ch0_ext[i] = dl_ch0[i];
@@ -471,7 +446,7 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF,
           }
           rxF = &rxdataF[aarx][(symbol * (frame_parms->ofdm_symbol_size))]; // we point at the 1st part of the rxdataF in symbol
           #ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n",
+        LOG_DDD("in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n",
         c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size)));
           #endif
           for (; i < 12; i++) {
@@ -497,10 +472,8 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF,
 
         // then we point at the begining of the symbol part of rxdataF do process second part of RB
         rxF = &rxdataF[aarx][((symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n",
+        LOG_DDD("in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n",
                c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size)));
-#endif
 
         for (; i < 12; i++) {
           if ((i != 9)) {
@@ -535,21 +508,17 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF,
         for (i = 0; i < 12; i++) {
           if ((i != 1) && (i != 5) && (i != 9)) {
             rxF_ext[j] = rxF[i];
-#ifdef NR_PDCCH_DCI_DEBUG
-            printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d)\n",
+            LOG_DDD("RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d)\n",
                    c_rb, i, j, *(short *) &rxF_ext[j],*(1 + (short *) &rxF_ext[j]), i,
                    *(short *) &rxF[i], *(1 + (short *) &rxF[i]));
-#endif
             dl_ch0_ext[j] = dl_ch0[i];
-            //printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> ch %d => dl_ch0(%d,%d)\n", i, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i]));
+            //LOG_DDD("ch %d => dl_ch0(%d,%d)\n", i, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i]));
             //printf("\t-> dl_ch0[%d] => dl_ch0_ext[%d](%d,%d)\n", i,j, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i]));
             j++;
           } else {
-#ifdef NR_PDCCH_DCI_DEBUG
-            printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d) \t\t <==> DM-RS PDCCH, this is a pilot symbol\n",
+            LOG_DDD("RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d) \t\t <==> DM-RS PDCCH, this is a pilot symbol\n",
                    c_rb, i, j, *(short *) &rxF_ext[j], *(1 + (short *) &rxF_ext[j]), i,
                    *(short *) &rxF[i], *(1 + (short *) &rxF[i]));
-#endif
           }
         }
 
@@ -658,15 +627,13 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext,
       //print_shorts("rx:",rxdataF128+2);
       //print_shorts("ch:",dl_ch128+2);
       //print_shorts("pack:",rxdataF_comp128+2);
-#ifdef NR_PDCCH_DCI_DEBUG
 
       for (int i=0; i<12 ; i++)
-        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF128[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n",
+        LOG_DDD("rxdataF128[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n",
                (rb*12)+i, ((short *)rxdataF128)[i<<1],((short *)rxdataF128)[1+(i<<1)],
                (rb*12)+i, ((short *)dl_ch128)[i<<1],((short *)dl_ch128)[1+(i<<1)],
                (rb*12)+i, ((short *)rxdataF_comp128)[i<<1],((short *)rxdataF_comp128)[1+(i<<1)]);
 
-#endif
       dl_ch128+=3;
       rxdataF128+=3;
       rxdataF_comp128+=3;
@@ -795,11 +762,9 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
     }
   }
 
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> symbol_mon=(%d) and start_symbol=(%d)\n",symbol_mon,start_symbol);
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) scrambling_ID=(%d) \n",
+  LOG_DD("symbol_mon=(%d) and start_symbol=(%d)\n",symbol_mon,start_symbol);
+  LOG_DD("coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) scrambling_ID=(%d) \n",
          coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R,pdcch_DMRS_scrambling_id);
-#endif
   //
   // according to 38.213 v15.1.0: a PDCCH monitoring pattern within a slot,
   // indicating first symbol(s) of the control resource set within a slot
@@ -815,9 +780,7 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
   // for (int j=0; j < coreset_nbr_act; j++) {
   // for each active CORESET (max number of active CORESETs in a BWP is 3),
   // we calculate the number of RB for each CORESET bitmap
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld)\n",coreset_freq_dom);
-#endif
+  LOG_DD("coreset_freq_dom=(%ld)\n",coreset_freq_dom);
   int i; //for each bit in the coreset_freq_dom bitmap
 
   for (i = 0; i < 45; i++) {
@@ -826,22 +789,18 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
   }
 
   coreset_nbr_rb = 6 * coreset_nbr_rb; // coreset_nbr_rb has to be multiplied by 6 to indicate the number of PRB or REG(=12 RE) within the CORESET
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld,%lx), coreset_nbr_rb=%d\n", coreset_freq_dom,coreset_freq_dom,coreset_nbr_rb);
-#endif
-#ifdef NR_PDCCH_DCI_DEBUG
-  uint8_t  coreset_nbr_reg = coreset_time_dur * coreset_nbr_rb;
-  uint32_t coreset_C = (uint32_t)(coreset_nbr_reg / (reg_bundle_size_L * coreset_interleaver_size_R));
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_nbr_rb=%d, coreset_nbr_reg=%d, coreset_C=(%d/(%d*%d))=%d\n",
-         coreset_nbr_rb, coreset_nbr_reg, coreset_nbr_reg, reg_bundle_size_L,coreset_interleaver_size_R, coreset_C);
-#endif
+  LOG_DD("coreset_freq_dom=(%ld,%lx), coreset_nbr_rb=%d\n", coreset_freq_dom,coreset_freq_dom,coreset_nbr_rb);
+  LOG_DD("coreset_nbr_rb=%d, coreset_nbr_reg=%d, coreset_C=(%d/(%d*%d))=%d\n",
+         coreset_nbr_rb, 
+	 coreset_time_dur * coreset_nbr_rb,
+	 coreset_time_dur * coreset_nbr_rb,
+	 reg_bundle_size_L,coreset_interleaver_size_R,
+	(uint32_t)((coreset_time_dur * coreset_nbr_rb) / (reg_bundle_size_L * coreset_interleaver_size_R)) );
 
   for (int s = start_symbol; s < (start_symbol + coreset_time_dur); s++) {
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_extract_rbs_single(is_secondary_ue=%d) to remove DM-RS PDCCH\n",
+    LOG_DD("we enter nr_pdcch_extract_rbs_single(is_secondary_ue=%d) to remove DM-RS PDCCH\n",
            is_secondary_ue);
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n");
-#endif
+    LOG_DD("in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n");
     nr_pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF,
                                 pdcch_vars[eNB_id]->dl_ch_estimates,
                                 pdcch_vars[eNB_id]->rxdataF_ext,
@@ -852,10 +811,8 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
                                 coreset_freq_dom,
                                 coreset_nbr_rb,
                                 n_rb_offset);
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",avgP);
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n");
-#endif
+    LOG_DD("we enter pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",*avgP);
+    LOG_DD("in pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n");
     // compute channel level based on ofdm symbol 0
     pdcch_channel_level(pdcch_vars[eNB_id]->dl_ch_estimates_ext,
                         frame_parms,
@@ -874,10 +831,8 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
     T(T_UE_PHY_PDCCH_ENERGY, T_INT(eNB_id), T_INT(0), T_INT(frame%1024), T_INT(nr_tti_rx),
       T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3]));
 #endif
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh);
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n");
-#endif
+    LOG_DD("we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh);
+    LOG_DD("in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n");
     // compute LLRs for ofdm symbol 0 only
     nr_pdcch_channel_compensation(pdcch_vars[eNB_id]->rxdataF_ext,
                                   pdcch_vars[eNB_id]->dl_ch_estimates_ext,
@@ -895,17 +850,13 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
 #endif
 
     if (frame_parms->nb_antennas_rx > 1) {
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n",
+      LOG_DD("we enter pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n",
              frame_parms->nb_antennas_rx);
-#endif
       pdcch_detection_mrc(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,s);
     }
 
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s);
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in nr_pdcch_llr(rxdataF_comp -> llr)\n");
-#endif
+    LOG_DD("we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s);
+    LOG_DD("in nr_pdcch_llr(rxdataF_comp -> llr)\n");
     nr_pdcch_llr(frame_parms,
                  pdcch_vars[eNB_id]->rxdataF_comp,
                  pdcch_vars[eNB_id]->llr,
@@ -923,9 +874,7 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
 #endif
   }
 
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_demapping_deinterleaving()\n");
-#endif
+  LOG_DD("we enter nr_pdcch_demapping_deinterleaving()\n");
   nr_pdcch_demapping_deinterleaving((uint32_t *) pdcch_vars[eNB_id]->llr,
                                     (uint32_t *) pdcch_vars[eNB_id]->e_rx,
                                     frame_parms,
@@ -942,12 +891,8 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
                         // get_nCCE(n_pdcch_symbols, frame_parms, mi) * 72,
                         pdcch_DMRS_scrambling_id,
                         do_common);
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we end nr_pdcch_unscrambling()\n");
-#endif
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> Ending nr_rx_pdcch() function\n");
-#endif
+  LOG_DD("we end nr_pdcch_unscrambling()\n");
+  LOG_DD("Ending nr_rx_pdcch() function\n");
   return (0);
 }
 #endif
@@ -1006,22 +951,20 @@ void nr_pdcch_unscrambling(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8
   //uint32_t calc_x2=puissance_2_16%puissance_2_31;
   x2 = (((1<<16)*n_rnti)+n_id); //mod 2^31 is implicit //this is c_init in 38.211 v15.1.0 Section 7.3.2.3
   //  x2 = (nr_tti_rx << 9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2
-#ifdef NR_PDCCH_DCI_DEBUG
-  //printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)->  (c_init=%d, n_id=%d, n_rnti=%d, length=%d)\n",x2,n_id,n_rnti,length);
-#endif
+  //LOG_DDD(" (c_init=%d, n_id=%d, n_rnti=%d, length=%d)\n",x2,n_id,n_rnti,length);
 
   for (i = 0; i < length; i++) {
     if ((i & 0x1f) == 0) {
       s = lte_gold_generic(&x1, &x2, reset);
-      //printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> lte_gold[%d]=%x\n",i,s);
+      //LOG_DDD("lte_gold[%d]=%x\n",i,s);
       reset = 0;
     }
 
     /*
     #ifdef NR_PDCCH_DCI_DEBUG
-    if (i%2 == 0) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)->  unscrambling %d : scrambled_z=%d, => ",
+    if (i%2 == 0) LOG_DDD(" unscrambling %d : scrambled_z=%d, => ",
        i,*(char*) &z[(int)floor(i/2)]);
-    if (i%2 == 1) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)->  unscrambling %d : scrambled_z=%d, => ",
+    if (i%2 == 1) LOG_DDD(" unscrambling %d : scrambled_z=%d, => ",
        i,*(1 + (char*) &z[(int)floor(i/2)]));
     #endif
     if (((s >> (i % 32)) & 1) == 1){
@@ -1035,16 +978,12 @@ void nr_pdcch_unscrambling(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8
     if (i%2 == 1) printf("unscrambled_z=%d\n",*(1 + (char*) &z[(int)floor(i/2)]));
     #endif
     */
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)->  unscrambling %d : scrambled_z=%d, => ",
+    LOG_DDD(" unscrambling %d : scrambled_z=%d, => ",
            i,z[i]);
-#endif
 
     if (((s >> (i % 32)) & 1) == 1) z[i] = -z[i];
 
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("unscrambled_z=%d\n",z[i]);
-#endif
+    LOG_DDD("unscrambled_z=%d\n",z[i]);
   }
 }
 
@@ -1090,19 +1029,15 @@ void nr_dci_decoding_procedure0(int s,
   //Table 10.1-3: Maximum number of non-overlapped CCEs per slot and per serving cell as a function of the subcarrier spacing value 2^mu*15 KHz, mu {0,1,2,3}
   //uint8_t cce_max_slot_pdcch_Table10_1_3 [4] = {56,56,48,32};
   int coreset_nbr_cce_per_symbol=0;
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> format_found is %d \n", *format_found);
-#endif
+  LOG_DDD("format_found is %d \n", *format_found);
   //if (mode == NO_DCI) {
   //  #ifdef NR_PDCCH_DCI_DEBUG
-  //    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> skip DCI decoding: expect no DCIs at nr_tti_rx %d in current searchSpace\n", nr_tti_rx);
+  //    LOG_DDD("skip DCI decoding: expect no DCIs at nr_tti_rx %d in current searchSpace\n", nr_tti_rx);
   //  #endif
   //  return;
   //}
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> frequencyDomainResources=%lx, duration=%d\n",
+  LOG_DDD("frequencyDomainResources=%lx, duration=%d\n",
          pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources, pdcch_vars[eNB_id]->coreset[p].duration);
-#endif
 
   // nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols, frame_parms, mi);
   for (int i = 0; i < 45; i++) {
@@ -1116,9 +1051,7 @@ void nr_dci_decoding_procedure0(int s,
   //   the number of symbols in the CORESET (pdcch_vars[eNB_id]->coreset[p].duration)
   //   multiplied by the number of bits set to '1' in the frequencyDomainResources bitmap
   //   (1 bit set to '1' corresponds to 6 RB and 1 CCE = 6 RB)
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> nCCE[%d]=%d\n",p,nCCE[p]);
-#endif
+  LOG_DDD("nCCE[%d]=%d\n",p,nCCE[p]);
 
   /*  if (nCCE > get_nCCE(3, frame_parms, 1)) {
   LOG_D(PHY,
@@ -1172,9 +1105,7 @@ void nr_dci_decoding_procedure0(int s,
       nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.srs_nrofCandidates;
     } else {
       nb_candidates = (L2 == 4) ? 4 : ((L2 == 8)? 2 : 1); // according to Table 10.1-1 (38.213 section 10.1)
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> we are in common searchSpace and nb_candidates=%u for L2=%d\n", nb_candidates, L2);
-#endif
+      LOG_DDD("we are in common searchSpace and nb_candidates=%u for L2=%d\n", nb_candidates, L2);
     }
   } else {
     switch (L2) {
@@ -1211,9 +1142,7 @@ void nr_dci_decoding_procedure0(int s,
       Yk = (Yk * A[p%3]) % 65537;
   }
 
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> L2(%d) | nCCE[%d](%d) | Yk(%u) | nb_candidates(%u)\n", L2, p, nCCE[p], Yk, nb_candidates);
-#endif
+  LOG_DDD("L2(%d) | nCCE[%d](%d) | Yk(%u) | nb_candidates(%u)\n", L2, p, nCCE[p], Yk, nb_candidates);
   /*  for (CCEind=0;
       CCEind<nCCE2;
       CCEind+=(1<<L)) {*/
@@ -1224,27 +1153,19 @@ void nr_dci_decoding_procedure0(int s,
 
   if (L==4) m_p_s_L_max=1; // Table 10.1-2 is not defined for L=4
 
-#ifdef NR_PDCCH_DCI_DEBUG
-  if(0 <= L && L < 4) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> m_max_slot_pdcch_Table10_1_2(%d)=%d\n",L,m_max_slot_pdcch_Table10_1_2[L]);
-#endif
+  if(0 <= L && L < 4) LOG_DDD("m_max_slot_pdcch_Table10_1_2(%d)=%d\n",L,m_max_slot_pdcch_Table10_1_2[L]);
 
   for (m = 0; m < nb_candidates; m++) {
     int n_ci = 0;
 
     if (nCCE[p] < L2) return;
 
-#ifdef NR_PDCCH_DCI_DEBUG
-  int debug1 = nCCE[p] / L2;
-  int debug2 = L2*m_p_s_L_max;
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> debug1(%d)=nCCE[p]/L2 | nCCE[%d](%d) | L2(%d)\n",debug1,p,nCCE[p],L2);
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> debug2(%d)=L2*m_p_s_L_max | L2(%d) | m_p_s_L_max(%d)\n",debug2,L2,m_p_s_L_max);
-#endif
+  LOG_DDD("debug1(%d)=nCCE[p]/L2 | nCCE[%d](%d) | L2(%d)\n",nCCE[p] / L2,p,nCCE[p],L2);
+  LOG_DDD("debug2(%d)=L2*m_p_s_L_max | L2(%d) | m_p_s_L_max(%d)\n",L2*m_p_s_L_max,L2,m_p_s_L_max);
   CCEind = (((Yk + (uint16_t)(floor((m*nCCE[p])/(L2*m_p_s_L_max))) + n_ci) % (uint16_t)(floor(nCCE[p] / L2))) * L2);
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> CCEind(%d) = (((Yk(%u) + ((m(%u)*nCCE[p](%d))/(L2(%d)*m_p_s_L_max(%d)))) %% (nCCE[p] / L2)) * L2)\n",
+  LOG_DDD("CCEind(%d) = (((Yk(%u) + ((m(%u)*nCCE[p](%d))/(L2(%d)*m_p_s_L_max(%d)))) %% (nCCE[p] / L2)) * L2)\n",
             CCEind,Yk,m,nCCE[p],L2,m_p_s_L_max);
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> n_candidate(m)=%u | CCEind=%d |",m,CCEind);
-#endif
+  LOG_DDD("n_candidate(m)=%u | CCEind=%d |",m,CCEind);
 
     if (CCEind < 32)
       CCEmap = CCEmap0;
@@ -1283,9 +1204,7 @@ void nr_dci_decoding_procedure0(int s,
 
     CCEmap_cand = (*CCEmap) & CCEmap_mask;
     // CCE is not allocated yet
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> CCEmap_cand=%u \n",CCEmap_cand);
-#endif
+    LOG_DDD("CCEmap_cand=%u \n",CCEmap_cand);
 
     if (CCEmap_cand == 0) {
 #ifdef DEBUG_DCI_DECODING
@@ -1298,15 +1217,11 @@ void nr_dci_decoding_procedure0(int s,
               pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_uss);
 
 #endif
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we enter function dci_decoding(sizeof_bits=%d L=%d) -----\n",sizeof_bits,L);
-      printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we have to replace this part of the code by polar decoding\n");
-#endif
+      LOG_DDD("... we enter function dci_decoding(sizeof_bits=%d L=%d) -----\n",sizeof_bits,L);
+      LOG_DDD("... we have to replace this part of the code by polar decoding\n");
       //      for (int m=0; m < (nCCE[p]*6*9*2); m++)
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0: polar decoding)-> polar intput (with coreset_time_dur=%d, coreset_nbr_rb=%d, p=%d, CCEind=%d): \n",
+      LOG_DDD("(polar decoding)-> polar intput (with coreset_time_dur=%d, coreset_nbr_rb=%d, p=%d, CCEind=%d): \n",
              coreset_time_dur,coreset_nbr_rb,p,CCEind);
-#endif
       /*
       int reg_p=0,reg_e=0;
       for (int m=0; m < (L2*6); m++){
@@ -1331,7 +1246,7 @@ void nr_dci_decoding_procedure0(int s,
       //polar_hex[j] = (polar_hex[j]<<1) + ((polar_input[i]==-1)? 1:0);
       polar_hex[j] = polar_hex[j] + (((polar_input[i]==((-1)/sqrt(2)))?1:0)<<(i%32));
       }
-      for (j=0;j<27;j++) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0: polar decoding input)-> polar_hex[%d]=%x\n",j,polar_hex[j]);
+      for (j=0;j<27;j++) LOG_DDD("polar_hex[%d]=%x\n",j,polar_hex[j]);
       #endif
       */
       uint64_t dci_estimation[2]= {0};
@@ -1342,17 +1257,13 @@ void nr_dci_decoding_procedure0(int s,
                                          currentPtrDCI);
       crc = decoderState;
       //crc = (crc16(&dci_decoded_output[current_thread_id][0], sizeof_bits) >> 16) ^ extract_crc(&dci_decoded_output[current_thread_id][0], sizeof_bits);
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we end function dci_decoding() with crc=%x\n",crc);
-      printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we have to replace this part of the code by polar decoding\n");
-#endif
+      LOG_DDD("... we end function dci_decoding() with crc=%x\n",crc);
+      LOG_DDD("... we have to replace this part of the code by polar decoding\n");
 #ifdef DEBUG_DCI_DECODING
-      printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0: crc =>%d\n",crc);
+      LOG_DDD("(nr_dci_decoding_procedure0: crc =>%d\n",crc);
 #endif //uint16_t tc_rnti, uint16_t int_rnti, uint16_t sfi_rnti, uint16_t tpc_pusch_rnti, uint16_t tpc_pucch_rnti, uint16_t tpc_srs__rnti
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> format_found=%d\n",*format_found);
-      printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> crc_scrambled=%d\n",*crc_scrambled);
-#endif
+      LOG_DDD("format_found=%d\n",*format_found);
+      LOG_DDD("crc_scrambled=%d\n",*crc_scrambled);
 
       if (crc == crc_scrambled_values[_C_RNTI_])  {
         *crc_scrambled =_c_rnti;
@@ -1420,10 +1331,8 @@ void nr_dci_decoding_procedure0(int s,
       }
 
 
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> format_found=%d\n",*format_found);
-      printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> crc_scrambled=%d\n",*crc_scrambled);
-#endif
+      LOG_DDD("format_found=%d\n",*format_found);
+      LOG_DDD("crc_scrambled=%d\n",*crc_scrambled);
 
       if (*format_found!=255) {
         dci_alloc[*dci_cnt].dci_length = sizeof_bits;
@@ -1432,31 +1341,29 @@ void nr_dci_decoding_procedure0(int s,
         dci_alloc[*dci_cnt].firstCCE = CCEind;
         memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_estimation,8);
 
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> rnti matches -> DCI FOUND !!! crc =>0x%x, sizeof_bits %d, sizeof_bytes %d \n",
+        LOG_DDD("rnti matches -> DCI FOUND !!! crc =>0x%x, sizeof_bits %d, sizeof_bytes %d \n",
                 dci_alloc[*dci_cnt].rnti, dci_alloc[*dci_cnt].dci_length, sizeof_bytes);
-        printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> dci_cnt %d (format_css %d crc_scrambled %d) L %d, firstCCE %d pdu[0] 0x%lx pdu[1] 0x%lx \n",
+        LOG_DDD("dci_cnt %d (format_css %d crc_scrambled %d) L %d, firstCCE %d pdu[0] 0x%lx pdu[1] 0x%lx \n",
                 *dci_cnt, format_css,*crc_scrambled,dci_alloc[*dci_cnt].L, dci_alloc[*dci_cnt].firstCCE,dci_alloc[*dci_cnt].dci_pdu[0],dci_alloc[*dci_cnt].dci_pdu[1]);
-#endif
         if ((format_css == cformat0_0_and_1_0) || (format_uss == uformat0_0_and_1_0)) {
           if ((*crc_scrambled == _p_rnti) || (*crc_scrambled == _si_rnti) || (*crc_scrambled == _ra_rnti)) {
             dci_alloc[*dci_cnt].format = format1_0;
             *dci_cnt = *dci_cnt + 1;
             *format_found=_format_1_0_found;
-            //      printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> a format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt);
+            //      LOG_DDD("a format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt);
           } else {
             if ((dci_estimation[0]&1) == 0) {
               dci_alloc[*dci_cnt].format = format0_0;
               *dci_cnt = *dci_cnt + 1;
               *format_found=_format_0_0_found;
-              //        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> b format0_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt);
+              //        LOG_DDD("b format0_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt);
             }
 
             if ((dci_estimation[0]&1) == 1) {
               dci_alloc[*dci_cnt].format = format1_0;
               *dci_cnt = *dci_cnt + 1;
               *format_found=_format_1_0_found;
-              //        printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> c format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt);
+              //        LOG_DDD("c format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt);
             }
           }
         }
@@ -1584,9 +1491,7 @@ void nr_dci_decoding_procedure0(int s,
     */
   } // candidate loop
 
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> end candidate loop\n");
-#endif
+  LOG_DDD("end candidate loop\n");
 }
 
 #endif
@@ -1628,7 +1533,7 @@ void nr_dci_decoding_procedure0(int s,
   unsigned int Yk,nb_candidates = 0,i,m;
   unsigned int CCEmap_cand;
   #ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (dci_decoding_procedure0)-> \n");
+  LOG_DDD("\n");
   #endif
   nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols,frame_parms,mi);
 
@@ -2053,9 +1958,7 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue,
                              uint16_t n_RB_DLBWP,
                              uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS],
                              uint8_t format) {
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size)-> crc_scrambled=%d, n_RB_ULBWP=%d, n_RB_DLBWP=%d\n",crc_scrambled,n_RB_ULBWP,n_RB_DLBWP);
-#endif
+  LOG_DDD("crc_scrambled=%d, n_RB_ULBWP=%d, n_RB_DLBWP=%d\n",crc_scrambled,n_RB_ULBWP,n_RB_DLBWP);
   /*
    * function nr_dci_format_size calculates and returns the size in bits of a determined format
    * it also returns an bi-dimensional array 'dci_fields_sizes' with x rows and y columns, where:
@@ -2524,7 +2427,7 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue,
 
   for (int i=0 ; i<NBR_NR_FORMATS ; i++) {
     //#ifdef NR_PDCCH_DCI_DEBUG
-    //  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size)-> i=%d, j=%d\n", i, j);
+    //  LOG_DDD("i=%d, j=%d\n", i, j);
     //#endif
     for (int j=0; j<NBR_NR_DCI_FIELDS; j++) {
       dci_size [i] = dci_size [i] + dci_field_size_table[j][i]; // dci_size[i] contains the size in bits of the dci pdu format i
@@ -2533,15 +2436,13 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue,
       //}
     }
 
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_size[%d]=%d for n_RB_ULBWP=%d\n",
+    LOG_DDD("(nr_dci_format_size) dci_size[%d]=%d for n_RB_ULBWP=%d\n",
            i,dci_size[i],n_RB_ULBWP);
-#endif
   }
 
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_fields_sizes[][] = { \n");
+  LOG_DDD("(nr_dci_format_size) dci_fields_sizes[][] = { \n");
 
+#ifdef NR_PDCCH_DCI_DEBUG
   for (int j=0; j<NBR_NR_DCI_FIELDS; j++) {
     printf("\t\t");
 
@@ -2552,9 +2453,7 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue,
 
   printf(" }\n");
 #endif
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\n\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_size[0_0]=%d, dci_size[0_1]=%d, dci_size[1_0]=%d, dci_size[1_1]=%d,\n",dci_size[0],dci_size[1],dci_size[2],dci_size[3]);
-#endif
+  LOG_DNL("(nr_dci_format_size) dci_size[0_0]=%d, dci_size[0_1]=%d, dci_size[1_0]=%d, dci_size[1_1]=%d,\n",dci_size[0],dci_size[1],dci_size[2],dci_size[3]);
 
   //UL/SUL indicator format0_0 (TS 38.212 subclause 7.3.1.1.1)
   // - 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding is larger than the number of bits for DCI format 0_0 before padding;
@@ -2574,9 +2473,7 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue,
     //if (format == format0_0) {
     dci_fields_sizes[PADDING_NR_DCI][0] = dci_size[2] - dci_size[0];
     dci_size[0] = dci_size[2];
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]);
-#endif
+    LOG_DDD("(nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]);
     //}
   }
 
@@ -2588,9 +2485,7 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue,
     //if (format == format0_0) {
     dci_fields_sizes[FREQ_DOM_RESOURCE_ASSIGNMENT_UL][0] -= (dci_size[0] - dci_size[2]);
     dci_size[0] = dci_size[2];
-#ifdef NR_PDCCH_DCI_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]);
-#endif
+    LOG_DDD("(nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]);
     //}
   }
 
@@ -2606,9 +2501,9 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue,
    *
    */
   //  }
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_fields_sizes[][] = { \n");
+  LOG_DDD("(nr_dci_format_size) dci_fields_sizes[][] = { \n");
 
+#ifdef NR_PDCCH_DCI_DEBUG
   for (int j=0; j<NBR_NR_DCI_FIELDS; j++) {
     printf("\t\t");
 
@@ -2640,10 +2535,8 @@ uint8_t nr_dci_decoding_procedure(int s,
                                   format_found_t *format_found,
                                   uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES]) {
   //                                  uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS],
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure) nr_tti_rx=%d n_RB_ULBWP=%d n_RB_DLBWP=%d format_found=%d\n",
+  LOG_DD("(nr_dci_decoding_procedure) nr_tti_rx=%d n_RB_ULBWP=%d n_RB_DLBWP=%d format_found=%d\n",
          nr_tti_rx,n_RB_ULBWP,n_RB_DLBWP,*format_found);
-#endif
   int do_common = (int)searchSpacetype;
   uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS];
   crc_scrambled_t crc_scrambled_ = *crc_scrambled;
@@ -2701,16 +2594,9 @@ uint8_t nr_dci_decoding_procedure(int s,
    * This can be implemented by setting variable 'mode = NO_DCI' when overlap occurs
    */
   //dci_detect_mode_t mode = 3; //dci_detect_mode_select(&ue->frame_parms, nr_tti_rx);
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> searSpaceType=%d\n",do_common);
-
-  if (do_common==0) {
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> css_dci_format=%d\n",css_dci_format);
-  } else {
-    printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> uss_dci_format=%d\n",uss_dci_format);
-  }
+  LOG_DD("searSpaceType=%d\n",do_common);
+  LOG_DD("%s_dci_format=%d\n",do_common?"uss":"css",css_dci_format);
 
-#endif
 
   // A set of PDCCH candidates for a UE to monitor is defined in terms of PDCCH search spaces
   if (do_common==0) { // COMMON SearchSpaceType assigned to current SearchSpace/CORESET
@@ -2739,18 +2625,14 @@ uint8_t nr_dci_decoding_procedure(int s,
       // for format0_0 and format1_0, first we calculate dci pdu size
       format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_c_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,0);
       format_0_0_1_0_size_bytes = (format_0_0_1_0_size_bits%8 == 0) ? (uint8_t)floor(format_0_0_1_0_size_bits/8) : (uint8_t)(floor(format_0_0_1_0_size_bits/8) + 1);
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format_0_0_1_0_size_bits=%d, format_0_0_1_0_size_bytes=%d\n",
+      LOG_DD("calculating dci format size for common searchSpaces with format css_dci_format=%d, format_0_0_1_0_size_bits=%d, format_0_0_1_0_size_bytes=%d\n",
              css_dci_format,format_0_0_1_0_size_bits,format_0_0_1_0_size_bytes);
-#endif
 
       for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8
         //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) {
         // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
+        LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
                css_dci_format,(1<<aggregationLevel));
-#endif
         old_dci_cnt = dci_cnt;
         nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms,
                                    crc_scrambled_values, aggregationLevel,
@@ -2778,16 +2660,12 @@ uint8_t nr_dci_decoding_procedure(int s,
       // for format2_0, first we calculate dci pdu size
       format_2_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_sfi_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,4);
       format_2_0_size_bytes = (format_2_0_size_bits%8 == 0) ? (uint8_t)floor(format_2_0_size_bits/8) : (uint8_t)(floor(format_2_0_size_bits/8) + 1);
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_0_size_bits=%d, format2_0_size_bytes=%d\n",
+      LOG_DD("calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_0_size_bits=%d, format2_0_size_bytes=%d\n",
              css_dci_format,format_2_0_size_bits,format_2_0_size_bytes);
-#endif
 
       for (int aggregationLevelSFI = 0; aggregationLevelSFI<5 ; aggregationLevelSFI++) {
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
+        LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
                css_dci_format,(1<<aggregationLevelSFI));
-#endif
         // for aggregation level 'aggregationLevelSFI'. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0
         old_dci_cnt = dci_cnt;
         nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms,
@@ -2812,16 +2690,12 @@ uint8_t nr_dci_decoding_procedure(int s,
       // for format2_1, first we calculate dci pdu size
       format_2_1_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_int_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,5);
       format_2_1_size_bytes = (format_2_1_size_bits%8 == 0) ? (uint8_t)floor(format_2_1_size_bits/8) : (uint8_t)(floor(format_2_1_size_bits/8) + 1);
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_1_size_bits=%d, format2_1_size_bytes=%d\n",
+      LOG_DD("calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_1_size_bits=%d, format2_1_size_bytes=%d\n",
              css_dci_format,format_2_1_size_bits,format_2_1_size_bytes);
-#endif
 
       for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) {
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
+        LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
                css_dci_format,(1<<aggregationLevel));
-#endif
         // for aggregation level 'aggregationLevelSFI'. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0
         old_dci_cnt = dci_cnt;
         nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms,
@@ -2846,16 +2720,12 @@ uint8_t nr_dci_decoding_procedure(int s,
       // for format2_2, first we calculate dci pdu size
       format_2_2_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_tpc_pucch_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,6);
       format_2_2_size_bytes = (format_2_2_size_bits%8 == 0) ? (uint8_t)floor(format_2_2_size_bits/8) : (uint8_t)(floor(format_2_2_size_bits/8) + 1);
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_2_size_bits=%d, format2_2_size_bytes=%d\n",
+      LOG_DD("calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_2_size_bits=%d, format2_2_size_bytes=%d\n",
              css_dci_format,format_2_2_size_bits,format_2_2_size_bytes);
-#endif
 
       for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) {
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
+        LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
                css_dci_format,(1<<aggregationLevel));
-#endif
         // for aggregation level 'aggregationLevelSFI'. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0
         old_dci_cnt = dci_cnt;
         nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms,
@@ -2880,16 +2750,12 @@ uint8_t nr_dci_decoding_procedure(int s,
       // for format2_1, first we calculate dci pdu size
       format_2_3_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_tpc_srs_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,7);
       format_2_3_size_bytes = (format_2_3_size_bits%8 == 0) ? (uint8_t)floor(format_2_3_size_bits/8) : (uint8_t)(floor(format_2_3_size_bits/8) + 1);
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_3_size_bits=%d, format2_3_size_bytes=%d\n",
+      LOG_DD("calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_3_size_bits=%d, format2_3_size_bytes=%d\n",
              css_dci_format,format_2_3_size_bits,format_2_3_size_bytes);
-#endif
 
       for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) {
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
+        LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
                css_dci_format,(1<<aggregationLevel));
-#endif
         // for aggregation level 'aggregationLevelSFI'. The number of candidates (nrofCandidates-SFI) will be calculated in function nr_dci_decoding_procedure0
         old_dci_cnt = dci_cnt;
         nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 1, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms,
@@ -2915,18 +2781,14 @@ uint8_t nr_dci_decoding_procedure(int s,
       // for format0_0 and format1_0, first we calculate dci pdu size
       format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_c_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,0);
       format_0_0_1_0_size_bytes = (format_0_0_1_0_size_bits%8 == 0) ? (uint8_t)floor(format_0_0_1_0_size_bits/8) : (uint8_t)(floor(format_0_0_1_0_size_bits/8) + 1);
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format_0_0_1_0_size_bits=%d, format_0_0_1_0_size_bytes=%d\n",
+      LOG_DD("calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format_0_0_1_0_size_bits=%d, format_0_0_1_0_size_bytes=%d\n",
              css_dci_format,format_0_0_1_0_size_bits,format_0_0_1_0_size_bytes);
-#endif
 
       for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8
         //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) {
         // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
+        LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
                css_dci_format,(1<<aggregationLevel));
-#endif
         old_dci_cnt = dci_cnt;
         nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms,
                                    crc_scrambled_values, aggregationLevel,
@@ -2950,18 +2812,14 @@ uint8_t nr_dci_decoding_procedure(int s,
       // for format0_0 and format1_0, first we calculate dci pdu size
       format_0_1_1_1_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_c_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,1);
       format_0_1_1_1_size_bytes = (format_0_1_1_1_size_bits%8 == 0) ? (uint8_t)floor(format_0_1_1_1_size_bits/8) : (uint8_t)(floor(format_0_1_1_1_size_bits/8) + 1);
-#ifdef NR_PDCCH_DCI_DEBUG
-      printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format_0_1_1_1_size_bits=%d, format_0_1_1_1_size_bytes=%d\n",
+      LOG_DD("calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format_0_1_1_1_size_bits=%d, format_0_1_1_1_size_bytes=%d\n",
              css_dci_format,format_0_1_1_1_size_bits,format_0_1_1_1_size_bytes);
-#endif
 
       for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8
         //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) {
         // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0
-#ifdef NR_PDCCH_DCI_DEBUG
-        printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
+        LOG_DD("common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n",
                css_dci_format,(1<<aggregationLevel));
-#endif
         old_dci_cnt = dci_cnt;
         nr_dci_decoding_procedure0(s,p,coreset_time_dur,coreset_nbr_rb,pdcch_vars, 0, nr_tti_rx, dci_alloc, eNB_id, ue->current_thread_id[nr_tti_rx], frame_parms,
                                    crc_scrambled_values, aggregationLevel,
@@ -2984,12 +2842,8 @@ uint8_t nr_dci_decoding_procedure(int s,
 
   *crc_scrambled = crc_scrambled_;
   *format_found  = format_found_;
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> at the end crc_scrambled=%d and format_found=%d\n",*crc_scrambled,*format_found);
-#endif
-#ifdef NR_PDCCH_DCI_DEBUG
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> at the end dci_cnt=%d \n",dci_cnt);
-#endif
+  LOG_DD("at the end crc_scrambled=%d and format_found=%d\n",*crc_scrambled,*format_found);
+  LOG_DD("at the end dci_cnt=%d \n",dci_cnt);
   return(dci_cnt);
 }
 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c
index 48125a01f83d2d7b9b6bea1c091dee17c6963b91..df79abefcdef6d2ce0decc771d8e77e216534581 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c
@@ -37,7 +37,7 @@
 //#include "PHY/extern.h"
 //#include "SCHED/defs.h"
 #ifdef DEBUG_DCI_TOOLS
-#include "PHY/vars.h"
+  #include "PHY/vars.h"
 #endif
 #include "assertions.h"
 
@@ -53,6 +53,12 @@
 //#define DEBUG_DCI
 #define NR_PDCCH_DCI_TOOLS
 //#define NR_PDCCH_DCI_TOOLS_DEBUG
+#ifdef NR_PDCCH_DCI_TOOLS_DEBUG
+#define LOG_DCI_D(a...) printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) ->" a)
+#else 
+#define LOG_DCI_D(a...)
+#endif
+#define LOG_DCI_PARM(a...) LOG_D(PHY,"\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci)" a)
 
 typedef unsigned __int128 uint128_t;
 
@@ -66,18 +72,16 @@ int8_t *nr_delta_PUCCH_lut = nr_delta_PUSCH_acc;
 
 uint16_t nr_dci_field(uint64_t dci_pdu[2],
                       uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS],
-                      uint8_t dci_field)
-{
+                      uint8_t dci_field) {
   int dci_size=0;
 
-  for (int i=0;i<NBR_NR_DCI_FIELDS;i++) dci_size+=dci_fields_sizes[i];
+  for (int i=0; i<NBR_NR_DCI_FIELDS; i++) dci_size+=dci_fields_sizes[i];
 
   AssertFatal(dci_size<65,"DCI has %d > 64 bits, not supported for now\n",
-	      dci_size);
-
+              dci_size);
   uint16_t first_bit_position = dci_size;
-  
-  for (int i=0; i<=dci_field ; i++){
+
+  for (int i=0; i<=dci_field ; i++) {
     first_bit_position = first_bit_position - dci_fields_sizes[i];
   }
 
@@ -85,928 +89,832 @@ uint16_t nr_dci_field(uint64_t dci_pdu[2],
   uint16_t tmp2 = 0;
   for (int i=0; i<dci_fields_sizes[dci_field]; i++)
     tmp2 |= ((tmp1>>i)&1)<<(dci_fields_sizes[dci_field]-i-1);*/
-
   return ((uint16_t)(*dci_pdu>>first_bit_position)&((1<<dci_fields_sizes[dci_field])-1));
 }
 
 int nr_extract_dci_info(PHY_VARS_NR_UE *ue,
-        uint8_t eNB_id,
-        lte_frame_type_t frame_type,
-        uint8_t dci_length,
-        uint16_t rnti,
-        uint64_t dci_pdu[2],
-        fapi_nr_dci_pdu_rel15_t *nr_pdci_info_extracted,
-        uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS],
-        NR_DCI_format_t dci_format,
-        uint8_t nr_tti_rx,
-        uint16_t n_RB_ULBWP,
-        uint16_t n_RB_DLBWP,
-        uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES])
-{
-
-/*
- * This function will extract the different elements of the dci pdu and interpret the values extracted to update correctly the parameters in:
- *                                                NR_DL_UE_HARQ_t *pdlsch0_harq,
- *                                                NR_UE_DLSCH_t *pdlsch0,
- *
- * We need to know the dci length and the dci_fields_sizes (array containing each field size in number of bits)
- * In order to get the value of a specific field we will proceed as follows (let's have a look to an example:
- * If the length of the pdu is 38 bits and the content of the dci_pdu is 0x3A8900789A (pdu is 11 1010 1000 1001 0000 0000 0111 1000 1001 1010)
- * If the dci_fields_sizes is {0 0 1 0 0 0 0 0 0 13 0 1 0 0 0 0 0 0 0 0 0 0 5 1 2 4 2 0 0 0 2 3 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...}
- * This means:
- *             number bits for carrier_ind field is 0
- *             number bits for sul_ind_0_1 field is 0
- *             number bits for identifier_dci_formats field is 0
- *             number bits for slot_format_ind field is 0
- *             number bits for pre_emption_ind field is 0
- *             ...
- *             number bits for freq_dom_resource_assignment_DL field is 13
- *             ...
- *             number bits for padding is 0
- * In order to extract the information of (e.g.) freq_dom_resource_assignment_DL field,
- * we will do a left-shift of 1 position (because previous to this field, and according to the dci_fields_sizes array, there is only one non-empty field of size 1 bit) -> (1 1010 1000 1001 0000 0000 0111 1000 1001 1010 0)
- * then we will do a right-shit of dci_length-13 positions -> (1 1010 1000 1001). And this is the content of the freq_dom_resource_assignment_DL field
- *
- *
- * At the moment we have implemented the following formats:
- *
- * Format 0_0, that contains the following fields according to Specification 38.212 V15.1.1 Section 7.3.1
- *  with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI
- *    0  IDENTIFIER_DCI_FORMATS:
- *    10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered
- *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
- *    17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0
- *    24 MCS:
- *    25 NDI:
- *    26 RV:
- *    27 HARQ_PROCESS_NUMBER:
- *    32 TPC_PUSCH:
- *    49 PADDING_NR_DCI: (Note 2) If DCI format 0_0 is monitored in common search space
- *    50 SUL_IND_0_0:
- *
- * Format 0_1, that contains the following fields
- *  with CRC scrambled by C-RNTI or CS-RNTI or SP-CSI-RNTI or new-RNTI
- *    0  IDENTIFIER_DCI_FORMATS:
- *    1  CARRIER_IND
- *    2  SUL_IND_0_1
- *    7  BANDWIDTH_PART_IND
- *    10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered
- *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
- *    17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0
- *    24 MCS:
- *    25 NDI:
- *    26 RV:
- *    27 HARQ_PROCESS_NUMBER:
- *    29 FIRST_DAI
- *    30 SECOND_DAI
- *    32 TPC_PUSCH:
- *    36 SRS_RESOURCE_IND:
- *    37 PRECOD_NBR_LAYERS:
- *    38 ANTENNA_PORTS:
- *    40 SRS_REQUEST:
- *    42 CSI_REQUEST:
- *    43 CBGTI
- *    45 PTRS_DMRS
- *    46 BETA_OFFSET_IND
- *    47 DMRS_SEQ_INI
- *    48 UL_SCH_IND
- *    49 PADDING_NR_DCI: (Note 2) If DCI format 0_0 is monitored in common search space
- *
- * Format 1_0, that contains the following fields
- *  with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI
- *    0  IDENTIFIER_DCI_FORMATS:
- *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
- *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
- *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
- *    24 MCS:
- *    25 NDI:
- *    26 RV:
- *    27 HARQ_PROCESS_NUMBER:
- *    28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
- *    33 TPC_PUCCH:
- *    34 PUCCH_RESOURCE_IND:
- *    35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND:
- *    55 RESERVED_NR_DCI
- *
- *    If the CRC of the DCI format 1_0 is scrambled by C-RNTI and the "Frequency domain resource assignment" field are of all ones,
- *    the DCI format 1_0 is for random access procedure initiated by a PDCCH order.
- *    This is not implemented, but the fields are already included: FIXME!!!
- *
- *  with CRC scrambled by P-RNTI
- *    8  SHORT_MESSAGE_IND
- *    9  SHORT_MESSAGES
- *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
- *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
- *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
- *    24 MCS:
- *    31 TB_SCALING
- *    55 RESERVED_NR_DCI
- *
- *  with CRC scrambled by SI-RNTI
- *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
- *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
- *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
- *    24 MCS:
- *    26 RV:
- *    55 RESERVED_NR_DCI
- *
- *  with CRC scrambled by RA-RNTI
- *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
- *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
- *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
- *    24 MCS:
- *    31 TB_SCALING
- *    55 RESERVED_NR_DCI
- *
- *  with CRC scrambled by TC-RNTI
- *    0  IDENTIFIER_DCI_FORMATS:
- *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
- *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
- *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
- *    24 MCS:
- *    25 NDI:
- *    26 RV:
- *    27 HARQ_PROCESS_NUMBER:
- *    28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
- *    33 TPC_PUCCH:
- *
- * Format 1_1, that contains the following fields
- *  with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI
- *    0  IDENTIFIER_DCI_FORMATS:
- *    1  CARRIER_IND:
- *    7  BANDWIDTH_PART_IND:
- *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
- *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
- *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
- *    14 PRB_BUNDLING_SIZE_IND:
- *    15 RATE_MATCHING_IND:
- *    16 ZP_CSI_RS_TRIGGER:
- *    18 TB1_MCS:
- *    19 TB1_NDI:
- *    20 TB1_RV:
- *    21 TB2_MCS:
- *    22 TB2_NDI:
- *    23 TB2_RV:
- *    27 HARQ_PROCESS_NUMBER:
- *    28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
- *    33 TPC_PUCCH:
- *    34 PUCCH_RESOURCE_IND:
- *    35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND:
- *    38 ANTENNA_PORTS:
- *    39 TCI:
- *    40 SRS_REQUEST:
- *    43 CBGTI:
- *    44 CBGFI:
- *    47 DMRS_SEQ_INI:
- *
- * We have not implemented the following formats:
- *
- * Format 2_0
- * Used for notifying the slot format
- *
- * Format 2_1
- * Used for notifying the PRB(s) and OFDM symbol(s) where UE may assume no transmission is intended for the UE
- *
- * Format 2_2
- * This format supports power control commands for semi-persistent scheduling.
- * As we can already support power control commands dynamically with formats 0_0/0_1 (TPC PUSCH) and 1_0/1_1 (TPC PUCCH)
- * This format will be implemented in the future FIXME!!!
- *
- * Format 2_3
- * This format is used for power control of uplink sounding reference signals for devices which have not coupled SRS power control to the PUSCH power control
- * either because independent control is desirable or because the device is configured without PUCCH and PUSCH
- * This format will be implemented in the future FIXME!!!
- *
- */
+                        uint8_t eNB_id,
+                        lte_frame_type_t frame_type,
+                        uint8_t dci_length,
+                        uint16_t rnti,
+                        uint64_t dci_pdu[2],
+                        fapi_nr_dci_pdu_rel15_t *nr_pdci_info_extracted,
+                        uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS],
+                        NR_DCI_format_t dci_format,
+                        uint8_t nr_tti_rx,
+                        uint16_t n_RB_ULBWP,
+                        uint16_t n_RB_DLBWP,
+                        uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES]) {
+  /*
+   * This function will extract the different elements of the dci pdu and interpret the values extracted to update correctly the parameters in:
+   *                                                NR_DL_UE_HARQ_t *pdlsch0_harq,
+   *                                                NR_UE_DLSCH_t *pdlsch0,
+   *
+   * We need to know the dci length and the dci_fields_sizes (array containing each field size in number of bits)
+   * In order to get the value of a specific field we will proceed as follows (let's have a look to an example:
+   * If the length of the pdu is 38 bits and the content of the dci_pdu is 0x3A8900789A (pdu is 11 1010 1000 1001 0000 0000 0111 1000 1001 1010)
+   * If the dci_fields_sizes is {0 0 1 0 0 0 0 0 0 13 0 1 0 0 0 0 0 0 0 0 0 0 5 1 2 4 2 0 0 0 2 3 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...}
+   * This means:
+   *             number bits for carrier_ind field is 0
+   *             number bits for sul_ind_0_1 field is 0
+   *             number bits for identifier_dci_formats field is 0
+   *             number bits for slot_format_ind field is 0
+   *             number bits for pre_emption_ind field is 0
+   *             ...
+   *             number bits for freq_dom_resource_assignment_DL field is 13
+   *             ...
+   *             number bits for padding is 0
+   * In order to extract the information of (e.g.) freq_dom_resource_assignment_DL field,
+   * we will do a left-shift of 1 position (because previous to this field, and according to the dci_fields_sizes array, there is only one non-empty field of size 1 bit) -> (1 1010 1000 1001 0000 0000 0111 1000 1001 1010 0)
+   * then we will do a right-shit of dci_length-13 positions -> (1 1010 1000 1001). And this is the content of the freq_dom_resource_assignment_DL field
+   *
+   *
+   * At the moment we have implemented the following formats:
+   *
+   * Format 0_0, that contains the following fields according to Specification 38.212 V15.1.1 Section 7.3.1
+   *  with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI
+   *    0  IDENTIFIER_DCI_FORMATS:
+   *    10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered
+   *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
+   *    17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0
+   *    24 MCS:
+   *    25 NDI:
+   *    26 RV:
+   *    27 HARQ_PROCESS_NUMBER:
+   *    32 TPC_PUSCH:
+   *    49 PADDING_NR_DCI: (Note 2) If DCI format 0_0 is monitored in common search space
+   *    50 SUL_IND_0_0:
+   *
+   * Format 0_1, that contains the following fields
+   *  with CRC scrambled by C-RNTI or CS-RNTI or SP-CSI-RNTI or new-RNTI
+   *    0  IDENTIFIER_DCI_FORMATS:
+   *    1  CARRIER_IND
+   *    2  SUL_IND_0_1
+   *    7  BANDWIDTH_PART_IND
+   *    10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered
+   *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
+   *    17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0
+   *    24 MCS:
+   *    25 NDI:
+   *    26 RV:
+   *    27 HARQ_PROCESS_NUMBER:
+   *    29 FIRST_DAI
+   *    30 SECOND_DAI
+   *    32 TPC_PUSCH:
+   *    36 SRS_RESOURCE_IND:
+   *    37 PRECOD_NBR_LAYERS:
+   *    38 ANTENNA_PORTS:
+   *    40 SRS_REQUEST:
+   *    42 CSI_REQUEST:
+   *    43 CBGTI
+   *    45 PTRS_DMRS
+   *    46 BETA_OFFSET_IND
+   *    47 DMRS_SEQ_INI
+   *    48 UL_SCH_IND
+   *    49 PADDING_NR_DCI: (Note 2) If DCI format 0_0 is monitored in common search space
+   *
+   * Format 1_0, that contains the following fields
+   *  with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI
+   *    0  IDENTIFIER_DCI_FORMATS:
+   *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
+   *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
+   *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
+   *    24 MCS:
+   *    25 NDI:
+   *    26 RV:
+   *    27 HARQ_PROCESS_NUMBER:
+   *    28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
+   *    33 TPC_PUCCH:
+   *    34 PUCCH_RESOURCE_IND:
+   *    35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND:
+   *    55 RESERVED_NR_DCI
+   *
+   *    If the CRC of the DCI format 1_0 is scrambled by C-RNTI and the "Frequency domain resource assignment" field are of all ones,
+   *    the DCI format 1_0 is for random access procedure initiated by a PDCCH order.
+   *    This is not implemented, but the fields are already included: FIXME!!!
+   *
+   *  with CRC scrambled by P-RNTI
+   *    8  SHORT_MESSAGE_IND
+   *    9  SHORT_MESSAGES
+   *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
+   *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
+   *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
+   *    24 MCS:
+   *    31 TB_SCALING
+   *    55 RESERVED_NR_DCI
+   *
+   *  with CRC scrambled by SI-RNTI
+   *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
+   *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
+   *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
+   *    24 MCS:
+   *    26 RV:
+   *    55 RESERVED_NR_DCI
+   *
+   *  with CRC scrambled by RA-RNTI
+   *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
+   *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
+   *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
+   *    24 MCS:
+   *    31 TB_SCALING
+   *    55 RESERVED_NR_DCI
+   *
+   *  with CRC scrambled by TC-RNTI
+   *    0  IDENTIFIER_DCI_FORMATS:
+   *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
+   *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
+   *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
+   *    24 MCS:
+   *    25 NDI:
+   *    26 RV:
+   *    27 HARQ_PROCESS_NUMBER:
+   *    28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
+   *    33 TPC_PUCCH:
+   *
+   * Format 1_1, that contains the following fields
+   *  with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI
+   *    0  IDENTIFIER_DCI_FORMATS:
+   *    1  CARRIER_IND:
+   *    7  BANDWIDTH_PART_IND:
+   *    11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL:
+   *    12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 5.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits,
+   *    13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0
+   *    14 PRB_BUNDLING_SIZE_IND:
+   *    15 RATE_MATCHING_IND:
+   *    16 ZP_CSI_RS_TRIGGER:
+   *    18 TB1_MCS:
+   *    19 TB1_NDI:
+   *    20 TB1_RV:
+   *    21 TB2_MCS:
+   *    22 TB2_NDI:
+   *    23 TB2_RV:
+   *    27 HARQ_PROCESS_NUMBER:
+   *    28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
+   *    33 TPC_PUCCH:
+   *    34 PUCCH_RESOURCE_IND:
+   *    35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND:
+   *    38 ANTENNA_PORTS:
+   *    39 TCI:
+   *    40 SRS_REQUEST:
+   *    43 CBGTI:
+   *    44 CBGFI:
+   *    47 DMRS_SEQ_INI:
+   *
+   * We have not implemented the following formats:
+   *
+   * Format 2_0
+   * Used for notifying the slot format
+   *
+   * Format 2_1
+   * Used for notifying the PRB(s) and OFDM symbol(s) where UE may assume no transmission is intended for the UE
+   *
+   * Format 2_2
+   * This format supports power control commands for semi-persistent scheduling.
+   * As we can already support power control commands dynamically with formats 0_0/0_1 (TPC PUSCH) and 1_0/1_1 (TPC PUCCH)
+   * This format will be implemented in the future FIXME!!!
+   *
+   * Format 2_3
+   * This format is used for power control of uplink sounding reference signals for devices which have not coupled SRS power control to the PUSCH power control
+   * either because independent control is desirable or because the device is configured without PUCCH and PUSCH
+   * This format will be implemented in the future FIXME!!!
+   *
+   */
   uint8_t dci_fields_sizes_format[NBR_NR_DCI_FIELDS] = {0};
-  for (int m=0; m<NBR_NR_DCI_FIELDS; m++) dci_fields_sizes_format[m]=dci_fields_sizes[m][dci_format];
 
+  for (int m=0; m<NBR_NR_DCI_FIELDS; m++) dci_fields_sizes_format[m]=dci_fields_sizes[m][dci_format];
 
-//  uint64_t pdu_bitmap = 0xFFFFFFFFFFFFFFFF;
-//  uint128_t pdu_bitmap = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
-//#define DCI_MAX_SIZE 128
-//  pdu_bitmap = (pdu_bitmap << (DCI_MAX_SIZE - dci_length)) >> (DCI_MAX_SIZE - dci_length); // this variable will help to remove the bits of other fields when left-switching
+  //  uint64_t pdu_bitmap = 0xFFFFFFFFFFFFFFFF;
+  //  uint128_t pdu_bitmap = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
+  //#define DCI_MAX_SIZE 128
+  //  pdu_bitmap = (pdu_bitmap << (DCI_MAX_SIZE - dci_length)) >> (DCI_MAX_SIZE - dci_length); // this variable will help to remove the bits of other fields when left-switching
   uint8_t dci_field=0;
-//  uint8_t sizes_count=0;
-//  uint8_t left_shift=0;
-  #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> Entering function nr_extract_dci_info() with dci_pdu=%lx %lx dci_length=%d\n",
+  //  uint8_t sizes_count=0;
+  //  uint8_t left_shift=0;
+  LOG_DCI_D("Entering function nr_extract_dci_info() with dci_pdu=%lx %lx dci_length=%d\n",
             dci_pdu[0],dci_pdu[1], dci_length);
-    printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> for format %d, dci_fields_sizes {",dci_format);
-    for (int i=0; i<NBR_NR_DCI_FIELDS; i++) printf("%d ",dci_fields_sizes[i][dci_format]);
-    printf("}\n");
-  #endif
+  LOG_DCI_D("for format %d, dci_fields_sizes {",dci_format);
+#ifdef NR_PDCCH_DCI_TOOLS_DEBUG
+
+  for (int i=0; i<NBR_NR_DCI_FIELDS; i++) printf("%d ",dci_fields_sizes[i][dci_format]);
 
-//  uint8_t  prev_ndi = pdlsch0_harq->DCINdi;
+  printf("}\n");
+#endif
 
+  //  uint8_t  prev_ndi = pdlsch0_harq->DCINdi;
 
- /*
-  * Some dci fields need to be interpreted before the others.
-  */
+  /*
+   * Some dci fields need to be interpreted before the others.
+   */
   if (dci_fields_sizes[HARQ_PROCESS_NUMBER][dci_format] != 0) { // E.g: 27 HARQ_PROCESS_NUMBER (27 is the position in dci_fields_sizes array for field HARQ_PROCESS_NUMBER)
     //for (int i=0; i<=HARQ_PROCESS_NUMBER; i++) left_shift = left_shift + dci_fields_sizes[i][dci_format];
     nr_pdci_info_extracted->harq_process_number = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,HARQ_PROCESS_NUMBER);
     //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[HARQ_PROCESS_NUMBER][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[HARQ_PROCESS_NUMBER][dci_format]));
     //left_shift = 0;
-    #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-      printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->harq_process_number=%x\n",nr_pdci_info_extracted->harq_process_number);
-    #endif
+    LOG_DCI_D("nr_pdci_info_extracted->harq_process_number=%x\n",nr_pdci_info_extracted->harq_process_number);
   }
-/*
-  if ((dci_format == format1_0) || (dci_format == format1_1)) {
-    if (rnti==crc_scrambled_values[_SI_RNTI_]) {
-      ue->dlsch_SI[eNB_id]->active = 1;
-    } else if (rnti==crc_scrambled_values[_P_RNTI_]) {
-      ue->dlsch_p[eNB_id]->active  = 1;
-    } else if (rnti==crc_scrambled_values[_RA_RNTI_]) {
-      ue->dlsch_ra[eNB_id]->active = 1;
-    } else {
-      pdlsch0->active          = 1;
-    }
-    pdlsch0->rnti              = rnti;
-    pdlsch0_harq->codeword     = 0;
-    pdlsch0_harq->Nl           = 1;
-//  pdlsch0_harq->mimo_mode    = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI;
-    pdlsch0_harq->dl_power_off = 1; //no power offset
-
-    if ((rnti==crc_scrambled_values[_SI_RNTI_]) || (rnti==crc_scrambled_values[_P_RNTI_]) || (rnti==crc_scrambled_values[_RA_RNTI_])) {
-      pdlsch0_harq->round    = 0;
-      pdlsch0_harq->status   = ACTIVE;
-    } else {
+
+  /*
+    if ((dci_format == format1_0) || (dci_format == format1_1)) {
+      if (rnti==crc_scrambled_values[_SI_RNTI_]) {
+        ue->dlsch_SI[eNB_id]->active = 1;
+      } else if (rnti==crc_scrambled_values[_P_RNTI_]) {
+        ue->dlsch_p[eNB_id]->active  = 1;
+      } else if (rnti==crc_scrambled_values[_RA_RNTI_]) {
+        ue->dlsch_ra[eNB_id]->active = 1;
+      } else {
+        pdlsch0->active          = 1;
+      }
+      pdlsch0->rnti              = rnti;
+      pdlsch0_harq->codeword     = 0;
+      pdlsch0_harq->Nl           = 1;
+  //  pdlsch0_harq->mimo_mode    = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI;
+      pdlsch0_harq->dl_power_off = 1; //no power offset
+
+      if ((rnti==crc_scrambled_values[_SI_RNTI_]) || (rnti==crc_scrambled_values[_P_RNTI_]) || (rnti==crc_scrambled_values[_RA_RNTI_])) {
+        pdlsch0_harq->round    = 0;
+        pdlsch0_harq->status   = ACTIVE;
+      } else {
+      }
     }
-  }
-*/
+  */
   for (dci_field=0; dci_field<NBR_NR_DCI_FIELDS; dci_field++) {
     //left_shift = left_shift + dci_fields_sizes[dci_field][dci_format];
-    if (dci_fields_sizes[dci_field][dci_format] != 0){
+    if (dci_fields_sizes[dci_field][dci_format] != 0) {
       //sizes_count = dci_fields_sizes[dci_field][dci_format];
-      #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> dci_fields_sizes[%d][%d] = %d\n",dci_field,dci_format,dci_fields_sizes[dci_field][dci_format]);
-      #endif
-
-      switch (dci_field){
-      case IDENTIFIER_DCI_FORMATS: // 0  IDENTIFIER_DCI_FORMATS: (field defined for format0_0,format0_1,format1_0,format1_1,format2_0,format2_1,format2_2,format2_3)
-              // if format 0_0: The value of this bit field is always set to 0, indicating an UL DCI format (TS38.212 Section 7.3.1.1.1)
-              // if format 1_0: The value of this bit field is always set to 1, indicating a  DL DCI format (TS38.212 Section 7.3.1.2.1)
-        nr_pdci_info_extracted->identifier_dci_formats           = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->identifier_dci_formats=%x\n",nr_pdci_info_extracted->identifier_dci_formats);
-        #endif
-        break;
+      LOG_DCI_D("dci_fields_sizes[%d][%d] = %d\n",dci_field,dci_format,dci_fields_sizes[dci_field][dci_format]);
+
+      switch (dci_field) {
+        case IDENTIFIER_DCI_FORMATS: // 0  IDENTIFIER_DCI_FORMATS: (field defined for format0_0,format0_1,format1_0,format1_1,format2_0,format2_1,format2_2,format2_3)
+          // if format 0_0: The value of this bit field is always set to 0, indicating an UL DCI format (TS38.212 Section 7.3.1.1.1)
+          // if format 1_0: The value of this bit field is always set to 1, indicating a  DL DCI format (TS38.212 Section 7.3.1.2.1)
+          nr_pdci_info_extracted->identifier_dci_formats           = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->identifier_dci_formats=%x\n",nr_pdci_info_extracted->identifier_dci_formats);
+          break;
 
-      case CARRIER_IND: // 1  CARRIER_IND: (field defined for -,format0_1,-,format1_1,-,-,-,-)
-              // 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213]
-        nr_pdci_info_extracted->carrier_ind                      = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-#ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->carrier_ind=%x\n",nr_pdci_info_extracted->carrier_ind);
-#endif
-        break;
-      case SUL_IND_0_1: // 2  SUL_IND_0_1: (field defined for -,format0_1,-,-,-,-,-,-)
-        nr_pdci_info_extracted->sul_ind_0_1                      = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->sul_ind_0_1=%x\n",nr_pdci_info_extracted->sul_ind_0_1);
-        #endif
-        break;
+        case CARRIER_IND: // 1  CARRIER_IND: (field defined for -,format0_1,-,format1_1,-,-,-,-)
+          // 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213]
+          nr_pdci_info_extracted->carrier_ind                      = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->carrier_ind=%x\n",nr_pdci_info_extracted->carrier_ind);
+          break;
 
-      case SLOT_FORMAT_IND: // 3  SLOT_FORMAT_IND: (field defined for -,-,-,-,format2_0,-,-,-)
-              // size of DCI format 2_0 is configurable by higher layers up to 128 bits, according to Subclause 11.1.1 of [5, TS 38.213]
-        nr_pdci_info_extracted->slot_format_ind                  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->slot_format_ind=%x\n",nr_pdci_info_extracted->slot_format_ind);
-        #endif
-        break;
-      case PRE_EMPTION_IND: // 4  PRE_EMPTION_IND: (field defined for -,-,-,-,-,format2_1,-,-)
-              // size of DCI format 2_1 is configurable by higher layers up to 126 bits, according to Subclause 11.2 of [5, TS 38.213]. Each pre-emption indication is 14 bits
-        nr_pdci_info_extracted->pre_emption_ind                  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->pre_emption_ind=%x\n",nr_pdci_info_extracted->pre_emption_ind);
-        #endif
-        break;
-      case BLOCK_NUMBER: // 5  BLOCK_NUMBER: (field defined for -,-,-,-,-,-,-,format2_3)
-              // starting position of a block is determined by the parameter startingBitOfFormat2_3
-        nr_pdci_info_extracted->block_number                     = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->block_number=%x\n",nr_pdci_info_extracted->block_number);
-        #endif
-        break;
-      case CLOSE_LOOP_IND: // 6  CLOSE_LOOP_IND: (field defined for -,-,-,-,-,-,format2_2,-)
-              // The parameter xxx provided by higher layers determines the index to the TPC command number for an UL of a cell. Each TPC command number is 2 bits
-        nr_pdci_info_extracted->close_loop_ind                   = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->close_loop_ind=%x\n",nr_pdci_info_extracted->close_loop_ind);
-        #endif
-        break;
-      case BANDWIDTH_PART_IND: // 7  BANDWIDTH_PART_IND: (field defined for -,format0_1,-,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->bandwidth_part_ind               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->bandwidth_part_ind=%x\n",nr_pdci_info_extracted->bandwidth_part_ind);
-        #endif
-        break;
+        case SUL_IND_0_1: // 2  SUL_IND_0_1: (field defined for -,format0_1,-,-,-,-,-,-)
+          nr_pdci_info_extracted->sul_ind_0_1                      = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->sul_ind_0_1=%x\n",nr_pdci_info_extracted->sul_ind_0_1);
+          break;
 
-      case SHORT_MESSAGE_IND: // 8  SHORT_MESSAGE_IND: (field defined for -,-,format1_0,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->short_message_ind                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->short_message_ind=%x\n",nr_pdci_info_extracted->short_message_ind);
-        #endif
-        break;
+        case SLOT_FORMAT_IND: // 3  SLOT_FORMAT_IND: (field defined for -,-,-,-,format2_0,-,-,-)
+          // size of DCI format 2_0 is configurable by higher layers up to 128 bits, according to Subclause 11.1.1 of [5, TS 38.213]
+          nr_pdci_info_extracted->slot_format_ind                  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->slot_format_ind=%x\n",nr_pdci_info_extracted->slot_format_ind);
+          break;
 
-      case SHORT_MESSAGES: // 9  SHORT_MESSAGES: (field defined for -,-,format1_0,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->short_messages                   = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->short_messages=%x\n",nr_pdci_info_extracted->short_messages);
-        #endif
-        break;
+        case PRE_EMPTION_IND: // 4  PRE_EMPTION_IND: (field defined for -,-,-,-,-,format2_1,-,-)
+          // size of DCI format 2_1 is configurable by higher layers up to 126 bits, according to Subclause 11.2 of [5, TS 38.213]. Each pre-emption indication is 14 bits
+          nr_pdci_info_extracted->pre_emption_ind                  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->pre_emption_ind=%x\n",nr_pdci_info_extracted->pre_emption_ind);
+          break;
 
-      case FREQ_DOM_RESOURCE_ASSIGNMENT_UL: // 10  FREQ_DOM_RESOURCE_ASSIGNMENT_UL: (field defined for format0_0,format0_1,-,-,-,-,-,-)
-              // PUSCH hopping with resource allocation type 1 not considered
-              // According to 38.214 V15.1.0 Section 6.1.2.2 Two uplink resource allocation schemes, type 0 and type 1, are supported.
-              // The UE shall assume that when the scheduling PDCCH is received with DCI format 0_0, then uplink resource allocation type 1 is used.
-        nr_pdci_info_extracted->freq_dom_resource_assignment_UL  = (uint16_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        /*if (dci_format == format0_1){ // uplink resource allocation type 0 or 1 can be used
-        }
-        if (dci_format == format0_0){ // only uplink resource allocation type 1
-              // At the moment we are supporting only format 1_0 (and not format 1_1), so we only support resource allocation type 1 (and not type 0).
-              // For resource allocation type 1, the resource allocation field consists of a resource indication value (RIV):
-              // RIV = n_RB_ULBWP * (l_RB - 1) + start_RB                                  if (l_RB - 1) <= floor (n_RB_ULBWP/2)
-              // RIV = n_RB_ULBWP * (n_RB_ULBWP - l_RB + 1) + (n_RB_ULBWP - 1 - start_RB)  if (l_RB - 1)  > floor (n_RB_ULBWP/2)
-          // the following two expressions apply only if (l_RB - 1) <= floor (n_RB_ULBWP/2)
-          l_RB = floor(nr_pdci_info_extracted->freq_dom_resource_assignment_DL/n_RB_ULBWP) + 1;
-          start_RB = nr_pdci_info_extracted->freq_dom_resource_assignment_DL%n_RB_ULBWP;
-          // if (l_RB - 1)  > floor (n_RB_ULBWP/2) we need to recalculate them using the following lines
-          tmp_RIV = n_RB_ULBWP * (l_RB - 1) + start_RB;
-          if (tmp_RIV != nr_pdci_info_extracted->freq_dom_resource_assignment_DL) { // then (l_RB - 1)  > floor (n_RB_ULBWP/2) and we need to recalculate l_RB and start_RB
-            l_RB = n_RB_ULBWP - l_RB + 2;
-            start_RB = n_RB_ULBWP - start_RB - 1;
-          }
-          ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->first_rb = start_RB;
-          ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->nb_rb    = l_RB;
-        }*/
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->freq_dom_resource_assignment_UL=%x\n",nr_pdci_info_extracted->freq_dom_resource_assignment_UL);
-          //printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> l_RB=%d, start_RB=%d, n_RB_DLBWP=%d\n",l_RB,start_RB,n_RB_ULBWP);
-        #endif
-        break;
+        case BLOCK_NUMBER: // 5  BLOCK_NUMBER: (field defined for -,-,-,-,-,-,-,format2_3)
+          // starting position of a block is determined by the parameter startingBitOfFormat2_3
+          nr_pdci_info_extracted->block_number                     = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->block_number=%x\n",nr_pdci_info_extracted->block_number);
+          break;
 
-      case FREQ_DOM_RESOURCE_ASSIGNMENT_DL: // 11  FREQ_DOM_RESOURCE_ASSIGNMENT_DL: (field defined for -,-,format1_0,format1_1,-,-,-,-)
-              // According to 38.214 V15.1.0 Section 5.1.2.2 Two downlink resource allocation schemes, type 0 and type 1, are supported.
-              // The UE shall assume that when the scheduling grant is received with DCI format 1_0, then downlink resource allocation type 1 is used.
-        nr_pdci_info_extracted->freq_dom_resource_assignment_DL  = (uint16_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        /*if (dci_format == format1_1){ // uplink resource allocation type 0 or 1 can be used
-        }
-        if (dci_format == format1_0){ // only uplink resource allocation type 1
-              // At the moment we are supporting only format 0_0 (and not format 0_1), so we only support resource allocation type 1 (and not type 0).
-              // For resource allocation type 1, the resource allocation field consists of a resource indication value (RIV):
-              // RIV = n_RB_DLBWP * (l_RB - 1) + start_RB                                  if (l_RB - 1) <= floor (n_RB_DLBWP/2)
-              // RIV = n_RB_DLBWP * (n_RB_DLBWP - l_RB + 1) + (n_RB_DLBWP - 1 - start_RB)  if (l_RB - 1)  > floor (n_RB_DLBWP/2)
-          // the following two expressions apply only if (l_RB - 1) <= floor (n_RB_DLBWP/2)
-          l_RB = floor(nr_pdci_info_extracted->freq_dom_resource_assignment_DL/n_RB_DLBWP) + 1;
-          start_RB = nr_pdci_info_extracted->freq_dom_resource_assignment_DL%n_RB_DLBWP;
-          // if (l_RB - 1)  > floor (n_RB_DLBWP/2) we need to recalculate them using the following lines
-          tmp_RIV = n_RB_DLBWP * (l_RB - 1) + start_RB;
-          if (tmp_RIV != nr_pdci_info_extracted->freq_dom_resource_assignment_DL) { // then (l_RB - 1)  > floor (n_RB_DLBWP/2) and we need to recalculate l_RB and start_RB
-            l_RB = n_RB_DLBWP - l_RB + 2;
-            start_RB = n_RB_DLBWP - start_RB - 1;
+        case CLOSE_LOOP_IND: // 6  CLOSE_LOOP_IND: (field defined for -,-,-,-,-,-,format2_2,-)
+          // The parameter xxx provided by higher layers determines the index to the TPC command number for an UL of a cell. Each TPC command number is 2 bits
+          nr_pdci_info_extracted->close_loop_ind                   = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->close_loop_ind=%x\n",nr_pdci_info_extracted->close_loop_ind);
+          break;
+
+        case BANDWIDTH_PART_IND: // 7  BANDWIDTH_PART_IND: (field defined for -,format0_1,-,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->bandwidth_part_ind               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->bandwidth_part_ind=%x\n",nr_pdci_info_extracted->bandwidth_part_ind);
+          break;
+
+        case SHORT_MESSAGE_IND: // 8  SHORT_MESSAGE_IND: (field defined for -,-,format1_0,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->short_message_ind                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->short_message_ind=%x\n",nr_pdci_info_extracted->short_message_ind);
+          break;
+
+        case SHORT_MESSAGES: // 9  SHORT_MESSAGES: (field defined for -,-,format1_0,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->short_messages                   = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->short_messages=%x\n",nr_pdci_info_extracted->short_messages);
+          break;
+
+        case FREQ_DOM_RESOURCE_ASSIGNMENT_UL: // 10  FREQ_DOM_RESOURCE_ASSIGNMENT_UL: (field defined for format0_0,format0_1,-,-,-,-,-,-)
+          // PUSCH hopping with resource allocation type 1 not considered
+          // According to 38.214 V15.1.0 Section 6.1.2.2 Two uplink resource allocation schemes, type 0 and type 1, are supported.
+          // The UE shall assume that when the scheduling PDCCH is received with DCI format 0_0, then uplink resource allocation type 1 is used.
+          nr_pdci_info_extracted->freq_dom_resource_assignment_UL  = (uint16_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          /*if (dci_format == format0_1){ // uplink resource allocation type 0 or 1 can be used
           }
-          pdlsch0_harq->nb_rb = l_RB;
-          pdlsch0->current_harq_pid = nr_pdci_info_extracted->harq_process_number;
-          pdlsch0->active           = 1;
-          pdlsch0->rnti             = rnti;
-        }*/
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->freq_dom_resource_assignment_DL=%x, RIV = %d\n",nr_pdci_info_extracted->freq_dom_resource_assignment_DL,nr_pdci_info_extracted->freq_dom_resource_assignment_DL);
-          //printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> l_RB=%d, start_RB=%d, n_RB_DLBWP=%d\n",l_RB,start_RB,n_RB_DLBWP);
-         /*
-          * According to TC 38.212 Subclause 7.3.1.2.1 (V15.2.0) (not implemented FIXME!!!)
-          * If the CRC of the DCI format 1_0 is scrambled by C-RNTI
-          * and the "Frequency domain resource assignment" field are of all ones,
-          * the DCI format 1_0 is for random access procedure initiated by a PDCCH order,
-          * with all remaining fields set as follows:
-          * - Random Access Preamble index (6 bits)
-          * - UL/SUL indicator (1 bit)
-          * - SS/PBCH index (6 bits)
-          * - PRACH Mask index (4 bits)
-          * - Reserved bits (10 bits)
-          *
-          */
-         /*
-         * The following commented code is used to verify that l_RB and start_RB are correctly calculated
-         *
-         *
-        printf("\ns_RB\t");
-        n_RB_DLBWP = 20;
-        for (int k = 0 ; k < n_RB_DLBWP; k++) printf("%d\t",k);
-        printf("\nl_RB");
-        for (int j = 1 ; j <= n_RB_DLBWP; j++){ // l_RB
-          printf("\n%d\t",j);
-          for (int i = 0 ; i < n_RB_DLBWP; i++) { // start_RB
-            if ((j-1) <= (floor(n_RB_DLBWP/2)) && ((j+i) <= n_RB_DLBWP)) {
-              tmp_RIV = n_RB_DLBWP * (j - 1) + i;
-              l_RB = floor(tmp_RIV/n_RB_DLBWP) + 1;
-              start_RB = tmp_RIV%n_RB_DLBWP;
-              printf("%d(%d,%d)  ",tmp_RIV,l_RB,start_RB);
-            }
-            if ((j-1) >  (floor(n_RB_DLBWP/2)) && ((j+i) <= n_RB_DLBWP)) {
-              tmp_RIV = n_RB_DLBWP * (n_RB_DLBWP - j + 1) + (n_RB_DLBWP - 1 - i);
-              //l_RB = floor(tmp_RIV/n_RB_DLBWP) + 1;
-              //start_RB = tmp_RIV%n_RB_DLBWP;
-              l_RB = n_RB_DLBWP - (floor(tmp_RIV/n_RB_DLBWP) + 1) + 2;
-              start_RB = n_RB_DLBWP - (tmp_RIV%n_RB_DLBWP) - 1;
-              printf("%d*(%d,%d)  ",tmp_RIV,l_RB,start_RB);
+          if (dci_format == format0_0){ // only uplink resource allocation type 1
+                // At the moment we are supporting only format 1_0 (and not format 1_1), so we only support resource allocation type 1 (and not type 0).
+                // For resource allocation type 1, the resource allocation field consists of a resource indication value (RIV):
+                // RIV = n_RB_ULBWP * (l_RB - 1) + start_RB                                  if (l_RB - 1) <= floor (n_RB_ULBWP/2)
+                // RIV = n_RB_ULBWP * (n_RB_ULBWP - l_RB + 1) + (n_RB_ULBWP - 1 - start_RB)  if (l_RB - 1)  > floor (n_RB_ULBWP/2)
+            // the following two expressions apply only if (l_RB - 1) <= floor (n_RB_ULBWP/2)
+            l_RB = floor(nr_pdci_info_extracted->freq_dom_resource_assignment_DL/n_RB_ULBWP) + 1;
+            start_RB = nr_pdci_info_extracted->freq_dom_resource_assignment_DL%n_RB_ULBWP;
+            // if (l_RB - 1)  > floor (n_RB_ULBWP/2) we need to recalculate them using the following lines
+            tmp_RIV = n_RB_ULBWP * (l_RB - 1) + start_RB;
+            if (tmp_RIV != nr_pdci_info_extracted->freq_dom_resource_assignment_DL) { // then (l_RB - 1)  > floor (n_RB_ULBWP/2) and we need to recalculate l_RB and start_RB
+              l_RB = n_RB_ULBWP - l_RB + 2;
+              start_RB = n_RB_ULBWP - start_RB - 1;
             }
+            ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->first_rb = start_RB;
+            ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->nb_rb    = l_RB;
+          }*/
+          LOG_DCI_D("nr_pdci_info_extracted->freq_dom_resource_assignment_UL=%x\n",nr_pdci_info_extracted->freq_dom_resource_assignment_UL);
+          //LOG_DCI_D("l_RB=%d, start_RB=%d, n_RB_DLBWP=%d\n",l_RB,start_RB,n_RB_ULBWP);
+          break;
+
+        case FREQ_DOM_RESOURCE_ASSIGNMENT_DL: // 11  FREQ_DOM_RESOURCE_ASSIGNMENT_DL: (field defined for -,-,format1_0,format1_1,-,-,-,-)
+          // According to 38.214 V15.1.0 Section 5.1.2.2 Two downlink resource allocation schemes, type 0 and type 1, are supported.
+          // The UE shall assume that when the scheduling grant is received with DCI format 1_0, then downlink resource allocation type 1 is used.
+          nr_pdci_info_extracted->freq_dom_resource_assignment_DL  = (uint16_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          /*if (dci_format == format1_1){ // uplink resource allocation type 0 or 1 can be used
           }
-        }*/
-        #endif
-        break;
+          if (dci_format == format1_0){ // only uplink resource allocation type 1
+                // At the moment we are supporting only format 0_0 (and not format 0_1), so we only support resource allocation type 1 (and not type 0).
+                // For resource allocation type 1, the resource allocation field consists of a resource indication value (RIV):
+                // RIV = n_RB_DLBWP * (l_RB - 1) + start_RB                                  if (l_RB - 1) <= floor (n_RB_DLBWP/2)
+                // RIV = n_RB_DLBWP * (n_RB_DLBWP - l_RB + 1) + (n_RB_DLBWP - 1 - start_RB)  if (l_RB - 1)  > floor (n_RB_DLBWP/2)
+            // the following two expressions apply only if (l_RB - 1) <= floor (n_RB_DLBWP/2)
+            l_RB = floor(nr_pdci_info_extracted->freq_dom_resource_assignment_DL/n_RB_DLBWP) + 1;
+            start_RB = nr_pdci_info_extracted->freq_dom_resource_assignment_DL%n_RB_DLBWP;
+            // if (l_RB - 1)  > floor (n_RB_DLBWP/2) we need to recalculate them using the following lines
+            tmp_RIV = n_RB_DLBWP * (l_RB - 1) + start_RB;
+            if (tmp_RIV != nr_pdci_info_extracted->freq_dom_resource_assignment_DL) { // then (l_RB - 1)  > floor (n_RB_DLBWP/2) and we need to recalculate l_RB and start_RB
+              l_RB = n_RB_DLBWP - l_RB + 2;
+              start_RB = n_RB_DLBWP - start_RB - 1;
+            }
+            pdlsch0_harq->nb_rb = l_RB;
+            pdlsch0->current_harq_pid = nr_pdci_info_extracted->harq_process_number;
+            pdlsch0->active           = 1;
+            pdlsch0->rnti             = rnti;
+          }*/
+          LOG_DCI_D("nr_pdci_info_extracted->freq_dom_resource_assignment_DL=%x, RIV = %d\n",nr_pdci_info_extracted->freq_dom_resource_assignment_DL,nr_pdci_info_extracted->freq_dom_resource_assignment_DL);
+          //LOG_DCI_D("l_RB=%d, start_RB=%d, n_RB_DLBWP=%d\n",l_RB,start_RB,n_RB_DLBWP);
+          /*
+           * According to TC 38.212 Subclause 7.3.1.2.1 (V15.2.0) (not implemented FIXME!!!)
+           * If the CRC of the DCI format 1_0 is scrambled by C-RNTI
+           * and the "Frequency domain resource assignment" field are of all ones,
+           * the DCI format 1_0 is for random access procedure initiated by a PDCCH order,
+           * with all remaining fields set as follows:
+           * - Random Access Preamble index (6 bits)
+           * - UL/SUL indicator (1 bit)
+           * - SS/PBCH index (6 bits)
+           * - PRACH Mask index (4 bits)
+           * - Reserved bits (10 bits)
+           *
+           */
+          /*
+          * The following commented code is used to verify that l_RB and start_RB are correctly calculated
+          *
+          *
+          printf("\ns_RB\t");
+          n_RB_DLBWP = 20;
+          for (int k = 0 ; k < n_RB_DLBWP; k++) printf("%d\t",k);
+          printf("\nl_RB");
+          for (int j = 1 ; j <= n_RB_DLBWP; j++){ // l_RB
+           printf("\n%d\t",j);
+           for (int i = 0 ; i < n_RB_DLBWP; i++) { // start_RB
+             if ((j-1) <= (floor(n_RB_DLBWP/2)) && ((j+i) <= n_RB_DLBWP)) {
+               tmp_RIV = n_RB_DLBWP * (j - 1) + i;
+               l_RB = floor(tmp_RIV/n_RB_DLBWP) + 1;
+               start_RB = tmp_RIV%n_RB_DLBWP;
+               printf("%d(%d,%d)  ",tmp_RIV,l_RB,start_RB);
+             }
+             if ((j-1) >  (floor(n_RB_DLBWP/2)) && ((j+i) <= n_RB_DLBWP)) {
+               tmp_RIV = n_RB_DLBWP * (n_RB_DLBWP - j + 1) + (n_RB_DLBWP - 1 - i);
+               //l_RB = floor(tmp_RIV/n_RB_DLBWP) + 1;
+               //start_RB = tmp_RIV%n_RB_DLBWP;
+               l_RB = n_RB_DLBWP - (floor(tmp_RIV/n_RB_DLBWP) + 1) + 2;
+               start_RB = n_RB_DLBWP - (tmp_RIV%n_RB_DLBWP) - 1;
+               printf("%d*(%d,%d)  ",tmp_RIV,l_RB,start_RB);
+             }
+           }
+          }*/
+          break;
 
-      case TIME_DOM_RESOURCE_ASSIGNMENT: // 12 TIME_DOM_RESOURCE_ASSIGNMENT: (field defined for format0_0,format0_1,format1_0,format1_1,-,-,-,-)
-               // 0, 1, 2, 3, or 4 bits as defined in:
-               //         Subclause 6.1.2.1 of [6, TS 38.214] for formats format0_0,format0_1
-               //         Subclause 5.1.2.1 of [6, TS 38.214] for formats format1_0,format1_1
-               // The bitwidth for this field is determined as log2(I) bits,
-               // where I the number of entries in the higher layer parameter pusch-AllocationList
-        nr_pdci_info_extracted->time_dom_resource_assignment     = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        /*if (dci_format == format0_0 || dci_format == format0_1){ // Subclause 6.1.2.1 of [6, TS 38.214]
-          k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][0];
-          sliv_S   = table_6_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][1];
-          sliv_L   = table_6_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][2];
-          // k_offset = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0];
-          // sliv_S   = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][1];
-          // sliv_L   = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][2];
+        case TIME_DOM_RESOURCE_ASSIGNMENT: // 12 TIME_DOM_RESOURCE_ASSIGNMENT: (field defined for format0_0,format0_1,format1_0,format1_1,-,-,-,-)
+          // 0, 1, 2, 3, or 4 bits as defined in:
+          //         Subclause 6.1.2.1 of [6, TS 38.214] for formats format0_0,format0_1
+          //         Subclause 5.1.2.1 of [6, TS 38.214] for formats format1_0,format1_1
+          // The bitwidth for this field is determined as log2(I) bits,
+          // where I the number of entries in the higher layer parameter pusch-AllocationList
+          nr_pdci_info_extracted->time_dom_resource_assignment     = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          /*if (dci_format == format0_0 || dci_format == format0_1){ // Subclause 6.1.2.1 of [6, TS 38.214]
+            k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][0];
+            sliv_S   = table_6_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][1];
+            sliv_L   = table_6_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][2];
+            // k_offset = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0];
+            // sliv_S   = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][1];
+            // sliv_L   = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][2];
 
-        }
-        if (dci_format == format1_0 || dci_format == format1_1){ // Subclause 5.1.2.1 of [6, TS 38.214]
-          // the Time domain resource assignment field of the DCI provides a row index of a higher layer configured table pdsch-symbolAllocation
-          // FIXME! To clarify which parameters to update after reception of row index
-          k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][0];
-          sliv_S   = table_5_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][1];
-          sliv_L   = table_5_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][2];
-          // k_offset = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0];
-          // sliv_S   = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][1];
-          // sliv_L   = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][2];
-          // k_offset = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][0];
-          // sliv_S   = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][1];
-          // sliv_L   = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][2];
-          // k_offset = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][0];
-          // sliv_S   = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][1];
-          // sliv_L   = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][2];
-        }*/
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->time_dom_resource_assignment=%x\n",nr_pdci_info_extracted->time_dom_resource_assignment);
-        #endif
-        break;
+          }
+          if (dci_format == format1_0 || dci_format == format1_1){ // Subclause 5.1.2.1 of [6, TS 38.214]
+            // the Time domain resource assignment field of the DCI provides a row index of a higher layer configured table pdsch-symbolAllocation
+            // FIXME! To clarify which parameters to update after reception of row index
+            k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][0];
+            sliv_S   = table_5_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][1];
+            sliv_L   = table_5_1_2_1_1_2_time_dom_res_alloc_A[nr_pdci_info_extracted->time_dom_resource_assignment][2];
+            // k_offset = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0];
+            // sliv_S   = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][1];
+            // sliv_L   = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][2];
+            // k_offset = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][0];
+            // sliv_S   = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][1];
+            // sliv_L   = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][2];
+            // k_offset = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][0];
+            // sliv_S   = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][1];
+            // sliv_L   = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][2];
+          }*/
+          LOG_DCI_D("nr_pdci_info_extracted->time_dom_resource_assignment=%x\n",nr_pdci_info_extracted->time_dom_resource_assignment);
+          break;
 
-      case VRB_TO_PRB_MAPPING: // 13 VRB_TO_PRB_MAPPING: (field defined for -,format0_1,format1_0,format1_1,-,-,-,-)
-      //0 bit if resource allocation type 0
-      //1 bit if resource allocation type 1
-                             //Table 7.3.1.1.2-33: VRB-to-PRB mapping
-                            // 0  Non-interleaved
-                            // 1  Interleaved
-        nr_pdci_info_extracted->vrb_to_prb_mapping               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //if (nr_pdci_info_extracted->vrb_to_prb_mapping == 0) { // Non-interleaved
-        //} else { // Interleaved
-                 // format 0_1 defined in TS 38.211 Section 6.3.1.7
-                 // formats 1_0 and 1_1 not defined yet
-        //}
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->vrb_to_prb_mapping=%x\n",nr_pdci_info_extracted->vrb_to_prb_mapping);
-        #endif
-        break;
+        case VRB_TO_PRB_MAPPING: // 13 VRB_TO_PRB_MAPPING: (field defined for -,format0_1,format1_0,format1_1,-,-,-,-)
+          //0 bit if resource allocation type 0
+          //1 bit if resource allocation type 1
+          //Table 7.3.1.1.2-33: VRB-to-PRB mapping
+          // 0  Non-interleaved
+          // 1  Interleaved
+          nr_pdci_info_extracted->vrb_to_prb_mapping               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //if (nr_pdci_info_extracted->vrb_to_prb_mapping == 0) { // Non-interleaved
+          //} else { // Interleaved
+          // format 0_1 defined in TS 38.211 Section 6.3.1.7
+          // formats 1_0 and 1_1 not defined yet
+          //}
+          LOG_DCI_D("nr_pdci_info_extracted->vrb_to_prb_mapping=%x\n",nr_pdci_info_extracted->vrb_to_prb_mapping);
+          break;
 
-      case PRB_BUNDLING_SIZE_IND: // 14 PRB_BUNDLING_SIZE_IND: (field defined for -,-,-,format1_1,-,-,-,-)
-               // 0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214]
-        nr_pdci_info_extracted->prb_bundling_size_ind            = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->prb_bundling_size_ind=%x\n",nr_pdci_info_extracted->prb_bundling_size_ind);
-        #endif
-        break;
-      case RATE_MATCHING_IND: // 15 RATE_MATCHING_IND: (field defined for -,-,-,format1_1,-,-,-,-)
-               // 0, 1, or 2 bits according to higher layer parameter rate-match-PDSCH-resource-set
-        nr_pdci_info_extracted->rate_matching_ind                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->rate_matching_ind=%x\n",nr_pdci_info_extracted->rate_matching_ind);
-        #endif
-        break;
-      case ZP_CSI_RS_TRIGGER: // 16 ZP_CSI_RS_TRIGGER: (field defined for -,-,-,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->zp_csi_rs_trigger                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->zp_csi_rs_trigger=%x\n",nr_pdci_info_extracted->zp_csi_rs_trigger);
-        #endif
-        break;
+        case PRB_BUNDLING_SIZE_IND: // 14 PRB_BUNDLING_SIZE_IND: (field defined for -,-,-,format1_1,-,-,-,-)
+          // 0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214]
+          nr_pdci_info_extracted->prb_bundling_size_ind            = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->prb_bundling_size_ind=%x\n",nr_pdci_info_extracted->prb_bundling_size_ind);
+          break;
 
-      case FREQ_HOPPING_FLAG: // 17 FREQ_HOPPING_FLAG: (field defined for format0_0,format0_1,-,-,-,-,-,-)
-               // 0 bit if only resource allocation type 0
-               // 1 bit otherwise, only applicable to resource allocation type 1, as defined in Subclause 6.3 of [6, TS 38.214]
-        nr_pdci_info_extracted->freq_hopping_flag                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //if (nr_pdci_info_extracted->freq_hopping_flag != 0) { // PUSCH frequency hopping is performed     (only resource allocation type 1)
+        case RATE_MATCHING_IND: // 15 RATE_MATCHING_IND: (field defined for -,-,-,format1_1,-,-,-,-)
+          // 0, 1, or 2 bits according to higher layer parameter rate-match-PDSCH-resource-set
+          nr_pdci_info_extracted->rate_matching_ind                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->rate_matching_ind=%x\n",nr_pdci_info_extracted->rate_matching_ind);
+          break;
 
-        //} else {                                              // PUSCH frequency hopping is not performed (only resource allocation type 1)
+        case ZP_CSI_RS_TRIGGER: // 16 ZP_CSI_RS_TRIGGER: (field defined for -,-,-,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->zp_csi_rs_trigger                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->zp_csi_rs_trigger=%x\n",nr_pdci_info_extracted->zp_csi_rs_trigger);
+          break;
+
+        case FREQ_HOPPING_FLAG: // 17 FREQ_HOPPING_FLAG: (field defined for format0_0,format0_1,-,-,-,-,-,-)
+          // 0 bit if only resource allocation type 0
+          // 1 bit otherwise, only applicable to resource allocation type 1, as defined in Subclause 6.3 of [6, TS 38.214]
+          nr_pdci_info_extracted->freq_hopping_flag                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //if (nr_pdci_info_extracted->freq_hopping_flag != 0) { // PUSCH frequency hopping is performed     (only resource allocation type 1)
+          //} else {                                              // PUSCH frequency hopping is not performed (only resource allocation type 1)
           // At the moment PUSCH hopping is not implemented. We are considering that the bit is present and the value is '0'
-        //}
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->freq_hopping_flag=%x\n",nr_pdci_info_extracted->freq_hopping_flag);
-        #endif
-        break;
+          //}
+          LOG_DCI_D("nr_pdci_info_extracted->freq_hopping_flag=%x\n",nr_pdci_info_extracted->freq_hopping_flag);
+          break;
 
-      case TB1_MCS: // 18 TB1_MCS: (field defined for -,-,-,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->tb1_mcs                          = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //if (nr_pdci_info_extracted->mcs < 29) pdlsch0_harq->mcs  = nr_pdci_info_extracted->tb1_mcs;
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb1_mcs=%x\n",nr_pdci_info_extracted->tb1_mcs);
-        #endif
-        break;
-      case TB1_NDI: // 19 TB1_NDI: (field defined for -,-,-,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->tb1_ndi                          = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //pdlsch0_harq->DCINdi = nr_pdci_info_extracted->tb1_ndi;
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb1_ndi=%x\n",nr_pdci_info_extracted->tb1_ndi);
-        #endif
-        break;
-      case TB1_RV: // 20 TB1_RV: (field defined for -,-,-,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->tb1_rv                           = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //pdlsch0_harq->rvidx  = nr_pdci_info_extracted->tb1_rv;
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb1_rv=%x\n",nr_pdci_info_extracted->tb1_rv);
-        #endif
-        break;
-      case TB2_MCS: // 21 TB2_MCS: (field defined for -,-,-,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->tb2_mcs                          = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //if (nr_pdci_info_extracted->mcs < 29) pdlsch0_harq->mcs  = nr_pdci_info_extracted->tb2_mcs;
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb2_mcs=%x\n",nr_pdci_info_extracted->tb2_mcs);
-        #endif
-        break;
-      case TB2_NDI: // 22 TB2_NDI: (field defined for -,-,-,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->tb2_ndi                          = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //pdlsch0_harq->DCINdi = nr_pdci_info_extracted->tb2_ndi;
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb2_ndi=%x\n",nr_pdci_info_extracted->tb2_ndi);
-        #endif
-        break;
-      case TB2_RV: // 23 TB2_RV: (field defined for -,-,-,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->tb2_rv                           = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //pdlsch0_harq->rvidx  = nr_pdci_info_extracted->tb2_rv;
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb2_rv=%x\n",nr_pdci_info_extracted->tb2_rv);
-        #endif
-        break;
+        case TB1_MCS: // 18 TB1_MCS: (field defined for -,-,-,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->tb1_mcs                          = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //if (nr_pdci_info_extracted->mcs < 29) pdlsch0_harq->mcs  = nr_pdci_info_extracted->tb1_mcs;
+          LOG_DCI_D("nr_pdci_info_extracted->tb1_mcs=%x\n",nr_pdci_info_extracted->tb1_mcs);
+          break;
 
-      case MCS: // 24 MCS: (field defined for format0_0,format0_1,format1_0,-,-,-,-,-)
-        nr_pdci_info_extracted->mcs                              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //if (nr_pdci_info_extracted->mcs < 29) {
-        //  if (dci_format == format0_0 || dci_format == format0_1)
-        //    ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->mcs = nr_pdci_info_extracted->mcs;
-        //  else
-        //    pdlsch0_harq->mcs = nr_pdci_info_extracted->mcs;
-        //} else {
-        //  return(0);
-        //}
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->mcs=%x\n",nr_pdci_info_extracted->mcs);
-        #endif
-        break;
+        case TB1_NDI: // 19 TB1_NDI: (field defined for -,-,-,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->tb1_ndi                          = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //pdlsch0_harq->DCINdi = nr_pdci_info_extracted->tb1_ndi;
+          LOG_DCI_D("nr_pdci_info_extracted->tb1_ndi=%x\n",nr_pdci_info_extracted->tb1_ndi);
+          break;
 
-      case NDI: // 25 NDI: (field defined for format0_0,format0_1,format1_0,-,-,-,-,-)
-        nr_pdci_info_extracted->ndi                              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //if (dci_format == format0_0 || dci_format == format0_1) {
-        //  ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi = nr_pdci_info_extracted->ndi;
-        //  if (ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->first_tx==1) {
-        //    ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->first_tx=0;
-        //    ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi= nr_pdci_info_extracted->ndi;
-        //    ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->round = 0;
-        //  } else {
-        //    if (ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi != nr_pdci_info_extracted->ndi) { // new SDU opportunity
-        //      ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi= nr_pdci_info_extracted->ndi;
-        //     ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->round = 0;
-        //    }
-        //  }
-        //} else {
-        //  if (rnti == crc_scrambled_values[_TC_RNTI_]) { //fix for standalone Contention Resolution Id
-        //    pdlsch0_harq->DCINdi = (uint8_t)-1;
-        //  } else {
-        //    if ((prev_ndi != nr_pdci_info_extracted->ndi) || (pdlsch0_harq->first_tx==1)) {
-        //      pdlsch0_harq->round    = 0;
-        //      pdlsch0_harq->first_tx = 0;
-        //      pdlsch0_harq->status   = ACTIVE;
-        //    }
-        //    pdlsch0_harq->DCINdi = nr_pdci_info_extracted->ndi;
-        //  }
-        //}
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->ndi=%x\n",nr_pdci_info_extracted->ndi);
-        #endif
-        break;
+        case TB1_RV: // 20 TB1_RV: (field defined for -,-,-,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->tb1_rv                           = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //pdlsch0_harq->rvidx  = nr_pdci_info_extracted->tb1_rv;
+          LOG_DCI_D("nr_pdci_info_extracted->tb1_rv=%x\n",nr_pdci_info_extracted->tb1_rv);
+          break;
 
-      case RV: // 26 RV: (field defined for format0_0,format0_1,format1_0,-,-,-,-,-)
-        nr_pdci_info_extracted->rv                               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //if (dci_format == format0_0 || dci_format == format0_1)
-        //  ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->rvidx = nr_pdci_info_extracted->rv;
-        //else
-        //  pdlsch0_harq->rvidx = nr_pdci_info_extracted->rv;
-        //if ((prev_ndi == nr_pdci_info_extracted->ndi) && (pdlsch0_harq->rvidx != 0)) { // NDI has not been toggled but rv was increased by eNB: retransmission
-        //  if (pdlsch0_harq->status == SCH_IDLE) {
-                        // packet was actually decoded in previous transmission (ACK was missed by eNB)
-                        // however, the round is not a good check as it might have been decoded in a retransmission prior to this one.
-                        // skip pdsch decoding and report ack
-            
-        //    pdlsch0->harq_processes[pdlsch0->current_harq_pid]->harq_ack.ack = 1;
-        //    pdlsch0->harq_processes[pdlsch0->current_harq_pid]->harq_ack.send_harq_status;
-#if 0            
-        //    pdlsch0->active       = 0;
-        //    pdlsch0->harq_ack[nr_tti_rx].ack = 1;
-        //    pdlsch0->harq_ack[nr_tti_rx].harq_id = nr_pdci_info_extracted->harq_process_number;
-        //    pdlsch0->harq_ack[nr_tti_rx].send_harq_status = 1;
-#endif            
-         // } else { // normal retransmission, nothing special to do
-         // }
-        //} else {
-        //  pdlsch0_harq->status   = ACTIVE;
-        //}
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-         printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->rv=%x\n",nr_pdci_info_extracted->rv);
-        #endif
-        break;
+        case TB2_MCS: // 21 TB2_MCS: (field defined for -,-,-,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->tb2_mcs                          = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //if (nr_pdci_info_extracted->mcs < 29) pdlsch0_harq->mcs  = nr_pdci_info_extracted->tb2_mcs;
+          LOG_DCI_D("nr_pdci_info_extracted->tb2_mcs=%x\n",nr_pdci_info_extracted->tb2_mcs);
+          break;
 
-      case HARQ_PROCESS_NUMBER: // 27 HARQ_PROCESS_NUMBER: (field defined for format0_0,format0_1,format1_0,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->harq_process_number              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //pdlsch0->current_harq_pid = nr_pdci_info_extracted->harq_process_number;
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->harq_process_number=%x\n",nr_pdci_info_extracted->harq_process_number);
-        #endif
-        break;
+        case TB2_NDI: // 22 TB2_NDI: (field defined for -,-,-,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->tb2_ndi                          = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //pdlsch0_harq->DCINdi = nr_pdci_info_extracted->tb2_ndi;
+          LOG_DCI_D("nr_pdci_info_extracted->tb2_ndi=%x\n",nr_pdci_info_extracted->tb2_ndi);
+          break;
 
-      case DAI_: // 28 DAI_: (field defined for -,-,format1_0,format1_1,-,-,-,-)
-               // For format1_0: 2 bits as defined in Subclause 9.1.3 at TS 38.213
-               // For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
-               // 2 if one serving cell is configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 bits are the counter DAI
-               // 0 otherwise
-        nr_pdci_info_extracted->dai                              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //pdlsch0->harq_processes[pdlsch0->current_harq_pid]->harq_ack.vDAI_DL = nr_pdci_info_extracted->dai+1;
-        //pdlsch0->harq_ack[nr_tti_rx].vDAI_DL = nr_pdci_info_extracted->dai+1;
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->dai=%x\n",nr_pdci_info_extracted->dai);
-        #endif
-        break;
+        case TB2_RV: // 23 TB2_RV: (field defined for -,-,-,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->tb2_rv                           = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //pdlsch0_harq->rvidx  = nr_pdci_info_extracted->tb2_rv;
+          LOG_DCI_D("nr_pdci_info_extracted->tb2_rv=%x\n",nr_pdci_info_extracted->tb2_rv);
+          break;
 
-      case FIRST_DAI: // 29 FIRST_DAI: (field defined for -,format0_1,-,-,-,-,-,-)
-               // (1 or 2 bits) 1 bit for semi-static HARQ-ACK
-        nr_pdci_info_extracted->first_dai                        = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-         printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->first_dai=%x\n",nr_pdci_info_extracted->first_dai);
-        #endif
-        break;
-      case SECOND_DAI: // 30 SECOND_DAI: (field defined for -,format0_1,-,-,-,-,-,-)
-               // (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks
-        nr_pdci_info_extracted->second_dai                       = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->second_dai=%x\n",nr_pdci_info_extracted->second_dai);
-        #endif
-        break;
+        case MCS: // 24 MCS: (field defined for format0_0,format0_1,format1_0,-,-,-,-,-)
+          nr_pdci_info_extracted->mcs                              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //if (nr_pdci_info_extracted->mcs < 29) {
+          //  if (dci_format == format0_0 || dci_format == format0_1)
+          //    ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->mcs = nr_pdci_info_extracted->mcs;
+          //  else
+          //    pdlsch0_harq->mcs = nr_pdci_info_extracted->mcs;
+          //} else {
+          //  return(0);
+          //}
+          LOG_DCI_D("nr_pdci_info_extracted->mcs=%x\n",nr_pdci_info_extracted->mcs);
+          break;
 
-      case TB_SCALING: // 31 TB_SCALING: (field defined for -,format0_1,-,-,-,-,-,-)
-               // (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks
-        nr_pdci_info_extracted->tb_scaling                       = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tb_scaling=%x\n",nr_pdci_info_extracted->tb_scaling);
-        #endif
-        break;
+        case NDI: // 25 NDI: (field defined for format0_0,format0_1,format1_0,-,-,-,-,-)
+          nr_pdci_info_extracted->ndi                              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //if (dci_format == format0_0 || dci_format == format0_1) {
+          //  ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi = nr_pdci_info_extracted->ndi;
+          //  if (ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->first_tx==1) {
+          //    ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->first_tx=0;
+          //    ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi= nr_pdci_info_extracted->ndi;
+          //    ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->round = 0;
+          //  } else {
+          //    if (ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi != nr_pdci_info_extracted->ndi) { // new SDU opportunity
+          //      ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->DCINdi= nr_pdci_info_extracted->ndi;
+          //     ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->round = 0;
+          //    }
+          //  }
+          //} else {
+          //  if (rnti == crc_scrambled_values[_TC_RNTI_]) { //fix for standalone Contention Resolution Id
+          //    pdlsch0_harq->DCINdi = (uint8_t)-1;
+          //  } else {
+          //    if ((prev_ndi != nr_pdci_info_extracted->ndi) || (pdlsch0_harq->first_tx==1)) {
+          //      pdlsch0_harq->round    = 0;
+          //      pdlsch0_harq->first_tx = 0;
+          //      pdlsch0_harq->status   = ACTIVE;
+          //    }
+          //    pdlsch0_harq->DCINdi = nr_pdci_info_extracted->ndi;
+          //  }
+          //}
+          LOG_DCI_D("nr_pdci_info_extracted->ndi=%x\n",nr_pdci_info_extracted->ndi);
+          break;
 
-      case TPC_PUSCH: // 32 TPC_PUSCH: (field defined for format0_0,format0_1,-,-,-,-,-,-)
-               // defined in Subclause 7.1.1 TS 38.213
-        nr_pdci_info_extracted->tpc_pusch                        = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->TPC = nr_pdci_info_extracted->tpc_pusch;
-        //if (ue->ul_power_control_dedicated[eNB_id].accumulationEnabled == 1) {
-        //  ulsch0->f_pusch += nr_delta_PUSCH_acc[ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->TPC];
-        //} else {
-        //  ulsch0->f_pusch  = nr_delta_PUSCH_abs[ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->TPC];
-        //}
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tpc_pusch=%x\n",nr_pdci_info_extracted->tpc_pusch);
-        #endif
-        break;
+        case RV: // 26 RV: (field defined for format0_0,format0_1,format1_0,-,-,-,-,-)
+          nr_pdci_info_extracted->rv                               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //if (dci_format == format0_0 || dci_format == format0_1)
+          //  ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->rvidx = nr_pdci_info_extracted->rv;
+          //else
+          //  pdlsch0_harq->rvidx = nr_pdci_info_extracted->rv;
+          //if ((prev_ndi == nr_pdci_info_extracted->ndi) && (pdlsch0_harq->rvidx != 0)) { // NDI has not been toggled but rv was increased by eNB: retransmission
+          //  if (pdlsch0_harq->status == SCH_IDLE) {
+          // packet was actually decoded in previous transmission (ACK was missed by eNB)
+          // however, the round is not a good check as it might have been decoded in a retransmission prior to this one.
+          // skip pdsch decoding and report ack
+          //    pdlsch0->harq_processes[pdlsch0->current_harq_pid]->harq_ack.ack = 1;
+          //    pdlsch0->harq_processes[pdlsch0->current_harq_pid]->harq_ack.send_harq_status;
+#if 0
+          //    pdlsch0->active       = 0;
+          //    pdlsch0->harq_ack[nr_tti_rx].ack = 1;
+          //    pdlsch0->harq_ack[nr_tti_rx].harq_id = nr_pdci_info_extracted->harq_process_number;
+          //    pdlsch0->harq_ack[nr_tti_rx].send_harq_status = 1;
+#endif
+          // } else { // normal retransmission, nothing special to do
+          // }
+          //} else {
+          //  pdlsch0_harq->status   = ACTIVE;
+          //}
+          LOG_DCI_D("nr_pdci_info_extracted->rv=%x\n",nr_pdci_info_extracted->rv);
+          break;
 
-      case TPC_PUCCH: // 33 TPC_PUCCH: (field defined for -,-,format1_0,format1_1,-,-,-,-)
-               // defined in Subclause 7.2.1 TS 38.213
-        nr_pdci_info_extracted->tpc_pucch                        = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        //pdlsch0_harq->delta_PUCCH  = nr_delta_PUCCH_lut[nr_pdci_info_extracted->tpc_pucch &3];
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tpc_pucch=%x\n",nr_pdci_info_extracted->tpc_pucch);
-        #endif
-        break;
+        case HARQ_PROCESS_NUMBER: // 27 HARQ_PROCESS_NUMBER: (field defined for format0_0,format0_1,format1_0,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->harq_process_number              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //pdlsch0->current_harq_pid = nr_pdci_info_extracted->harq_process_number;
+          LOG_DCI_D("nr_pdci_info_extracted->harq_process_number=%x\n",nr_pdci_info_extracted->harq_process_number);
+          break;
 
-      case PUCCH_RESOURCE_IND: // 34 PUCCH_RESOURCE_IND: (field defined for -,-,format1_0,format1_1,-,-,-,-)
-               // defined in Subclause 9.2.3 TS 38.213
-               // PUCCH_RESOURCE_IND points to PUCCH-ResourceId, but PUCCH-ResourceId is not defined yet
-        nr_pdci_info_extracted->pucch_resource_ind               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->pucch_resource_ind=%x\n",nr_pdci_info_extracted->pucch_resource_ind);
-        #endif
-        break;
+        case DAI_: // 28 DAI_: (field defined for -,-,format1_0,format1_1,-,-,-,-)
+          // For format1_0: 2 bits as defined in Subclause 9.1.3 at TS 38.213
+          // For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
+          // 2 if one serving cell is configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 bits are the counter DAI
+          // 0 otherwise
+          nr_pdci_info_extracted->dai                              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //pdlsch0->harq_processes[pdlsch0->current_harq_pid]->harq_ack.vDAI_DL = nr_pdci_info_extracted->dai+1;
+          //pdlsch0->harq_ack[nr_tti_rx].vDAI_DL = nr_pdci_info_extracted->dai+1;
+          LOG_DCI_D("nr_pdci_info_extracted->dai=%x\n",nr_pdci_info_extracted->dai);
+          break;
 
-      case PDSCH_TO_HARQ_FEEDBACK_TIME_IND: // 35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND: (field defined for -,-,format1_0,format1_1,-,-,-,-)
-               // defined in Subclause 9.2.3 TS 38.213
-               // PDSCH_TO_HARQ_FEEDBACK_TIME_IND points to DL-data-DL-acknowledgement, but DL-data-DL-acknowledgement is not defined yet
-        nr_pdci_info_extracted->pdsch_to_harq_feedback_time_ind  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-          printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->pdsch_to_harq_feedback_time_ind=%x\n",nr_pdci_info_extracted->pdsch_to_harq_feedback_time_ind);
-        #endif
-        break;
+        case FIRST_DAI: // 29 FIRST_DAI: (field defined for -,format0_1,-,-,-,-,-,-)
+          // (1 or 2 bits) 1 bit for semi-static HARQ-ACK
+          nr_pdci_info_extracted->first_dai                        = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->first_dai=%x\n",nr_pdci_info_extracted->first_dai);
+          break;
 
-      case SRS_RESOURCE_IND: // 36 SRS_RESOURCE_IND: (field defined for -,format0_1,-,-,-,-,-,-)
-        nr_pdci_info_extracted->srs_resource_ind                 = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->srs_resource_ind=%x\n",nr_pdci_info_extracted->srs_resource_ind);
-        #endif
-        break;
-      case PRECOD_NBR_LAYERS: // 37 PRECOD_NBR_LAYERS: (field defined for -,format0_1,-,-,-,-,-,-)
-        nr_pdci_info_extracted->precod_nbr_layers                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->precod_nbr_layers=%x\n",nr_pdci_info_extracted->precod_nbr_layers);
-        #endif
-        break;
-      case ANTENNA_PORTS: // 38 ANTENNA_PORTS: (field defined for -,format0_1,-,format1_1,-,-,-,-)
-        nr_pdci_info_extracted->antenna_ports                    = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->antenna_ports=%x\n",nr_pdci_info_extracted->antenna_ports);
-        #endif
-        break;
-      case TCI: // 39 TCI: (field defined for -,-,-,format1_1,-,-,-,-)
-               // 0 bit if higher layer parameter tci-PresentInDCI is not enabled; otherwise 3 bits
-        nr_pdci_info_extracted->tci                              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tci=%x\n",nr_pdci_info_extracted->tci);
-        #endif
-        break;
-      case SRS_REQUEST: // 40 SRS_REQUEST: (field defined for -,format0_1,-,format1_1,-,-,-,format2_3)
-        nr_pdci_info_extracted->srs_request                      = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->srs_request=%x\n",nr_pdci_info_extracted->srs_request);
-        #endif
-        break;
-      case TPC_CMD: // 41 TPC_CMD: (field defined for -,-,-,-,-,-,-,format2_3)
-        nr_pdci_info_extracted->tpc_cmd         = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->tpc_cmd=%x\n",nr_pdci_info_extracted->tpc_cmd);
-        #endif
-        break;
-      case CSI_REQUEST: // 42 CSI_REQUEST: (field defined for -,format0_1,-,-,-,-,-,-)
-        nr_pdci_info_extracted->csi_request                      = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->csi_request=%x\n",nr_pdci_info_extracted->csi_request);
-        #endif
-        break;
-      case CBGTI: // 43 CBGTI: (field defined for -,format0_1,-,format1_1,-,-,-,-)
-               // 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH
-        nr_pdci_info_extracted->cbgti                            = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->cbgti=%x\n",nr_pdci_info_extracted->cbgti);
-        #endif
-        break;
-      case CBGFI: // 44 CBGFI: (field defined for -,-,-,format1_1,-,-,-,-)
-                  // 0 or 1 bit determined by higher layer parameter codeBlockGroupFlushIndicator
-        nr_pdci_info_extracted->cbgfi                            = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->cbgfi=%x\n",nr_pdci_info_extracted->cbgfi);
-        #endif
-        break;
-      case PTRS_DMRS: // 45 PTRS_DMRS: (field defined for -,format0_1,-,-,-,-,-,-)
-        nr_pdci_info_extracted->ptrs_dmrs                        = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->ptrs_dmrs=%x\n",nr_pdci_info_extracted->ptrs_dmrs);
-        #endif
-        break;
-      case BETA_OFFSET_IND: // 46 BETA_OFFSET_IND: (field defined for -,format0_1,-,-,-,-,-,-)
-        nr_pdci_info_extracted->beta_offset_ind                  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->beta_offset_ind=%x\n",nr_pdci_info_extracted->beta_offset_ind);
-        #endif
-        break;
-      case DMRS_SEQ_INI: // 47 DMRS_SEQ_INI: (field defined for -,format0_1,-,format1_1,-,-,-,-)
-               // 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding is larger than the number of bits for DCI format 0_0 before padding; 0 bit otherwise
-        nr_pdci_info_extracted->dmrs_seq_ini                     = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->dmrs_seq_ini=%x\n",nr_pdci_info_extracted->dmrs_seq_ini);
-        #endif
-        break;
-      case UL_SCH_IND: // 48 UL_SCH_IND: (field defined for -,format0_1,-,-,-,-,-,-)
-               // value of "1" indicates UL-SCH shall be transmitted on the PUSCH and a value of "0" indicates UL-SCH shall not be transmitted on the PUSCH
-        nr_pdci_info_extracted->ul_sch_ind                     = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->dmrs_seq_ini=%x\n",nr_pdci_info_extracted->ul_sch_ind);
-        #endif
-        break;
+        case SECOND_DAI: // 30 SECOND_DAI: (field defined for -,format0_1,-,-,-,-,-,-)
+          // (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks
+          nr_pdci_info_extracted->second_dai                       = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->second_dai=%x\n",nr_pdci_info_extracted->second_dai);
+          break;
 
-      case PADDING_NR_DCI: // 49 PADDING_NR_DCI: (field defined for format0_0,-,format1_0,-,-,-,-,-)
-               // (Note 2) If DCI format 0_0 is monitored in common search space
-        nr_pdci_info_extracted->padding_nr_dci                 = (uint16_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->padding=%x\n",nr_pdci_info_extracted->padding_nr_dci);
-        #endif
-        break;
+        case TB_SCALING: // 31 TB_SCALING: (field defined for -,format0_1,-,-,-,-,-,-)
+          // (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks
+          nr_pdci_info_extracted->tb_scaling                       = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->tb_scaling=%x\n",nr_pdci_info_extracted->tb_scaling);
+          break;
 
-      case SUL_IND_0_0: // 50 SUL_IND_0_0: (field defined for format0_0,-,-,-,-,-,-,-)
-        nr_pdci_info_extracted->sul_ind_0_0                    = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->sul_ind_0_0=%x\n",nr_pdci_info_extracted->sul_ind_0_0);
-        #endif
-        break;
+        case TPC_PUSCH: // 32 TPC_PUSCH: (field defined for format0_0,format0_1,-,-,-,-,-,-)
+          // defined in Subclause 7.1.1 TS 38.213
+          nr_pdci_info_extracted->tpc_pusch                        = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->TPC = nr_pdci_info_extracted->tpc_pusch;
+          //if (ue->ul_power_control_dedicated[eNB_id].accumulationEnabled == 1) {
+          //  ulsch0->f_pusch += nr_delta_PUSCH_acc[ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->TPC];
+          //} else {
+          //  ulsch0->f_pusch  = nr_delta_PUSCH_abs[ulsch0->harq_processes[nr_pdci_info_extracted->harq_process_number]->TPC];
+          //}
+          LOG_DCI_D("nr_pdci_info_extracted->tpc_pusch=%x\n",nr_pdci_info_extracted->tpc_pusch);
+          break;
 
-      case RA_PREAMBLE_INDEX: // 51 RA_PREAMBLE_INDEX: (field defined for format0_0,-,-,-,-,-,-,-)
-        nr_pdci_info_extracted->ra_preamble_index              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->ra_preamble_index=%x\n",nr_pdci_info_extracted->ra_preamble_index);
-        #endif
-        break;
+        case TPC_PUCCH: // 33 TPC_PUCCH: (field defined for -,-,format1_0,format1_1,-,-,-,-)
+          // defined in Subclause 7.2.1 TS 38.213
+          nr_pdci_info_extracted->tpc_pucch                        = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          //pdlsch0_harq->delta_PUCCH  = nr_delta_PUCCH_lut[nr_pdci_info_extracted->tpc_pucch &3];
+          LOG_DCI_D("nr_pdci_info_extracted->tpc_pucch=%x\n",nr_pdci_info_extracted->tpc_pucch);
+          break;
 
-      case SUL_IND_1_0: // 52 SUL_IND_1_0: (field defined for -,-,format1_0,-,-,-,-,-)
-        nr_pdci_info_extracted->sul_ind_1_0                    = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->sul_ind_1_0=%x\n",nr_pdci_info_extracted->sul_ind_1_0);
-        #endif
-        break;
+        case PUCCH_RESOURCE_IND: // 34 PUCCH_RESOURCE_IND: (field defined for -,-,format1_0,format1_1,-,-,-,-)
+          // defined in Subclause 9.2.3 TS 38.213
+          // PUCCH_RESOURCE_IND points to PUCCH-ResourceId, but PUCCH-ResourceId is not defined yet
+          nr_pdci_info_extracted->pucch_resource_ind               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->pucch_resource_ind=%x\n",nr_pdci_info_extracted->pucch_resource_ind);
+          break;
 
-      case SS_PBCH_INDEX: // 53 SS_PBCH_INDEX: (field defined for -,-,format1_0,-,-,-,-,-)
-        nr_pdci_info_extracted->ss_pbch_index                  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->ss_pbch_index=%x\n",nr_pdci_info_extracted->ss_pbch_index);
-        #endif
-        break;
+        case PDSCH_TO_HARQ_FEEDBACK_TIME_IND: // 35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND: (field defined for -,-,format1_0,format1_1,-,-,-,-)
+          // defined in Subclause 9.2.3 TS 38.213
+          // PDSCH_TO_HARQ_FEEDBACK_TIME_IND points to DL-data-DL-acknowledgement, but DL-data-DL-acknowledgement is not defined yet
+          nr_pdci_info_extracted->pdsch_to_harq_feedback_time_ind  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->pdsch_to_harq_feedback_time_ind=%x\n",nr_pdci_info_extracted->pdsch_to_harq_feedback_time_ind);
+          break;
 
-      case PRACH_MASK_INDEX: // 54 PRACH_MASK_INDEX: (field defined for -,-,-,format1_0,-,-,-,-)
-        nr_pdci_info_extracted->prach_mask_index               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->prach_mask_index=%x\n",nr_pdci_info_extracted->prach_mask_index);
-        #endif
-        break;
+        case SRS_RESOURCE_IND: // 36 SRS_RESOURCE_IND: (field defined for -,format0_1,-,-,-,-,-,-)
+          nr_pdci_info_extracted->srs_resource_ind                 = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->srs_resource_ind=%x\n",nr_pdci_info_extracted->srs_resource_ind);
+          break;
 
-      case RESERVED_NR_DCI: // 55 RESERVED_NR_DCI: (field defined for -,-,-,format1_0,-,-,-,-)
-        nr_pdci_info_extracted->reserved_nr_dci                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
-        //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
-        #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-        printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> nr_pdci_info_extracted->reserved_nr_dci=%x\n",nr_pdci_info_extracted->reserved_nr_dci);
-        #endif
-        break;
+        case PRECOD_NBR_LAYERS: // 37 PRECOD_NBR_LAYERS: (field defined for -,format0_1,-,-,-,-,-,-)
+          nr_pdci_info_extracted->precod_nbr_layers                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->precod_nbr_layers=%x\n",nr_pdci_info_extracted->precod_nbr_layers);
+          break;
+
+        case ANTENNA_PORTS: // 38 ANTENNA_PORTS: (field defined for -,format0_1,-,format1_1,-,-,-,-)
+          nr_pdci_info_extracted->antenna_ports                    = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->antenna_ports=%x\n",nr_pdci_info_extracted->antenna_ports);
+          break;
+
+        case TCI: // 39 TCI: (field defined for -,-,-,format1_1,-,-,-,-)
+          // 0 bit if higher layer parameter tci-PresentInDCI is not enabled; otherwise 3 bits
+          nr_pdci_info_extracted->tci                              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->tci=%x\n",nr_pdci_info_extracted->tci);
+          break;
+
+        case SRS_REQUEST: // 40 SRS_REQUEST: (field defined for -,format0_1,-,format1_1,-,-,-,format2_3)
+          nr_pdci_info_extracted->srs_request                      = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->srs_request=%x\n",nr_pdci_info_extracted->srs_request);
+          break;
+
+        case TPC_CMD: // 41 TPC_CMD: (field defined for -,-,-,-,-,-,-,format2_3)
+          nr_pdci_info_extracted->tpc_cmd         = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->tpc_cmd=%x\n",nr_pdci_info_extracted->tpc_cmd);
+          break;
+
+        case CSI_REQUEST: // 42 CSI_REQUEST: (field defined for -,format0_1,-,-,-,-,-,-)
+          nr_pdci_info_extracted->csi_request                      = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->csi_request=%x\n",nr_pdci_info_extracted->csi_request);
+          break;
+
+        case CBGTI: // 43 CBGTI: (field defined for -,format0_1,-,format1_1,-,-,-,-)
+          // 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH
+          nr_pdci_info_extracted->cbgti                            = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->cbgti=%x\n",nr_pdci_info_extracted->cbgti);
+          break;
+
+        case CBGFI: // 44 CBGFI: (field defined for -,-,-,format1_1,-,-,-,-)
+          // 0 or 1 bit determined by higher layer parameter codeBlockGroupFlushIndicator
+          nr_pdci_info_extracted->cbgfi                            = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->cbgfi=%x\n",nr_pdci_info_extracted->cbgfi);
+          break;
+
+        case PTRS_DMRS: // 45 PTRS_DMRS: (field defined for -,format0_1,-,-,-,-,-,-)
+          nr_pdci_info_extracted->ptrs_dmrs                        = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->ptrs_dmrs=%x\n",nr_pdci_info_extracted->ptrs_dmrs);
+          break;
+
+        case BETA_OFFSET_IND: // 46 BETA_OFFSET_IND: (field defined for -,format0_1,-,-,-,-,-,-)
+          nr_pdci_info_extracted->beta_offset_ind                  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->beta_offset_ind=%x\n",nr_pdci_info_extracted->beta_offset_ind);
+          break;
+
+        case DMRS_SEQ_INI: // 47 DMRS_SEQ_INI: (field defined for -,format0_1,-,format1_1,-,-,-,-)
+          // 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding is larger than the number of bits for DCI format 0_0 before padding; 0 bit otherwise
+          nr_pdci_info_extracted->dmrs_seq_ini                     = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->dmrs_seq_ini=%x\n",nr_pdci_info_extracted->dmrs_seq_ini);
+          break;
+
+        case UL_SCH_IND: // 48 UL_SCH_IND: (field defined for -,format0_1,-,-,-,-,-,-)
+          // value of "1" indicates UL-SCH shall be transmitted on the PUSCH and a value of "0" indicates UL-SCH shall not be transmitted on the PUSCH
+          nr_pdci_info_extracted->ul_sch_ind                     = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->dmrs_seq_ini=%x\n",nr_pdci_info_extracted->ul_sch_ind);
+          break;
+
+        case PADDING_NR_DCI: // 49 PADDING_NR_DCI: (field defined for format0_0,-,format1_0,-,-,-,-,-)
+          // (Note 2) If DCI format 0_0 is monitored in common search space
+          nr_pdci_info_extracted->padding_nr_dci                 = (uint16_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->padding=%x\n",nr_pdci_info_extracted->padding_nr_dci);
+          break;
+
+        case SUL_IND_0_0: // 50 SUL_IND_0_0: (field defined for format0_0,-,-,-,-,-,-,-)
+          nr_pdci_info_extracted->sul_ind_0_0                    = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->sul_ind_0_0=%x\n",nr_pdci_info_extracted->sul_ind_0_0);
+          break;
+
+        case RA_PREAMBLE_INDEX: // 51 RA_PREAMBLE_INDEX: (field defined for format0_0,-,-,-,-,-,-,-)
+          nr_pdci_info_extracted->ra_preamble_index              = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->ra_preamble_index=%x\n",nr_pdci_info_extracted->ra_preamble_index);
+          break;
+
+        case SUL_IND_1_0: // 52 SUL_IND_1_0: (field defined for -,-,format1_0,-,-,-,-,-)
+          nr_pdci_info_extracted->sul_ind_1_0                    = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->sul_ind_1_0=%x\n",nr_pdci_info_extracted->sul_ind_1_0);
+          break;
+
+        case SS_PBCH_INDEX: // 53 SS_PBCH_INDEX: (field defined for -,-,format1_0,-,-,-,-,-)
+          nr_pdci_info_extracted->ss_pbch_index                  = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->ss_pbch_index=%x\n",nr_pdci_info_extracted->ss_pbch_index);
+          break;
 
+        case PRACH_MASK_INDEX: // 54 PRACH_MASK_INDEX: (field defined for -,-,-,format1_0,-,-,-,-)
+          nr_pdci_info_extracted->prach_mask_index               = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->prach_mask_index=%x\n",nr_pdci_info_extracted->prach_mask_index);
+          break;
+
+        case RESERVED_NR_DCI: // 55 RESERVED_NR_DCI: (field defined for -,-,-,format1_0,-,-,-,-)
+          nr_pdci_info_extracted->reserved_nr_dci                = (uint8_t)nr_dci_field(dci_pdu,dci_fields_sizes_format,dci_field);
+          //(((((*(uint128_t *)dci_pdu)  << (left_shift - dci_fields_sizes[dci_field][dci_format]))) & pdu_bitmap) >> (dci_length - dci_fields_sizes[dci_field][dci_format]));
+          LOG_DCI_D("nr_pdci_info_extracted->reserved_nr_dci=%x\n",nr_pdci_info_extracted->reserved_nr_dci);
+          break;
       }
     }
   }
-  #ifdef NR_PDCCH_DCI_TOOLS_DEBUG
-    printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> Ending function nr_extract_dci_info()\n");
-  #endif
+
+  LOG_DCI_D("Ending function nr_extract_dci_info()\n");
   return(1);
 }
 
@@ -1015,34 +923,29 @@ int nr_extract_dci_info(PHY_VARS_NR_UE *ue,
 #ifdef NR_PDCCH_DCI_TOOLS
 
 int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue,
-        uint8_t eNB_id,
-        int frame,
-        uint8_t nr_tti_rx,
-        uint64_t dci_pdu[2],
-        uint16_t rnti,
-        uint8_t dci_length,
-        NR_DCI_format_t dci_format,
-        NR_DL_FRAME_PARMS *frame_parms,
-        PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated,
-        uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS],
-        uint16_t n_RB_ULBWP,
-        uint16_t n_RB_DLBWP,
-        uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES],
-        fapi_nr_dci_pdu_rel15_t *nr_dci_info_extracted)
-{
+    uint8_t eNB_id,
+    int frame,
+    uint8_t nr_tti_rx,
+    uint64_t dci_pdu[2],
+    uint16_t rnti,
+    uint8_t dci_length,
+    NR_DCI_format_t dci_format,
+    NR_DL_FRAME_PARMS *frame_parms,
+    PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated,
+    uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS],
+    uint16_t n_RB_ULBWP,
+    uint16_t n_RB_DLBWP,
+    uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES],
+    fapi_nr_dci_pdu_rel15_t *nr_dci_info_extracted) {
   /*
    * Note only format0_0 and format1_0 are implemented
    */
-
   uint8_t frame_type=frame_parms->frame_type;
   uint8_t status=0;
-
-  LOG_D(PHY,"\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> dci_format=%d, rnti=%d, dci_length=%d, dci_pdu[0]=0x%lx, dci_pdu[1]=0x%lx\n",dci_format,rnti,dci_length,dci_pdu[0],dci_pdu[1]);
-
+  LOG_DCI_PARM("dci_format=%d, rnti=%d, dci_length=%d, dci_pdu[0]=0x%lx, dci_pdu[1]=0x%lx\n",dci_format,rnti,dci_length,dci_pdu[0],
+        dci_pdu[1]);
   memset(nr_dci_info_extracted,0,sizeof(*nr_dci_info_extracted));
-
-  LOG_D(PHY,"\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> Entering function nr_extract_dci_info(dci_format=%d) \n",dci_format);
-
+  LOG_DCI_PARM("Entering function nr_extract_dci_info(dci_format=%d) \n",dci_format);
   status = nr_extract_dci_info(ue,
                                eNB_id,
                                frame_type,
@@ -1058,21 +961,18 @@ int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue,
                                crc_scrambled_values);
 
   if(status == 0) {
-    LOG_W(PHY,"\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> bad DCI %d !!! \n",dci_format);
+    LOG_DCI_PARM("bad DCI %d !!! \n",dci_format);
     return(-1);
   }
 
-  LOG_D(PHY,"\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> Ending function nr_extract_dci_info()\n");
-
-  //fill 
-  
+  LOG_DCI_PARM("Ending function nr_extract_dci_info()\n");
+  //fill
   return(0);
 }
 
 #endif
 
-uint8_t nr_subframe2harq_pid(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t nr_tti_rx)
-{
+uint8_t nr_subframe2harq_pid(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t nr_tti_rx) {
   /*
     #ifdef DEBUG_DCI
     if (frame_parms->frame_type == TDD)
@@ -1081,81 +981,77 @@ uint8_t nr_subframe2harq_pid(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8
     printf("dci_tools.c: subframe2_harq_pid, subframe %d for FDD \n",subframe);
     #endif
   */
-
   uint8_t ret = 255;
   uint8_t subframe = nr_tti_rx>>((int)(log2 (frame_parms->ttis_per_subframe)));
 
   if (frame_parms->frame_type == FDD) {
     ret = (((frame<<1)+nr_tti_rx)&7);
   } else {
-
     switch (frame_parms->tdd_config) {
+      case 1:
+        if ((subframe==2) ||
+            (subframe==3) ||
+            (subframe==7) ||
+            (subframe==8))
+          switch (subframe) {
+            case 2:
+            case 3:
+              ret = (subframe-2);
+              break;
+
+            case 7:
+            case 8:
+              ret = (subframe-5);
+              break;
+
+            default:
+              LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+              ret = (255);
+              break;
+          }
 
-    case 1:
-      if ((subframe==2) ||
-          (subframe==3) ||
-          (subframe==7) ||
-          (subframe==8))
-        switch (subframe) {
-        case 2:
-        case 3:
-          ret = (subframe-2);
-          break;
-
-        case 7:
-        case 8:
-          ret = (subframe-5);
-          break;
+        break;
 
-        default:
+      case 2:
+        if ((subframe!=2) && (subframe!=7)) {
           LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+          //mac_xface->macphy_exit("subframe2_harq_pid, Illegal subframe");
           ret = (255);
-          break;
         }
 
-      break;
+        ret = (subframe/7);
+        break;
 
-    case 2:
-      if ((subframe!=2) && (subframe!=7)) {
-        LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
-        //mac_xface->macphy_exit("subframe2_harq_pid, Illegal subframe");
-        ret = (255);
-      }
+      case 3:
+        if ((subframe<2) || (subframe>4)) {
+          LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+          ret = (255);
+        }
 
-      ret = (subframe/7);
-      break;
+        ret = (subframe-2);
+        break;
 
-    case 3:
-      if ((subframe<2) || (subframe>4)) {
-        LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
-        ret = (255);
-      }
+      case 4:
+        if ((subframe<2) || (subframe>3)) {
+          LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+          ret = (255);
+        }
 
-      ret = (subframe-2);
-      break;
+        ret = (subframe-2);
+        break;
 
-    case 4:
-      if ((subframe<2) || (subframe>3)) {
-        LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
-        ret = (255);
-      }
+      case 5:
+        if (subframe!=2) {
+          LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+          ret = (255);
+        }
 
-      ret = (subframe-2);
-      break;
+        ret = (subframe-2);
+        break;
 
-    case 5:
-      if (subframe!=2) {
-        LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+      default:
+        LOG_E(PHY,"subframe2_harq_pid, Unsupported TDD mode %d\n",frame_parms->tdd_config);
         ret = (255);
-      }
-
-      ret = (subframe-2);
-      break;
-
-    default:
-      LOG_E(PHY,"subframe2_harq_pid, Unsupported TDD mode %d\n",frame_parms->tdd_config);
-      ret = (255);
-
     }
   }
 
@@ -1163,12 +1059,12 @@ uint8_t nr_subframe2harq_pid(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8
     LOG_E(PHY, "invalid harq_pid(%d) at SFN/SF = %d/%d\n", ret, frame, subframe);
     //mac_xface->macphy_exit("invalid harq_pid");
   }
+
   return ret;
 }
 
 
-uint8_t nr_pdcch_alloc2ul_subframe(NR_DL_FRAME_PARMS *frame_parms,uint8_t n)
-{
+uint8_t nr_pdcch_alloc2ul_subframe(NR_DL_FRAME_PARMS *frame_parms,uint8_t n) {
   uint8_t ul_subframe = 255;
 
   if ((frame_parms->frame_type == TDD) &&
@@ -1190,8 +1086,7 @@ uint8_t nr_pdcch_alloc2ul_subframe(NR_DL_FRAME_PARMS *frame_parms,uint8_t n)
   return ul_subframe;
 }
 
-uint32_t nr_pdcch_alloc2ul_frame(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t n)
-{
+uint32_t nr_pdcch_alloc2ul_frame(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame, uint8_t n) {
   uint32_t ul_frame = 255;
 
   if ((frame_parms->frame_type == TDD) &&
@@ -1211,6 +1106,5 @@ uint32_t nr_pdcch_alloc2ul_frame(NR_DL_FRAME_PARMS *frame_parms,uint32_t frame,
 
   LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n", frame, n, ul_frame);
   return ul_frame;
-
 }
 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
index 12aaebc91755ca214322d4e30f6b1dffa2e8c402..d2dbd6fef2869a3d4ff290767b7f95c6b942b72c 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
@@ -124,7 +124,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
     ulsch_ue->length_dmrs = length_dmrs;
     ulsch_ue->rnti        = n_rnti;
     ulsch_ue->Nid_cell    = Nid_cell;
-    ulsch_ue->nb_re_dmrs  = UE->dmrs_UplinkConfig.pusch_maxLength*(UE->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)?6:4;
+    ulsch_ue->nb_re_dmrs  = UE->dmrs_UplinkConfig.pusch_maxLength*(UE->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1?6:4);
 
     N_RE_prime = NR_NB_SC_PER_RB*harq_process_ul_ue->number_of_symbols - ulsch_ue->nb_re_dmrs - N_PRB_oh;
 
diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h
index 80d63cbdd9e307d56d8108f8cfd519def8b9bc62..0ec04dd5370ac200e8e12f68fc95c88484882d8a 100644
--- a/openair1/PHY/defs_RU.h
+++ b/openair1/PHY/defs_RU.h
@@ -104,6 +104,10 @@ typedef struct {
   /// - first index: tx antenna [0..nb_antennas_tx[
   /// - second index: sample [0..]
   int32_t **txdataF_BF;
+  /// \brief holds the transmit data before beamforming in the frequency domain.
+  /// - first index: tx antenna [0..nb_antennas_tx[
+  /// - second index: sample [0..]
+  int32_t **txdataF;
   /// \brief holds the transmit data before beamforming for epdcch/mpdcch
   /// - first index : tx antenna [0..nb_epdcch_antenna_ports[
   /// - second index: sampl [0..]
@@ -147,6 +151,44 @@ typedef struct {
 } RU_CALIBRATION;
 
 
+typedef struct RU_prec_t_s{
+  /// \internal This variable is protected by \ref mutex_feptx_prec
+  int instance_cnt_feptx_prec;
+  /// pthread struct for RU TX FEP PREC worker thread
+  pthread_t pthread_feptx_prec;
+  /// pthread attributes for worker feptx prec thread
+  pthread_attr_t attr_feptx_prec;
+  /// condition varible for RU TX FEP PREC thread
+  pthread_cond_t cond_feptx_prec;
+  /// mutex for fep PREC TX worker thread
+  pthread_mutex_t mutex_feptx_prec;
+  int symbol;
+  int p;//logical
+  int aa;//physical MAX nb_tx
+  struct RU_t_s *ru;
+  int index;
+} RU_prec_t;
+
+typedef struct RU_feptx_t_s{
+  /// \internal This variable is protected by \ref mutex_feptx_prec
+  int instance_cnt_feptx;
+  /// pthread struct for RU TX FEP PREC worker thread
+  pthread_t pthread_feptx;
+  /// pthread attributes for worker feptx prec thread
+  pthread_attr_t attr_feptx;
+  /// condition varible for RU TX FEP PREC thread
+  pthread_cond_t cond_feptx;
+  /// mutex for fep PREC TX worker thread
+  pthread_mutex_t mutex_feptx;
+  struct RU_t_s *ru;
+  int aa;//physical MAX nb_tx
+  int half_slot;//first or second half of a slot
+  int slot;//current slot
+  int symbol;//current symbol
+  int nb_antenna_ports;//number of logical port
+  int index;
+}RU_feptx_t;
+
 typedef struct RU_proc_t_s {
   /// Pointer to associated RU descriptor
   struct RU_t_s *ru;
@@ -339,8 +381,14 @@ typedef struct RU_proc_t_s {
   int ru_rx_ready;
   int ru_tx_ready;
   int emulate_rf_busy;
-} RU_proc_t;
 
+  /// structure for precoding thread
+  RU_prec_t prec[16];
+  /// structure for feptx thread
+  RU_feptx_t feptx[16];
+  /// mask for checking process finished
+  int feptx_mask;
+} RU_proc_t;
 
 typedef enum {
   LOCAL_RF        =0,
@@ -495,10 +543,16 @@ typedef struct RU_t_s {
   void (*eNB_top)(struct PHY_VARS_eNB_s *eNB, int frame_rx, int subframe_rx, char *string, struct RU_t_s *ru);
   void (*gNB_top)(struct PHY_VARS_gNB_s *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru);
 
+  /// Timing data copy statistics (TX)
+  time_stats_t txdataF_copy_stats;
+  /// Timing statistics (TX)
+  time_stats_t precoding_stats;
   /// Timing statistics
   time_stats_t ofdm_demod_stats;
   /// Timing statistics (TX)
   time_stats_t ofdm_mod_stats;
+  /// Timing statistics (TX)
+  time_stats_t ofdm_total_stats;
   /// Timing wait statistics
   time_stats_t ofdm_demod_wait_stats;
   /// Timing wakeup statistics
@@ -518,10 +572,12 @@ typedef struct RU_t_s {
   /// RX and TX buffers for precoder output
   RU_COMMON common;
   RU_CALIBRATION calibration;
-  /// beamforming weight vectors per eNB
+  /// beamforming weight list size
+  int nb_bfw;
+  /// beamforming weight list of values
+  int32_t *bw_list[NUMBER_OF_eNB_MAX+1];
+  /// beamforming weight vectors
   int32_t **beam_weights[NUMBER_OF_eNB_MAX+1][15];
-  /// beamforming weight vectors per gNB
-  int32_t **nrbeam_weights[NUMBER_OF_gNB_MAX+1][16];
   /// received frequency-domain signal for PRACH (IF4p5 RRU)
   int16_t **prach_rxsigF;
   /// received frequency-domain signal for PRACH BR (IF4p5 RRU)
diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h
index 86d2a7531d2bb340067f643113db21e1fb04d797..048e48ae458569f2e0eb2e5104ed6f930b0892e5 100644
--- a/openair1/PHY/defs_nr_common.h
+++ b/openair1/PHY/defs_nr_common.h
@@ -319,6 +319,8 @@ typedef struct NR_DL_FRAME_PARMS {
   uint8_t Lmax;
   /// SS block pattern (max 64 ssb, each bit is on/off ssb)
   uint64_t L_ssb;
+  /// Total number of SSB transmitted
+  uint8_t N_ssb;
   /// PBCH polar encoder params
   t_nrPolar_params pbch_polar_params;
 
diff --git a/openair1/SCHED/sched_eNB.h b/openair1/SCHED/sched_eNB.h
index 150b0c194fddaac0326b1b83a5379605c69623a5..e74b9a312fda7bc7ed76430b83a73b4b92d9fa15 100644
--- a/openair1/SCHED/sched_eNB.h
+++ b/openair1/SCHED/sched_eNB.h
@@ -218,6 +218,8 @@ int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subf
 void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset);
 
 void release_rnti_of_phy(module_id_t mod_id);
+
+void ru_fep_full_2thread(RU_t *ru, int subframe);
 /*@}*/
 
 
diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c
index 793e26232f5c705c126a898da77d7242cc48a369..270ab5772cc3c0e0780ca726a34a16f4654463e4 100644
--- a/openair1/SCHED_NR/fapi_nr_l1.c
+++ b/openair1/SCHED_NR/fapi_nr_l1.c
@@ -139,7 +139,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
   gNB         = RC.gNB[Mod_id][CC_id];
 
   uint8_t number_dl_pdu             = DL_req->dl_config_request_body.number_pdu;
-  uint8_t number_ul_pdu             = UL_tti_req->n_pdus;
+  //uint8_t number_ul_pdu             = UL_tti_req->n_pdus;
 
   nfapi_nr_dl_config_request_pdu_t *dl_config_pdu;
  
diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c
index e726bdc71173e2fdf8c4abcddd0a3f14aee1a936..0ce3172bfd8ce4813159a09e89a03f868d738458 100644
--- a/openair1/SCHED_NR/nr_ru_procedures.c
+++ b/openair1/SCHED_NR/nr_ru_procedures.c
@@ -56,160 +56,236 @@ extern openair0_config_t openair0_cfg[MAX_CARDS];
 
 extern int oai_exit;
 
-void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols) {
+void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) {
 
   NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
 
-  unsigned int aa,slot_offset,slot_offsetF;
+  unsigned int slot_offset,slot_offsetF;
   int slot = tti_tx;
 
 
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0) , 1 );
+  //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0) , 1 );
 
   slot_offset  = slot*fp->samples_per_slot;
   slot_offsetF = first_symbol*fp->ofdm_symbol_size;
 
+
   if (first_symbol>0) slot_offset += (fp->ofdm_symbol_size*first_symbol) + (fp->nb_prefix_samples0) + (fp->nb_prefix_samples*(first_symbol-1));
 
   LOG_D(PHY,"SFN/SF:RU:TX:%d/%d Generating slot %d (first_symbol %d num_symbols %d)\n",ru->proc.frame_tx, ru->proc.tti_tx,slot,first_symbol,num_symbols);
 
-  for (aa=0; aa<ru->nb_tx; aa++) {
-    if (fp->Ncp == 1) {
+  if (fp->Ncp == 1) {
+    PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
+                 (int*)&ru->common.txdata[aa][slot_offset],
+                 fp->ofdm_symbol_size,
+                 num_symbols,
+                 fp->nb_prefix_samples,
+                 CYCLIC_PREFIX);
+  }
+  else {
+    if (first_symbol==0) {
       PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
-		   (int*)&ru->common.txdata[aa][slot_offset],
-		   fp->ofdm_symbol_size,
-		   num_symbols,
-		   fp->nb_prefix_samples,
-		   CYCLIC_PREFIX);
+                   (int*)&ru->common.txdata[aa][slot_offset],
+                   fp->ofdm_symbol_size,
+                   1,
+                   fp->nb_prefix_samples0,
+                   CYCLIC_PREFIX);
+      PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size],
+                   (int*)&ru->common.txdata[aa][slot_offset+fp->nb_prefix_samples0+fp->ofdm_symbol_size],
+                   fp->ofdm_symbol_size,
+                   num_symbols-1,
+                   fp->nb_prefix_samples,
+                   CYCLIC_PREFIX);
     }
     else {
-      if (first_symbol==0) {
-	PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
-		     (int*)&ru->common.txdata[aa][slot_offset],
-                     fp->ofdm_symbol_size,
-                     1,
-                     fp->nb_prefix_samples0,
-                     CYCLIC_PREFIX);
-	PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size],
-		     (int*)&ru->common.txdata[aa][slot_offset+fp->nb_prefix_samples0+fp->ofdm_symbol_size],
-                     fp->ofdm_symbol_size,
-                     num_symbols-1,
-                     fp->nb_prefix_samples,
-                     CYCLIC_PREFIX);
-      }
-      else {
-	PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
-		     (int*)&ru->common.txdata[aa][slot_offset],
-                     fp->ofdm_symbol_size,
-                     num_symbols,
-                     fp->nb_prefix_samples,
-                     CYCLIC_PREFIX);
-      }
+      PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
+                   (int*)&ru->common.txdata[aa][slot_offset],
+                   fp->ofdm_symbol_size,
+                   num_symbols,
+                   fp->nb_prefix_samples,
+                   CYCLIC_PREFIX);
     }
   }
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0), 0);
+  //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0), 0);
 }
 
 void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx) {
 
-  NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms;
   nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
-  RU_proc_t *proc = &ru->proc;
-  struct timespec wait;
-  int slot = tti_tx;
+  RU_proc_t  *proc  = &ru->proc;
+  RU_feptx_t *feptx = proc->feptx;
 
-  wait.tv_sec=0;
-  wait.tv_nsec=5000000L;
+  PHY_VARS_gNB *gNB;
+  NR_DL_FRAME_PARMS *fp   = ru->nr_frame_parms;
 
-  start_meas(&ru->ofdm_mod_stats);
+  int slot = tti_tx;
+  int i    = 0;
+  int j    = 0;
+  int aa   = 0;
+  int ret  = 0;
+  int nb_antenna_ports = fp->N_ssb;
+  int ofdm_mask_full   = (1<<(ru->nb_tx*2))-1;
+  int txdataF_offset   = ((tti_tx%2)*fp->samples_per_slot_wCP);
 
   if (nr_slot_select(cfg,slot,frame_tx) == SF_UL) return;
+  for (aa=0; aa<fp->Lmax; aa++) {
+    memset(ru->common.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t));
+  }
 
-  // this copy should be done in the precoding thread (currently inactive)
-  for (int aa=0;aa<ru->nb_tx;aa++)
-    memcpy((void*)ru->common.txdataF_BF[aa],
+  start_meas(&ru->ofdm_total_stats);
 
-	   (void*)ru->gNB_list[0]->common_vars.txdataF[aa], fp->samples_per_slot_wCP*sizeof(int32_t));
+  for(j=0; j<fp->symbols_per_slot; ++j){
 
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+j , 1);
+    start_meas(&ru->txdataF_copy_stats);
+    if (ru->num_gNB == 1){
+      gNB = ru->gNB_list[0];
+      cfg = &gNB->gNB_config;
 
-  if (nr_slot_select(cfg,slot,frame_tx)==SF_DL) {
-    // If this is not an S-tti
-    if (pthread_mutex_timedlock(&proc->mutex_feptx,&wait) != 0) {
-      printf("[RU] ERROR pthread_mutex_lock for feptx thread (IC %d)\n", proc->instance_cnt_feptx);
-      exit_fun( "error locking mutex_feptx" );
-      return;
-    }
-    
-    if (proc->instance_cnt_feptx==0) {
-      printf("[RU] FEPtx thread busy\n");
-      exit_fun("FEPtx thread busy");
-      pthread_mutex_unlock( &proc->mutex_feptx );
-      return;
-    }
-    
-    ++proc->instance_cnt_feptx;
-    // slot to pass to worker thread
-    proc->slot_feptx = slot;
-    pthread_mutex_unlock( &proc->mutex_feptx );
-  
-    
-    if (pthread_cond_signal(&proc->cond_feptx) != 0) {
-      printf("[RU] ERROR pthread_cond_signal for feptx thread\n");
-      exit_fun( "ERROR pthread_cond_signal" );
-      return;
+      for(i=0; i<nb_antenna_ports; ++i){
+        memcpy((void*)&ru->common.txdataF[i][j*fp->ofdm_symbol_size],
+           (void*)&gNB->common_vars.txdataF[i][j*fp->ofdm_symbol_size + txdataF_offset],
+           fp->ofdm_symbol_size*sizeof(int32_t));
+      }
+
+    }//num_gNB == 1
+    stop_meas(&ru->txdataF_copy_stats);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+j , 0);
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
+
+    if (nr_slot_select(cfg,slot,frame_tx)==SF_DL) {
+      // If this is not an S-tti
+      for(i=0; i<ru->nb_tx; ++i){
+        if(j%2 == 0){
+          while(feptx[i].instance_cnt_feptx != -1){
+            usleep(5);
+          }
+          AssertFatal((ret=pthread_mutex_lock(&feptx[i].mutex_feptx))==0,"mutex_lock return %d\n",ret);
+          feptx[i].aa                      = i;
+          feptx[i].index                   = i;
+          feptx[i].ru                      = ru;
+          feptx[i].symbol                  = j;
+          feptx[i].slot                    = slot;
+          feptx[i].nb_antenna_ports        = nb_antenna_ports;
+          feptx[i].instance_cnt_feptx      = 0;
+          AssertFatal(pthread_cond_signal(&feptx[i].cond_feptx) == 0,"ERROR pthread_cond_signal for feptx_ofdm_thread\n");
+          AssertFatal((ret=pthread_mutex_unlock(&feptx[i].mutex_feptx))==0,"mutex_lock returns %d\n",ret);
+        }
+        else{
+          while(feptx[i+ru->nb_tx].instance_cnt_feptx != -1){
+            usleep(5);
+          }
+          AssertFatal((ret=pthread_mutex_lock(&feptx[i+ru->nb_tx].mutex_feptx))==0,"mutex_lock return %d\n",ret);
+          feptx[i+ru->nb_tx].aa                      = i;
+          feptx[i+ru->nb_tx].index                   = i+ru->nb_tx;
+          feptx[i+ru->nb_tx].ru                      = ru;
+          feptx[i+ru->nb_tx].symbol                  = j;
+          feptx[i+ru->nb_tx].slot                    = slot;
+          feptx[i+ru->nb_tx].nb_antenna_ports        = nb_antenna_ports;
+          feptx[i+ru->nb_tx].instance_cnt_feptx      = 0;
+          AssertFatal(pthread_cond_signal(&feptx[i+ru->nb_tx].cond_feptx) == 0,"ERROR pthread_cond_signal for feptx_ofdm_thread\n");
+          AssertFatal((ret=pthread_mutex_unlock(&feptx[i+ru->nb_tx].mutex_feptx))==0,"mutex_lock returns %d\n",ret);
+        }
+      }
+       
+    }//if == SF_DL
+    else {
+      proc->feptx_mask = ofdm_mask_full;
     }
-    
+  }//j<fp->symbols_per_slot
+
+  // wait all process to finish
+  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_feptx))==0,"mutex_lock return %d\n",ret);
+  while (proc->feptx_mask != ofdm_mask_full) {
+    // most of the time the thread is waiting here
+    // proc->instance_cnt_rxtx is -1
+    pthread_cond_wait(&proc->cond_feptx,&proc->mutex_feptx); // this unlocks mutex_rxtx while waiting and then locks it again
   }
+  proc->feptx_mask = 0;
+  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_feptx))==0,"mutex_lock return %d\n",ret);
 
-  // call first half-slot in this thread
-  nr_feptx0(ru,slot,0,fp->symbols_per_slot>>1);
-  wait_on_busy_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"NR feptx thread");
-
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RU_TX_OFDM_MASK, proc->feptx_mask );
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 );
 
   //write_output
 
-  stop_meas(&ru->ofdm_mod_stats);
+  stop_meas(&ru->ofdm_total_stats);
 
 }
 
 static void *nr_feptx_thread(void *param) {
 
-  RU_t *ru = (RU_t *)param;
-  RU_proc_t *proc  = &ru->proc;
+  RU_feptx_t *feptx = (RU_feptx_t *)param;
+  RU_t       *ru;
+  int         aa, slot, start, l, nb_antenna_ports, ret;
+  int32_t ***bw;
+  NR_DL_FRAME_PARMS *fp;
+  int ofdm_mask_full;
 
 
   while (!oai_exit) {
 
-    if (wait_on_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"NR feptx thread")<0) break;
-    int slot=proc->slot_feptx;
-    if (release_thread(&proc->mutex_feptx,&proc->instance_cnt_feptx,"NR feptx thread")<0) break;
+    ret = 0;
+    if (wait_on_condition(&feptx->mutex_feptx,&feptx->cond_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break;
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+feptx->index+1 , 1 );
+
+    ru    = feptx->ru;
+    slot  = feptx->slot;
+    aa    = feptx->aa;
+    l     = feptx->symbol;
+    fp    = ru->nr_frame_parms;
+    start = feptx->symbol;
+    nb_antenna_ports = feptx->nb_antenna_ports;
+    ofdm_mask_full   = (1<<(ru->nb_tx*2))-1;
+
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 1);
+    start_meas(&ru->precoding_stats);
+    if (ru->nb_tx == 1) {
+      AssertFatal(fp->N_ssb==ru->nb_tx,"Attempting to transmit %d SSB while Nb_tx = %d",fp->N_ssb,ru->nb_tx);
+      for (int p=0; p<fp->Lmax; p++) {
+        if ((fp->L_ssb >> p) & 0x01){
+          memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size],
+                 (void*)&ru->common.txdataF[p][l*fp->ofdm_symbol_size],
+                 fp->ofdm_symbol_size*sizeof(int32_t));
+        }
+      }
+    }
+    else {
+      bw  = ru->beam_weights[0];
+      nr_beam_precoding(ru->common.txdataF,
+                        ru->common.txdataF_BF,
+                        fp,
+                        bw,
+                        slot,
+                        l,
+                        aa,
+                        nb_antenna_ports);
+    }
+    stop_meas(&ru->precoding_stats);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 0);
 
-    nr_feptx0(ru,slot,ru->nr_frame_parms->symbols_per_slot>>1,ru->nr_frame_parms->symbols_per_slot>>1);
 
-    if (pthread_cond_signal(&proc->cond_feptx) != 0) {
-      LOG_E(PHY,"[gNB] ERROR pthread_cond_signal for NR feptx thread exit\n");
-      exit_fun( "ERROR pthread_cond_signal" );
-      return NULL;
+    start_meas(&ru->ofdm_mod_stats);
+    nr_feptx0(ru,slot,start,1,aa);
+    stop_meas(&ru->ofdm_mod_stats);
+
+    if (release_thread(&feptx->mutex_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break;
+
+    if(l >= fp->symbols_per_slot -2){
+      AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_feptx))==0,"mutex_lock return %d\n",ret);
+      ru->proc.feptx_mask |= 1<<(feptx->index);
+      if(ru->proc.feptx_mask == ofdm_mask_full)
+        AssertFatal(pthread_cond_signal(&ru->proc.cond_feptx) == 0,"ERROR pthread_cond_signal for precoding and ofdm finish\n");
+      AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_feptx))==0,"mutex_lock returns %d\n",ret);
     }
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RU_TX_OFDM_MASK, ru->proc.feptx_mask );
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+feptx->index+1 , 0 );
   }
   return(NULL);
 }
 
-void nr_init_feptx_thread(RU_t *ru) {
-
-  RU_proc_t *proc = &ru->proc;
-
-  proc->instance_cnt_feptx         = -1;
-    
-  pthread_mutex_init( &proc->mutex_feptx, NULL);
-  pthread_cond_init( &proc->cond_feptx, NULL);
-
-  threadCreate(&proc->pthread_feptx, nr_feptx_thread, (void*)ru, "feptx", -1, OAI_PRIORITY_RT);
-
-
-}
 
 // is this supposed to generate a slot or a subframe???
 // seems to be hardcoded to numerology 1 (2 slots=1 subframe)
@@ -224,21 +300,14 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
   int slot = tti_tx;
   int *txdata = &ru->common.txdata[aa][slot*fp->samples_per_slot];
 
+  if (nr_slot_select(cfg,slot, frame_tx) == SF_UL) return;
+
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
   start_meas(&ru->ofdm_mod_stats);
 
-  // this copy should be done in the precoding thread (currently inactive)
-  for (int aa=0;aa<ru->nb_tx;aa++)
-    memcpy((void*)ru->common.txdataF_BF[aa],
-	   (void*)ru->gNB_list[0]->common_vars.txdataF[aa], fp->samples_per_slot_wCP*sizeof(int32_t));
-
-  if ((nr_slot_select(cfg,slot,frame_tx)==SF_DL)||
-      ((nr_slot_select(cfg,slot,frame_tx)==SF_S))) {
     //    LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);
 
-    nr_feptx0(ru,slot,0,fp->symbols_per_slot);
-
-  }
+    nr_feptx0(ru,slot,0,fp->symbols_per_slot,aa);
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 );
   stop_meas(&ru->ofdm_mod_stats);
@@ -249,6 +318,79 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
 
 }
 
+void nr_init_feptx_thread(RU_t *ru) {
+
+  RU_proc_t  *proc  = &ru->proc;
+  RU_feptx_t *feptx = proc->feptx;
+  int i = 0;
+
+  for(i=0; i<16; i++){
+    feptx[i].instance_cnt_feptx         = -1;
+    
+    pthread_mutex_init( &feptx[i].mutex_feptx, NULL);
+    pthread_cond_init( &feptx[i].cond_feptx, NULL);
+
+    threadCreate(&feptx[i].pthread_feptx, nr_feptx_thread, (void*)&feptx[i], "feptx", -1, OAI_PRIORITY_RT);
+    LOG_I(PHY,"init feptx thread %d\n", i);
+  }
+
+}
+
+
+void nr_feptx_prec(RU_t *ru,int frame,int tti_tx) {
+
+  int l,aa;
+  PHY_VARS_gNB **gNB_list = ru->gNB_list,*gNB;
+  NR_DL_FRAME_PARMS *fp   = ru->nr_frame_parms;
+  nfapi_nr_config_request_t *cfg;
+  int32_t ***bw;
+  int i=0;
+
+  start_meas(&ru->precoding_stats);
+  if (ru->num_gNB == 1){
+    gNB = gNB_list[0];
+    cfg = &gNB->gNB_config;
+    if (nr_slot_select(cfg,tti_tx,frame) == SF_UL) return;
+
+    for(i=0; i<fp->Lmax; ++i)
+      memcpy((void*)ru->common.txdataF[i],
+           (void*)gNB->common_vars.txdataF[i],
+           fp->samples_per_slot_wCP*sizeof(int32_t));
+
+    if (ru->nb_tx == 1) {
+    
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 1);
+
+      AssertFatal(fp->N_ssb==ru->nb_tx,"Attempting to transmit %d SSB while Nb_tx = %d",fp->N_ssb,ru->nb_tx);
+
+      for (int p=0; p<fp->Lmax; p++) {
+        if ((fp->L_ssb >> p) & 0x01){
+          memcpy((void*)ru->common.txdataF_BF[0],
+                 (void*)ru->common.txdataF[p],
+                 fp->samples_per_slot_wCP*sizeof(int32_t));
+        }
+      }
+
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 0);
+    }// if (ru->nb_tx == 1)
+    else {
+      bw  = ru->beam_weights[0];
+      for (l=0;l<fp->symbols_per_slot;l++) {
+        for (aa=0;aa<ru->nb_tx;aa++) {
+          nr_beam_precoding(ru->common.txdataF,
+                            ru->common.txdataF_BF,
+                            fp,
+                            bw,
+                            tti_tx,
+                            l,
+                            aa,
+                            fp->Lmax);
+        }// for (aa=0;aa<ru->nb_tx;aa++)
+      }// for (l=0;l<fp->symbols_per_slot;l++)
+    }// if (ru->nb_tx == 1)
+  }// if (ru->num_gNB == 1)
+  stop_meas(&ru->precoding_stats);
+}
 
 void nr_fep0(RU_t *ru, int first_half) {
   
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index caf76528410f6b2bfc1c981c81d3a85dd65537c3..a665a14112bbdc007c8b4b2d5fc6061df0ef05e3 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -96,6 +96,7 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
   uint8_t *pbch_pdu=&gNB->pbch_pdu[0];
   uint8_t ssb_index, n_hf;
   int ssb_start_symbol, rel_slot;
+  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
   uint16_t slots_per_hf = fp->slots_per_frame / 2;
 
   n_hf = cfg->sch_config.half_frame_index.value;
@@ -124,19 +125,20 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
 
 	  nr_set_ssb_first_subcarrier(cfg, fp);  // setting the first subcarrier
 	  
+	  // it is supposed that each logical antenna port correspont to a different beam so each SSB is stored into its own index of txdataF
     	  LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol);
-    	  nr_generate_pss(gNB->d_pss, txdataF[0], AMP, ssb_start_symbol, cfg, fp);
-    	  nr_generate_sss(gNB->d_sss, txdataF[0], AMP, ssb_start_symbol, cfg, fp);
+    	  nr_generate_pss(gNB->d_pss, &txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
+    	  nr_generate_sss(gNB->d_sss, &txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
 
 	  if (fp->Lmax == 4)
-	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp);
+	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],&txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
 	  else
-	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp);
+	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index],&txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
 
     	  nr_generate_pbch(&gNB->pbch,
                       pbch_pdu,
                       gNB->nr_pbch_interleaver,
-                      txdataF[0],
+                      &txdataF[ssb_index][txdataF_offset],
                       AMP,
                       ssb_start_symbol,
                       n_hf,fp->Lmax,ssb_index,
@@ -155,6 +157,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
   nfapi_nr_config_request_t *cfg = &gNB->gNB_config;
   int offset = gNB->CC_id;
   uint8_t ssb_frame_periodicity;  // every how many frames SSB are generated
+  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
 
   if (cfg->sch_config.ssb_periodicity.value < 20)
     ssb_frame_periodicity = 1;
@@ -168,8 +171,8 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
   if (do_meas==1) start_meas(&gNB->phy_proc_tx);
 
   // clear the transmit data array for the current subframe
-  for (aa=0; aa<1/*15*/; aa++) {
-    memset(gNB->common_vars.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t));
+  for (aa=0; aa<fp->Lmax; aa++) {
+    memset(&gNB->common_vars.txdataF[aa][txdataF_offset],0,fp->samples_per_slot_wCP*sizeof(int32_t));
   }
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_COMMON_TX,1);
@@ -187,10 +190,12 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
     Calling nr_generate_dci_top (number of DCI %d)\n", gNB->Mod_id, frame, slot, num_dci);
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
+
     nr_generate_dci_top(gNB->pdcch_vars.dci_alloc[i],
-			gNB->nr_gold_pdcch_dmrs[slot],
-			gNB->common_vars.txdataF[0],
-			AMP, *fp, *cfg);
+                        gNB->nr_gold_pdcch_dmrs[slot],
+                        &gNB->common_vars.txdataF[0][txdataF_offset],  // hardcoded to beam 0
+                        AMP, *fp, *cfg);
+
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
   }
       
@@ -361,7 +366,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
     switch (UL_tti_req->pdus_list[i].pdu_type) {
     case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE:
       {
-	LOG_I(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE\n",frame_rx,slot_rx);
+	LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE\n",frame_rx,slot_rx);
 
 	nfapi_nr_pusch_pdu_t  *pusch_pdu = &UL_tti_req->pdus_list[0].pusch_pdu;
 	nr_fill_ulsch(gNB,frame_rx,slot_rx,pusch_pdu);      
diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h
index 91035854930a04839d6d86ab4453ded98a73a360..5b53aa919a588f0611aea286b66faff06d6aa542 100644
--- a/openair1/SCHED_NR/sched_nr.h
+++ b/openair1/SCHED_NR/sched_nr.h
@@ -42,8 +42,12 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
 void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot);
 void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
 void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx);
-void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols);
+void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa);
 void nr_init_feptx_thread(RU_t *ru);
+void fep_full(RU_t *ru,int slot);
+void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx);
+void nr_init_feptx_prec_thread(RU_t *ru);
+void nr_feptx_prec_control(RU_t *ru,int frame,int tti_tx);
 void nr_init_feprx_thread(RU_t *ru);
 void nr_fep_full(RU_t *ru, int slot);
 void nr_fep_full_2thread(RU_t *ru, int slot);
diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
index ced40c491aecffd2914d460b13101f1d949ca55a..1bd7071b9950cf10d8773905b98401ffbb577827 100644
--- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
+++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
@@ -214,7 +214,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response)
 
 int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){
 
-  fapi_nr_config_request_t nrUE_config = PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config;
+  fapi_nr_config_request_t *nrUE_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config;
   
   if(phy_config != NULL){
     if(phy_config->config_req.config_mask & FAPI_NR_CONFIG_REQUEST_MASK_PBCH){
@@ -230,7 +230,7 @@ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){
       LOG_I(MAC,"half frame bit:              %d\n", phy_config->config_req.pbch_config.half_frame_bit);
       LOG_I(MAC,"-------------------------------\n");
 
-      memcpy(&nrUE_config.pbch_config,&phy_config->config_req.pbch_config,sizeof(fapi_nr_pbch_config_t));
+      memcpy(&nrUE_config->pbch_config,&phy_config->config_req.pbch_config,sizeof(fapi_nr_pbch_config_t));
       
     }
         
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index bf350cea710fa00c995cb3a15e2df0bf9e49f6cc..8d8140e19254131f98a15ed72ac1554e0e437b61 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -68,7 +68,7 @@ uint16_t NB_UE_INST = 1;
 
 //Dummy Functions
 lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms, unsigned char subframe) {return(SF_DL);}
-int rlc_module_init (void) {return(0);}
+int rlc_module_init (int enb) {return(0);}
 void pdcp_layer_init (void) {}
 int rrc_init_nr_global_param (void) {return(0);}
 void config_common(int Mod_idP,int CC_idP,int Nid_cell,int nr_bandP,uint64_t SSB_positions,uint16_t ssb_periodicity,uint64_t dl_CarrierFreqP,uint32_t dl_BandwidthP);
@@ -86,7 +86,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( const module_id_t       module_idP,
 					  const tb_size_t         tb_sizeP,
 					  const uint32_t sourceL2Id,
 					  const uint32_t destinationL2Id)
-{mac_rlc_status_resp_t  mac_rlc_status_resp; return mac_rlc_status_resp;}
+{mac_rlc_status_resp_t  mac_rlc_status_resp={0}; return mac_rlc_status_resp;}
 tbs_size_t mac_rlc_data_req(  const module_id_t       module_idP,
 			      const rnti_t            rntiP,
 			      const eNB_index_t       eNB_index,
@@ -602,24 +602,26 @@ int main(int argc, char **argv)
     phy_procedures_gNB_TX(gNB,frame,slot,0);
     
     //nr_common_signal_procedures (gNB,frame,subframe);
+    int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP;
 
     LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1);
     if (gNB->frame_parms.nb_antennas_tx>1)
       LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1);
 
     int tx_offset = slot*frame_parms->samples_per_slot;
+    printf("samples_per_slot_wCP = %d\n", frame_parms->samples_per_slot_wCP);
 
     //TODO: loop over slots
     for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
       if (gNB_config->subframe_config.dl_cyclic_prefix_type.value == 1) {
-	PHY_ofdm_mod(gNB->common_vars.txdataF[aa],
+	PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
 		     &txdata[aa][tx_offset],
 		     frame_parms->ofdm_symbol_size,
 		     12,
 		     frame_parms->nb_prefix_samples,
 		     CYCLIC_PREFIX);
       } else {
-	nr_normal_prefix_mod(gNB->common_vars.txdataF[aa],
+	nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
 			     &txdata[aa][tx_offset],
 			     14,
 			     frame_parms);
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index 15e7d3ca0e2deeaa6fc92132455272a8955eec26..724faf1d7f86806a34524944420c34595347f3c6 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -115,7 +115,7 @@ int generate_dlsch_header(unsigned char *mac_header,
                           unsigned char short_padding,
                           unsigned short post_padding){return 0;}
 uint64_t get_softmodem_optmask(void) {return 0;}
-int rlc_module_init (void) {return(0);}
+int rlc_module_init (int enb) {return(0);}
 void pdcp_layer_init (void) {}
 void nr_ip_over_LTE_DRB_preconfiguration(void){}
 
@@ -146,7 +146,7 @@ int main(int argc, char **argv)
   uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1;
   //unsigned char frame_type = 0;
   int number_of_frames = 1;
-  int frame_length_complex_samples, frame_length_complex_samples_no_prefix ;
+  int frame_length_complex_samples;
   NR_DL_FRAME_PARMS *frame_parms;
   int loglvl = OAILOG_WARNING;
   uint64_t SSB_positions=0x01;
@@ -409,7 +409,7 @@ int main(int argc, char **argv)
   //init_eNB_afterRU();
 
   frame_length_complex_samples = frame_parms->samples_per_subframe;
-  frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP;
+  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP;
 
   //configure UE
   UE = malloc(sizeof(PHY_VARS_NR_UE));
@@ -443,7 +443,7 @@ int main(int argc, char **argv)
   unsigned char harq_pid = 0;
   unsigned int TBS;
   unsigned int available_bits;
-  uint8_t nb_re_dmrs = UE->dmrs_UplinkConfig.pusch_maxLength*(UE->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)?6:4;
+  uint8_t nb_re_dmrs = UE->dmrs_UplinkConfig.pusch_maxLength*(UE->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1?6:4);
   uint8_t length_dmrs = 1;
   unsigned char mod_order;
   uint16_t code_rate;
diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h
index 4f81c22fb0bee322e307222890e6ff51c456ddb8..054f3f37341477ed5b033531cad4869cf7f1cddd 100644
--- a/openair2/COMMON/gtpv1_u_messages_types.h
+++ b/openair2/COMMON/gtpv1_u_messages_types.h
@@ -133,7 +133,7 @@ typedef struct gtpv1u_enb_data_forwarding_req_s {
 typedef struct gtpv1u_enb_data_forwarding_ind_s {
   uint32_t 				 frame;
   uint8_t 				 enb_flag;
-  uint32_t 				 rb_id;
+  rb_id_t 				 rb_id;
   uint32_t 				 muip;
   uint32_t 				 confirmp;
   uint32_t 				 sdu_size;
@@ -155,7 +155,7 @@ typedef struct gtpv1u_enb_end_marker_req_s {
 typedef struct gtpv1u_enb_end_marker_ind_s {
   uint32_t 			 frame;
   uint8_t 			 enb_flag;
-  uint32_t 			 rb_id;
+  rb_id_t 			 rb_id;
   uint32_t 			 muip;
   uint32_t 			 confirmp;
   uint32_t 			 sdu_size;
diff --git a/openair2/COMMON/pdcp_messages_types.h b/openair2/COMMON/pdcp_messages_types.h
index c90490b0fd36077c99f1c023ec33655244b01ca0..1551e4283f38327be795b84d86d419ef9e0e8f6b 100644
--- a/openair2/COMMON/pdcp_messages_types.h
+++ b/openair2/COMMON/pdcp_messages_types.h
@@ -40,7 +40,7 @@
 typedef struct RrcDcchDataReq_s {
   uint32_t frame;
   uint8_t enb_flag;
-  uint32_t rb_id;
+  rb_id_t rb_id;
   uint32_t muip;
   uint32_t confirmp;
   uint32_t sdu_size;
diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h
index 977f44a31050f387d778dd1b9728d83e1e6bf7bf..49c1b340a6994a70c22176c46c1ddcb52aa49833 100644
--- a/openair2/COMMON/platform_types.h
+++ b/openair2/COMMON/platform_types.h
@@ -71,8 +71,8 @@ typedef uint8_t               slice_id_t;
 typedef uint8_t               eNB_index_t;
 typedef uint16_t              ue_id_t;
 typedef int16_t               smodule_id_t;
-typedef uint16_t              rb_id_t;
-typedef uint16_t              srb_id_t;
+typedef long              rb_id_t;
+typedef long              srb_id_t;
 
 typedef boolean_t             MBMS_flag_t;
 #define  MBMS_FLAG_NO         FALSE
diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h
index 106a9f297ee92f9516985093441ee2d5e079eaf9..0fedc04abd8404a547869093e28e342adcc1ac24 100644
--- a/openair2/ENB_APP/enb_paramdef.h
+++ b/openair2/ENB_APP/enb_paramdef.h
@@ -93,6 +93,7 @@ typedef enum {
 #define CONFIG_STRING_RU_SF_EXTENSION             "sf_extension"
 #define CONFIG_STRING_RU_END_OF_BURST_DELAY       "end_of_burst_delay"
 #define CONFIG_STRING_RU_OTA_SYNC_ENABLE          "ota_sync_enabled"
+#define CONFIG_STRING_RU_BF_WEIGHTS_LIST          "bf_weights"
 
 #define RU_LOCAL_IF_NAME_IDX          0
 #define RU_LOCAL_ADDRESS_IDX          1
@@ -118,23 +119,22 @@ typedef enum {
 #define RU_SF_EXTENSION_IDX           21
 #define RU_END_OF_BURST_DELAY_IDX     22
 #define RU_OTA_SYNC_ENABLE_IDX        23
-
-
+#define RU_BF_WEIGHTS_LIST_IDX        24
 
 /*-----------------------------------------------------------------------------------------------------------------------------------------*/
 /*                                            RU configuration parameters                                                                  */
 /*   optname                                   helpstr   paramflags    XXXptr          defXXXval                   type      numelt        */
 /*-----------------------------------------------------------------------------------------------------------------------------------------*/
 #define RUPARAMS_DESC { \
-    {CONFIG_STRING_RU_LOCAL_IF_NAME,               NULL,       0,       strptr:NULL,     defstrval:"lo",          TYPE_STRING,    0}, \
-    {CONFIG_STRING_RU_LOCAL_ADDRESS,               NULL,       0,       strptr:NULL,     defstrval:"127.0.0.2",   TYPE_STRING,    0}, \
-    {CONFIG_STRING_RU_REMOTE_ADDRESS,              NULL,       0,       strptr:NULL,     defstrval:"127.0.0.1",   TYPE_STRING,    0}, \
+    {CONFIG_STRING_RU_LOCAL_IF_NAME,               NULL,       0,       strptr:NULL,     defstrval:"lo",          TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_LOCAL_ADDRESS,               NULL,       0,       strptr:NULL,     defstrval:"127.0.0.2",   TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_REMOTE_ADDRESS,              NULL,       0,       strptr:NULL,     defstrval:"127.0.0.1",   TYPE_STRING,      0}, \
     {CONFIG_STRING_RU_LOCAL_PORTC,                 NULL,       0,       uptr:NULL,       defuintval:50000,        TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_REMOTE_PORTC,                NULL,       0,       uptr:NULL,       defuintval:50000,        TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_LOCAL_PORTD,                 NULL,       0,       uptr:NULL,       defuintval:50001,        TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_REMOTE_PORTD,                NULL,       0,       uptr:NULL,       defuintval:50001,        TYPE_UINT,        0}, \
-    {CONFIG_STRING_RU_TRANSPORT_PREFERENCE,        NULL,       0,       strptr:NULL,     defstrval:"udp_if5",     TYPE_STRING,    0}, \
-    {CONFIG_STRING_RU_LOCAL_RF,                    NULL,       0,       strptr:NULL,     defstrval:"yes",         TYPE_STRING,    0}, \
+    {CONFIG_STRING_RU_TRANSPORT_PREFERENCE,        NULL,       0,       strptr:NULL,     defstrval:"udp_if5",     TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_LOCAL_RF,                    NULL,       0,       strptr:NULL,     defstrval:"yes",         TYPE_STRING,      0}, \
     {CONFIG_STRING_RU_NB_TX,                       NULL,       0,       uptr:NULL,       defuintval:1,            TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_NB_RX,                       NULL,       0,       uptr:NULL,       defuintval:1,            TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_MAX_RS_EPRE,                 NULL,       0,       iptr:NULL,       defintval:-29,           TYPE_INT,         0}, \
@@ -143,13 +143,14 @@ typedef enum {
     {CONFIG_STRING_RU_ENB_LIST,                    NULL,       0,       uptr:NULL,       defintarrayval:DEFENBS,  TYPE_INTARRAY,    1}, \
     {CONFIG_STRING_RU_ATT_TX,                      NULL,       0,       uptr:NULL,       defintval:0,             TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_ATT_RX,                      NULL,       0,       uptr:NULL,       defintval:0,             TYPE_UINT,        0}, \
-    {CONFIG_STRING_RU_IS_SLAVE,                      NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
-    {CONFIG_STRING_RU_NBIOTRRC_LIST,                 NULL,       0,       uptr:NULL,       defintarrayval:DEFENBS,  TYPE_INTARRAY,    1}, \
+    {CONFIG_STRING_RU_IS_SLAVE,                    NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_NBIOTRRC_LIST,               NULL,       0,       uptr:NULL,       defintarrayval:DEFENBS,  TYPE_INTARRAY,    1}, \
     {CONFIG_STRING_RU_SDR_ADDRS,                   NULL,       0,       strptr:NULL,     defstrval:"type=b200",   TYPE_STRING,      0}, \
     {CONFIG_STRING_RU_SDR_CLK_SRC,                 NULL,       0,       strptr:NULL,     defstrval:"internal",    TYPE_STRING,      0}, \
-    {CONFIG_STRING_RU_SF_EXTENSION,                  NULL,       0,       uptr:NULL,       defuintval:312,          TYPE_UINT,        0}, \
-    {CONFIG_STRING_RU_END_OF_BURST_DELAY,            NULL,       0,       uptr:NULL,       defuintval:400,          TYPE_UINT,        0}, \
-    {CONFIG_STRING_RU_OTA_SYNC_ENABLE,               NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_SF_EXTENSION,                NULL,       0,       uptr:NULL,       defuintval:312,          TYPE_UINT,        0}, \
+    {CONFIG_STRING_RU_END_OF_BURST_DELAY,          NULL,       0,       uptr:NULL,       defuintval:400,          TYPE_UINT,        0}, \
+    {CONFIG_STRING_RU_OTA_SYNC_ENABLE,             NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_BF_WEIGHTS_LIST,             NULL,       0,       iptr:NULL,       defintarrayval:DEFBFW,   TYPE_INTARRAY,    0}, \
   }
 
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h
index 1ca6f2d7ec6e3feb4e52cbd394fca6293bac1e25..8a55c61cd7f5d22a35dcd629d2e1b719a9ae07d1 100644
--- a/openair2/GNB_APP/gnb_paramdef.h
+++ b/openair2/GNB_APP/gnb_paramdef.h
@@ -67,83 +67,9 @@ typedef enum {
 
 #define CONFIG_STRING_ACTIVE_RUS                  "Active_RUs"
 /*------------------------------------------------------------------------------------------------------------------------------------------*/
-/*    RUs  configuration section name */
-#define CONFIG_STRING_RU_LIST                     "RUs"
-#define CONFIG_STRING_RU_CONFIG                   "ru_config"
-
-/*    RUs configuration parameters name   */
-#define CONFIG_STRING_RU_LOCAL_IF_NAME            "local_if_name"
-#define CONFIG_STRING_RU_LOCAL_ADDRESS            "local_address"
-#define CONFIG_STRING_RU_REMOTE_ADDRESS           "remote_address"
-#define CONFIG_STRING_RU_LOCAL_PORTC              "local_portc"
-#define CONFIG_STRING_RU_REMOTE_PORTC             "remote_portc"
-#define CONFIG_STRING_RU_LOCAL_PORTD              "local_portd"
-#define CONFIG_STRING_RU_REMOTE_PORTD             "remote_portd"
-#define CONFIG_STRING_RU_LOCAL_RF                 "local_rf"
-#define CONFIG_STRING_RU_TRANSPORT_PREFERENCE     "tr_preference"
-#define CONFIG_STRING_RU_BAND_LIST                "bands"
-#define CONFIG_STRING_RU_GNB_LIST                 "gNB_instances"
-#define CONFIG_STRING_RU_NB_TX                    "nb_tx"
-#define CONFIG_STRING_RU_NB_RX                    "nb_rx"
-#define CONFIG_STRING_RU_ATT_TX                   "att_tx"
-#define CONFIG_STRING_RU_ATT_RX                   "att_rx"
-#define CONFIG_STRING_RU_MAX_RS_EPRE              "max_pdschReferenceSignalPower"
-#define CONFIG_STRING_RU_MAX_RXGAIN               "max_rxgain"
-#define CONFIG_STRING_RU_IF_COMPRESSION           "if_compression"
-#define CONFIG_STRING_RU_NBIOTRRC_LIST            "NbIoT_RRC_instances"
-#define CONFIG_STRING_RU_SDR_ADDRS                "sdr_addrs"
-#define CONFIG_STRING_RU_SDR_CLK_SRC              "clock_src"
-
-#define RU_LOCAL_IF_NAME_IDX          0
-#define RU_LOCAL_ADDRESS_IDX          1
-#define RU_REMOTE_ADDRESS_IDX         2
-#define RU_LOCAL_PORTC_IDX            3
-#define RU_REMOTE_PORTC_IDX           4
-#define RU_LOCAL_PORTD_IDX            5
-#define RU_REMOTE_PORTD_IDX           6
-#define RU_TRANSPORT_PREFERENCE_IDX   7
-#define RU_LOCAL_RF_IDX               8
-#define RU_NB_TX_IDX                  9
-#define RU_NB_RX_IDX                  10
-#define RU_MAX_RS_EPRE_IDX            11
-#define RU_MAX_RXGAIN_IDX             12
-#define RU_BAND_LIST_IDX              13
-#define RU_GNB_LIST_IDX               14
-#define RU_ATT_TX_IDX                 15
-#define RU_ATT_RX_IDX                 16
-#define RU_IS_SLAVE_IDX               17
-#define RU_NBIOTRRC_LIST_IDX          18
-#define RU_SDR_ADDRS                  19
-#define RU_SDR_CLK_SRC                20
-#define RU_SF_EXTENSION_IDX           21
-#define RU_END_OF_BURST_DELAY_IDX     22
 
-
-
-/*-----------------------------------------------------------------------------------------------------------------------------------------*/
-/*                                            RU configuration parameters                                                                  */
-/*   optname                                   helpstr   paramflags    XXXptr          defXXXval                 type           numelt     */
-/*-----------------------------------------------------------------------------------------------------------------------------------------*/
-#define GNBRUPARAMS_DESC { \
-{CONFIG_STRING_RU_LOCAL_IF_NAME,            	 NULL,       0,       strptr:NULL,     defstrval:"lo",  	      TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_LOCAL_ADDRESS,            	 NULL,       0,       strptr:NULL,     defstrval:"127.0.0.2",     TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_REMOTE_ADDRESS,           	 NULL,       0,       strptr:NULL,     defstrval:"127.0.0.1",	  TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_LOCAL_PORTC,              	 NULL,       0,       uptr:NULL,       defuintval:50000,          TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_REMOTE_PORTC,             	 NULL,       0,       uptr:NULL,       defuintval:50000,          TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_LOCAL_PORTD,              	 NULL,       0,       uptr:NULL,       defuintval:50001,          TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_REMOTE_PORTD,             	 NULL,       0,       uptr:NULL,       defuintval:50001,          TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_TRANSPORT_PREFERENCE,     	 NULL,       0,       strptr:NULL,     defstrval:"udp_if5",       TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_LOCAL_RF,                 	 NULL,       0,       strptr:NULL,     defstrval:"yes",           TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_NB_TX,                    	 NULL,       0,       uptr:NULL,       defuintval:1,              TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_NB_RX,                    	 NULL,       0,       uptr:NULL,       defuintval:1,              TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_MAX_RS_EPRE,              	 NULL,       0,       iptr:NULL,       defintval:-29,             TYPE_INT,         0}, \
-{CONFIG_STRING_RU_MAX_RXGAIN,               	 NULL,       0,       iptr:NULL,       defintval:120,             TYPE_INT,         0}, \
-{CONFIG_STRING_RU_BAND_LIST,                	 NULL,       0,       uptr:NULL,       defintarrayval:DEFNRBANDS, TYPE_INTARRAY,    1}, \
-{CONFIG_STRING_RU_GNB_LIST,                 	 NULL,       0,       uptr:NULL,       defintarrayval:DEFGNBS,    TYPE_INTARRAY,    1}, \
-{CONFIG_STRING_RU_ATT_TX,                   	 NULL,       0,       uptr:NULL,       defintval:0,               TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_ATT_RX,                   	 NULL,       0,       uptr:NULL,       defintval:0,               TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_NBIOTRRC_LIST,                 NULL,       0,       uptr:NULL,       defintarrayval:DEFGNBS,    TYPE_INTARRAY,    1}, \
-}
+/*    RUs  configuration for gNB is the same for eNB */
+/*    Check file enb_paramdef.h */
 
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
index b1e1fb5d73022fa83a545b933fce51885379971c..04757dab16275b09c7e8c6448ec6f06977a1eee0 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
@@ -171,7 +171,7 @@ void dlsch_scheduler_pre_ue_select_fairRR(
   frame_t         frameP,
   sub_frame_t     subframeP,
   int            *mbsfn_flag,
-  uint16_t        nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+  uint16_t        nb_rbs_required[MAX_NUM_CCs][MAX_MOBILES_PER_ENB],
   DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]) {
   eNB_MAC_INST                   *eNB      = RC.mac[module_idP];
   COMMON_channels_t              *cc       = eNB->common_channels;
@@ -573,8 +573,8 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t   Mod_id,
   uint8_t slice_allocation[MAX_NUM_CCs][N_RBG_MAX];
   int                     UE_id, i;
   uint16_t                j,c;
-  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[MAX_NUM_CCs][MAX_MOBILES_PER_ENB];
+  uint16_t                nb_rbs_required_remaining[MAX_NUM_CCs][MAX_MOBILES_PER_ENB];
   //  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;
@@ -617,7 +617,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t   Mod_id,
                                           frameP,
                                           subframeP,
                                           min_rb_unit,
-                                          (uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required,
+                                          (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required,
                                           rballoc_sub,
                                           MIMO_mode_indicator,
                                           mbsfn_flag);
@@ -631,7 +631,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t   Mod_id,
   assign_rbs_required(Mod_id, 0, frameP, subframeP, nb_rbs_required,
                       min_rb_unit);
 #else
-  memcpy(nb_rbs_required, pre_nb_rbs_required[dlsch_ue_select_tbl_in_use], sizeof(uint16_t)*MAX_NUM_CCs*NUMBER_OF_UE_MAX);
+  memcpy(nb_rbs_required, pre_nb_rbs_required[dlsch_ue_select_tbl_in_use], sizeof(uint16_t)*MAX_NUM_CCs*MAX_MOBILES_PER_ENB);
 #endif
   dlsch_scheduler_pre_ue_select_fairRR(Mod_id,frameP,subframeP, mbsfn_flag,nb_rbs_required,dlsch_ue_select);
 
@@ -701,8 +701,8 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t   Mod_id,
                                               CC_id,
                                               N_RBG[CC_id],
                                               min_rb_unit[CC_id],
-                                              (uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required,
-                                              (uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required_remaining,
+                                              (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required,
+                                              (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required_remaining,
                                               rballoc_sub,
                                               slice_allocation,
                                               MIMO_mode_indicator);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h
index 8c901186098c24b1a861dd208c97f8212c638ef0..5355a614a6c8c14b8dc7e2e3a1cd95ff270957c3 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h
+++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h
@@ -82,7 +82,7 @@ void dlsch_scheduler_pre_ue_select_fairRR(
     frame_t         frameP,
     sub_frame_t     subframeP,
     int*            mbsfn_flag,
-    uint16_t        nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
+    uint16_t        nb_rbs_required[MAX_NUM_CCs][MAX_MOBILES_PER_ENB],
     DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]);
 
 void dlsch_scheduler_pre_processor_fairRR (module_id_t   Mod_id,
diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c
index 8fb8d44e0abc80301bb20f566162f7b206e45ac6..4e139dcf92682280a0453e808237a1a4b5f0d66b 100644
--- a/openair2/LAYER2/MAC/main.c
+++ b/openair2/LAYER2/MAC/main.c
@@ -146,7 +146,7 @@ void mac_top_init_eNB(void)
 
   RC.mac = mac;
 
-  AssertFatal(rlc_module_init() == 0,
+  AssertFatal(rlc_module_init(1) == 0,
       "Could not initialize RLC layer\n");
 
   // These should be out of here later
@@ -184,7 +184,7 @@ int rlcmac_init_global_param(void)
 
     LOG_I(MAC, "[MAIN] CALLING RLC_MODULE_INIT...\n");
 
-    if (rlc_module_init() != 0) {
+    if (rlc_module_init(1) != 0) {
 	return (-1);
     }
 
diff --git a/openair2/LAYER2/MAC/main_ue.c b/openair2/LAYER2/MAC/main_ue.c
index f482806e1d198ef7ed98a3e97f6cf6c1192e5ab2..e8b05937170a3026f70b972d11047f81e61a6dc2 100644
--- a/openair2/LAYER2/MAC/main_ue.c
+++ b/openair2/LAYER2/MAC/main_ue.c
@@ -110,7 +110,7 @@ mac_top_init_ue(int eMBMS_active, char *uecap_xer,
 int rlcmac_init_global_param_ue(void) {
   LOG_I(MAC, "[MAIN] CALLING RLC_MODULE_INIT...\n");
 
-  if (rlc_module_init() != 0) {
+  if (rlc_module_init(0) != 0) {
     return (-1);
   }
 
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index f196293ea0890a44070c7c989b072cd4bb4ab984..a74615c3d3309236c193fa4dd7ec1e30b49205f1 100755
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -63,7 +63,8 @@
 
 typedef enum {
     SFN_C_MOD_2_EQ_0, 
-    SFN_C_MOD_2_EQ_1
+    SFN_C_MOD_2_EQ_1,
+    SFN_C_IMPOSSIBLE
 } SFN_C_TYPE;
 
 
diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
index c96acccf9b36cbbc224332a980e74e8fb0032a99..0478a6b7d51464fe885023ce0a81dc3b14f7fbce 100644
--- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
+++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
@@ -47,7 +47,7 @@ nr_l2_init_ue(void)
     nr_ue_mac_inst = (NR_UE_MAC_INST_t *)malloc(sizeof(NR_UE_MAC_INST_t)*NB_NR_UE_MAC_INST);
     
     if (IS_SOFTMODEM_NOS1){
-    	if (rlc_module_init() != 0) {
+        if (rlc_module_init(0) != 0) {
     		LOG_I(RLC, "Problem at RLC initiation \n");
     	}
     	pdcp_layer_init();
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 6b9e79d51025cb9c41e88c899cf9b2aac9a5ee48..ef94d5db7e10f3c176f69dd5414833c0b996b886 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -441,10 +441,10 @@ int8_t nr_ue_decode_mib(
         float big_o;
         float big_m;
         uint32_t temp;
-        SFN_C_TYPE sfn_c;   //  only valid for mux=1
-        uint32_t n_c;
-        uint32_t number_of_search_space_per_slot;
-        uint32_t first_symbol_index;
+        SFN_C_TYPE sfn_c=SFN_C_IMPOSSIBLE;   //  only valid for mux=1
+        uint32_t n_c=UINT_MAX;
+        uint32_t number_of_search_space_per_slot=UINT_MAX;
+        uint32_t first_symbol_index=UINT_MAX;
         uint32_t search_space_duration;  //  element of search space
         uint32_t coreset_duration;  //  element of coreset
         
@@ -582,6 +582,7 @@ int8_t nr_ue_decode_mib(
             search_space_duration = 1;
         }
 
+	AssertFatal(number_of_search_space_per_slot!=UINT_MAX,"");
         coreset_duration = num_symbols * number_of_search_space_per_slot;
 
         mac->type0_pdcch_dci_config.number_of_candidates[0] = table_38213_10_1_1_c2[0];
@@ -591,8 +592,11 @@ int8_t nr_ue_decode_mib(
         mac->type0_pdcch_dci_config.number_of_candidates[4] = table_38213_10_1_1_c2[4];   //  CCE aggregation level = 16
         mac->type0_pdcch_dci_config.duration = search_space_duration;
         mac->type0_pdcch_dci_config.coreset.duration = coreset_duration;   //  coreset
+	AssertFatal(first_symbol_index!=UINT_MAX,"");
         mac->type0_pdcch_dci_config.monitoring_symbols_within_slot = (0x3fff << first_symbol_index) & (0x3fff >> (14-coreset_duration-first_symbol_index)) & 0x3fff;
 
+	AssertFatal(sfn_c!=SFN_C_IMPOSSIBLE,"");
+	AssertFatal(n_c!=UINT_MAX,"");
         mac->type0_pdcch_ss_sfn_c = sfn_c;
         mac->type0_pdcch_ss_n_c = n_c;
         
diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c
index 88f6c387585a743432ac0659c944793936da1a63..c5dad59d98f9d7c27bdac79241de6e39bf77826f 100644
--- a/openair2/LAYER2/NR_MAC_gNB/main.c
+++ b/openair2/LAYER2/NR_MAC_gNB/main.c
@@ -128,7 +128,7 @@ void mac_top_init_gNB(void)
 
     }//END for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
 
-  AssertFatal(rlc_module_init() == 0,"Could not initialize RLC layer\n");
+  AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n");
 
   // These should be out of here later
   pdcp_layer_init();
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index d7cbb33c9eea307b1c181fb02e7c02e8a7a412f5..f234e02c04b7086ca6e81c9552bbd00aeb47410d 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -146,12 +146,12 @@ boolean_t pdcp_data_req(
               sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
 
   if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
-    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
+    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
   } else {
     if (srb_flagP) {
-      AssertError (rb_idP < 3, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti);
+      AssertError (rb_idP < 3, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti);
     } else {
-      AssertError (rb_idP < LTE_maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
+      AssertError (rb_idP < LTE_maxDRB, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
     }
   }
 
@@ -160,7 +160,7 @@ boolean_t pdcp_data_req(
 
   if (h_rc != HASH_TABLE_OK) {
     if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
-      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %d Ignoring SDU...\n",
+      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %ld Ignoring SDU...\n",
             PROTOCOL_CTXT_ARGS(ctxt_pP),
             rb_idP);
       ctxt_pP->configured=FALSE;
@@ -190,7 +190,7 @@ boolean_t pdcp_data_req(
         rlc_util_print_hex_octets(PDCP,
                                   (unsigned char *)&pdcp_pdu_p->data[0],
                                   sdu_buffer_sizeP);
-        LOG_UI(PDCP, "Before rlc_data_req 1, srb_flagP: %d, rb_idP: %d \n", srb_flagP, rb_idP);
+        LOG_UI(PDCP, "Before rlc_data_req 1, srb_flagP: %d, rb_idP: %ld \n", srb_flagP, rb_idP);
       }
 
       rlc_status = pdcp_params.send_rlc_data_req_func(ctxt_pP, srb_flagP, NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)?MBMS_FLAG_NO:MBMS_FLAG_YES, rb_idP, muiP,
@@ -338,7 +338,7 @@ boolean_t pdcp_data_req(
         stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
       }
 
-      LOG_E(PDCP,  "[FRAME %5u][%s][PDCP][MOD %u][RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
+      LOG_E(PDCP,  "[FRAME %5u][%s][PDCP][MOD %u][RB %ld] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
             ctxt_pP->frame,
             (ctxt_pP->enb_flag) ? "eNB" : "UE",
             ctxt_pP->module_id,
@@ -352,11 +352,11 @@ boolean_t pdcp_data_req(
      * to see if RLC succeeded
      */
     LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)pdcp_pdu_p->data,pdcp_pdu_size,
-                "[MSG] PDCP DL %s PDU on rb_id %d\n",(srb_flagP)? "CONTROL" : "DATA", rb_idP);
+                "[MSG] PDCP DL %s PDU on rb_id %ld\n",(srb_flagP)? "CONTROL" : "DATA", rb_idP);
 
     if ((pdcp_pdu_p!=NULL) && (srb_flagP == 0) && (ctxt_pP->enb_flag == 1)) {
-      LOG_D(PDCP, "pdcp data req on drb %d, size %d, rnti %x, node_type %d \n",
-            rb_idP, pdcp_pdu_size, ctxt_pP->rnti, RC.rrc[ctxt_pP->module_id]->node_type);
+      LOG_D(PDCP, "pdcp data req on drb %ld, size %d, rnti %x, node_type %d \n",
+            rb_idP, pdcp_pdu_size, ctxt_pP->rnti, RC.rrc ? RC.rrc[ctxt_pP->module_id]->node_type: -1);
 
       // The check on nos1 is done only for the use case of LTE stack running over 5g-nr PHY. This should be changed
       // before future merge of develop with develop-nr and instead of a check of IS_SOFTMODEM_NOS1, we should use a check
@@ -374,7 +374,7 @@ boolean_t pdcp_data_req(
         rlc_status = pdcp_params.send_rlc_data_req_func(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP,
                      confirmP, pdcp_pdu_size, pdcp_pdu_p,sourceL2Id,
                      destinationL2Id);
-
+	ret=FALSE;
         switch (rlc_status) {
           case RLC_OP_STATUS_OK:
             LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
@@ -383,22 +383,18 @@ boolean_t pdcp_data_req(
 
           case RLC_OP_STATUS_BAD_PARAMETER:
             LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
-            ret= FALSE;
             break;
 
           case RLC_OP_STATUS_INTERNAL_ERROR:
             LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
-            ret= FALSE;
             break;
 
           case RLC_OP_STATUS_OUT_OF_RESSOURCES:
             LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
-            ret= FALSE;
             break;
 
           default:
             LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
-            ret= FALSE;
             break;
         } // switch case
       } /* end if node_type is not DU */
@@ -527,19 +523,11 @@ pdcp_data_ind(
   int         security_ok;
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
   LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)sdu_buffer_pP->data,sdu_buffer_sizeP,
-              "[MSG] PDCP UL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
-
-
-#if T_TRACER
-
-  if (ctxt_pP->enb_flag != ENB_FLAG_NO)
-    T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_buffer_sizeP));
-
-#endif
+              "[MSG] PDCP UL %s PDU on rb_id %ld\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
 
   if (MBMS_flagP) {
     AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE,
-                 "RB id is too high (%u/%d) %u rnti %x!\n",
+                 "RB id is too high (%ld/%d) %u rnti %x!\n",
                  rb_idP,
                  NB_RB_MBMS_MAX,
                  ctxt_pP->module_id,
@@ -547,7 +535,7 @@ pdcp_data_ind(
 
     if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
       LOG_D(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %x "
-            "and radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
+            "and radio bearer ID %ld rlc sdu size %d ctxt_pP->enb_flag %d\n",
             ctxt_pP->module_id,
             ctxt_pP->rnti,
             rb_idP,
@@ -555,7 +543,7 @@ pdcp_data_ind(
             ctxt_pP->enb_flag);
     } else {
       LOG_D(PDCP, "Data indication notification for PDCP entity from UE %x to eNB %u "
-            "and radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
+            "and radio bearer ID %ld rlc sdu size %d ctxt_pP->enb_flag %d\n",
             ctxt_pP->rnti,
             ctxt_pP->module_id,
             rb_idP,
@@ -564,12 +552,12 @@ pdcp_data_ind(
     }
   } else {
     rb_id = rb_idP % LTE_maxDRB;
-    AssertError (rb_id < LTE_maxDRB, return FALSE, "RB id is too high (%u/%d) %u UE %x!\n",
+    AssertError (rb_id < LTE_maxDRB, return FALSE, "RB id is too high (%ld/%d) %u UE %x!\n",
                  rb_id,
                  LTE_maxDRB,
                  ctxt_pP->module_id,
                  ctxt_pP->rnti);
-    AssertError (rb_id > 0, return FALSE, "RB id is too low (%u/%d) %u UE %x!\n",
+    AssertError (rb_id > 0, return FALSE, "RB id is too low (%ld/%d) %u UE %x!\n",
                  rb_id,
                  LTE_maxDRB,
                  ctxt_pP->module_id,
@@ -735,14 +723,6 @@ pdcp_data_ind(
         pdcp_p->rx_hfn++;
       }
 
-      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
-      MSC_LOG_TX_MESSAGE(
-        (ctxt_pP->enb_flag == ENB_FLAG_NO)? MSC_PDCP_UE:MSC_PDCP_ENB,
-        (ctxt_pP->enb_flag == ENB_FLAG_NO)? MSC_RRC_UE:MSC_RRC_ENB,
-        NULL,0,
-        PROTOCOL_PDCP_CTXT_FMT" DATA-IND len %u",
-        PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
-        sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len);
       rrc_data_ind(ctxt_pP,
                    rb_id,
                    sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
@@ -945,7 +925,7 @@ pdcp_data_ind(
 
   if (LINK_ENB_PDCP_TO_GTPV1U) {
     if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
-      LOG_D(PDCP, "Sending packet to GTP, Calling GTPV1U_ENB_TUNNEL_DATA_REQ  ue %x rab %u len %u\n",
+      LOG_D(PDCP, "Sending packet to GTP, Calling GTPV1U_ENB_TUNNEL_DATA_REQ  ue %x rab %ld len %u\n",
             ctxt_pP->rnti,
             rb_id + 4,
             sdu_buffer_sizeP - payload_offset );
@@ -1186,7 +1166,7 @@ pdcp_run (
             RRC_DCCH_DATA_REQ (msg_p).frame,
             0,
             RRC_DCCH_DATA_REQ (msg_p).eNB_index);
-          LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
+          LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %ld, muiP %d, confirmP %d, mode %d\n",
                 PROTOCOL_CTXT_ARGS(&ctxt),
                 ITTI_MSG_NAME (msg_p),
                 ITTI_MSG_ORIGIN_NAME(msg_p),
@@ -1195,7 +1175,7 @@ pdcp_run (
                 RRC_DCCH_DATA_REQ (msg_p).muip,
                 RRC_DCCH_DATA_REQ (msg_p).confirmp,
                 RRC_DCCH_DATA_REQ (msg_p).mode);
-          LOG_D(PDCP, "Before calling pdcp_data_req from pdcp_run! RRC_DCCH_DATA_REQ (msg_p).rb_id: %d \n", RRC_DCCH_DATA_REQ (msg_p).rb_id);
+          LOG_D(PDCP, "Before calling pdcp_data_req from pdcp_run! RRC_DCCH_DATA_REQ (msg_p).rb_id: %ld \n", RRC_DCCH_DATA_REQ (msg_p).rb_id);
           result = pdcp_data_req (&ctxt,
                                   SRB_FLAG_YES,
                                   RRC_DCCH_DATA_REQ (msg_p).rb_id,
@@ -1846,7 +1826,7 @@ pdcp_config_req_asn1 (
       pdcp_pP->rx_hfn                           = 0;
       pdcp_pP->last_submitted_pdcp_rx_sn        = 4095;
       pdcp_pP->first_missing_pdu                = -1;
-      LOG_I(PDCP, PROTOCOL_PDCP_CTXT_FMT" Action ADD  LCID %d (%s id %d) "
+      LOG_I(PDCP, PROTOCOL_PDCP_CTXT_FMT" Action ADD  LCID %d (%s id %ld) "
             "configured with SN size %d bits and RLC %s\n",
             PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
             lc_idP,
@@ -1898,7 +1878,7 @@ pdcp_config_req_asn1 (
       }
 
       LOG_I(PDCP,PROTOCOL_PDCP_CTXT_FMT" Action MODIFY LCID %d "
-            "RB id %d reconfigured with SN size %d and RLC %s \n",
+            "RB id %ld reconfigured with SN size %d and RLC %s \n",
             PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
             lc_idP,
             rb_idP,
@@ -1910,7 +1890,7 @@ pdcp_config_req_asn1 (
       DevAssert(pdcp_pP != NULL);
       //#warning "TODO pdcp_module_id_to_rnti"
       //pdcp_module_id_to_rnti[ctxt_pP.module_id ][dst_id] = NOT_A_RNTI;
-      LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE LCID %d RBID %d configured\n",
+      LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE LCID %d RBID %ld configured\n",
             PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
             lc_idP,
             rb_idP);
@@ -1937,7 +1917,7 @@ pdcp_config_req_asn1 (
 
     case CONFIG_ACTION_MBMS_ADD:
     case CONFIG_ACTION_MBMS_MODIFY:
-      LOG_D(PDCP," %s service_id/mch index %d, session_id/lcid %d, rbid %d configured\n",
+      LOG_D(PDCP," %s service_id/mch index %d, session_id/lcid %d, rbid %ld configured\n",
             //PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
             actionP == CONFIG_ACTION_MBMS_ADD ? "CONFIG_ACTION_MBMS_ADD" : "CONFIG_ACTION_MBMS_MODIFY",
             mch_idP,
@@ -2063,7 +2043,7 @@ rrc_pdcp_config_req (
         }
 
         pdcp_p->first_missing_pdu = -1;
-        LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %d (already added) configured\n",
+        LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %ld (already added) configured\n",
               PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
               rb_idP);
         break;
@@ -2072,7 +2052,7 @@ rrc_pdcp_config_req (
         break;
 
       case CONFIG_ACTION_REMOVE:
-        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE: radio bearer id %d configured\n",
+        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE: radio bearer id %ld configured\n",
               PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
               rb_idP);
         pdcp_p->next_pdcp_tx_sn = 0;
@@ -2141,7 +2121,7 @@ rrc_pdcp_config_req (
           pdcp_p->first_missing_pdu = -1;
           LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Inserting PDCP instance in collection key 0x%"PRIx64"\n",
                 PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), key);
-          LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %d configured\n",
+          LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %ld configured\n",
                 PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
                 rb_idP);
         }
@@ -2323,10 +2303,8 @@ void nr_ip_over_LTE_DRB_preconfiguration(void){
 	               DRB_configList,
 	               (LTE_DRB_ToReleaseList_t *) NULL,
 	               0xff, NULL, NULL, NULL
-	//#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
-	               , (LTE_PMCH_InfoList_r9_t *) NULL
-	//#endif
-	               ,NULL);
+	               , (LTE_PMCH_InfoList_r9_t *) NULL,
+	               &DRB_config->drb_Identity);
 
 	rrc_rlc_config_asn1_req(&ctxt,
 	               (LTE_SRB_ToAddModList_t*)NULL,
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
index 14507f25894b08af00350400db24b955f423bf10..1d4c6127434e6b57d67601ab07edc321a02efa03 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
@@ -87,7 +87,7 @@ extern pthread_mutex_t pdcp_mutex;
 extern pthread_cond_t  pdcp_cond;
 extern int             pdcp_instance_cnt;
 
-#define PROTOCOL_PDCP_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02u] "
+#define PROTOCOL_PDCP_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02ld] "
 
 #define PROTOCOL_PDCP_CTXT_ARGS(CTXT_Pp, pDCP_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp),\
   (pDCP_Pp->is_srb) ? "SRB" : "DRB",\
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
index bc3474a369e59690cf8943cc29912724cfd7bc53..9e873379b135d598ddd027dbfd4b3fe7be3c9e5c 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
@@ -98,7 +98,7 @@ extern int gtpv1u_new_data_req( uint8_t  enb_module_idP, rnti_t   ue_rntiP, uint
 
 void debug_pdcp_pc5s_sdu(sidelink_pc5s_element *sl_pc5s_msg, char *title) {
   LOG_I(PDCP,"%s: \nPC5S message, header traffic_type: %d)\n", title, sl_pc5s_msg->pc5s_header.traffic_type);
-  LOG_I(PDCP,"PC5S message, header rb_id: %d)\n", sl_pc5s_msg->pc5s_header.rb_id);
+  LOG_I(PDCP,"PC5S message, header rb_id: %ld)\n", sl_pc5s_msg->pc5s_header.rb_id);
   LOG_I(PDCP,"PC5S message, header data_size: %d)\n", sl_pc5s_msg->pc5s_header.data_size);
   LOG_I(PDCP,"PC5S message, header inst: %d)\n", sl_pc5s_msg->pc5s_header.inst);
   LOG_I(PDCP,"PC5-S message, sourceL2Id: 0x%08x\n)\n", sl_pc5s_msg->pc5s_header.sourceL2Id);
@@ -181,33 +181,19 @@ int pdcp_fifo_read_input_sdus_fromtun (const protocol_ctxt_t *const  ctxt_pP) {
           ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
 
     if (h_rc == HASH_TABLE_OK) {
-      LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d on Rab %d \n",
+      LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d on Rab %ld \n",
             ctxt.frame, ctxt.instance, len, rab_id);
-      LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %04x][RB %u]\n",
+      LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %04x][RB %ld]\n",
             ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id,
             ctxt.rnti, rab_id);
-      MSC_LOG_RX_MESSAGE((ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
-                         (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
-                         NULL, 0,
-                         MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
-                         MSC_AS_TIME_ARGS(ctxt_pP),
-                         ctxt.instance, rab_id, rab_id, len);
       pdcp_data_req(&ctxt, SRB_FLAG_NO, rab_id, RLC_MUI_UNDEFINED,
                     RLC_SDU_CONFIRM_NO, len, (unsigned char *)nl_rx_buf,
                     PDCP_TRANSMISSION_MODE_DATA
                     , NULL, NULL
                    );
     } else {
-      MSC_LOG_RX_DISCARDED_MESSAGE(
-        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
-        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
-        NULL,
-        0,
-        MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
-        MSC_AS_TIME_ARGS(ctxt_pP),
-        ctxt.instance, rab_id, rab_id, len);
       LOG_D(PDCP,
-            "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %04x][RB %u] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
+            "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %04x][RB %ld] TUN NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
             ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id,
             ctxt.rnti, rab_id, key);
     }
@@ -253,7 +239,7 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
           if (nas_nlh_rx->nlmsg_len == sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)) {
             pdcp_read_state_g = 1;  //get
             memcpy((void *)&pdcp_read_header_g, (void *)NLMSG_DATA(nas_nlh_rx), sizeof(pdcp_data_req_header_t));
-            LOG_D(PDCP, "[PDCP][NETLINK] RX pdcp_data_req_header_t inst %u, rb_id %u data_size %d, source L2Id 0x%08x, destination L2Id 0x%08x\n",
+            LOG_D(PDCP, "[PDCP][NETLINK] RX pdcp_data_req_header_t inst %u, rb_id %ld data_size %d, source L2Id 0x%08x, destination L2Id 0x%08x\n",
                   pdcp_read_header_g.inst, pdcp_read_header_g.rb_id, pdcp_read_header_g.data_size,pdcp_read_header_g.sourceL2Id, pdcp_read_header_g.destinationL2Id );
           } else {
             LOG_E(PDCP, "[PDCP][NETLINK] WRONG size %d should be sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)\n",
@@ -269,7 +255,7 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
           //#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id"
           ctxt.frame         = ctxt_cpy.frame;
           ctxt.enb_flag      = ctxt_cpy.enb_flag;
-          LOG_D(PDCP, "[PDCP][NETLINK] pdcp_read_header_g.rb_id = %d, source L2Id = 0x%08x, destination L2Id = 0x%08x \n", pdcp_read_header_g.rb_id, pdcp_read_header_g.sourceL2Id,
+          LOG_D(PDCP, "[PDCP][NETLINK] pdcp_read_header_g.rb_id = %ld, source L2Id = 0x%08x, destination L2Id = 0x%08x \n", pdcp_read_header_g.rb_id, pdcp_read_header_g.sourceL2Id,
                 pdcp_read_header_g.destinationL2Id);
 
           if (ctxt.enb_flag) {
@@ -283,25 +269,14 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
               h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
 
               if (h_rc == HASH_TABLE_OK) {
-                LOG_D(PDCP, "[FRAME %5u][eNB][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %zu) on Rab %d for rnti: %d \n",
+                LOG_D(PDCP, "[FRAME %5u][eNB][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %zu) on Rab %ld for rnti: %d \n",
                       ctxt.frame,
                       pdcp_read_header_g.inst,
                       len,
                       nas_nlh_rx->nlmsg_len-sizeof(struct nlmsghdr),
                       pdcp_read_header_g.rb_id,
                       ctxt.rnti);
-                MSC_LOG_RX_MESSAGE(
-                  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
-                  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
-                  NULL,
-                  0,
-                  MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
-                  MSC_AS_TIME_ARGS(ctxt_pP),
-                  pdcp_read_header_g.inst,
-                  pdcp_read_header_g.rb_id,
-                  rab_id,
-                  pdcp_read_header_g.data_size);
-                LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u]UE %u][RB %u]\n",
+                LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u]UE %u][RB %ld]\n",
                       ctxt_cpy.frame,
                       pdcp_read_header_g.inst,
                       pdcp_read_header_g.rb_id,
@@ -320,7 +295,7 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
                               ,NULL, NULL
                              );
               } else {
-                LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE, DROPPED\n",
+                LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %ld] NON INSTANCIATED INSTANCE, DROPPED\n",
                       ctxt.frame,
                       pdcp_read_header_g.inst,
                       pdcp_read_header_g.rb_id,
@@ -335,7 +310,7 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
               for (ue_id = 0; ue_id < NB_UE_INST; ue_id++) {
                 if (oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt_cpy.module_id][ue_id] != NOT_A_RNTI) {
                   ctxt.rnti = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt_cpy.module_id][ue_id];
-                  LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
+                  LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
                         ctxt.frame,
                         pdcp_read_header_g.inst,
                         pdcp_read_header_g.rb_id,
@@ -377,27 +352,27 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
                       ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
                 key = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
                 h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
-                LOG_D(PDCP,"request key %x : (%d,%x,%d,%d)\n",
+                LOG_D(PDCP,"request key %x : (%d,%x,%d,%ld)\n",
                       (uint8_t)key,ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id);
               } else {
                 rab_id = rab_id % LTE_maxDRB;
-                LOG_D(PDCP, "PDCP_COLL_KEY_VALUE(module_id=%d, rnti=%x, enb_flag=%d, rab_id=%d, SRB_FLAG=%d)\n",
+                LOG_D(PDCP, "PDCP_COLL_KEY_VALUE(module_id=%d, rnti=%x, enb_flag=%d, rab_id=%ld, SRB_FLAG=%d)\n",
                       ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
                 key = PDCP_COLL_KEY_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
                 h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
-                LOG_D(PDCP,"request key %x : (%d,%x,%d,%d)\n",
+                LOG_D(PDCP,"request key %x : (%d,%x,%d,%ld)\n",
                       (uint8_t)key,ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id);
               }
 
               if (h_rc == HASH_TABLE_OK) {
                 rab_id = pdcp_p->rb_id;
-                LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %zu) on Rab %d \n",
+                LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %zu) on Rab %ld \n",
                       ctxt.frame,
                       pdcp_read_header_g.inst,
                       len,
                       nas_nlh_rx->nlmsg_len-sizeof(struct nlmsghdr),
                       pdcp_read_header_g.rb_id);
-                LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %u]\n",
+                LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %ld]\n",
                       ctxt.frame,
                       pdcp_read_header_g.inst,
                       pdcp_read_header_g.rb_id,
@@ -405,17 +380,6 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
                       ctxt.module_id,
                       ctxt.rnti,
                       rab_id);
-                MSC_LOG_RX_MESSAGE(
-                  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
-                  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
-                  NULL,
-                  0,
-                  MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
-                  MSC_AS_TIME_ARGS(ctxt_pP),
-                  pdcp_read_header_g.inst,
-                  pdcp_read_header_g.rb_id,
-                  rab_id,
-                  pdcp_read_header_g.data_size);
                 pdcp_data_req(
                   &ctxt,
                   SRB_FLAG_NO,
@@ -441,7 +405,7 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
                   rab_id,
                   pdcp_read_header_g.data_size);
                 LOG_D(PDCP,
-                      "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
+                      "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %ld] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
                       ctxt.frame,
                       pdcp_read_header_g.inst,
                       pdcp_read_header_g.rb_id,
@@ -453,7 +417,7 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
               } /* h_rc != HASH_TABLE_OK */
             }  else {/* else of rab_id != 0 */
               LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
-              LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
+              LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
                     ctxt.frame,
                     pdcp_read_header_g.inst,
                     pdcp_read_header_g.rb_id,
@@ -461,16 +425,6 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const  ctx
                     ctxt.module_id,
                     ctxt.rnti,
                     DEFAULT_RAB_ID);
-              MSC_LOG_RX_MESSAGE(
-                (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
-                (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
-                NULL,0,
-                MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u default rab %u size %u",
-                MSC_AS_TIME_ARGS(ctxt_pP),
-                pdcp_read_header_g.inst,
-                pdcp_read_header_g.rb_id,
-                DEFAULT_RAB_ID,
-                pdcp_read_header_g.data_size);
               pdcp_data_req (
                 &ctxt,
                 SRB_FLAG_NO,
@@ -555,7 +509,7 @@ void pdcp_fifo_read_input_sdus_frompc5s (const protocol_ctxt_t *const  ctxt_pP)
         //#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id"
         ctxt.frame         = ctxt_cpy.frame;
         ctxt.enb_flag      = ctxt_cpy.enb_flag;
-        LOG_I(PDCP, "[PDCP] pc5s_header->rb_id = %d\n", pc5s_header->rb_id);
+        LOG_I(PDCP, "[PDCP] pc5s_header->rb_id = %ld\n", pc5s_header->rb_id);
 
         if (ctxt_cpy.enb_flag) {
           ctxt.module_id = 0;
@@ -575,26 +529,26 @@ void pdcp_fifo_read_input_sdus_frompc5s (const protocol_ctxt_t *const  ctxt_pP)
                     ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
               key = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
               h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
-              LOG_D(PDCP,"request key %x : (%d,%x,%d,%d)\n",
+              LOG_D(PDCP,"request key %x : (%d,%x,%d,%ld)\n",
                     (uint8_t)key,ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id);
             } else {
               rab_id = rab_id % LTE_maxDRB;
-              LOG_I(PDCP, "PDCP_COLL_KEY_VALUE(module_id=%d, rnti=%x, enb_flag=%d, rab_id=%d, SRB_FLAG=%d)\n",
+              LOG_I(PDCP, "PDCP_COLL_KEY_VALUE(module_id=%d, rnti=%x, enb_flag=%d, rab_id=%ld, SRB_FLAG=%d)\n",
                     ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
               key = PDCP_COLL_KEY_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
               h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
-              LOG_I(PDCP,"request key %x : (%d,%x,%d,%d)\n",
+              LOG_I(PDCP,"request key %x : (%d,%x,%d,%ld)\n",
                     (uint8_t)key,ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id);
             }
 
             if (h_rc == HASH_TABLE_OK) {
               rab_id = pdcp_p->rb_id;
-              LOG_I(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d  on Rab %d \n",
+              LOG_I(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d  on Rab %ld \n",
                     ctxt.frame,
                     pc5s_header->inst,
                     bytes_received,
                     pc5s_header->rb_id);
-              LOG_I(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %u]\n",
+              LOG_I(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %ld]\n",
                     ctxt.frame,
                     pc5s_header->inst,
                     pc5s_header->rb_id,
@@ -638,7 +592,7 @@ void pdcp_fifo_read_input_sdus_frompc5s (const protocol_ctxt_t *const  ctxt_pP)
                 rab_id,
                 pc5s_header->data_size);
               LOG_D(PDCP,
-                    "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
+                    "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %ld] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
                     ctxt.frame,
                     pc5s_header->inst,
                     pc5s_header->rb_id,
@@ -650,7 +604,7 @@ void pdcp_fifo_read_input_sdus_frompc5s (const protocol_ctxt_t *const  ctxt_pP)
             }
           }  else { /* else of if (rab_id == 0) */
             LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
-            LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
+            LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
                   ctxt.frame,
                   pc5s_header->inst,
                   pc5s_header->rb_id,
@@ -706,28 +660,6 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t *const  ctxt_pP) {
   return 0;
 }
 
-
-void pdcp_fifo_read_input_sdus_from_otg (const protocol_ctxt_t *const  ctxt_pP) {
-  module_id_t          dst_id; // dst for otg
-  protocol_ctxt_t      ctxt;
-
-  // we need to add conditions to avoid transmitting data when the UE is not RRC connected.
-  if ((otg_enabled==1) && (ctxt_pP->enb_flag == ENB_FLAG_YES)) { // generate DL traffic
-    PROTOCOL_CTXT_SET_BY_MODULE_ID(
-      &ctxt,
-      ctxt_pP->module_id,
-      ctxt_pP->enb_flag,
-      NOT_A_RNTI,
-      ctxt_pP->frame,
-      ctxt_pP->subframe,
-      ctxt_pP->module_id);
-
-    for (dst_id = 0; dst_id<NUMBER_OF_UE_MAX; dst_id++) {
-      ctxt.rnti = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id][dst_id];
-    }
-  }
-}
-
 //TTN for D2D (PC5S)
 
 void
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c
index 0bf3d86bae4f0db6549207de73e9c65a812e0e34..891c38209b5eda9637cc17fabb7c81c186d24eb0 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c
@@ -221,7 +221,7 @@ void *pdcp_netlink_thread_fct(void *arg)
             pdcp_thread_read_state = 1;
             memcpy((void *)&new_data_p->pdcp_read_header, (void *)NLMSG_DATA(nas_nlh_rx), sizeof(pdcp_data_req_header_t));
             LOG_I(PDCP, "[NETLINK_THREAD] RX pdcp_data_req_header_t inst %u, "
-                  "rb_id %u data_size %d\n",
+                  "rb_id %ld data_size %d\n",
                   new_data_p->pdcp_read_header.inst,
                   new_data_p->pdcp_read_header.rb_id,
                   new_data_p->pdcp_read_header.data_size);
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_security.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_security.c
index a18713fbb67a32c94a91a922e47f7e7f67657310..8f9ee0af188e93a7fdb9a15c21d0c3b0551ccf99 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_security.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_security.c
@@ -128,7 +128,7 @@ pdcp_apply_security(
     /* SRBs */
     uint8_t *mac_i;
 
-    LOG_D(PDCP, "[OSA][RB %d] %s Applying control-plane security %d \n",
+    LOG_D(PDCP, "[OSA][RB %ld] %s Applying control-plane security %d \n",
           rb_id, (pdcp_pP->is_ue != 0) ? "UE -> eNB" : "eNB -> UE", pdcp_pP->integrityProtAlgorithm);
 
     encrypt_params.message    = pdcp_pdu_buffer;
@@ -145,7 +145,7 @@ pdcp_apply_security(
 
     encrypt_params.key = pdcp_pP->kRRCenc;  // + 128  // bit key
   } else {
-    LOG_D(PDCP, "[OSA][RB %d] %s Applying user-plane security\n",
+    LOG_D(PDCP, "[OSA][RB %ld] %s Applying user-plane security\n",
           rb_id, (pdcp_pP->is_ue != 0) ? "UE -> eNB" : "eNB -> UE");
 
     encrypt_params.key = pdcp_pP->kUPenc;//  + 128;
@@ -200,11 +200,11 @@ pdcp_validate_security(
   decrypt_params.key_length = 16;
 
   if (srb_flagP) {
-    LOG_D(PDCP, "[OSA][RB %d] %s Validating control-plane security\n",
+    LOG_D(PDCP, "[OSA][RB %ld] %s Validating control-plane security\n",
           rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
     decrypt_params.key = pdcp_pP->kRRCenc;// + 128;
   } else {
-    LOG_D(PDCP, "[OSA][RB %d] %s Validating user-plane security\n",
+    LOG_D(PDCP, "[OSA][RB %ld] %s Validating user-plane security\n",
           rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
     decrypt_params.key = pdcp_pP->kUPenc;// + 128;
   }
@@ -228,7 +228,7 @@ pdcp_validate_security(
     	  " Security: failed MAC-I Algo %X UE %"PRIx16" ",
     	  pdcp_pP->integrityProtAlgorithm,
     	  ctxt_pP->rnti);
-      LOG_E(PDCP, "[OSA][RB %d] %s failed to validate MAC-I (key %llx) of incoming PDU\n",
+      LOG_E(PDCP, "[OSA][RB %ld] %s failed to validate MAC-I (key %llx) of incoming PDU\n",
             rb_id, (pdcp_pP->is_ue != 0) ? "UE" : "eNB",((long long unsigned int*)decrypt_params.key)[0]);
       VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);
       return -1;
diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c
index 02e1b63129668e97eb6dae7a98ee0990be15f499..a11c029bd3637e022a8699562f65f3863f56b5b3 100644
--- a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c
+++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c
@@ -543,7 +543,7 @@ int proto_agent_pdcp_data_ind_process(mod_id_t mod_id, const void *params, Proto
   //   if (xid == 1)
   //     pdcp_data_ind_wifi((const protocol_ctxt_t*) ctxt_pP, (const srb_flag_t) srb_flagP, (const MBMS_flag_t) flag_MBMS, (const rb_id_t) rb_idP, pdcp_pdu_size, pdcp_pdu_p);
   //   else if (xid == 0)   // FIXME: USE a preprocessed definition
-  LOG_D(PROTO_AGENT, "[inst %d] Received PDCP PDU with size %d for UE RNTI %x RB %d, Calling pdcp_data_ind\n", ctxt_pP.instance, pdcp_pdu_size,ctxt_pP.rnti,rb_idP);
+  LOG_D(PROTO_AGENT, "[inst %d] Received PDCP PDU with size %d for UE RNTI %x RB %ld, Calling pdcp_data_ind\n", ctxt_pP.instance, pdcp_pdu_size,ctxt_pP.rnti,rb_idP);
   result = pdcp_data_ind(&ctxt_pP,
                          srb_flagP,
                          flag_MBMS,
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 ef40b186e001e01a3472ea00fb8ec63ff282b8df..865a81535946cd927d847a5e17d5c5c643982313 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c
@@ -672,7 +672,7 @@ rlc_am_mac_data_request (
 
           if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
             message_string_size = 0;
-            message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", l_rlc_p->rb_id);
+            message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %ld\n", l_rlc_p->rb_id);
             message_string_size += sprintf(&message_string[message_string_size], "PDU size    : %u\n", tb_size_in_bytes);
             message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
             message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
@@ -771,7 +771,7 @@ rlc_am_mac_data_request (
 
           if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
             message_string_size = 0;
-            message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", l_rlc_p->rb_id);
+            message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %ld\n", l_rlc_p->rb_id);
             message_string_size += sprintf(&message_string[message_string_size], "PDU size    : %u\n", tb_size_in_bytes);
             message_string_size += sprintf(&message_string[message_string_size], "PDU type    : RLC AM DATA REQ: STATUS PDU\n\n");
             message_string_size += sprintf(&message_string[message_string_size], "Header      :\n");
@@ -874,7 +874,7 @@ rlc_am_mac_data_indication (
             }
 
             if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
-              message_string_size += sprintf(&message_string[message_string_size], "Bearer	: %u\n", l_rlc_p->rb_id);
+              message_string_size += sprintf(&message_string[message_string_size], "Bearer	: %ld\n", l_rlc_p->rb_id);
               message_string_size += sprintf(&message_string[message_string_size], "PDU size	: %u\n", tb_size_in_bytes);
               message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
               message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
@@ -971,7 +971,7 @@ rlc_am_mac_data_indication (
 
             if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
               message_string_size = 0;
-              message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", l_rlc_p->rb_id);
+              message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %ld\n", l_rlc_p->rb_id);
               message_string_size += sprintf(&message_string[message_string_size], "PDU size    : %u\n", ((struct mac_tb_ind *) (tb_p->data))->size);
               message_string_size += sprintf(&message_string[message_string_size], "PDU type    : RLC AM DATA IND: STATUS PDU\n\n");
               message_string_size += sprintf(&message_string[message_string_size], "Header      :\n");
@@ -1039,7 +1039,7 @@ rlc_am_data_req (
       mui);
 
     if (LOG_DEBUGFLAG(DEBUG_RLC)) {
-      message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", l_rlc_p->rb_id);
+      message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %ld\n", l_rlc_p->rb_id);
       message_string_size += sprintf(&message_string[message_string_size], "SDU size    : %u\n", data_size);
       message_string_size += sprintf(&message_string[message_string_size], "MUI         : %u\n", mui);
       message_string_size += sprintf(&message_string[message_string_size], "CONF        : %u\n", ((struct rlc_am_data_req *) (sdu_pP->data))->conf);
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 c6a5ca721320915ccda6dbd98c5dbfca4e65a742..f2cb456e8cfb94816d46d77cecbb4e260cec5990 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h
@@ -60,12 +60,12 @@
 //#        include "rlc_am_test.h"
 
 
-#define PROTOCOL_RLC_AM_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02u]"
+#define PROTOCOL_RLC_AM_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02ld]"
 #define PROTOCOL_RLC_AM_CTXT_ARGS(CTXT_Pp, rLC_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp),\
           (rLC_Pp->is_data_plane) ? "DRB AM" : "SRB AM",\
           rLC_Pp->rb_id
 
-#define PROTOCOL_RLC_AM_MSC_FMT "[RNTI %" PRIx16 " %s %02u]"
+#define PROTOCOL_RLC_AM_MSC_FMT "[RNTI %" PRIx16 " %s %02ld]"
 #define PROTOCOL_RLC_AM_MSC_ARGS(CTXT_Pp, rLC_Pp) \
         CTXT_Pp->rnti,\
           (rLC_Pp->is_data_plane) ? "DRB AM" : "SRB AM",\
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c
index 369c7fd0da56576168243e6c8de429a2f557e773..793d0057ac99a149fb27c1011c23aa27e24f62f5 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c
@@ -111,7 +111,7 @@ rlc_am_send_sdu (
         char                 message_string[7000];
         size_t               message_string_size = 0;
         int                  octet_index, index;
-        message_string_size += sprintf(&message_string[message_string_size], "Bearer	  : %u\n", rlc_pP->rb_id);
+        message_string_size += sprintf(&message_string[message_string_size], "Bearer	  : %ld\n", rlc_pP->rb_id);
         message_string_size += sprintf(&message_string[message_string_size], "SDU size    : %u\n", rlc_pP->output_sdu_size_to_write);
         message_string_size += sprintf(&message_string[message_string_size], "\nPayload  : \n");
         message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h
index a5bd0b9ef59d4d077791498f75204750410e345c..1ea99887071397ebccb8c2b9f9c7d5ceaf92ff3d 100644
--- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h
+++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h
@@ -42,7 +42,7 @@
 #        include "mem_block.h"
 #        include "rlc_tm_init.h"
 
-#define PROTOCOL_RLC_TM_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02u]"
+#define PROTOCOL_RLC_TM_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02ld]"
 #define PROTOCOL_RLC_TM_CTXT_ARGS(CTXT_Pp, rLC_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp),\
           (rLC_Pp->is_data_plane) ? "DRB TM" : "SRB TM",\
           rLC_Pp->rb_id
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 78d7cc515f4ae713991cd7ec51c964242a232c10..22e6f4d78d1a4d1b8d0dc4c855216bda7068caed 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
@@ -42,7 +42,7 @@ void config_req_rlc_tm (
 
   if (h_rc == HASH_TABLE_OK) {
     rlc_p = &rlc_union_p->rlc.tm;
-    LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT" CONFIG_REQ (is_uplink_downlink=%d) RB %u\n",
+    LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT" CONFIG_REQ (is_uplink_downlink=%d) RB %ld\n",
           PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_p),
           config_tmP->is_uplink_downlink,
           rb_idP);
@@ -52,7 +52,7 @@ void config_req_rlc_tm (
     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",
+    LOG_E(RLC, PROTOCOL_RLC_TM_CTXT_FMT" CONFIG_REQ RB %ld RLC NOT FOUND\n",
           PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_p),
           rb_idP);
   }
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 66a544f96287c20a875d69277780e7cb1d4f2940..c7dc11f51dc62dfe4d615d427b5d45ce2d3edbd5 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
@@ -279,7 +279,7 @@ rlc_um_rx (const protocol_ctxt_t *const ctxt_pP, void *argP, struct mac_data_ind
 
           if (LOG_DEBUGFLAG(DEBUG_RLC)) {
             message_string_size = 0;
-            message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", l_rlc_p->rb_id);
+            message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %ld\n", l_rlc_p->rb_id);
             message_string_size += sprintf(&message_string[message_string_size], "PDU size    : %u\n", tb_size_in_bytes);
             message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
             message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
@@ -525,7 +525,7 @@ rlc_um_mac_data_request (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP,cons
 
         if(LOG_DEBUGFLAG(DEBUG_RLC)) {
           message_string_size = 0;
-          message_string_size += sprintf(&message_string[message_string_size], "Bearer	  : %u\n", l_rlc_p->rb_id);
+          message_string_size += sprintf(&message_string[message_string_size], "Bearer	  : %ld\n", l_rlc_p->rb_id);
           message_string_size += sprintf(&message_string[message_string_size], "PDU size    : %u\n", tb_size_in_bytes);
           message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
           message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
@@ -631,7 +631,7 @@ rlc_um_data_req (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP, mem_block_t
   if (LOG_DEBUGFLAG(DEBUG_RLC) ) {
     data_offset = sizeof (struct rlc_um_data_req_alloc);
     data_size = ((struct rlc_um_tx_sdu_management *)(sdu_pP->data))->sdu_size;
-    message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", rlc_p->rb_id);
+    message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %ld\n", rlc_p->rb_id);
     message_string_size += sprintf(&message_string[message_string_size], "SDU size    : %u\n", data_size);
     message_string_size += sprintf(&message_string[message_string_size], "\nPayload  : \n");
     message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
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 fc6e449acf7b7e38dfd1d8dd229c24af58181e90..8000196b32d7ec033d0a9af9099320e8d9db2b79 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
@@ -50,13 +50,13 @@
 #        include "rlc_um_segment.h"
 #        include "rlc_um_test.h"
 
-#define PROTOCOL_RLC_UM_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02u] %s()"
+#define PROTOCOL_RLC_UM_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02ld] %s()"
 #define PROTOCOL_RLC_UM_CTXT_ARGS(CTXT_Pp, rLC_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp),\
           (rLC_Pp->is_data_plane) ? "DRB UM" : "SRB UM",\
           rLC_Pp->rb_id,\
           __FUNCTION__
 
-#define PROTOCOL_RLC_UM_MSC_FMT "[RNTI %" PRIx16 " %s %02u]"
+#define PROTOCOL_RLC_UM_MSC_FMT "[RNTI %" PRIx16 " %s %02ld]"
 #define PROTOCOL_RLC_UM_MSC_ARGS(CTXT_Pp, rLC_Pp) \
         CTXT_Pp->rnti,\
           (rLC_Pp->is_data_plane) ? "DRB UM" : "SRB UM",\
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 77194f3a9e219712ae274c98e6d35383ff60f747..940740943e06b4da2125a9f88cd257f3e523ebf3 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
@@ -50,7 +50,7 @@ void config_req_rlc_um (
 
   if (h_rc == HASH_TABLE_OK) {
     rlc_p = &rlc_union_p->rlc.um;
-    LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" CONFIG_REQ timer_reordering=%d sn_field_length=%d is_mXch=%d RB %u\n",
+    LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" CONFIG_REQ timer_reordering=%d sn_field_length=%d is_mXch=%d RB %ld\n",
           PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
           config_um_pP->timer_reordering,
           config_um_pP->sn_field_length,
@@ -69,7 +69,7 @@ void config_req_rlc_um (
         config_um_pP->is_mXch);
     }
   } else {
-    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT"  CONFIG_REQ RB %u  RLC UM NOT FOUND\n",
+    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT"  CONFIG_REQ RB %ld  RLC UM NOT FOUND\n",
           PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
           rb_idP);
   }
@@ -143,14 +143,14 @@ void config_req_rlc_um_asn1 (
   //             rb_idP,
   //             srb_flagP);
   if(h_rc != HASH_TABLE_OK) {
-    LOG_E(RLC, "RLC NOT FOUND enb id %u ue id %i enb flag %u rb id %u, srb flag %u\n",
+    LOG_E(RLC, "RLC NOT FOUND enb id %u ue id %i enb flag %u rb id %ld, srb flag %u\n",
           ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
     return;
   }
 
   rlc_p = &rlc_union_p->rlc.um;
   //-----------------------------------------------------------------------------
-  LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT"  CONFIG_REQ timer_reordering=%dms sn_field_length=   RB %u \n",
+  LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT"  CONFIG_REQ timer_reordering=%dms sn_field_length=   RB %ld \n",
         PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
         (dl_rlc_pP && dl_rlc_pP->t_Reordering<31)?t_Reordering_tab[dl_rlc_pP->t_Reordering]:-1,
         rb_idP);
@@ -170,7 +170,7 @@ void config_req_rlc_um_asn1 (
           break;
 
         default:
-          LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID UL sn_FieldLength %ld, RLC NOT CONFIGURED\n",
+          LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID UL sn_FieldLength %ld, RLC NOT CONFIGURED\n",
                 PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
                 rlc_p->rb_id,
                 ul_rlc_pP->sn_FieldLength);
@@ -198,7 +198,7 @@ void config_req_rlc_um_asn1 (
           break;
 
         default:
-          LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID DL sn_FieldLength %ld, RLC NOT CONFIGURED\n",
+          LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID DL sn_FieldLength %ld, RLC NOT CONFIGURED\n",
                 PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
                 rlc_p->rb_id,
                 dl_rlc_pP->sn_FieldLength);
@@ -217,7 +217,7 @@ void config_req_rlc_um_asn1 (
       if (dl_rlc_pP->t_Reordering<32) {
         t_Reordering = t_Reordering_tab[dl_rlc_pP->t_Reordering];
       } else {
-        LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID T_Reordering %ld, RLC NOT CONFIGURED\n",
+        LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID T_Reordering %ld, RLC NOT CONFIGURED\n",
               PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
               rlc_p->rb_id,
               dl_rlc_pP->t_Reordering);
@@ -382,7 +382,7 @@ void rlc_um_configure(
     rlc_pP->rx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_5_BITS;
     rlc_pP->rx_header_min_length_in_bytes = 1;
   } else if (rx_sn_field_lengthP != 0) {
-    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
+    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
           PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
           rlc_pP->rb_id,
           rx_sn_field_lengthP);
@@ -400,7 +400,7 @@ void rlc_um_configure(
     rlc_pP->tx_um_window_size             = RLC_UM_WINDOW_SIZE_SN_5_BITS;
     rlc_pP->tx_header_min_length_in_bytes = 1;
   } else if (tx_sn_field_lengthP != 0) {
-    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
+    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
           PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
           rlc_pP->rb_id,
           tx_sn_field_lengthP);
@@ -428,7 +428,7 @@ void rlc_um_set_debug_infos(
   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",
+  LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [SET DEBUG INFOS] rb_id %ld srb_flag %d\n",
         PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
         rb_idP,
         srb_flagP);
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_receiver.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_receiver.c
index b6ab367bc1a112318c0c68073bf1a6a47b4586b2..90e006cd1782bdacc9b78d8213fbf1fa16ea78dd 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_receiver.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_receiver.c
@@ -50,7 +50,7 @@ rlc_um_display_rx_window(
   LOG_T(RLC, "\n");
   sprintf(time_out_str, "%010d", rlc_pP->t_reordering.ms_duration);
   time_out_str[10] = 0;
-  LOG_T(RLC, "| RLC UM RB %02d    VR(UR)=%03d    VR(UX)=%03d    VR(UH)=%03d    t-Reordering: %s %s %s             |",
+  LOG_T(RLC, "| RLC UM RB %02ld    VR(UR)=%03d    VR(UX)=%03d    VR(UH)=%03d    t-Reordering: %s %s %s             |",
         rlc_pP->rb_id, rlc_pP->vr_ur, rlc_pP->vr_ux, rlc_pP->vr_uh,
         (rlc_pP->t_reordering.running)?" ON":"OFF",
         (rlc_pP->t_reordering.running)?"Time-out frameP:":"               ",
diff --git a/openair2/LAYER2/RLC/rlc.c b/openair2/LAYER2/RLC/rlc.c
index 1563a01de352a809ab698161d059754a7e7a6e3c..2fb844f05a8b5d567cc559896e19a71643a1fe56 100644
--- a/openair2/LAYER2/RLC/rlc.c
+++ b/openair2/LAYER2/RLC/rlc.c
@@ -137,7 +137,7 @@ rlc_op_status_t rlc_stat_req     (
 
   //AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
   if(rb_idP >= NB_RB_MAX) {
-    LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
+    LOG_E(RLC, "RB id is too high (%ld/%d)!\n", rb_idP, NB_RB_MAX);
     return RLC_OP_STATUS_BAD_PARAMETER;
   }
 
@@ -332,7 +332,7 @@ rlc_op_status_t rlc_data_req     (const protocol_ctxt_t *const ctxt_pP,
   rlc_mbms_id_t         *mbms_id_p  = NULL;
   logical_chan_id_t      log_ch_id  = 0;
 #ifdef DEBUG_RLC_DATA_REQ
-  LOG_D(RLC,PROTOCOL_CTXT_FMT"rlc_data_req:  rb_id %u (MAX %d), muip %d, confirmP %d, sdu_sizeP %d, sdu_pP %p\n",
+  LOG_D(RLC,PROTOCOL_CTXT_FMT"rlc_data_req:  rb_id %ld (MAX %d), muip %d, confirmP %d, sdu_sizeP %d, sdu_pP %p\n",
         PROTOCOL_CTXT_ARGS(ctxt_pP),
         rb_idP,
         NB_RAB_MAX,
@@ -351,13 +351,13 @@ rlc_op_status_t rlc_data_req     (const protocol_ctxt_t *const ctxt_pP,
   if (MBMS_flagP) {
     //AssertFatal (rb_idP < NB_RB_MBMS_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MBMS_MAX);
     if(rb_idP >= NB_RB_MBMS_MAX) {
-      LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MBMS_MAX);
+      LOG_E(RLC, "RB id is too high (%ld/%d)!\n", rb_idP, NB_RB_MBMS_MAX);
       return RLC_OP_STATUS_BAD_PARAMETER;
     }
   } else {
     //AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
     if(rb_idP >= NB_RB_MAX) {
-      LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
+      LOG_E(RLC, "RB id is too high (%ld/%d)!\n", rb_idP, NB_RB_MAX);
       return RLC_OP_STATUS_BAD_PARAMETER;
     }
   }
@@ -387,14 +387,14 @@ rlc_op_status_t rlc_data_req     (const protocol_ctxt_t *const ctxt_pP,
 
     key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_id_p->service_id, mbms_id_p->session_id);
   } else if (sourceL2Id && destinationL2Id) {
-    LOG_D (RLC, "RLC_COLL_KEY_VALUE: ctxt_pP->module_id: %d, ctxt_pP->rnti: %d, ctxt_pP->enb_flag: %d, rb_idP:%d, srb_flagP: %d \n \n", ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP,
+    LOG_D (RLC, "RLC_COLL_KEY_VALUE: ctxt_pP->module_id: %d, ctxt_pP->rnti: %d, ctxt_pP->enb_flag: %d, rb_idP:%ld, srb_flagP: %d \n \n", ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP,
            srb_flagP);
     key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
     //Thinh's line originally uncommented
     //key = RLC_COLL_KEY_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, *sourceL2Id, *destinationL2Id, srb_flagP);
     //key_lcid = RLC_COLL_KEY_LCID_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, chan_idP, *sourceL2Id, *destinationL2Id, srb_flagP);
   } else {
-    LOG_D (RLC, "RLC_COLL_KEY_VALUE: ctxt_pP->module_id: %d, ctxt_pP->rnti: %d, ctxt_pP->enb_flag: %d, rb_idP:%d, srb_flagP: %d \n \n", ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP,
+    LOG_D (RLC, "RLC_COLL_KEY_VALUE: ctxt_pP->module_id: %d, ctxt_pP->rnti: %d, ctxt_pP->enb_flag: %d, rb_idP:%ld, srb_flagP: %d \n \n", ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP,
            srb_flagP);
     key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
   }
@@ -411,7 +411,7 @@ rlc_op_status_t rlc_data_req     (const protocol_ctxt_t *const ctxt_pP,
   }
 
   if (MBMS_flagP == 0) {
-    LOG_D(RLC, PROTOCOL_CTXT_FMT"[RB %u] Display of rlc_data_req:\n",
+    LOG_D(RLC, PROTOCOL_CTXT_FMT"[RB %ld] Display of rlc_data_req:\n",
           PROTOCOL_CTXT_ARGS(ctxt_pP),
           rb_idP);
 #if defined(TRACE_RLC_PAYLOAD)
@@ -424,7 +424,7 @@ rlc_op_status_t rlc_data_req     (const protocol_ctxt_t *const ctxt_pP,
     switch (rlc_mode) {
       case RLC_MODE_NONE:
         free_mem_block(sdu_pP, __func__);
-        LOG_E(RLC, PROTOCOL_CTXT_FMT" Received RLC_MODE_NONE as rlc_type for rb_id %u\n",
+        LOG_E(RLC, PROTOCOL_CTXT_FMT" Received RLC_MODE_NONE as rlc_type for rb_id %ld\n",
               PROTOCOL_CTXT_ARGS(ctxt_pP),
               rb_idP);
         VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_OUT);
@@ -558,7 +558,7 @@ void rlc_data_ind     (
   const sdu_size_t  sdu_sizeP,
   mem_block_t      *sdu_pP) {
   //-----------------------------------------------------------------------------
-  LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u] Display of rlc_data_ind: size %u\n",
+  LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %ld] Display of rlc_data_ind: size %u\n",
         PROTOCOL_CTXT_ARGS(ctxt_pP),
         (srb_flagP) ? "SRB" : "DRB",
         rb_idP,
@@ -601,7 +601,8 @@ void rlc_data_conf     (const protocol_ctxt_t *const ctxt_pP,
 }
 //-----------------------------------------------------------------------------
 int
-rlc_module_init (void) {
+rlc_module_init (int enb_flag) { /* enb_flag is unused, but needed for binary
+                                  * compatibility with rlc_v2 */
   //-----------------------------------------------------------------------------
   int          k;
   module_id_t  module_id1;
diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h
index dddffed241a1ecc9efd281739056589990834246..dfdf527123536d125e2c64420ab796f0e78a6cf7 100644
--- a/openair2/LAYER2/RLC/rlc.h
+++ b/openair2/LAYER2/RLC/rlc.h
@@ -197,7 +197,7 @@ rlc_mbms_id_t        rlc_mbms_lcid2service_session_id_eNB[MAX_eNB][RLC_MAX_MBMS_
 #define rlc_mbms_ue_get_lcid_by_rb_id(uE_mOD,rB_iD) rlc_mbms_rbid2lcid_ue[uE_mOD][rB_iD]
 
 #define rlc_mbms_ue_set_lcid_by_rb_id(uE_mOD,rB_iD,lOG_cH_iD) do { \
-    AssertFatal(rB_iD<NB_RB_MBMS_MAX, "INVALID RB ID %u", rB_iD); \
+    AssertFatal(rB_iD<NB_RB_MBMS_MAX, "INVALID RB ID %ld", rB_iD); \
     rlc_mbms_rbid2lcid_ue[uE_mOD][rB_iD] = lOG_cH_iD; \
   } while (0);
 
@@ -620,10 +620,10 @@ rlc_op_status_t rlc_stat_req     (
   unsigned int *const stat_timer_poll_retransmit_timed_out,
   unsigned int *const stat_timer_status_prohibit_timed_out);
 
-/*! \fn int rlc_module_init(void)
+/*! \fn int rlc_module_init(int enb_flag)
 * \brief    RAZ the memory of the RLC layer, initialize the memory pool manager (mem_block_t structures mainly used in RLC module).
 */
-int rlc_module_init(void);
+int rlc_module_init(int enb_flag);
 
 /** @} */
 
diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c
index 4c04b9f66208ef5ca353c03ed2ce3a2f2ff84308..49f7420216c1dde675249d62118d80e78c4532ac 100644
--- a/openair2/LAYER2/RLC/rlc_rrc.c
+++ b/openair2/LAYER2/RLC/rlc_rrc.c
@@ -81,7 +81,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
     for (cnt=0; cnt<srb2add_listP->list.count; cnt++) {
       rb_id = srb2add_listP->list.array[cnt]->srb_Identity;
       lc_id = rb_id;
-      LOG_D(RLC, "Adding SRB %ld, rb_id %d\n",srb2add_listP->list.array[cnt]->srb_Identity,rb_id);
+      LOG_D(RLC, "Adding SRB %ld, rb_id %ld\n",srb2add_listP->list.array[cnt]->srb_Identity,rb_id);
       srb_toaddmod_p = srb2add_listP->list.array[cnt];
 
       if (srb_toaddmod_p->rlc_Config) {
@@ -102,7 +102,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
                     &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.am,
                     rb_id, lc_id);
                 } else {
-                  LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
+                  LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %ld \n",
                         PROTOCOL_CTXT_ARGS(ctxt_pP),
                         rb_id);
                 }
@@ -122,7 +122,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
                     rb_id, lc_id,0, 0
                   );
                 } else {
-                  LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
+                  LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %ld \n",
                         PROTOCOL_CTXT_ARGS(ctxt_pP),
                         rb_id);
                 }
@@ -142,7 +142,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
                     rb_id, lc_id,0, 0
                   );
                 } else {
-                  LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
+                  LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %ld \n",
                         PROTOCOL_CTXT_ARGS(ctxt_pP),
                         rb_id);
                 }
@@ -162,7 +162,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
                     rb_id, lc_id,0, 0
                   );
                 } else {
-                  LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
+                  LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %ld \n",
                         PROTOCOL_CTXT_ARGS(ctxt_pP),
                         rb_id);
                 }
@@ -196,7 +196,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
                 &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.am,
                 rb_id,lc_id);
             } else {
-              LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
+              LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %ld \n",
                     PROTOCOL_CTXT_ARGS(ctxt_pP),
                     rb_id);
             }
@@ -213,7 +213,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
                           NULL, // TO DO DEFAULT CONFIG
                           rb_id, lc_id);
                       } else {
-                        LOG_D(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
+                        LOG_D(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %ld \n",
                               PROTOCOL_CTXT_ARGS(ctxt_pP),
                               rb_id);
                       }
@@ -379,7 +379,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t    *const ctxt_pP
           }
         }
 
-        LOG_D(RLC, PROTOCOL_CTXT_FMT" CONFIG REQ MBMS ASN1 LC ID %u RB ID %u SESSION ID %u SERVICE ID %u\n",
+        LOG_D(RLC, PROTOCOL_CTXT_FMT" CONFIG REQ MBMS ASN1 LC ID %u RB ID %ld SESSION ID %u SERVICE ID %u\n",
               PROTOCOL_CTXT_ARGS(ctxt_pP),
               lc_id,
               rb_id,
@@ -502,7 +502,7 @@ rlc_op_status_t rrc_rlc_remove_rlc   (
 
   //AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
   if(rb_idP >= NB_RB_MAX) {
-    LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
+    LOG_E(RLC, "RB id is too high (%ld/%d)!\n", rb_idP, NB_RB_MAX);
     return RLC_OP_STATUS_BAD_PARAMETER;
   }
 
@@ -524,7 +524,7 @@ rlc_op_status_t rrc_rlc_remove_rlc   (
         break;
 
       default:
-        LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] RLC mode is unknown!\n",
+        LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %ld] RLC mode is unknown!\n",
               PROTOCOL_CTXT_ARGS(ctxt_pP),
               (srb_flagP) ? "SRB" : "DRB",
               rb_idP);
@@ -539,20 +539,20 @@ rlc_op_status_t rrc_rlc_remove_rlc   (
   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 LCID %d] RELEASED %s\n",
+    LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %ld LCID %d] RELEASED %s\n",
           PROTOCOL_CTXT_ARGS(ctxt_pP),
           (srb_flagP) ? "SRB" : "DRB",
           rb_idP, lcid,
           (srb_flagP) ? "SRB" : "DRB");
   } 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",
+    LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %ld 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, lcid,
           (srb_flagP) ? "SRB" : "DRB",
           h_rc, h_lcid_rc);
   } else {
-    LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u LCID %d] RELEASE : INTERNAL ERROR %s\n",
+    LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %ld LCID %d] RELEASE : INTERNAL ERROR %s\n",
           PROTOCOL_CTXT_ARGS(ctxt_pP),
           (srb_flagP) ? "SRB" : "DRB",
           rb_idP, lcid,
@@ -585,7 +585,7 @@ rlc_union_t *rrc_rlc_add_rlc   (
     //AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
     //AssertFatal (chan_idP < RLC_MAX_LC, "LC id is too high (%u/%d)!\n", chan_idP, RLC_MAX_LC);
     if(rb_idP >= NB_RB_MAX) {
-      LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
+      LOG_E(RLC, "RB id is too high (%ld/%d)!\n", rb_idP, NB_RB_MAX);
       return NULL;
     }
 
@@ -624,7 +624,7 @@ rlc_union_t *rrc_rlc_add_rlc   (
   h_rc = hashtable_get(rlc_coll_p, key, (void **)&rlc_union_p);
 
   if (h_rc == HASH_TABLE_OK) {
-    LOG_W(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_add_rlc , already exist %s\n",
+    LOG_W(RLC, PROTOCOL_CTXT_FMT"[%s %ld] rrc_rlc_add_rlc , already exist %s\n",
           PROTOCOL_CTXT_ARGS(ctxt_pP),
           (srb_flagP) ? "SRB" : "DRB",
           rb_idP,
@@ -649,7 +649,7 @@ rlc_union_t *rrc_rlc_add_rlc   (
               mbms_id_p->service_id,
               mbms_id_p->session_id);
       } else {
-        LOG_I(RLC, PROTOCOL_CTXT_FMT" [%s %u] rrc_rlc_add_rlc  %s\n",
+        LOG_I(RLC, PROTOCOL_CTXT_FMT" [%s %ld] rrc_rlc_add_rlc  %s\n",
               PROTOCOL_CTXT_ARGS(ctxt_pP),
               (srb_flagP) ? "SRB" : "DRB",
               rb_idP,
@@ -659,7 +659,7 @@ 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 (add by RB_id=%d; add by LC_id=%d)\n",
+      LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %ld] 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,
@@ -670,7 +670,7 @@ rlc_union_t *rrc_rlc_add_rlc   (
       return NULL;
     }
   } else {
-    LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_add_rlc , INTERNAL ERROR %s\n",
+    LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %ld] rrc_rlc_add_rlc , INTERNAL ERROR %s\n",
           PROTOCOL_CTXT_ARGS(ctxt_pP),
           (srb_flagP) ? "SRB" : "DRB",
           rb_idP,
@@ -689,13 +689,13 @@ rlc_op_status_t rrc_rlc_config_req   (
   const rlc_info_t      rlc_infoP) {
   //-----------------------------------------------------------------------------
   //rlc_op_status_t status;
-  LOG_D(RLC, PROTOCOL_CTXT_FMT" CONFIG_REQ for RAB %u\n",
+  LOG_D(RLC, PROTOCOL_CTXT_FMT" CONFIG_REQ for RAB %ld\n",
         PROTOCOL_CTXT_ARGS(ctxt_pP),
         rb_idP);
 
   //AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
   if(rb_idP >= NB_RB_MAX) {
-    LOG_E(RLC, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
+    LOG_E(RLC, "RB id is too high (%ld/%d)!\n", rb_idP, NB_RB_MAX);
     return RLC_OP_STATUS_BAD_PARAMETER;
   }
 
@@ -709,7 +709,7 @@ rlc_op_status_t rrc_rlc_config_req   (
     case CONFIG_ACTION_MODIFY:
       switch (rlc_infoP.rlc_mode) {
         case RLC_MODE_AM:
-          LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %u] MODIFY RB AM\n",
+          LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %ld] MODIFY RB AM\n",
                 PROTOCOL_CTXT_ARGS(ctxt_pP),
                 rb_idP);
           config_req_rlc_am(
@@ -720,7 +720,7 @@ rlc_op_status_t rrc_rlc_config_req   (
           break;
 
         case RLC_MODE_UM:
-          LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %u] MODIFY RB UM\n",
+          LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %ld] MODIFY RB UM\n",
                 PROTOCOL_CTXT_ARGS(ctxt_pP),
                 rb_idP);
           config_req_rlc_um(
@@ -731,7 +731,7 @@ rlc_op_status_t rrc_rlc_config_req   (
           break;
 
         case RLC_MODE_TM:
-          LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %u] MODIFY RB TM\n",
+          LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %ld] MODIFY RB TM\n",
                 PROTOCOL_CTXT_ARGS(ctxt_pP),
                 rb_idP);
           config_req_rlc_tm(
diff --git a/openair2/LAYER2/nr_rlc/Makefile b/openair2/LAYER2/nr_rlc/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..071930c4f4b6dc573a1be9f817e91edd369a111b
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/Makefile
@@ -0,0 +1,15 @@
+CC=gcc
+CFLAGS=-Wall -g -Itests
+
+OBJS=nr_rlc_entity.o nr_rlc_entity_am.o nr_rlc_entity_um.o \
+     nr_rlc_entity_tm.o nr_rlc_sdu.o nr_rlc_pdu.o test.o
+PROG=test
+
+$(PROG): $(OBJS)
+	$(CC) $(CFLAGS) -o $@ $^
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+clean:
+	rm -f test *.o
diff --git a/openair2/LAYER2/nr_rlc/TODO b/openair2/LAYER2/nr_rlc/TODO
new file mode 100644
index 0000000000000000000000000000000000000000..4e2d3147c983682871c5f014949e0d4a3389220f
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/TODO
@@ -0,0 +1,10 @@
+RLC AM:
+
+    - status reporting (38.322 5.3.4): implement this (not done because not
+      clearly understood):
+
+        "delay triggering the STATUS report until x < RX_Highest_Status
+         or x >= RX_Next + AM_Window_Size."
+
+    - send indication of successful delivery as soon as possible. Today we
+      signal successful delivery in order. Probably not a big issue though.
diff --git a/openair2/LAYER2/nr_rlc/asn1_utils.c b/openair2/LAYER2/nr_rlc/asn1_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..46f7d90da57d2cb7d15cee8c60614a49a832e955
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/asn1_utils.c
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "rlc.h"
+
+int decode_t_reordering(int v)
+{
+  static int tab[32] = {
+    0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85,
+    90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 1600
+  };
+
+  if (v < 0 || v > 31) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  return tab[v];
+}
+
+int decode_t_status_prohibit(int v)
+{
+  static int tab[62] = {
+    0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90,
+    95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165,
+    170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240,
+    245, 250, 300, 350, 400, 450, 500, 800, 1000, 1200, 1600, 2000, 2400
+  };
+
+  if (v < 0 || v > 61) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  return tab[v];
+}
+
+int decode_t_poll_retransmit(int v)
+{
+  static int tab[59] = {
+    5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95,
+    100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170,
+    175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240, 245,
+    250, 300, 350, 400, 450, 500, 800, 1000, 2000, 4000
+  };
+
+  if (v < 0 || v > 58) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  return tab[v];
+}
+
+int decode_poll_pdu(int v)
+{
+  static int tab[8] = {
+    4, 8, 16, 32, 64, 128, 256, -1 /* -1 means infinity */
+  };
+
+  if (v < 0 || v > 7) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  return tab[v];
+}
+
+int decode_poll_byte(int v)
+{
+  static int tab[15] = {
+    25, 50, 75, 100, 125, 250, 375, 500, 750, 1000, 1250, 1500, 2000, 3000,
+    -1 /* -1 means infinity */
+  };
+
+  if (v < 0 || v > 14) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  if (tab[v] == -1) return -1;
+  return tab[v] * 1024;
+}
+
+int decode_max_retx_threshold(int v)
+{
+  static int tab[8] = {
+    1, 2, 3, 4, 6, 8, 16, 32
+  };
+
+  if (v < 0 || v > 7) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  return tab[v];
+}
+
+int decode_sn_field_length(int v)
+{
+  static int tab[2] = {
+    5, 10
+  };
+
+  if (v < 0 || v > 1) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  return tab[v];
+}
diff --git a/openair2/LAYER2/nr_rlc/asn1_utils.h b/openair2/LAYER2/nr_rlc/asn1_utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..61394c9c6991ccdc32722bfb039bfdac82a741ae
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/asn1_utils.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _ASN1_UTILS_H_
+#define _ASN1_UTILS_H_
+
+int decode_t_reordering(int v);
+int decode_t_status_prohibit(int v);
+int decode_t_poll_retransmit(int v);
+int decode_poll_pdu(int v);
+int decode_poll_byte(int v);
+int decode_max_retx_threshold(int v);
+int decode_sn_field_length(int v);
+
+#endif /* _ASN1_UTILS_H_ */
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c
new file mode 100644
index 0000000000000000000000000000000000000000..fefe2fc77d4bf6a4ca606343133579cd4f2ecc2c
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.c
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "nr_rlc_entity.h"
+
+#include <stdlib.h>
+
+#include "nr_rlc_entity_am.h"
+#include "nr_rlc_entity_um.h"
+#include "nr_rlc_entity_tm.h"
+
+#include "LOG/log.h"
+
+nr_rlc_entity_t *new_nr_rlc_entity_am(
+    int rx_maxsize,
+    int tx_maxsize,
+    void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
+                      char *buf, int size),
+    void *deliver_sdu_data,
+    void (*sdu_successful_delivery)(void *sdu_successful_delivery_data,
+                                    struct nr_rlc_entity_t *entity,
+                                    int sdu_id),
+    void *sdu_successful_delivery_data,
+    void (*max_retx_reached)(void *max_retx_reached_data,
+                             struct nr_rlc_entity_t *entity),
+    void *max_retx_reached_data,
+    int t_poll_retransmit,
+    int t_reassembly,
+    int t_status_prohibit,
+    int poll_pdu,
+    int poll_byte,
+    int max_retx_threshold,
+    int sn_field_length)
+{
+  nr_rlc_entity_am_t *ret;
+
+  ret = calloc(1, sizeof(nr_rlc_entity_am_t));
+  if (ret == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  ret->tx_maxsize = tx_maxsize;
+  ret->rx_maxsize = rx_maxsize;
+
+  ret->t_poll_retransmit  = t_poll_retransmit;
+  ret->t_reassembly       = t_reassembly;
+  ret->t_status_prohibit  = t_status_prohibit;
+  ret->poll_pdu           = poll_pdu;
+  ret->poll_byte          = poll_byte;
+  ret->max_retx_threshold = max_retx_threshold;
+  ret->sn_field_length    = sn_field_length;
+
+  if (!(sn_field_length == 12 || sn_field_length == 18)) {
+    LOG_E(RLC, "%s:%d:%s: wrong SN field_lenght (%d), must be 12 or 18\n",
+          __FILE__, __LINE__, __FUNCTION__, sn_field_length);
+    exit(1);
+  }
+  ret->sn_modulus = 1 << ret->sn_field_length;
+  ret->window_size = ret->sn_modulus / 2;
+
+  ret->common.recv_pdu        = nr_rlc_entity_am_recv_pdu;
+  ret->common.buffer_status   = nr_rlc_entity_am_buffer_status;
+  ret->common.generate_pdu    = nr_rlc_entity_am_generate_pdu;
+  ret->common.recv_sdu        = nr_rlc_entity_am_recv_sdu;
+  ret->common.set_time        = nr_rlc_entity_am_set_time;
+  ret->common.discard_sdu     = nr_rlc_entity_am_discard_sdu;
+  ret->common.reestablishment = nr_rlc_entity_am_reestablishment;
+  ret->common.delete          = nr_rlc_entity_am_delete;
+
+  ret->common.deliver_sdu                  = deliver_sdu;
+  ret->common.deliver_sdu_data             = deliver_sdu_data;
+  ret->common.sdu_successful_delivery      = sdu_successful_delivery;
+  ret->common.sdu_successful_delivery_data = sdu_successful_delivery_data;
+  ret->common.max_retx_reached             = max_retx_reached;
+  ret->common.max_retx_reached_data        = max_retx_reached_data;
+
+  return (nr_rlc_entity_t *)ret;
+}
+
+nr_rlc_entity_t *new_nr_rlc_entity_um(
+    int rx_maxsize,
+    int tx_maxsize,
+    void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
+                      char *buf, int size),
+    void *deliver_sdu_data,
+    int t_reassembly,
+    int sn_field_length)
+{
+  nr_rlc_entity_um_t *ret;
+
+  ret = calloc(1, sizeof(nr_rlc_entity_um_t));
+  if (ret == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  ret->tx_maxsize = tx_maxsize;
+  ret->rx_maxsize = rx_maxsize;
+
+  ret->t_reassembly    = t_reassembly;
+  ret->sn_field_length = sn_field_length;
+
+  if (!(sn_field_length == 6 || sn_field_length == 12)) {
+    LOG_E(RLC, "%s:%d:%s: wrong SN field_lenght (%d), must be 6 or 12\n",
+          __FILE__, __LINE__, __FUNCTION__, sn_field_length);
+    exit(1);
+  }
+  ret->sn_modulus = 1 << ret->sn_field_length;
+  ret->window_size = ret->sn_modulus / 2;
+
+  ret->common.recv_pdu        = nr_rlc_entity_um_recv_pdu;
+  ret->common.buffer_status   = nr_rlc_entity_um_buffer_status;
+  ret->common.generate_pdu    = nr_rlc_entity_um_generate_pdu;
+  ret->common.recv_sdu        = nr_rlc_entity_um_recv_sdu;
+  ret->common.set_time        = nr_rlc_entity_um_set_time;
+  ret->common.discard_sdu     = nr_rlc_entity_um_discard_sdu;
+  ret->common.reestablishment = nr_rlc_entity_um_reestablishment;
+  ret->common.delete          = nr_rlc_entity_um_delete;
+
+  ret->common.deliver_sdu                  = deliver_sdu;
+  ret->common.deliver_sdu_data             = deliver_sdu_data;
+
+  return (nr_rlc_entity_t *)ret;
+}
+
+nr_rlc_entity_t *new_nr_rlc_entity_tm(
+    int tx_maxsize,
+    void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
+                      char *buf, int size),
+    void *deliver_sdu_data)
+{
+  nr_rlc_entity_tm_t *ret;
+
+  ret = calloc(1, sizeof(nr_rlc_entity_tm_t));
+  if (ret == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  ret->tx_maxsize = tx_maxsize;
+
+  ret->common.recv_pdu        = nr_rlc_entity_tm_recv_pdu;
+  ret->common.buffer_status   = nr_rlc_entity_tm_buffer_status;
+  ret->common.generate_pdu    = nr_rlc_entity_tm_generate_pdu;
+  ret->common.recv_sdu        = nr_rlc_entity_tm_recv_sdu;
+  ret->common.set_time        = nr_rlc_entity_tm_set_time;
+  ret->common.discard_sdu     = nr_rlc_entity_tm_discard_sdu;
+  ret->common.reestablishment = nr_rlc_entity_tm_reestablishment;
+  ret->common.delete          = nr_rlc_entity_tm_delete;
+
+  ret->common.deliver_sdu                  = deliver_sdu;
+  ret->common.deliver_sdu_data             = deliver_sdu_data;
+
+  return (nr_rlc_entity_t *)ret;
+}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b12a90cfd1daf04437a276d5258e0849e7d9ca1
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity.h
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _NR_RLC_ENTITY_H_
+#define _NR_RLC_ENTITY_H_
+
+#include <stdint.h>
+
+#define NR_SDU_MAX 16000   /* max NR PDCP SDU size is 9000, let's take more */
+
+typedef struct {
+  int status_size;
+  int tx_size;
+  int retx_size;
+} nr_rlc_entity_buffer_status_t;
+
+typedef struct nr_rlc_entity_t {
+  /* functions provided by the RLC module */
+  void (*recv_pdu)(struct nr_rlc_entity_t *entity, char *buffer, int size);
+  nr_rlc_entity_buffer_status_t (*buffer_status)(
+      struct nr_rlc_entity_t *entity, int maxsize);
+  int (*generate_pdu)(struct nr_rlc_entity_t *entity, char *buffer, int size);
+
+  void (*recv_sdu)(struct nr_rlc_entity_t *entity, char *buffer, int size,
+                   int sdu_id);
+
+  void (*set_time)(struct nr_rlc_entity_t *entity, uint64_t now);
+
+  void (*discard_sdu)(struct nr_rlc_entity_t *entity, int sdu_id);
+
+  void (*reestablishment)(struct nr_rlc_entity_t *entity);
+
+  void (*delete)(struct nr_rlc_entity_t *entity);
+
+  /* callbacks provided to the RLC module */
+  void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
+                      char *buf, int size);
+  void *deliver_sdu_data;
+
+  void (*sdu_successful_delivery)(void *sdu_successful_delivery_data,
+                                  struct nr_rlc_entity_t *entity,
+                                  int sdu_id);
+  void *sdu_successful_delivery_data;
+
+  void (*max_retx_reached)(void *max_retx_reached_data,
+                           struct nr_rlc_entity_t *entity);
+  void *max_retx_reached_data;
+} nr_rlc_entity_t;
+
+nr_rlc_entity_t *new_nr_rlc_entity_am(
+    int rx_maxsize,
+    int tx_maxsize,
+    void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
+                      char *buf, int size),
+    void *deliver_sdu_data,
+    void (*sdu_successful_delivery)(void *sdu_successful_delivery_data,
+                                    struct nr_rlc_entity_t *entity,
+                                    int sdu_id),
+    void *sdu_successful_delivery_data,
+    void (*max_retx_reached)(void *max_retx_reached_data,
+                             struct nr_rlc_entity_t *entity),
+    void *max_retx_reached_data,
+    int t_poll_retransmit,
+    int t_reassembly,
+    int t_status_prohibit,
+    int poll_pdu,
+    int poll_byte,
+    int max_retx_threshold,
+    int sn_field_length);
+
+nr_rlc_entity_t *new_nr_rlc_entity_um(
+    int rx_maxsize,
+    int tx_maxsize,
+    void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
+                      char *buf, int size),
+    void *deliver_sdu_data,
+    int t_reassembly,
+    int sn_field_length);
+
+nr_rlc_entity_t *new_nr_rlc_entity_tm(
+    int tx_maxsize,
+    void (*deliver_sdu)(void *deliver_sdu_data, struct nr_rlc_entity_t *entity,
+                      char *buf, int size),
+    void *deliver_sdu_data);
+
+#endif /* _NR_RLC_ENTITY_H_ */
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c
new file mode 100644
index 0000000000000000000000000000000000000000..8f3d49d8c2391b98daf24f8d74ad7bb54a951905
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c
@@ -0,0 +1,1844 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "nr_rlc_entity_am.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nr_rlc_pdu.h"
+
+#include "LOG/log.h"
+
+/*************************************************************************/
+/* PDU RX functions                                                      */
+/*************************************************************************/
+
+static int modulus_rx(nr_rlc_entity_am_t *entity, int a)
+{
+  /* as per 38.322 7.1, modulus base is rx_next */
+  int r = a - entity->rx_next;
+  if (r < 0) r += entity->sn_modulus;
+  return r;
+}
+
+static int modulus_tx(nr_rlc_entity_am_t *entity, int a)
+{
+  int r = a - entity->tx_next_ack;
+  if (r < 0) r += entity->sn_modulus;
+  return r;
+}
+
+static int sn_in_recv_window(void *_entity, int sn)
+{
+  nr_rlc_entity_am_t *entity = _entity;
+  int mod_sn = modulus_rx(entity, sn);
+  /* we simplify rx_next <= sn < rx_next + am_window_size */
+  return mod_sn < entity->window_size;
+}
+
+static int sn_compare_rx(void *_entity, int a, int b)
+{
+  nr_rlc_entity_am_t *entity = _entity;
+  return modulus_rx(entity, a) - modulus_rx(entity, b);
+}
+
+static int sn_compare_tx(void *_entity, int a, int b)
+{
+  nr_rlc_entity_am_t *entity = _entity;
+  return modulus_tx(entity, a) - modulus_tx(entity, b);
+}
+
+static int segment_already_received(nr_rlc_entity_am_t *entity,
+    int sn, int so, int size)
+{
+  nr_rlc_pdu_t *l = entity->rx_list;
+  int covered;
+
+  while (l != NULL && size > 0) {
+    if (l->sn == sn) {
+      if (l->so <= so && so < l->so + l->size) {
+        covered = l->size - (so - l->so);
+        size -= covered;
+        so += covered;
+      } else if (l->so <= so+size-1 && so+size-1 < l->so + l->size) {
+        covered = size - (l->so - so);
+        size -= covered;
+      }
+    }
+    l = l->next;
+  }
+
+  return size <= 0;
+}
+
+static void consider_retransmission(nr_rlc_entity_am_t *entity,
+    nr_rlc_sdu_segment_t *cur, int update_retx)
+{
+  if (update_retx)
+    cur->sdu->retx_count++;
+
+  /* let's report max RETX reached for all retx_count >= max_retx_threshold
+   * (specs say to report if retx_count == max_retx_threshold).
+   * Upper layers should react (radio link failure), so no big deal actually.
+   */
+  if (update_retx && cur->sdu->retx_count >= entity->max_retx_threshold) {
+    entity->common.max_retx_reached(entity->common.max_retx_reached_data,
+                                    (nr_rlc_entity_t *)entity);
+  }
+
+  /* let's put in retransmit list even if we are over max_retx_threshold.
+   * upper layers should deal with this condition, internally it's better
+   * for the RLC code to keep going with this segment (we only remove
+   * a segment that was ACKed)
+   */
+  nr_rlc_sdu_segment_list_append(&entity->retransmit_list,
+                                 &entity->retransmit_end,
+                                 cur);
+}
+
+/* checks that all the bytes of the SDU sn have been received (but SDU
+ * has not been already processed)
+ */
+static int sdu_full(nr_rlc_entity_am_t *entity, int sn)
+{
+  nr_rlc_pdu_t *l = entity->rx_list;
+  int last_byte;
+  int new_last_byte;
+
+  last_byte = -1;
+  while (l != NULL) {
+    if (l->sn == sn)
+      break;
+    l = l->next;
+  }
+
+  /* check if the data has already been processed */
+  if (l != NULL && l->data == NULL)
+    return 0;
+
+  while (l != NULL && l->sn == sn) {
+    if (l->so > last_byte + 1)
+      return 0;
+    if (l->is_last)
+      return 1;
+    new_last_byte = l->so + l->size - 1;
+    if (new_last_byte > last_byte)
+      last_byte = new_last_byte;
+    l = l->next;
+  }
+
+  return 0;
+}
+
+/* checks that an SDU has already been delivered */
+static int sdu_delivered(nr_rlc_entity_am_t *entity, int sn)
+{
+  nr_rlc_pdu_t *l = entity->rx_list;
+
+  while (l != NULL) {
+    if (l->sn == sn)
+      break;
+    l = l->next;
+  }
+
+  return l != NULL && l->data == NULL;
+}
+
+/* check if there is some missing bytes before the last received of SDU sn */
+/* todo: be sure that when no byte was received or the SDU has already been
+ *       processed then the SDU has no missing byte
+ */
+static int sdu_has_missing_bytes(nr_rlc_entity_am_t *entity, int sn)
+{
+  nr_rlc_pdu_t *l = entity->rx_list;
+  int last_byte;
+  int new_last_byte;
+
+  last_byte = -1;
+  while (l != NULL) {
+    if (l->sn == sn)
+      break;
+    l = l->next;
+  }
+
+  /* check if the data has already been processed */
+  if (l != NULL && l->data == NULL)
+    return 0;                    /* data already processed: no missing byte */
+
+  while (l != NULL && l->sn == sn) {
+    if (l->so > last_byte + 1)
+      return 1;
+    new_last_byte = l->so + l->size - 1;
+    if (new_last_byte > last_byte)
+      last_byte = new_last_byte;
+    l = l->next;
+  }
+
+  return 0;
+}
+
+static void reassemble_and_deliver(nr_rlc_entity_am_t *entity, int sn)
+{
+  nr_rlc_pdu_t *pdu;
+  char sdu[NR_SDU_MAX];
+  int so = 0;
+  int bad_sdu = 0;
+
+  /* go to first segment of sn */
+  pdu = entity->rx_list;
+  while (pdu->sn != sn)
+    pdu = pdu->next;
+
+  /* reassemble - free 'data' of each segment after processing */
+  while (pdu != NULL && pdu->sn == sn) {
+    int len = pdu->size - (so - pdu->so);
+    if (so + len > NR_SDU_MAX && !bad_sdu) {
+      LOG_E(RLC, "%s:%d:%s: bad SDU, too big, discarding\n",
+            __FILE__, __LINE__, __FUNCTION__);
+      bad_sdu = 1;
+    }
+    if (!bad_sdu && len > 0) {
+      memcpy(sdu + so, pdu->data, len);
+      so += len;
+    }
+    free(pdu->data);
+    pdu->data = NULL;
+    entity->rx_size -= pdu->size;
+    pdu = pdu->next;
+  }
+
+  if (bad_sdu)
+    return;
+
+  /* deliver */
+  entity->common.deliver_sdu(entity->common.deliver_sdu_data,
+                             (nr_rlc_entity_t *)entity,
+                             sdu, so);
+}
+
+static void reception_actions(nr_rlc_entity_am_t *entity, nr_rlc_pdu_t *pdu)
+{
+  int x = pdu->sn;
+
+  if (sn_compare_rx(entity, x, entity->rx_next_highest) >= 0)
+    entity->rx_next_highest = (x + 1) % entity->sn_modulus;
+
+  /* todo: room for optimization: we can run through rx_list only once */
+  if (sdu_full(entity, x)) {
+    reassemble_and_deliver(entity, x);
+
+    if (x == entity->rx_highest_status) {
+      int rx_highest_status = entity->rx_highest_status;
+      while (sdu_delivered(entity, rx_highest_status))
+        rx_highest_status = (rx_highest_status + 1) % entity->sn_modulus;
+      entity->rx_highest_status = rx_highest_status;
+    }
+
+    if (x == entity->rx_next) {
+      /* update rx_next and free all delivered SDUs at the head of the
+       * rx_list
+       */
+      int rx_next = entity->rx_next;
+      while (entity->rx_list != NULL && entity->rx_list->data == NULL &&
+             entity->rx_list->sn == rx_next) {
+        /* free all segments of this SDU */
+        do {
+          nr_rlc_pdu_t *p = entity->rx_list;
+          entity->rx_list = p->next;
+          free(p);
+        } while (entity->rx_list != NULL &&
+                 entity->rx_list->sn == rx_next);
+        rx_next = (rx_next + 1) % entity->sn_modulus;
+      }
+      entity->rx_next = rx_next;
+    }
+  }
+
+  if (entity->t_reassembly_start) {
+    if (entity->rx_next_status_trigger == entity->rx_next ||
+        (entity->rx_next_status_trigger == (entity->rx_next + 1)
+                                             % entity->sn_modulus &&
+         !sdu_has_missing_bytes(entity, entity->rx_next)) ||
+        (!sn_in_recv_window(entity, entity->rx_next_status_trigger) &&
+         entity->rx_next_status_trigger !=
+           (entity->rx_next + entity->window_size) % entity->sn_modulus)) {
+      entity->t_reassembly_start = 0;
+    }
+  }
+
+  if (entity->t_reassembly_start == 0) {
+    if (sn_compare_rx(entity, entity->rx_next_highest,
+                      (entity->rx_next + 1) % entity->sn_modulus) > 0 ||
+        (entity->rx_next_highest == (entity->rx_next + 1)
+                                      % entity->sn_modulus &&
+         sdu_has_missing_bytes(entity, entity->rx_next))) {
+      entity->t_reassembly_start = entity->t_current;
+      entity->rx_next_status_trigger = entity->rx_next_highest;
+    }
+  }
+}
+
+static void process_received_ack(nr_rlc_entity_am_t *entity, int ack_sn)
+{
+  nr_rlc_sdu_segment_t head;
+  nr_rlc_sdu_segment_t *cur;
+  nr_rlc_sdu_segment_t *prev;
+  unsigned char sn_set[32768];  /* used to dec retx_count only once per sdu */
+
+  memset(sn_set, 0, 32768);
+
+#define IS_SN_SET(b) (sn_set[(b)/8] & (1 << ((b) % 8)))
+#define SET_SN(b) do { sn_set[(b)/8] |= (1 << ((b) % 8)); } while (0)
+
+  /* put SDUs from wait and retransmit lists with SN < 'ack_sn' to ack_list */
+
+  /* process wait list */
+  head.next = entity->wait_list;
+  prev = &head;
+  cur = entity->wait_list;
+  while (cur != NULL) {
+    if (sn_compare_tx(entity, cur->sdu->sn, ack_sn) < 0) {
+      /* remove from wait list */
+      prev->next = cur->next;
+      /* put the PDU in the ack list */
+      entity->ack_list = nr_rlc_sdu_segment_list_add(sn_compare_tx, entity,
+                                                     entity->ack_list, cur);
+      entity->wait_end = prev;
+      cur = prev->next;
+    } else {
+      entity->wait_end = cur;
+      prev = cur;
+      cur = cur->next;
+    }
+  }
+  entity->wait_list = head.next;
+  if (entity->wait_list == NULL)
+    entity->wait_end = NULL;
+
+  /* process retransmit list */
+  head.next = entity->retransmit_list;
+  prev = &head;
+  cur = entity->retransmit_list;
+  while (cur != NULL) {
+    if (sn_compare_tx(entity, cur->sdu->sn, ack_sn) < 0) {
+      /* dec. retx_count in case we put this segment back in retransmit list
+       * in 'process_received_nack'
+       * do it only once per SDU
+       */
+      if (!IS_SN_SET(cur->sdu->sn)) {
+        cur->sdu->retx_count--;
+        SET_SN(cur->sdu->sn);
+      }
+      /* remove from retransmit list */
+      prev->next = cur->next;
+      /* put the PDU in the ack list */
+      entity->ack_list = nr_rlc_sdu_segment_list_add(sn_compare_tx, entity,
+                                                     entity->ack_list, cur);
+      entity->retransmit_end = prev;
+      cur = prev->next;
+    } else {
+      entity->retransmit_end = cur;
+      prev = cur;
+      cur = cur->next;
+    }
+  }
+  entity->retransmit_list = head.next;
+  if (entity->retransmit_list == NULL)
+    entity->retransmit_end = NULL;
+
+#undef IS_BIT_SET
+#undef SET_BIT
+}
+
+static int so_overlap(int s1, int e1, int s2, int e2)
+{
+  if (s1 < s2) {
+    if (e1 == -1 || e1 >= s2)
+      return 1;
+    return 0;
+  }
+  if (e2 == -1 || s1 <= e2)
+    return 1;
+  return 0;
+}
+
+static void process_nack_sn(nr_rlc_entity_am_t *entity, int nack_sn,
+                            int so_start, int so_end, unsigned char *sn_set)
+{
+  /* put all SDU segments with SN == 'sn' and with an overlapping so start/end
+   * to the retransmit list
+   * source lists are ack list and wait list.
+   * Not sure if we should consider wait list, isn't the other end supposed
+   * to only NACK SNs lower than the ACK SN sent in the status PDU, in which
+   * case all potential SDU segments should all be in ack list when calling
+   * the current function? in doubt let's accept anything and thus process
+   * also wait list.
+   */
+  nr_rlc_sdu_segment_t head;
+  nr_rlc_sdu_segment_t *cur;
+  nr_rlc_sdu_segment_t *prev;
+
+#define IS_SN_SET(b) (sn_set[(b)/8] & (1 << ((b) % 8)))
+#define SET_SN(b) do { sn_set[(b)/8] |= (1 << ((b) % 8)); } while (0)
+
+  /* check that tx_next_ack <= sn < tx_next */
+  if (!(sn_compare_tx(entity, entity->tx_next_ack, nack_sn) <= 0 &&
+        sn_compare_tx(entity, nack_sn, entity->tx_next) < 0))
+    return;
+
+  /* process wait list */
+  head.next = entity->wait_list;
+  prev = &head;
+  cur = entity->wait_list;
+  while (cur != NULL) {
+    if (cur->sdu->sn == nack_sn &&
+        so_overlap(so_start, so_end, cur->so, cur->so + cur->size - 1)) {
+      /* remove from wait list */
+      prev->next = cur->next;
+      cur->next = NULL;
+      /* consider the SDU segment for retransmission */
+      consider_retransmission(entity, cur, !IS_SN_SET(cur->sdu->sn));
+      SET_SN(cur->sdu->sn);
+      entity->wait_end = prev;
+      cur = prev->next;
+    } else {
+      entity->wait_end = cur;
+      prev = cur;
+      cur = cur->next;
+    }
+  }
+  entity->wait_list = head.next;
+  if (entity->wait_list == NULL)
+    entity->wait_end = NULL;
+
+  /* process ack list */
+  head.next = entity->ack_list;
+  prev = &head;
+  cur = entity->ack_list;
+  while (cur != NULL) {
+    if (cur->sdu->sn == nack_sn &&
+        so_overlap(so_start, so_end, cur->so, cur->so + cur->size - 1)) {
+      /* remove from ack list */
+      prev->next = cur->next;
+      cur->next = NULL;
+      /* consider the SDU segment for retransmission */
+      consider_retransmission(entity, cur, !IS_SN_SET(cur->sdu->sn));
+      SET_SN(cur->sdu->sn);
+      cur = prev->next;
+    } else {
+      prev = cur;
+      cur = cur->next;
+    }
+  }
+  entity->ack_list = head.next;
+
+#undef IS_BIT_SET
+#undef SET_BIT
+}
+
+static void process_received_nack(nr_rlc_entity_am_t *entity, int nack_sn,
+                                  int so_start, int so_end, int range,
+                                  unsigned char *sn_set)
+{
+  int i;
+
+  for (i = 0; i < range; i++)
+    process_nack_sn(entity, (nack_sn + i) % entity->sn_modulus,
+                    i == 0 ?         so_start : 0,
+                    i == range - 1 ? so_end : -1,
+                    sn_set);
+}
+
+static int sdu_segment_in_ack_list_full(nr_rlc_sdu_segment_t *sdu)
+{
+  int target_count = sdu->sdu->ref_count;
+  int actual_count = 0;
+  int sn = sdu->sdu->sn;
+
+  while (sdu != NULL && sdu->sdu->sn == sn) {
+    actual_count++;
+    sdu = sdu->next;
+  }
+
+  return actual_count == target_count;
+}
+
+static void finalize_ack_nack_processing(nr_rlc_entity_am_t *entity)
+{
+  nr_rlc_sdu_segment_t *cur = entity->ack_list;
+  int sn;
+
+  /* - send indication of successful delivery for all consecutive acked SDUs
+   *   starting from tx_next_ack. Also free them.
+   * - update tx_next_ack to the next SN not acked yet
+   */
+  /* todo: send indication of successful delivery as soon as possible as
+   *       the specs say (38.322 5.2.3.1.1). As the code is, if we receive
+   *       ack for SN+2 we won't indicate successful delivery before
+   *       SN+1 has been indicated.
+   */
+  while (cur != NULL && cur->sdu->sn == entity->tx_next_ack &&
+         sdu_segment_in_ack_list_full(cur)) {
+    entity->tx_size -= cur->sdu->size;
+    sn = cur->sdu->sn;
+    entity->common.sdu_successful_delivery(
+        entity->common.sdu_successful_delivery_data,
+        (nr_rlc_entity_t *)entity, cur->sdu->upper_layer_id);
+    while (cur != NULL && cur->sdu->sn == sn) {
+      nr_rlc_sdu_segment_t *s = cur;
+      cur = cur->next;
+      nr_rlc_free_sdu_segment(s);
+    }
+    entity->ack_list = cur;
+    entity->tx_next_ack = (entity->tx_next_ack + 1) % entity->sn_modulus;
+  }
+}
+
+void nr_rlc_entity_am_recv_pdu(nr_rlc_entity_t *_entity,
+                               char *buffer, int size)
+{
+#define R(d) do { if (nr_rlc_pdu_decoder_in_error(&d)) goto err; } while (0)
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  nr_rlc_pdu_decoder_t decoder;
+  nr_rlc_pdu_decoder_t control_decoder;
+  nr_rlc_pdu_t *pdu;
+  int dc;
+  int p = 0;
+  int si;
+  int sn;
+  int so = 0;
+  int data_size;
+  int is_first;
+  int is_last;
+
+  int cpt;
+  int e1;
+  int e2;
+  int e3;
+  int ack_sn;
+  int nack_sn;
+  int so_start;
+  int so_end;
+  int range;
+  int control_e1;
+  int control_e2;
+  int control_e3;
+  unsigned char sn_set[32768];  /* used to dec retx_count only once per sdu */
+
+  nr_rlc_pdu_decoder_init(&decoder, buffer, size);
+  dc = nr_rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder);
+  if (dc == 0) goto control;
+
+  /* data PDU */
+  p  = nr_rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder);
+  si = nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder);
+
+  is_first = (si & 0x2) == 0;
+  is_last = (si & 0x1) == 0;
+
+  if (entity->sn_field_length == 18) {
+    nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder);
+  }
+
+  sn = nr_rlc_pdu_decoder_get_bits(&decoder, entity->sn_field_length);
+  R(decoder);
+
+  if (!is_first) {
+    so = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder);
+    if (so == 0) {
+      LOG_E(RLC, "%s:%d:%s: warning: discard PDU, bad so\n",
+            __FILE__, __LINE__, __FUNCTION__);
+      goto discard;
+    }
+  }
+
+  data_size = size - decoder.byte;
+
+  /* dicard PDU if no data */
+  if (data_size <= 0) {
+    LOG_D(RLC, "%s:%d:%s: warning: discard PDU, no data\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    goto discard;
+  }
+
+  /* dicard PDU if rx buffer is full */
+  if (entity->rx_size + data_size > entity->rx_maxsize) {
+    LOG_D(RLC, "%s:%d:%s: warning: discard PDU, RX buffer full\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    goto discard;
+  }
+
+  if (!sn_in_recv_window(entity, sn)) {
+    LOG_D(RLC, "%s:%d:%s: warning: discard PDU, sn out of window (sn %d rx_next %d)\n",
+          __FILE__, __LINE__, __FUNCTION__,
+           sn, entity->rx_next);
+    goto discard;
+  }
+
+  /* discard segment if all the bytes of the segment are already there */
+  if (segment_already_received(entity, sn, so, data_size)) {
+    LOG_D(RLC, "%s:%d:%s: warning: discard PDU, already received\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    goto discard;
+  }
+
+  /* put in pdu reception list */
+  entity->rx_size += data_size;
+  pdu = nr_rlc_new_pdu(sn, so, is_first, is_last,
+                       buffer + size - data_size, data_size);
+  entity->rx_list = nr_rlc_pdu_list_add(sn_compare_rx, entity,
+                                        entity->rx_list, pdu);
+
+  /* do reception actions (38.322 5.2.3.2.3) */
+  reception_actions(entity, pdu);
+
+  if (p) {
+    /* 38.322 5.3.4 says status triggering should be delayed
+     * until x < rx_highest_status or x >= rx_next + am_window_size.
+     * This is not clear (what is x then? we keep the same?). So let's
+     * trigger no matter what.
+     * todo: delay status triggering properly
+     */
+    int v = (entity->rx_next + entity->window_size) % entity->sn_modulus;
+    entity->status_triggered = 1;
+    if (!(sn_compare_rx(entity, sn, entity->rx_highest_status) < 0 ||
+          sn_compare_rx(entity, sn, v) >= 0)) {
+      LOG_D(RLC, "%s:%d:%s: warning: STATUS trigger should be delayed, according to specs\n",
+            __FILE__, __LINE__, __FUNCTION__);
+    }
+  }
+
+  return;
+
+control:
+  cpt = nr_rlc_pdu_decoder_get_bits(&decoder, 3); R(decoder);
+  if (cpt != 0) {
+    LOG_D(RLC, "%s:%d:%s: warning: discard PDU, CPT not 0 (%d)\n",
+          __FILE__, __LINE__, __FUNCTION__, cpt);
+    goto discard;
+  }
+  ack_sn = nr_rlc_pdu_decoder_get_bits(&decoder, entity->sn_field_length); R(decoder);
+  e1 = nr_rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder);
+  /* r bits */
+  if (entity->sn_field_length == 18) {
+    nr_rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder);
+  } else {
+    nr_rlc_pdu_decoder_get_bits(&decoder, 7); R(decoder);
+  }
+
+  /* let's try to parse the control PDU once to check consistency */
+  control_decoder = decoder;
+  control_e1 = e1;
+  while (control_e1) {
+    nr_rlc_pdu_decoder_get_bits(&control_decoder, entity->sn_field_length); R(control_decoder); /* NACK_SN */
+    control_e1 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder);
+    control_e2 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder);
+    control_e3 = nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder);
+    /* r bits */
+    if (entity->sn_field_length == 18) {
+      nr_rlc_pdu_decoder_get_bits(&control_decoder, 3); R(control_decoder);
+    } else {
+      nr_rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder);
+    }
+    if (control_e2) {
+      nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); /* SOstart */
+      nr_rlc_pdu_decoder_get_bits(&control_decoder, 16); R(control_decoder); /* SOend */
+    }
+    if (control_e3) {
+      nr_rlc_pdu_decoder_get_bits(&control_decoder, 8); R(control_decoder); /* NACK range */
+    }
+  }
+
+  /* 38.322 5.3.3.3 says to stop t_poll_retransmit if a ACK or NACK is
+   * received for the SN 'poll_sn'
+   */
+  if (sn_compare_tx(entity, entity->poll_sn, ack_sn) < 0)
+    entity->t_poll_retransmit_start = 0;
+
+  /* at this point, accept the PDU even if the actual values
+   * may be incorrect (eg. if so_start > so_end)
+   */
+  process_received_ack(entity, ack_sn);
+
+  if (e1)
+    memset(sn_set, 0, 32768);
+
+  while (e1) {
+    nack_sn = nr_rlc_pdu_decoder_get_bits(&decoder, entity->sn_field_length); R(decoder);
+    e1 = nr_rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder);
+    e2 = nr_rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder);
+    e3 = nr_rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder);
+    /* r bits */
+    if (entity->sn_field_length == 18) {
+      nr_rlc_pdu_decoder_get_bits(&decoder, 3); R(decoder);
+    } else {
+      nr_rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder);
+    }
+    if (e2) {
+      so_start = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder);
+      so_end = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder);
+      if (so_end < so_start) {
+        LOG_W(RLC, "%s:%d:%s: warning, bad so start/end, NACK the whole PDU (sn %d)\n",
+              __FILE__, __LINE__, __FUNCTION__, nack_sn);
+        so_start = 0;
+        so_end = -1;
+      }
+      /* special value 0xffff indicates 'all bytes to the end' */
+      if (so_end == 0xffff)
+        so_end = -1;
+    } else {
+      so_start = 0;
+      so_end = -1;
+    }
+    if (e3) {
+      range = nr_rlc_pdu_decoder_get_bits(&decoder, 8); R(decoder);
+    } else {
+      range = 1;
+    }
+    process_received_nack(entity, nack_sn, so_start, so_end, range, sn_set);
+
+    /* 38.322 5.3.3.3 says to stop t_poll_retransmit if a ACK or NACK is
+     * received for the SN 'poll_sn'
+     */
+    if (sn_compare_tx(entity, nack_sn, entity->poll_sn) <= 0 &&
+        sn_compare_tx(entity, entity->poll_sn, (nack_sn + range) % entity->sn_modulus) < 0)
+      entity->t_poll_retransmit_start = 0;
+  }
+
+  finalize_ack_nack_processing(entity);
+
+  return;
+
+err:
+  LOG_W(RLC, "%s:%d:%s: error decoding PDU, discarding\n", __FILE__, __LINE__, __FUNCTION__);
+  goto discard;
+
+discard:
+  if (p)
+    entity->status_triggered = 1;
+
+#undef R
+}
+
+/*************************************************************************/
+/* TX functions                                                          */
+/*************************************************************************/
+
+static int is_window_stalling(nr_rlc_entity_am_t *entity)
+{
+  /* we are stalling if tx_next is not:
+   *   tx_next_ack <= tx_next < tx_next_ack + window_size
+   */
+  return !(sn_compare_tx(entity, entity->tx_next_ack, entity->tx_next) <= 0 &&
+           sn_compare_tx(entity, entity->tx_next,
+                         (entity->tx_next_ack + entity->window_size) %
+                           entity->sn_modulus) < 0);
+}
+
+static void include_poll(nr_rlc_entity_am_t *entity, char *buffer)
+{
+  /* set the P bit to 1 */
+  buffer[0] |= 0x40;
+
+  entity->pdu_without_poll = 0;
+  entity->byte_without_poll = 0;
+
+  /* set POLL_SN to highest SN submitted to lower layer
+   * (this is: entity->tx_next - 1) (todo: be sure of this)
+   */
+  entity->poll_sn = (entity->tx_next - 1 + entity->sn_modulus)
+                      % entity->sn_modulus;
+
+  /* start/restart t_poll_retransmit */
+  entity->t_poll_retransmit_start = entity->t_current;
+}
+
+static int check_poll_after_pdu_assembly(nr_rlc_entity_am_t *entity)
+{
+  int retransmission_buffer_empty;
+  int transmission_buffer_empty;
+
+  /* is transmission buffer empty? */
+  if (entity->tx_list == NULL)
+    transmission_buffer_empty = 1;
+  else
+    transmission_buffer_empty = 0;
+
+  /* is retransmission buffer empty? */
+  if (entity->retransmit_list == NULL)
+    retransmission_buffer_empty = 1;
+  else
+    retransmission_buffer_empty = 0;
+
+  return (transmission_buffer_empty && retransmission_buffer_empty) ||
+         is_window_stalling(entity);
+}
+
+static int serialize_sdu(nr_rlc_entity_am_t *entity,
+                         nr_rlc_sdu_segment_t *sdu, char *buffer, int bufsize,
+                         int p)
+{
+  nr_rlc_pdu_encoder_t encoder;
+
+  /* generate header */
+  nr_rlc_pdu_encoder_init(&encoder, buffer, bufsize);
+
+  nr_rlc_pdu_encoder_put_bits(&encoder, 1, 1);             /* D/C: 1 = data */
+  nr_rlc_pdu_encoder_put_bits(&encoder, 0, 1);     /* P: reserve, set later */
+
+  nr_rlc_pdu_encoder_put_bits(&encoder, 1-sdu->is_first,1);/* 1st bit of SI */
+  nr_rlc_pdu_encoder_put_bits(&encoder, 1-sdu->is_last,1); /* 2nd bit of SI */
+
+  if (entity->sn_field_length == 18)
+    nr_rlc_pdu_encoder_put_bits(&encoder, 0, 2);                       /* R */
+
+  nr_rlc_pdu_encoder_put_bits(&encoder, sdu->sdu->sn,
+                                        entity->sn_field_length);     /* SN */
+
+  if (!sdu->is_first)
+    nr_rlc_pdu_encoder_put_bits(&encoder, sdu->so, 16);               /* SO */
+
+  /* data */
+  memcpy(buffer + encoder.byte, sdu->sdu->data + sdu->so, sdu->size);
+
+  if (p)
+    include_poll(entity, buffer);
+
+  return encoder.byte + sdu->size;
+}
+
+/* for a given SDU/SDU segment, computes the corresponding PDU header size */
+static int compute_pdu_header_size(nr_rlc_entity_am_t *entity,
+                                   nr_rlc_sdu_segment_t *sdu)
+{
+  int header_size = 2;
+  /* one more byte if SN field length is 18 */
+  if (entity->sn_field_length == 18)
+    header_size++;
+  /* two more bytes for SO if SDU segment is not the first */
+  if (!sdu->is_first) header_size += 2;
+  return header_size;
+}
+
+/* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size'
+ * bytes
+ * - modifies SDU/SDU segment to become an SDU segment
+ * - returns a new SDU segment covering the remaining data bytes
+ */
+static nr_rlc_sdu_segment_t *resegment(nr_rlc_sdu_segment_t *sdu,
+                                       nr_rlc_entity_am_t *entity,
+                                       int pdu_size)
+{
+  nr_rlc_sdu_segment_t *next;
+  int pdu_header_size;
+  int over_size;
+
+  sdu->sdu->ref_count++;
+
+  pdu_header_size = compute_pdu_header_size(entity, sdu);
+
+  next = calloc(1, sizeof(nr_rlc_sdu_segment_t));
+  if (next == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__,  __FUNCTION__);
+    exit(1);
+  }
+  *next = *sdu;
+
+  over_size = pdu_header_size + sdu->size - pdu_size;
+
+  /* update SDU */
+  sdu->size -= over_size;
+  sdu->is_last = 0;
+
+  /* create new segment */
+  next->size = over_size;
+  next->so = sdu->so + sdu->size;
+  next->is_first = 0;
+
+  return next;
+}
+
+/*************************************************************************/
+/* TX functions - status reporting [begin]                               */
+/*************************************************************************/
+
+typedef struct {
+  /* data for missing bytes */
+  int sn_start;    /* set to -1 when no more missing part to report */
+  int so_start;
+  int sn_end;
+  int so_end;
+  /* data for maximum ack */
+  int ack_sn;                               /* -1 if not to be used */
+  /* pdu to use for next call to 'next_missing' */
+  nr_rlc_pdu_t *next;
+} missing_data_t;
+
+/* todo: rewrite this function, too messy */
+static missing_data_t next_missing(nr_rlc_entity_am_t *entity,
+                                        nr_rlc_pdu_t *cur, int check_head)
+{
+  missing_data_t ret;
+  int cur_max_so;
+  int sn;
+  int max_so       = 0;
+  int last_reached = 0;
+
+  ret.ack_sn = -1;
+
+  /* special case: missing part before the head of RX list */
+  if (check_head) {
+    if (cur->sn != entity->rx_next || !cur->is_first) {
+      /* don't report if out of reporting window */
+      if (sn_compare_rx(entity, entity->rx_highest_status, cur->sn) <= 0) {
+        ret.sn_start = -1;
+        return ret;
+      }
+      /* the missing part is starting from rx_next(0)
+       * going to min of:
+       *     - cur->sn(cur->so-1) [if cur->sn is not first]
+       *       or (cur->sn-1)(0xffff) [if cur->sn is first]
+       *     - (entity->rx_highest_status-1)(0xffff)
+       */
+      ret.sn_start = entity->rx_next;
+      ret.so_start = 0;
+      goto set_end_different_sdu;
+    }
+  }
+
+next_pdu:
+  sn = cur->sn;
+  cur_max_so = cur->so + cur->size - 1;
+  if (cur_max_so > max_so)
+    max_so = cur_max_so;
+  last_reached = last_reached | cur->is_last;
+
+  /* if cur already processed, it can be the acked SDU */
+  if (cur->data == NULL)
+    ret.ack_sn = (cur->sn + 1) % entity->sn_modulus;
+
+  /* no next? */
+  if (cur->next == NULL) {
+    /* inform the caller that work is over */
+    ret.next = NULL;
+
+    /* already processed => next SDU to rx_highest_status - 1 to be nacked */
+    if (cur->data == NULL) {
+      ret.sn_start = (cur->sn + 1) % entity->sn_modulus;
+      /* don't report if out of reporting window */
+      if (sn_compare_rx(entity, entity->rx_highest_status,
+                        ret.sn_start) <= 0) {
+        ret.sn_start = -1;
+        return ret;
+      }
+      ret.so_start = 0;
+      ret.sn_end   = (entity->rx_highest_status - 1 + entity->sn_modulus) %
+                        entity->sn_modulus;
+      ret.so_end   = 0xffff;
+      return ret;
+    }
+    /* not already processed => all bytes after max_so (if any) then all SDU
+     * to rx_highest_status-1 to be nacked
+     */
+    if (last_reached) {
+      ret.sn_start = (cur->sn + 1) % entity->sn_modulus;
+      ret.so_start = 0;
+    } else {
+      ret.sn_start = cur->sn;
+      ret.so_start = max_so + 1;
+    }
+    /* don't report if out of reporting window */
+    if (sn_compare_rx(entity, entity->rx_highest_status,
+                      ret.sn_start) <= 0) {
+      ret.sn_start = -1;
+      return ret;
+    }
+    ret.sn_end   = (entity->rx_highest_status - 1 + entity->sn_modulus) %
+                      entity->sn_modulus;
+    ret.so_end   = 0xffff;
+    return ret;
+  }
+
+  cur = cur->next;
+
+  /* no discontinuity in data => process to next PDU */
+  if (cur->sn == sn && max_so >= cur->so - 1)
+    goto next_pdu;
+  if (cur->sn == (sn + 1) % entity->sn_modulus && last_reached &&
+      cur->is_first) {
+    last_reached = 0;
+    max_so       = 0;
+    goto next_pdu;
+  }
+
+  /* discontinuity in data */
+
+  /* remember where to start from for the next call */
+  ret.next = cur;
+
+  /* discontinuity in same SDU */
+  if (cur->sn == sn) {
+    ret.sn_start = sn;
+    /* don't report if out of reporting window */
+    if (sn_compare_rx(entity, entity->rx_highest_status,
+                      ret.sn_start) <= 0) {
+      ret.sn_start = -1;
+      return ret;
+    }
+    ret.so_start = max_so + 1;
+    ret.sn_end = sn;
+    ret.so_end = cur->so - 1;
+    return ret;
+  }
+
+  /* discontinuity between different SDUs */
+  ret.sn_start = sn;
+  /* don't report if out of reporting window */
+  if (sn_compare_rx(entity, entity->rx_highest_status, ret.sn_start) <= 0) {
+    ret.sn_start = -1;
+    return ret;
+  }
+  ret.so_start = max_so + 1;
+
+set_end_different_sdu:
+  /* don't go more than rx_highest_status - 1 */
+  if (sn_compare_rx(entity, entity->rx_highest_status, cur->sn) <= 0) {
+    ret.so_end = (entity->rx_highest_status - 1 + entity->sn_modulus) %
+                      entity->sn_modulus;
+    ret.so_end   = 0xffff;
+    return ret;
+  }
+
+  /* if cur is the head of a SDU, then use cur-1 */
+  if (cur->is_first) {
+    ret.sn_end = (cur->sn - 1 + entity->sn_modulus) % entity->sn_modulus;
+    ret.so_end = 0xffff;
+    return ret;
+  }
+
+  ret.sn_end = cur->sn;
+  ret.so_end = cur->so - 1;
+  return ret;
+}
+
+static int nack_size(nr_rlc_entity_am_t *entity, missing_data_t *m)
+{
+  int nack_length = 2 + (entity->sn_field_length == 18);
+
+  if (m->sn_start == m->sn_end) {
+    /* only nack_sn, no so_start/end, no nack range */
+    if (m->so_start == 0 && m->so_end == 0xffff)
+      return nack_length;
+    /* nack_sn + so_start/end */
+    return nack_length + 4;
+  }
+
+  /* nack_sn + nack range, no so_start/end */
+  if (m->so_start == 0 && m->so_end == 0xffff)
+    return nack_length + 1;
+
+  /* nack_sn + so_start/end + nack range */
+  return nack_length + 5;
+}
+
+/* returns the e1 byte/bit position supposing the encoder points at
+ * the beginning of a nack_sn block
+ */
+static void get_e1_position(nr_rlc_entity_am_t *entity,
+                            nr_rlc_pdu_encoder_t *encoder,
+                            int *e1_byte, int *e1_bit)
+{
+  if (entity->sn_field_length == 18) {
+    *e1_byte = encoder->byte + 2;
+    *e1_bit = 5;
+  } else {
+    *e1_byte = encoder->byte + 1;
+    *e1_bit = 3;
+  }
+}
+
+/* returns the number of nacks serialized.
+ * In most cases it is 1, it can be more if the
+ * missing data consists of a range that is more
+ * than 255 SNs in which case it has to be cut in
+ * smaller ranges.
+ * If there is no more room in the status buffer,
+ * will set m->next = NULL (and may serialize
+ * less nacks than required by 'm').
+ */
+static int generate_missing(nr_rlc_entity_am_t *entity,
+                            nr_rlc_pdu_encoder_t *encoder,
+                            missing_data_t *m, int *e1_byte, int *e1_bit)
+{
+  int r_bits = entity->sn_field_length == 18 ? 3 : 1;
+  int range_count = 0;
+  int sn_start;
+  int so_start;
+  int sn_end;
+  int so_end;
+  int sn_count;
+  missing_data_t m_nack;
+  int e2;
+  int e3;
+
+  /* be careful to limit a range to 255 SNs, that is: cut if needed */
+  sn_count = (m->sn_end - m->sn_start + entity->sn_modulus)
+              % entity->sn_modulus + 1;
+
+  sn_start = m->sn_start;
+
+  while (sn_count) {
+    int cur_sn_count = sn_count;
+    if (cur_sn_count > 255)
+      cur_sn_count = 255;
+
+    /* for first range, so_start is the one of the initial range
+     * for the following ones, it is 0
+     */
+    if (sn_start == m->sn_start) {
+      /* first range */
+      so_start = m->so_start;
+    } else {
+      /* following ranges */
+      so_start = 0;
+    }
+
+    /* for the last range, sn_end/so_end are the ones of the initial range
+     * for the previous ones, it is sn_start+254/0xffff
+     */
+    if (cur_sn_count == sn_count) {
+      /* last range */
+      sn_end = m->sn_end;
+      so_end = m->so_end;
+    } else {
+      /* previous ranges */
+      sn_end = (sn_start + 254) % entity->sn_modulus;
+      so_end = 0xffff;
+    }
+
+    /* check that there is room for a nack */
+    m_nack.sn_start = sn_start;
+    m_nack.so_start = so_start;
+    m_nack.sn_end = sn_end;
+    m_nack.so_end = so_end;
+    if (encoder->byte + nack_size(entity, &m_nack) > encoder->size) {
+      m->next = NULL;
+      break;
+    }
+
+    /* set the previous e1 bit to 1 */
+    encoder->buffer[*e1_byte] |= 1 << *e1_bit;
+
+    get_e1_position(entity, encoder, e1_byte, e1_bit);
+
+    if (sn_start == sn_end) {
+      if (so_start == 0 && so_end == 0xffff) {
+        /* only nack_sn, no so_start/end, no nack range */
+        e2 = 0;
+        e3 = 0;
+      } else {
+        /* nack_sn + so_start/end, no nack range */
+        e2 = 1;
+        e3 = 0;
+      }
+    } else {
+      if (so_start == 0 && so_end == 0xffff) {
+        /* nack_sn + nack range, no so_start/end */
+        e2 = 0;
+        e3 = 1;
+      } else {
+        /* nack_sn + so_start/end + nack range */
+        e2 = 1;
+        e3 = 1;
+      }
+    }
+
+    /* nack_sn */
+    nr_rlc_pdu_encoder_put_bits(encoder, sn_start,
+                                entity->sn_field_length);
+    /* e1 = 0 (set later if needed) */
+    nr_rlc_pdu_encoder_put_bits(encoder, 0, 1);
+    /* e2 */
+    nr_rlc_pdu_encoder_put_bits(encoder, e2, 1);
+    /* e3 */
+    nr_rlc_pdu_encoder_put_bits(encoder, e3, 1);
+    /* r */
+    nr_rlc_pdu_encoder_put_bits(encoder, 0, r_bits);
+    /* so_start/so_end */
+    if (e2) {
+      nr_rlc_pdu_encoder_put_bits(encoder, so_start, 16);
+      nr_rlc_pdu_encoder_put_bits(encoder, so_end, 16);
+    }
+    /* nack range */
+    if (e3)
+      nr_rlc_pdu_encoder_put_bits(encoder, cur_sn_count, 8);
+
+    sn_count -= cur_sn_count;
+    sn_start = (sn_start + cur_sn_count) % entity->sn_modulus;
+    range_count++;
+  }
+
+  return range_count;
+}
+
+static int generate_status(nr_rlc_entity_am_t *entity, char *buffer, int size)
+{
+  int                  ack_sn = entity->rx_next;
+  missing_data_t  m;
+  nr_rlc_pdu_t         *cur;
+  int                  nack_count = 0;
+  nr_rlc_pdu_encoder_t encoder;
+  int                  e1_byte;
+  int                  e1_bit;
+
+  /* if not enough room, do nothing */
+  if (size < 3)
+    return 0;
+
+  nr_rlc_pdu_encoder_init(&encoder, buffer, size);
+
+  /* first 3 bytes, ack_sn and e1 will be set later */
+  nr_rlc_pdu_encoder_put_bits(&encoder, 0, 8*3);
+
+  cur = entity->rx_list;
+
+  /* store the position of the e1 bit to be set if
+   * there is a nack following
+   */
+  e1_byte = 2;
+  e1_bit = entity->sn_field_length == 18 ? 1 : 7;
+
+  while (cur != NULL) {
+    m = next_missing(entity, cur, nack_count == 0);
+
+    /* update ack_sn if the returned value is valid */
+    if (m.ack_sn != -1)
+      ack_sn = m.ack_sn;
+
+    /* stop here if no more nack to report */
+    if (m.sn_start == -1)
+      break;
+
+    nack_count += generate_missing(entity, &encoder, &m, &e1_byte, &e1_bit);
+
+    cur = m.next;
+  }
+
+  /* put ack_sn */
+  if (entity->sn_field_length == 12) {
+    buffer[0] = ack_sn >> 8;
+    buffer[1] = ack_sn & 255;
+  } else {
+    buffer[0] = ack_sn >> 14;
+    buffer[1] = (ack_sn >> 6) & 255;
+    buffer[2] |= (ack_sn & 0x3f) << 2;
+  }
+
+  /* reset the trigger */
+  entity->status_triggered = 0;
+
+  /* start t_status_prohibit */
+  entity->t_status_prohibit_start = entity->t_current;
+
+  return encoder.byte;
+}
+
+static int status_to_report(nr_rlc_entity_am_t *entity)
+{
+  return entity->status_triggered &&
+         (entity->t_status_prohibit_start == 0 ||
+          entity->t_current - entity->t_status_prohibit_start >
+              entity->t_status_prohibit);
+}
+
+static int missing_size(nr_rlc_entity_am_t *entity, missing_data_t *m,
+                        int *size, int maxsize)
+{
+  int r_bits = entity->sn_field_length == 18 ? 3 : 1;
+  int range_count = 0;
+  int sn_start;
+  int so_start;
+  int sn_end;
+  int so_end;
+  int sn_count;
+  missing_data_t m_nack;
+
+  /* be careful to limit a range to 255 SNs, that is: cut if needed */
+  sn_count = m->sn_end - m->sn_start;
+  if (sn_count < 0)
+    sn_count += entity->sn_modulus;
+
+  sn_start = m->sn_start;
+
+  while (sn_count) {
+    int cur_sn_count = sn_count;
+    if (cur_sn_count > 255)
+      cur_sn_count = 255;
+
+    /* for first range, so_start is the one of the initial range
+     * for the following ones, it is 0
+     */
+    if (sn_start == m->sn_start) {
+      /* first range */
+      so_start = m->so_start;
+    } else {
+      /* following ranges */
+      so_start = 0;
+    }
+
+    /* for the last range, sn_end/so_end are the ones of the initial range
+     * for the previous ones, it is sn_start+254/0xffff
+     */
+    if (cur_sn_count == sn_count) {
+      /* last range */
+      sn_end = m->sn_end;
+      so_end = m->so_end;
+    } else {
+      /* previous ranges */
+      sn_end = (sn_start + 254) % entity->sn_modulus;
+      so_end = 0xffff;
+    }
+
+    /* check that there is room for a nack */
+    m_nack.sn_start = sn_start;
+    m_nack.so_start = so_start;
+    m_nack.sn_end = sn_end;
+    m_nack.so_end = so_end;
+    if (*size + nack_size(entity, &m_nack) > maxsize) {
+      m->next = NULL;
+      break;
+    }
+
+    if (sn_start == sn_end) {
+      if (so_start == 0 && so_end == 0xffff) {
+        /* only nack_sn, no so_start/end, no nack range */
+        *size += (entity->sn_field_length + 3 + r_bits) / 8;
+      } else {
+        /* nack_sn + so_start/end, no nack range */
+        *size += (entity->sn_field_length + 3 + r_bits + 16*2) / 8;
+      }
+    } else {
+      if (so_start == 0 && so_end == 0xffff) {
+        /* nack_sn + nack range, no so_start/end */
+        *size += (entity->sn_field_length + 3 + r_bits + 8) / 8;
+      } else {
+        /* nack_sn + so_start/end + nack range */
+        *size += (entity->sn_field_length + 3 + r_bits + 16*2 + 8) / 8;
+      }
+    }
+
+    sn_count -= cur_sn_count;
+    sn_start = (sn_start + cur_sn_count) % entity->sn_modulus;
+    range_count++;
+  }
+
+  return range_count;
+}
+
+static int status_size(nr_rlc_entity_am_t *entity, int maxsize)
+{
+  missing_data_t  m;
+  nr_rlc_pdu_t    *cur;
+  int             nack_count = 0;
+  int             size;
+
+  /* if not enough room, do nothing */
+  if (maxsize < 3)
+    return 0;
+
+  /* minimum 3 bytes */
+  size = 3;
+
+  cur = entity->rx_list;
+
+  while (cur != NULL) {
+    m = next_missing(entity, cur, nack_count == 0);
+
+    /* stop here if no more nack to report */
+    if (m.sn_start == -1)
+      break;
+
+    nack_count += missing_size(entity, &m, &size, maxsize);
+
+    cur = m.next;
+  }
+
+  return size;
+}
+
+/*************************************************************************/
+/* TX functions - status reporting [end]                                 */
+/*************************************************************************/
+
+static int generate_retx_pdu(nr_rlc_entity_am_t *entity, char *buffer,
+                             int size)
+{
+  nr_rlc_sdu_segment_t *sdu;
+  int pdu_header_size;
+  int pdu_size;
+  int p;
+
+  sdu = entity->retransmit_list;
+
+  pdu_header_size = compute_pdu_header_size(entity, sdu);
+
+  /* not enough room for at least one byte of data? do nothing */
+  if (pdu_header_size + 1 > size)
+    return 0;
+
+  entity->retransmit_list = entity->retransmit_list->next;
+  if (entity->retransmit_list == NULL)
+    entity->retransmit_end = NULL;
+
+  sdu->next = NULL;
+
+  /* segment if necessary */
+  pdu_size = pdu_header_size + sdu->size;
+  if (pdu_size > size) {
+    nr_rlc_sdu_segment_t *next_sdu;
+    next_sdu = resegment(sdu, entity, size);
+    /* put the second SDU back at the head of the retransmit list */
+    next_sdu->next = entity->retransmit_list;
+    entity->retransmit_list = next_sdu;
+    if (entity->retransmit_end == NULL)
+      entity->retransmit_end = entity->retransmit_list;
+  }
+
+  /* put SDU/SDU segment in the wait list */
+  nr_rlc_sdu_segment_list_append(&entity->wait_list, &entity->wait_end, sdu);
+
+  p = check_poll_after_pdu_assembly(entity);
+
+  if (entity->force_poll) {
+    p = 1;
+    entity->force_poll = 0;
+  }
+
+  return serialize_sdu(entity, sdu, buffer, size, p);
+}
+
+static int generate_tx_pdu(nr_rlc_entity_am_t *entity, char *buffer, int size)
+{
+  nr_rlc_sdu_segment_t *sdu;
+  int pdu_header_size;
+  int pdu_size;
+  int p;
+
+  /* sn out of window (that is: we have window stalling)? do nothing */
+  if (is_window_stalling(entity))
+    return 0;
+
+  if (entity->tx_list == NULL)
+    return 0;
+
+  sdu = entity->tx_list;
+
+  pdu_header_size = compute_pdu_header_size(entity, sdu);
+
+  /* not enough room for at least one byte of data? do nothing */
+  if (pdu_header_size + 1 > size)
+    return 0;
+
+  entity->tx_list = entity->tx_list->next;
+  if (entity->tx_list == NULL)
+    entity->tx_end = NULL;
+
+  sdu->next = NULL;
+
+  /* assign SN to SDU */
+  sdu->sdu->sn = entity->tx_next;
+
+  /* segment if necessary */
+  pdu_size = pdu_header_size + sdu->size;
+  if (pdu_size > size) {
+    nr_rlc_sdu_segment_t *next_sdu;
+    next_sdu = resegment(sdu, entity, size);
+    /* put the second SDU back at the head of the TX list */
+    next_sdu->next = entity->tx_list;
+    entity->tx_list = next_sdu;
+    if (entity->tx_end == NULL)
+      entity->tx_end = entity->tx_list;
+  }
+
+  /* update tx_next if the SDU segment is the last */
+  if (sdu->is_last)
+    entity->tx_next = (entity->tx_next + 1) % entity->sn_modulus;
+
+  /* put SDU/SDU segment in the wait list */
+  nr_rlc_sdu_segment_list_append(&entity->wait_list, &entity->wait_end, sdu);
+
+  /* polling actions for a new PDU */
+  entity->pdu_without_poll++;
+  entity->byte_without_poll += sdu->size;
+  if ((entity->poll_pdu != -1 &&
+       entity->pdu_without_poll >= entity->poll_pdu) ||
+      (entity->poll_byte != -1 &&
+       entity->byte_without_poll >= entity->poll_byte))
+    p = 1;
+  else
+    p = check_poll_after_pdu_assembly(entity);
+
+  if (entity->force_poll) {
+    p = 1;
+    entity->force_poll = 0;
+  }
+
+  return serialize_sdu(entity, sdu, buffer, size, p);
+}
+
+/* Pretend to serialize all the SDUs in a list and return the size
+ * of all the PDUs it would produce, limited to 'maxsize'.
+ * Used for buffer status reporting.
+ */
+static int tx_list_size(nr_rlc_entity_am_t *entity,
+                        nr_rlc_sdu_segment_t *l, int maxsize)
+{
+  int ret = 0;
+
+  while (l != NULL) {
+    ret += compute_pdu_header_size(entity, l) + l->size;
+    l = l->next;
+  }
+
+  if (ret > maxsize) ret = maxsize;
+  return ret;
+}
+
+nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status(
+    nr_rlc_entity_t *_entity, int maxsize)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  nr_rlc_entity_buffer_status_t ret;
+
+  if (status_to_report(entity))
+    ret.status_size = status_size(entity, maxsize);
+  else
+    ret.status_size = 0;
+
+  ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize);
+  ret.retx_size = tx_list_size(entity, entity->retransmit_list, maxsize);
+
+  return ret;
+}
+
+int nr_rlc_entity_am_generate_pdu(nr_rlc_entity_t *_entity,
+                                  char *buffer, int size)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  int ret;
+
+  if (status_to_report(entity)) {
+    ret = generate_status(entity, buffer, size);
+    if (ret != 0)
+      return ret;
+  }
+
+  if (entity->retransmit_list != NULL) {
+    ret = generate_retx_pdu(entity, buffer, size);
+    if (ret != 0)
+      return ret;
+  }
+
+  return generate_tx_pdu(entity, buffer, size);
+}
+
+/*************************************************************************/
+/* SDU RX functions                                                      */
+/*************************************************************************/
+
+void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
+                               char *buffer, int size,
+                               int sdu_id)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  nr_rlc_sdu_segment_t *sdu;
+
+  if (size > NR_SDU_MAX) {
+    LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n",
+          __FILE__, __LINE__, __FUNCTION__, size);
+    exit(1);
+  }
+
+  if (entity->tx_size + size > entity->tx_maxsize) {
+    LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    return;
+  }
+
+  entity->tx_size += size;
+
+  sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
+
+  nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
+}
+
+/*************************************************************************/
+/* time/timers                                                           */
+/*************************************************************************/
+
+static void check_t_poll_retransmit(nr_rlc_entity_am_t *entity)
+{
+  nr_rlc_sdu_segment_t head;
+  nr_rlc_sdu_segment_t *cur;
+  nr_rlc_sdu_segment_t *prev;
+  int sn;
+  int old_retx_count;
+
+  /* 38.322 5.3.3.4 */
+  /* did t_poll_retransmit expire? */
+  if (entity->t_poll_retransmit_start == 0 ||
+      entity->t_current <= entity->t_poll_retransmit_start +
+                               entity->t_poll_retransmit)
+    return;
+
+  /* stop timer */
+  entity->t_poll_retransmit_start = 0;
+
+  /* 38.322 5.3.3.4 says:
+   *
+   *     - include a poll in a RLC data PDU as described in section 5.3.3.2
+   *
+   * That does not seem to be conditional. So we forcefully will send
+   * a poll as soon as we generate a PDU.
+   * Hopefully this interpretation is correct. In the worst case we generate
+   * more polling than necessary, but it's not a big deal. When
+   * 't_poll_retransmit' expires it means we didn't receive a status report,
+   * meaning a bad radio link, so things are quite bad at this point and
+   * asking again for a poll won't hurt much more.
+   */
+  entity->force_poll = 1;
+
+  LOG_D(RLC, "%s:%d:%s: warning: t_poll_retransmit expired\n",
+        __FILE__, __LINE__, __FUNCTION__);
+
+  /* do we meet conditions of 38.322 5.3.3.4? */
+  if (!check_poll_after_pdu_assembly(entity))
+    return;
+
+  /* search wait list for SDU with highest SN */
+  /* this code may be incorrect: in LTE we had to look for PDU
+   * with SN = VT(S) - 1, but for NR the specs say "highest SN among the
+   * ones submitted to lower layers" not 'tx_next - 1'. So we should look
+   * for the highest SN in the wait list. But that's no big deal. If the
+   * program runs this code, then the connection is in a bad state and we
+   * can retransmit whatever we want. At some point we will receive a status
+   * report and retransmit what we really have to. Actually we could just
+   * retransmit the head of wait list (the specs have this 'or').
+   * (Actually, maybe this interpretation is not correct and what the code
+   * does is correct. The specs are confusing.)
+   */
+  sn = (entity->tx_next - 1 + entity->sn_modulus) % entity->sn_modulus;
+
+  head.next = entity->wait_list;
+  cur = entity->wait_list;
+  prev = &head;
+
+  while (cur != NULL) {
+    if (cur->sdu->sn == sn)
+      break;
+    prev = cur;
+    cur = cur->next;
+  }
+
+  /* SDU with highest SN not found? take the head of wait list */
+  if (cur == NULL) {
+    cur = entity->wait_list;
+    prev = &head;
+    sn = cur->sdu->sn;
+  }
+
+  /* todo: do we need to for check cur == NULL?
+   * It seems that no, the wait list should not be empty here, but not sure.
+   */
+
+  old_retx_count = cur->sdu->retx_count;
+
+  /* 38.322 says "SDU", not "SDU segment", so let's retransmit all
+   * SDU segments with this SN
+   */
+  /* todo: maybe we could simply retransmit the current SDU segment,
+   * so that we don't have to run through the full wait list.
+   */
+  while (cur != NULL) {
+    if (cur->sdu->sn == sn) {
+      prev->next = cur->next;
+      cur->next = NULL;
+      /* put in retransmit list */
+      consider_retransmission(entity, cur,
+                              old_retx_count == cur->sdu->retx_count);
+    } else {
+      prev = cur;
+    }
+    cur = prev->next;
+  }
+  entity->wait_list = head.next;
+  /* reset wait_end (todo: optimize?) */
+  entity->wait_end = entity->wait_list;
+  while (entity->wait_end != NULL && entity->wait_end->next != NULL)
+    entity->wait_end = entity->wait_end->next;
+}
+
+static void check_t_reassembly(nr_rlc_entity_am_t *entity)
+{
+  int sn;
+
+  /* is t_reassembly running and if yes has it expired? */
+  if (entity->t_reassembly_start == 0 ||
+      entity->t_current <= entity->t_reassembly_start + entity->t_reassembly)
+    return;
+
+  /* stop timer */
+  entity->t_reassembly_start = 0;
+
+  LOG_D(RLC, "%s:%d:%s: t_reassembly expired\n",
+        __FILE__, __LINE__, __FUNCTION__);
+
+  /* update RX_Highest_Status */
+  sn = entity->rx_next_status_trigger;
+  while (sdu_delivered(entity, sn))
+    sn = (sn + 1) % entity->sn_modulus;
+  entity->rx_highest_status = sn;
+
+  if (sn_compare_rx(entity, entity->rx_next_highest,
+                    (entity->rx_highest_status+1) % entity->sn_modulus) > 0 ||
+      (entity->rx_next_highest ==
+         (entity->rx_highest_status+1) % entity->sn_modulus &&
+       sdu_has_missing_bytes(entity, entity->rx_highest_status))) {
+    entity->t_reassembly_start = entity->t_current;
+    entity->rx_next_status_trigger = entity->rx_next_highest;
+  }
+}
+
+void nr_rlc_entity_am_set_time(nr_rlc_entity_t *_entity, uint64_t now)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+
+  entity->t_current = now;
+
+  check_t_poll_retransmit(entity);
+
+  check_t_reassembly(entity);
+}
+
+/*************************************************************************/
+/* discard/re-establishment/delete                                       */
+/*************************************************************************/
+
+void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
+{
+  /* implements 38.322 5.4 */
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  nr_rlc_sdu_segment_t head;
+  nr_rlc_sdu_segment_t *cur;
+  nr_rlc_sdu_segment_t *prev;
+
+  head.next = entity->tx_list;
+  cur = entity->tx_list;
+  prev = &head;
+
+  while (cur != NULL && cur->sdu->upper_layer_id != sdu_id) {
+    prev = cur;
+    cur = cur->next;
+  }
+
+  /* if sdu_id not found or some bytes have already been 'PDU-ized'
+   * then do nothing
+   */
+  if (cur == NULL || !cur->is_first || !cur->is_last)
+    return;
+
+  /* remove SDU from tx_list */
+  prev->next = cur->next;
+  entity->tx_list = head.next;
+  if (entity->tx_end == cur) {
+    if (prev != &head)
+      entity->tx_end = prev;
+    else
+      entity->tx_end = NULL;
+  }
+
+  nr_rlc_free_sdu_segment(cur);
+}
+
+static void clear_entity(nr_rlc_entity_am_t *entity)
+{
+  nr_rlc_pdu_t *cur_rx;
+
+  entity->rx_next                = 0;
+  entity->rx_next_status_trigger = 0;
+  entity->rx_highest_status      = 0;
+  entity->rx_next_highest        = 0;
+
+  entity->status_triggered = 0;
+
+  entity->tx_next           = 0;
+  entity->tx_next_ack       = 0;
+  entity->poll_sn           = 0;
+  entity->pdu_without_poll  = 0;
+  entity->byte_without_poll = 0;
+  entity->force_poll        = 0;
+
+  entity->t_current = 0;
+
+  entity->t_poll_retransmit_start = 0;
+  entity->t_reassembly_start      = 0;
+  entity->t_status_prohibit_start = 0;
+
+  cur_rx = entity->rx_list;
+  while (cur_rx != NULL) {
+    nr_rlc_pdu_t *p = cur_rx;
+    cur_rx = cur_rx->next;
+    nr_rlc_free_pdu(p);
+  }
+  entity->rx_list = NULL;
+  entity->rx_size = 0;
+
+  nr_rlc_free_sdu_segment_list(entity->tx_list);
+  nr_rlc_free_sdu_segment_list(entity->wait_list);
+  nr_rlc_free_sdu_segment_list(entity->retransmit_list);
+  nr_rlc_free_sdu_segment_list(entity->ack_list);
+
+  entity->tx_list         = NULL;
+  entity->tx_end          = NULL;
+  entity->tx_size         = 0;
+
+  entity->wait_list       = NULL;
+  entity->wait_end        = NULL;
+
+  entity->retransmit_list = NULL;
+  entity->retransmit_end  = NULL;
+
+  entity->ack_list        = NULL;
+}
+
+void nr_rlc_entity_am_reestablishment(nr_rlc_entity_t *_entity)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  clear_entity(entity);
+}
+
+void nr_rlc_entity_am_delete(nr_rlc_entity_t *_entity)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  clear_entity(entity);
+  free(entity);
+}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a553a22a9d166bcd36b24ccc6b9fda6929897a7
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _NR_RLC_ENTITY_AM_H_
+#define _NR_RLC_ENTITY_AM_H_
+
+#include "nr_rlc_entity.h"
+#include "nr_rlc_sdu.h"
+#include "nr_rlc_pdu.h"
+
+typedef struct {
+  nr_rlc_entity_t common;
+
+  /* configuration */
+  int t_poll_retransmit;
+  int t_reassembly;
+  int t_status_prohibit;
+  int poll_pdu;              /* -1 means infinity */
+  int poll_byte;             /* -1 means infinity */
+  int max_retx_threshold;
+  int sn_field_length;
+
+  int sn_modulus;
+  int window_size;
+
+  /* runtime rx */
+  int rx_next;
+  int rx_next_status_trigger;
+  int rx_highest_status;
+  int rx_next_highest;
+
+  int status_triggered;
+
+  /* runtime tx */
+  int tx_next;
+  int tx_next_ack;
+  int poll_sn;
+  int pdu_without_poll;
+  int byte_without_poll;
+  int force_poll;
+
+  /* set to the latest know time by the user of the module. Unit: ms */
+  uint64_t t_current;
+
+  /* timers (stores the TTI of activation, 0 means not active) */
+  uint64_t t_poll_retransmit_start;
+  uint64_t t_reassembly_start;
+  uint64_t t_status_prohibit_start;
+
+  /* rx management */
+  nr_rlc_pdu_t *rx_list;
+  int          rx_size;
+  int          rx_maxsize;
+
+  /* tx management */
+  nr_rlc_sdu_segment_t *tx_list;
+  nr_rlc_sdu_segment_t *tx_end;
+  int                  tx_size;
+  int                  tx_maxsize;
+
+  nr_rlc_sdu_segment_t *wait_list;
+  nr_rlc_sdu_segment_t *wait_end;
+
+  nr_rlc_sdu_segment_t *retransmit_list;
+  nr_rlc_sdu_segment_t *retransmit_end;
+
+  nr_rlc_sdu_segment_t *ack_list;
+} nr_rlc_entity_am_t;
+
+void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *entity,
+                               char *buffer, int size,
+                               int sdu_id);
+void nr_rlc_entity_am_recv_pdu(nr_rlc_entity_t *entity,
+                               char *buffer, int size);
+nr_rlc_entity_buffer_status_t nr_rlc_entity_am_buffer_status(
+    nr_rlc_entity_t *entity, int maxsize);
+int nr_rlc_entity_am_generate_pdu(nr_rlc_entity_t *entity,
+                                  char *buffer, int size);
+void nr_rlc_entity_am_set_time(nr_rlc_entity_t *entity, uint64_t now);
+void nr_rlc_entity_am_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id);
+void nr_rlc_entity_am_reestablishment(nr_rlc_entity_t *_entity);
+void nr_rlc_entity_am_delete(nr_rlc_entity_t *entity);
+
+#endif /* _NR_RLC_ENTITY_AM_H_ */
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c
new file mode 100644
index 0000000000000000000000000000000000000000..86a0697624091d9d41dae21a095753ed8bf928d4
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.c
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "nr_rlc_entity_tm.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nr_rlc_pdu.h"
+
+#include "LOG/log.h"
+
+/*************************************************************************/
+/* PDU RX functions                                                      */
+/*************************************************************************/
+
+void nr_rlc_entity_tm_recv_pdu(nr_rlc_entity_t *_entity,
+                               char *buffer, int size)
+{
+  nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
+  entity->common.deliver_sdu(entity->common.deliver_sdu_data,
+                             (nr_rlc_entity_t *)entity,
+                             buffer, size);
+}
+
+/*************************************************************************/
+/* TX functions                                                          */
+/*************************************************************************/
+
+static int generate_tx_pdu(nr_rlc_entity_tm_t *entity, char *buffer, int size)
+{
+  nr_rlc_sdu_segment_t *sdu;
+  int ret;
+
+  if (entity->tx_list == NULL)
+    return 0;
+
+  sdu = entity->tx_list;
+
+  /* not enough room? do nothing */
+  if (sdu->size > size)
+    return 0;
+
+  entity->tx_list = entity->tx_list->next;
+  if (entity->tx_list == NULL)
+    entity->tx_end = NULL;
+
+  ret = sdu->size;
+
+  memcpy(buffer, sdu->sdu->data, sdu->size);
+
+  entity->tx_size -= sdu->size;
+  nr_rlc_free_sdu_segment(sdu);
+
+  return ret;
+}
+
+static int tx_list_size(nr_rlc_entity_tm_t *entity,
+                        nr_rlc_sdu_segment_t *l, int maxsize)
+{
+  int ret = 0;
+
+  while (l != NULL) {
+    ret += l->size;
+    l = l->next;
+  }
+
+  if (ret > maxsize) ret = maxsize;
+  return ret;
+}
+
+nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status(
+    nr_rlc_entity_t *_entity, int maxsize)
+{
+  nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
+  nr_rlc_entity_buffer_status_t ret;
+
+  ret.status_size = 0;
+  ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize);
+  ret.retx_size = 0;
+
+  return ret;
+}
+
+int nr_rlc_entity_tm_generate_pdu(nr_rlc_entity_t *_entity,
+                                  char *buffer, int size)
+{
+  nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
+
+  return generate_tx_pdu(entity, buffer, size);
+}
+
+/*************************************************************************/
+/* SDU RX functions                                                      */
+/*************************************************************************/
+
+void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *_entity,
+                               char *buffer, int size,
+                               int sdu_id)
+{
+  nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
+  nr_rlc_sdu_segment_t *sdu;
+
+  if (size > NR_SDU_MAX) {
+    LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n",
+          __FILE__, __LINE__, __FUNCTION__, size);
+    exit(1);
+  }
+
+  if (entity->tx_size + size > entity->tx_maxsize) {
+    LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    return;
+  }
+
+  entity->tx_size += size;
+
+  sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
+
+  nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
+}
+
+/*************************************************************************/
+/* time/timers                                                           */
+/*************************************************************************/
+
+void nr_rlc_entity_tm_set_time(nr_rlc_entity_t *_entity, uint64_t now)
+{
+  nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
+
+  entity->t_current = now;
+}
+
+/*************************************************************************/
+/* discard/re-establishment/delete                                       */
+/*************************************************************************/
+
+void nr_rlc_entity_tm_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
+{
+  /* nothing to do */
+}
+
+static void clear_entity(nr_rlc_entity_tm_t *entity)
+{
+  nr_rlc_free_sdu_segment_list(entity->tx_list);
+
+  entity->tx_list         = NULL;
+  entity->tx_end          = NULL;
+  entity->tx_size         = 0;
+}
+
+void nr_rlc_entity_tm_reestablishment(nr_rlc_entity_t *_entity)
+{
+  nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
+  clear_entity(entity);
+}
+
+void nr_rlc_entity_tm_delete(nr_rlc_entity_t *_entity)
+{
+  nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
+  clear_entity(entity);
+  free(entity);
+}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.h
new file mode 100644
index 0000000000000000000000000000000000000000..7c8c7e40a01cabb2b013f83469f0e9d91c4ed124
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_tm.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.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _NR_RLC_ENTITY_TM_H_
+#define _NR_RLC_ENTITY_TM_H_
+
+#include "nr_rlc_entity.h"
+#include "nr_rlc_sdu.h"
+
+typedef struct {
+  nr_rlc_entity_t common;
+
+  /* set to the latest know time by the user of the module. Unit: ms */
+  uint64_t t_current;
+
+  /* tx management */
+  nr_rlc_sdu_segment_t *tx_list;
+  nr_rlc_sdu_segment_t *tx_end;
+  int                  tx_size;
+  int                  tx_maxsize;
+} nr_rlc_entity_tm_t;
+
+void nr_rlc_entity_tm_recv_sdu(nr_rlc_entity_t *entity,
+                               char *buffer, int size,
+                               int sdu_id);
+void nr_rlc_entity_tm_recv_pdu(nr_rlc_entity_t *entity,
+                               char *buffer, int size);
+nr_rlc_entity_buffer_status_t nr_rlc_entity_tm_buffer_status(
+    nr_rlc_entity_t *entity, int maxsize);
+int nr_rlc_entity_tm_generate_pdu(nr_rlc_entity_t *entity,
+                                  char *buffer, int size);
+void nr_rlc_entity_tm_set_time(nr_rlc_entity_t *entity, uint64_t now);
+void nr_rlc_entity_tm_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id);
+void nr_rlc_entity_tm_reestablishment(nr_rlc_entity_t *_entity);
+void nr_rlc_entity_tm_delete(nr_rlc_entity_t *entity);
+
+#endif /* _NR_RLC_ENTITY_TM_H_ */
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c
new file mode 100644
index 0000000000000000000000000000000000000000..09f29ebe6784a7b190cd5147ffe533be29d660b3
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c
@@ -0,0 +1,697 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "nr_rlc_entity_um.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nr_rlc_pdu.h"
+
+#include "LOG/log.h"
+
+/*************************************************************************/
+/* PDU RX functions                                                      */
+/*************************************************************************/
+
+static int modulus_rx(nr_rlc_entity_um_t *entity, int a)
+{
+  /* as per 38.322 7.1, modulus base is rx_next_highest - window_size */
+  int r = a - (entity->rx_next_highest - entity->window_size);
+  if (r < 0) r += entity->sn_modulus;
+  return r % entity->sn_modulus;
+}
+
+static int sn_compare_rx(void *_entity, int a, int b)
+{
+  nr_rlc_entity_um_t *entity = _entity;
+  return modulus_rx(entity, a) - modulus_rx(entity, b);
+}
+
+/* checks that all the bytes of the SDU sn have been received (but SDU
+ * has not been already processed)
+ */
+static int sdu_full(nr_rlc_entity_um_t *entity, int sn)
+{
+  nr_rlc_pdu_t *l = entity->rx_list;
+  int last_byte;
+  int new_last_byte;
+
+  last_byte = -1;
+  while (l != NULL) {
+    if (l->sn == sn)
+      break;
+    l = l->next;
+  }
+
+  /* check if the data has already been processed */
+  if (l != NULL && l->data == NULL)
+    return 0;
+
+  while (l != NULL && l->sn == sn) {
+    if (l->so > last_byte + 1)
+      return 0;
+    if (l->is_last)
+      return 1;
+    new_last_byte = l->so + l->size - 1;
+    if (new_last_byte > last_byte)
+      last_byte = new_last_byte;
+    l = l->next;
+  }
+
+  return 0;
+}
+
+/* checks that an SDU has already been delivered */
+static int sdu_delivered(nr_rlc_entity_um_t *entity, int sn)
+{
+  nr_rlc_pdu_t *l = entity->rx_list;
+
+  while (l != NULL) {
+    if (l->sn == sn)
+      break;
+    l = l->next;
+  }
+
+  return l != NULL && l->data == NULL;
+}
+
+/* check if there is some missing bytes before the last received of SDU sn */
+/* todo: be sure that when no byte was received or the SDU has already been
+ *       processed then the SDU has no missing byte
+ */
+static int sdu_has_missing_bytes(nr_rlc_entity_um_t *entity, int sn)
+{
+  nr_rlc_pdu_t *l = entity->rx_list;
+  int last_byte;
+  int new_last_byte;
+
+  last_byte = -1;
+  while (l != NULL) {
+    if (l->sn == sn)
+      break;
+    l = l->next;
+  }
+
+  /* check if the data has already been processed */
+  if (l != NULL && l->data == NULL)
+    return 0;                    /* data already processed: no missing byte */
+
+  while (l != NULL && l->sn == sn) {
+    if (l->so > last_byte + 1)
+      return 1;
+    new_last_byte = l->so + l->size - 1;
+    if (new_last_byte > last_byte)
+      last_byte = new_last_byte;
+    l = l->next;
+  }
+
+  return 0;
+}
+
+static void reassemble_and_deliver(nr_rlc_entity_um_t *entity, int sn)
+{
+  nr_rlc_pdu_t *pdu;
+  char sdu[NR_SDU_MAX];
+  int so = 0;
+  int bad_sdu = 0;
+
+  /* go to first segment of sn */
+  pdu = entity->rx_list;
+  while (pdu->sn != sn)
+    pdu = pdu->next;
+
+  /* reassemble - free 'data' of each segment after processing */
+  while (pdu != NULL && pdu->sn == sn) {
+    int len = pdu->size - (so - pdu->so);
+    if (so + len > NR_SDU_MAX && !bad_sdu) {
+      LOG_E(RLC, "%s:%d:%s: bad SDU, too big, discarding\n",
+            __FILE__, __LINE__, __FUNCTION__);
+      bad_sdu = 1;
+    }
+    if (!bad_sdu && len > 0) {
+      memcpy(sdu + so, pdu->data, len);
+      so += len;
+    }
+    free(pdu->data);
+    pdu->data = NULL;
+    entity->rx_size -= pdu->size;
+    pdu->size = 0;
+    pdu = pdu->next;
+  }
+
+  if (bad_sdu)
+    return;
+
+  /* deliver */
+  entity->common.deliver_sdu(entity->common.deliver_sdu_data,
+                             (nr_rlc_entity_t *)entity,
+                             sdu, so);
+}
+
+static void reception_actions(nr_rlc_entity_um_t *entity, nr_rlc_pdu_t *pdu)
+{
+  int x = pdu->sn;
+
+  if (sdu_full(entity, x)) {
+    /* SDU full */
+    reassemble_and_deliver(entity, x);
+
+    if (x == entity->rx_next_reassembly) {
+      int rx_next_reassembly = entity->rx_next_reassembly;
+      while (sdu_delivered(entity, rx_next_reassembly))
+        rx_next_reassembly = (rx_next_reassembly + 1) % entity->sn_modulus;
+      entity->rx_next_reassembly = rx_next_reassembly;
+    }
+  } else {
+    /* SDU not full */
+    /* test if x is not in reassembly window, that is x >= rx_next_highest */
+    if (sn_compare_rx(entity, x, entity->rx_next_highest) >= 0) {
+      entity->rx_next_highest = (x + 1) % entity->sn_modulus;
+
+      /* discard PDUs not in reassembly window */
+      while (entity->rx_list != NULL &&
+             sn_compare_rx(entity, entity->rx_list->sn,
+                           entity->rx_next_highest) >= 0) {
+        nr_rlc_pdu_t *p = entity->rx_list;
+        entity->rx_size -= p->size;
+        entity->rx_list = p->next;
+        nr_rlc_free_pdu(p);
+      }
+
+      /* if rx_next_reassembly not in reassembly window */
+      if (sn_compare_rx(entity, entity->rx_next_reassembly,
+                        entity->rx_next_highest) >= 0) {
+        int rx_next_reassembly;
+        /* set rx_next_reassembly to first SN >= rx_next_highest - window_size
+         * not delivered yet
+         */
+        rx_next_reassembly = (entity->rx_next_highest - entity->window_size
+                                 + entity->sn_modulus) % entity->sn_modulus;
+        while (sdu_delivered(entity, rx_next_reassembly))
+          rx_next_reassembly = (rx_next_reassembly + 1) % entity->sn_modulus;
+        entity->rx_next_reassembly = rx_next_reassembly;
+      }
+    }
+  }
+
+  if (entity->t_reassembly_start) {
+    if (/* rx_timer_trigger <= rx_next_reassembly */
+        sn_compare_rx(entity, entity->rx_timer_trigger,
+                      entity->rx_next_reassembly) <= 0 ||
+        /* or rx_timer_trigger outside of reassembly window and not equal
+         * to rx_next_highest, that is is > rx_next_highest
+         */
+        sn_compare_rx(entity, entity->rx_timer_trigger,
+                      entity->rx_next_highest) > 0 ||
+        /* or rx_next_highest == rx_next_reassembly + 1 and no missing byte
+         * for rx_next_reassembly
+         */
+       (entity->rx_next_highest == (entity->rx_next_reassembly + 1) %
+           entity->sn_modulus &&
+        !sdu_has_missing_bytes(entity, entity->rx_next_reassembly)))
+      entity->t_reassembly_start = 0;
+  }
+
+  if (entity->t_reassembly_start == 0) {
+    if (sn_compare_rx(entity, entity->rx_next_highest,
+                      (entity->rx_next_reassembly + 1)
+                          % entity->sn_modulus) > 0 ||
+        (entity->rx_next_highest == (entity->rx_next_reassembly + 1)
+                                        % entity->sn_modulus &&
+         sdu_has_missing_bytes(entity, entity->rx_next_reassembly))) {
+      entity->t_reassembly_start = entity->t_current;
+      entity->rx_timer_trigger = entity->rx_next_highest;
+    }
+  }
+}
+
+void nr_rlc_entity_um_recv_pdu(nr_rlc_entity_t *_entity,
+                               char *buffer, int size)
+{
+#define R(d) do { if (nr_rlc_pdu_decoder_in_error(&d)) goto err; } while (0)
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+  nr_rlc_pdu_decoder_t decoder;
+  nr_rlc_pdu_t *pdu;
+  int si;
+  int sn;
+  int so = 0;
+  int data_size;
+  int is_first;
+  int is_last;
+
+  nr_rlc_pdu_decoder_init(&decoder, buffer, size);
+
+  si = nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder);
+
+  is_first = (si & 0x2) == 0;
+  is_last = (si & 0x1) == 0;
+
+  /* if full, deliver SDU */
+  if (is_first && is_last) {
+    if (size < 2) {
+      LOG_E(RLC, "%s:%d:%s: warning: discard PDU, no data\n",
+            __FILE__, __LINE__, __FUNCTION__);
+      goto discard;
+    }
+    /* deliver */
+    entity->common.deliver_sdu(entity->common.deliver_sdu_data,
+                               (nr_rlc_entity_t *)entity,
+                               buffer + 1, size - 1);
+    return;
+  }
+
+  if (entity->sn_field_length == 12) {
+    nr_rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder);
+  }
+
+  sn = nr_rlc_pdu_decoder_get_bits(&decoder, entity->sn_field_length);
+  R(decoder);
+
+  if (!is_first) {
+    so = nr_rlc_pdu_decoder_get_bits(&decoder, 16); R(decoder);
+    if (so == 0) {
+      LOG_E(RLC, "%s:%d:%s: warning: discard PDU, bad so\n",
+            __FILE__, __LINE__, __FUNCTION__);
+      goto discard;
+    }
+  }
+
+  data_size = size - decoder.byte;
+
+  /* dicard PDU if no data */
+  if (data_size <= 0) {
+    LOG_D(RLC, "%s:%d:%s: warning: discard PDU, no data\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    goto discard;
+  }
+
+  /* dicard PDU if rx buffer is full */
+  if (entity->rx_size + data_size > entity->rx_maxsize) {
+    LOG_D(RLC, "%s:%d:%s: warning: discard PDU, RX buffer full\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    goto discard;
+  }
+
+  /* discard PDU if sn < rx_next_reassembly */
+  if (sn_compare_rx(entity, sn, entity->rx_next_reassembly) < 0) {
+    LOG_D(RLC, "%s:%d:%s: warning: discard PDU, SN (%d) < rx_next_reassembly (%d)\n",
+          __FILE__, __LINE__, __FUNCTION__,
+          sn, entity->rx_next_reassembly);
+    goto discard;
+  }
+
+  /* put in pdu reception list */
+  entity->rx_size += data_size;
+  pdu = nr_rlc_new_pdu(sn, so, is_first, is_last,
+                       buffer + size - data_size, data_size);
+  entity->rx_list = nr_rlc_pdu_list_add(sn_compare_rx, entity,
+                                        entity->rx_list, pdu);
+
+  /* do reception actions (38.322 5.2.2.2.3) */
+  reception_actions(entity, pdu);
+
+  return;
+
+err:
+  LOG_W(RLC, "%s:%d:%s: error decoding PDU, discarding\n", __FILE__, __LINE__, __FUNCTION__);
+  goto discard;
+
+discard:
+  return;
+
+#undef R
+}
+
+/*************************************************************************/
+/* TX functions                                                          */
+/*************************************************************************/
+
+static int serialize_sdu(nr_rlc_entity_um_t *entity,
+                         nr_rlc_sdu_segment_t *sdu, char *buffer, int bufsize)
+{
+  nr_rlc_pdu_encoder_t encoder;
+
+  /* generate header */
+  nr_rlc_pdu_encoder_init(&encoder, buffer, bufsize);
+
+  nr_rlc_pdu_encoder_put_bits(&encoder, 1-sdu->is_first,1);/* 1st bit of SI */
+  nr_rlc_pdu_encoder_put_bits(&encoder, 1-sdu->is_last,1); /* 2nd bit of SI */
+
+  /* SN, if required */
+  if (sdu->is_first == 1 && sdu->is_last == 1) {
+    nr_rlc_pdu_encoder_put_bits(&encoder, 0, 6);                       /* R */
+  } else {
+    if (entity->sn_field_length == 12)
+      nr_rlc_pdu_encoder_put_bits(&encoder, 0, 2);                     /* R */
+    nr_rlc_pdu_encoder_put_bits(&encoder, sdu->sdu->sn,
+                                entity->sn_field_length);             /* SN */
+  }
+
+  if (!sdu->is_first)
+    nr_rlc_pdu_encoder_put_bits(&encoder, sdu->so, 16);               /* SO */
+
+  /* data */
+  memcpy(buffer + encoder.byte, sdu->sdu->data + sdu->so, sdu->size);
+
+  return encoder.byte + sdu->size;
+}
+
+/* for a given SDU/SDU segment, computes the corresponding PDU header size */
+static int compute_pdu_header_size(nr_rlc_entity_um_t *entity,
+                                   nr_rlc_sdu_segment_t *sdu)
+{
+  int header_size = 1;
+
+  /* if SN to be included then one more byte if SN field length is 12 */
+  if (!(sdu->is_first && sdu->is_last) && entity->sn_field_length == 12)
+    header_size++;
+  /* two more bytes for SO if SDU segment is not the first */
+  if (!sdu->is_first) header_size += 2;
+  return header_size;
+}
+
+/* resize SDU/SDU segment for the corresponding PDU to fit into 'pdu_size'
+ * bytes
+ * - modifies SDU/SDU segment to become an SDU segment
+ * - returns a new SDU segment covering the remaining data bytes
+ * returns NULL if pdu_size is too small to contain the new segment
+ */
+static nr_rlc_sdu_segment_t *resegment(nr_rlc_sdu_segment_t *sdu,
+                                       nr_rlc_entity_um_t *entity,
+                                       int pdu_size)
+{
+  nr_rlc_sdu_segment_t *next;
+  int pdu_header_size;
+  int over_size;
+  int old_is_last;
+
+  sdu->sdu->ref_count++;
+
+  /* clear is_last to compute header size */
+  old_is_last = sdu->is_last;
+  sdu->is_last = 0;
+  pdu_header_size = compute_pdu_header_size(entity, sdu);
+  sdu->is_last = old_is_last;
+
+  /* if no room for at least 1 data byte, do nothing */
+  if (pdu_header_size + 1 > pdu_size)
+    return NULL;
+
+  next = calloc(1, sizeof(nr_rlc_sdu_segment_t));
+  if (next == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__,  __FUNCTION__);
+    exit(1);
+  }
+  *next = *sdu;
+
+  over_size = pdu_header_size + sdu->size - pdu_size;
+
+  /* update SDU */
+  sdu->size -= over_size;
+  sdu->is_last = 0;
+
+  /* create new segment */
+  next->size = over_size;
+  next->so = sdu->so + sdu->size;
+  next->is_first = 0;
+
+  return next;
+}
+
+static int generate_tx_pdu(nr_rlc_entity_um_t *entity, char *buffer, int size)
+{
+  nr_rlc_sdu_segment_t *sdu;
+  int pdu_header_size;
+  int pdu_size;
+  int ret;
+
+  if (entity->tx_list == NULL)
+    return 0;
+
+  sdu = entity->tx_list;
+
+  pdu_header_size = compute_pdu_header_size(entity, sdu);
+
+  /* not enough room for at least one byte of data? do nothing */
+  if (pdu_header_size + 1 > size)
+    return 0;
+
+  entity->tx_list = entity->tx_list->next;
+  if (entity->tx_list == NULL)
+    entity->tx_end = NULL;
+
+  /* assign SN to SDU */
+  sdu->sdu->sn = entity->tx_next;
+
+  /* segment if necessary */
+  pdu_size = pdu_header_size + sdu->size;
+  if (pdu_size > size) {
+    nr_rlc_sdu_segment_t *next_sdu;
+    next_sdu = resegment(sdu, entity, size);
+    if (next_sdu == NULL)
+      return 0;
+    /* put the second SDU back at the head of the TX list */
+    next_sdu->next = entity->tx_list;
+    entity->tx_list = next_sdu;
+    if (entity->tx_end == NULL)
+      entity->tx_end = entity->tx_list;
+  }
+
+  /* update tx_next if the SDU is an SDU segment and is the last */
+  if (!sdu->is_first && sdu->is_last)
+    entity->tx_next = (entity->tx_next + 1) % entity->sn_modulus;
+
+  ret = serialize_sdu(entity, sdu, buffer, size);
+
+  entity->tx_size -= sdu->size;
+  nr_rlc_free_sdu_segment(sdu);
+
+  return ret;
+}
+
+/* Pretend to serialize all the SDUs in a list and return the size
+ * of all the PDUs it would produce, limited to 'maxsize'.
+ * Used for buffer status reporting.
+ */
+static int tx_list_size(nr_rlc_entity_um_t *entity,
+                        nr_rlc_sdu_segment_t *l, int maxsize)
+{
+  int ret = 0;
+
+  while (l != NULL) {
+    ret += compute_pdu_header_size(entity, l) + l->size;
+    l = l->next;
+  }
+
+  if (ret > maxsize) ret = maxsize;
+  return ret;
+}
+
+nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status(
+    nr_rlc_entity_t *_entity, int maxsize)
+{
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+  nr_rlc_entity_buffer_status_t ret;
+
+  ret.status_size = 0;
+  ret.tx_size = tx_list_size(entity, entity->tx_list, maxsize);
+  ret.retx_size = 0;
+
+  return ret;
+}
+
+int nr_rlc_entity_um_generate_pdu(nr_rlc_entity_t *_entity,
+                                  char *buffer, int size)
+{
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+
+  return generate_tx_pdu(entity, buffer, size);
+}
+
+/*************************************************************************/
+/* SDU RX functions                                                      */
+/*************************************************************************/
+
+void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *_entity,
+                               char *buffer, int size,
+                               int sdu_id)
+{
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+  nr_rlc_sdu_segment_t *sdu;
+
+  if (size > NR_SDU_MAX) {
+    LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n",
+          __FILE__, __LINE__, __FUNCTION__, size);
+    exit(1);
+  }
+
+  if (entity->tx_size + size > entity->tx_maxsize) {
+    LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    return;
+  }
+
+  entity->tx_size += size;
+
+  sdu = nr_rlc_new_sdu(buffer, size, sdu_id);
+
+  nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu);
+}
+
+/*************************************************************************/
+/* time/timers                                                           */
+/*************************************************************************/
+
+static void check_t_reassembly(nr_rlc_entity_um_t *entity)
+{
+  nr_rlc_pdu_t *cur;
+
+  /* is t_reassembly running and if yes has it expired? */
+  if (entity->t_reassembly_start == 0 ||
+      entity->t_current <= entity->t_reassembly_start + entity->t_reassembly)
+    return;
+
+  /* stop timer */
+  entity->t_reassembly_start = 0;
+
+  LOG_D(RLC, "%s:%d:%s: t_reassembly expired\n",
+        __FILE__, __LINE__, __FUNCTION__);
+
+  /* update rx_next_reassembly to first SN >= rx_timer_trigger not reassembled
+   * (ie. not delivered yet)
+   */
+  entity->rx_next_reassembly = entity->rx_timer_trigger;
+  while (sdu_delivered(entity, entity->rx_next_reassembly))
+    entity->rx_next_reassembly = (entity->rx_next_reassembly + 1)
+                                     % entity->sn_modulus;
+
+  /* discard all segments < entity->rx_next_reassembly */
+  cur = entity->rx_list;
+  while (cur != NULL &&
+         sn_compare_rx(entity, cur->sn, entity->rx_next_reassembly) < 0) {
+    nr_rlc_free_pdu(cur);
+    cur = cur->next;
+    entity->rx_list = cur;
+  }
+
+  if (sn_compare_rx(entity, entity->rx_next_highest,
+                    (entity->rx_next_reassembly + 1)
+                        % entity->sn_modulus) > 0 ||
+      (entity->rx_next_highest == entity->rx_next_reassembly + 1 &&
+       sdu_has_missing_bytes(entity, entity->rx_next_reassembly))) {
+    entity->t_reassembly_start = entity->t_current;
+    entity->rx_timer_trigger = entity->rx_next_highest;
+  }
+}
+
+void nr_rlc_entity_um_set_time(nr_rlc_entity_t *_entity, uint64_t now)
+{
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+
+  entity->t_current = now;
+
+  check_t_reassembly(entity);
+}
+
+/*************************************************************************/
+/* discard/re-establishment/delete                                       */
+/*************************************************************************/
+
+void nr_rlc_entity_um_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id)
+{
+  /* implements 38.322 5.4 */
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+  nr_rlc_sdu_segment_t head;
+  nr_rlc_sdu_segment_t *cur;
+  nr_rlc_sdu_segment_t *prev;
+
+  head.next = entity->tx_list;
+  cur = entity->tx_list;
+  prev = &head;
+
+  while (cur != NULL && cur->sdu->upper_layer_id != sdu_id) {
+    prev = cur;
+    cur = cur->next;
+  }
+
+  /* if sdu_id not found or some bytes have already been 'PDU-ized'
+   * then do nothing
+   */
+  if (cur == NULL || !cur->is_first || !cur->is_last)
+    return;
+
+  /* remove SDU from tx_list */
+  prev->next = cur->next;
+  entity->tx_list = head.next;
+  if (entity->tx_end == cur) {
+    if (prev != &head)
+      entity->tx_end = prev;
+    else
+      entity->tx_end = NULL;
+  }
+
+  nr_rlc_free_sdu_segment(cur);
+}
+
+static void clear_entity(nr_rlc_entity_um_t *entity)
+{
+  nr_rlc_pdu_t *cur_rx;
+
+  entity->rx_next_highest    = 0;
+  entity->rx_next_reassembly = 0;
+  entity->rx_timer_trigger   = 0;
+
+
+  entity->tx_next           = 0;
+
+  entity->t_current = 0;
+
+  entity->t_reassembly_start      = 0;
+
+  cur_rx = entity->rx_list;
+  while (cur_rx != NULL) {
+    nr_rlc_pdu_t *p = cur_rx;
+    cur_rx = cur_rx->next;
+    nr_rlc_free_pdu(p);
+  }
+  entity->rx_list = NULL;
+  entity->rx_size = 0;
+
+  nr_rlc_free_sdu_segment_list(entity->tx_list);
+
+  entity->tx_list         = NULL;
+  entity->tx_end          = NULL;
+  entity->tx_size         = 0;
+}
+
+void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity)
+{
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+  clear_entity(entity);
+}
+
+void nr_rlc_entity_um_delete(nr_rlc_entity_t *_entity)
+{
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+  clear_entity(entity);
+  free(entity);
+}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h
new file mode 100644
index 0000000000000000000000000000000000000000..21063a1ea18f08abc2e00d0aedd1f09fc4b86d6a
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.h
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _NR_RLC_ENTITY_UM_H_
+#define _NR_RLC_ENTITY_UM_H_
+
+#include "nr_rlc_entity.h"
+#include "nr_rlc_sdu.h"
+#include "nr_rlc_pdu.h"
+
+typedef struct {
+  nr_rlc_entity_t common;
+
+  /* configuration */
+  int t_reassembly;
+  int sn_field_length;
+
+  int sn_modulus;
+  int window_size;
+
+  /* runtime rx */
+  int rx_next_highest;
+  int rx_next_reassembly;
+  int rx_timer_trigger;
+
+  /* runtime tx */
+  int tx_next;
+
+  /* set to the latest know time by the user of the module. Unit: ms */
+  uint64_t t_current;
+
+  /* timers (stores the TTI of activation, 0 means not active) */
+  uint64_t t_reassembly_start;
+
+  /* rx management */
+  nr_rlc_pdu_t *rx_list;
+  int          rx_size;
+  int          rx_maxsize;
+
+  /* tx management */
+  nr_rlc_sdu_segment_t *tx_list;
+  nr_rlc_sdu_segment_t *tx_end;
+  int                  tx_size;
+  int                  tx_maxsize;
+} nr_rlc_entity_um_t;
+
+void nr_rlc_entity_um_recv_sdu(nr_rlc_entity_t *entity,
+                               char *buffer, int size,
+                               int sdu_id);
+void nr_rlc_entity_um_recv_pdu(nr_rlc_entity_t *entity,
+                               char *buffer, int size);
+nr_rlc_entity_buffer_status_t nr_rlc_entity_um_buffer_status(
+    nr_rlc_entity_t *entity, int maxsize);
+int nr_rlc_entity_um_generate_pdu(nr_rlc_entity_t *entity,
+                                  char *buffer, int size);
+void nr_rlc_entity_um_set_time(nr_rlc_entity_t *entity, uint64_t now);
+void nr_rlc_entity_um_discard_sdu(nr_rlc_entity_t *_entity, int sdu_id);
+void nr_rlc_entity_um_reestablishment(nr_rlc_entity_t *_entity);
+void nr_rlc_entity_um_delete(nr_rlc_entity_t *entity);
+
+#endif /* _NR_RLC_ENTITY_UM_H_ */
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..b56e8b11e96c3831b3e1979e90a30286deb5044b
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
@@ -0,0 +1,874 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/* from openair */
+#include "rlc.h"
+#include "pdcp.h"
+
+/* from nr rlc module */
+#include "asn1_utils.h"
+#include "nr_rlc_ue_manager.h"
+#include "nr_rlc_entity.h"
+
+#include <stdint.h>
+
+static nr_rlc_ue_manager_t *nr_rlc_ue_manager;
+
+/* TODO: handle time a bit more properly */
+static uint64_t nr_rlc_current_time;
+static int      nr_rlc_current_time_last_frame;
+static int      nr_rlc_current_time_last_subframe;
+
+void mac_rlc_data_ind     (
+  const module_id_t         module_idP,
+  const rnti_t              rntiP,
+  const eNB_index_t         eNB_index,
+  const frame_t             frameP,
+  const eNB_flag_t          enb_flagP,
+  const MBMS_flag_t         MBMS_flagP,
+  const logical_chan_id_t   channel_idP,
+  char                     *buffer_pP,
+  const tb_size_t           tb_sizeP,
+  num_tb_t                  num_tbP,
+  crc_t                    *crcs_pP)
+{
+  nr_rlc_ue_t *ue;
+  nr_rlc_entity_t *rb;
+
+  if (module_idP != 0 || eNB_index != 0 || /*enb_flagP != 1 ||*/ MBMS_flagP != 0) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  if (enb_flagP)
+    T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(rntiP),
+      T_INT(channel_idP), T_INT(tb_sizeP));
+
+  nr_rlc_manager_lock(nr_rlc_ue_manager);
+  ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rntiP);
+
+  switch (channel_idP) {
+  case 1 ... 2: rb = ue->srb[channel_idP - 1]; break;
+  case 3 ... 7: rb = ue->drb[channel_idP - 3]; break;
+  default:      rb = NULL;                     break;
+  }
+
+  if (rb != NULL) {
+    rb->set_time(rb, nr_rlc_current_time);
+    rb->recv_pdu(rb, buffer_pP, tb_sizeP);
+  } else {
+    LOG_E(RLC, "%s:%d:%s: fatal: no RB found (channel ID %d)\n",
+          __FILE__, __LINE__, __FUNCTION__, channel_idP);
+    exit(1);
+  }
+
+  nr_rlc_manager_unlock(nr_rlc_ue_manager);
+}
+
+tbs_size_t mac_rlc_data_req(
+  const module_id_t       module_idP,
+  const rnti_t            rntiP,
+  const eNB_index_t       eNB_index,
+  const frame_t           frameP,
+  const eNB_flag_t        enb_flagP,
+  const MBMS_flag_t       MBMS_flagP,
+  const logical_chan_id_t channel_idP,
+  const tb_size_t         tb_sizeP,
+  char             *buffer_pP
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+  ,const uint32_t sourceL2Id
+  ,const uint32_t destinationL2Id
+#endif
+   )
+{
+  int ret;
+  nr_rlc_ue_t *ue;
+  nr_rlc_entity_t *rb;
+  int is_enb;
+  int maxsize;
+
+  nr_rlc_manager_lock(nr_rlc_ue_manager);
+  ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rntiP);
+
+  switch (channel_idP) {
+  case 1 ... 2: rb = ue->srb[channel_idP - 1]; break;
+  case 3 ... 7: rb = ue->drb[channel_idP - 3]; break;
+  default:      rb = NULL;                     break;
+  }
+
+  if (rb != NULL) {
+    rb->set_time(rb, nr_rlc_current_time);
+    /* UE does not seem to use saved_status_ind_tb_size */
+    is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager);
+    if (is_enb)
+      maxsize = ue->saved_status_ind_tb_size[channel_idP - 1];
+    else
+      maxsize = tb_sizeP;
+    ret = rb->generate_pdu(rb, buffer_pP, maxsize);
+  } else {
+    LOG_E(RLC, "%s:%d:%s: fatal: data req for unknown RB\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+    ret = 0;
+  }
+
+  nr_rlc_manager_unlock(nr_rlc_ue_manager);
+
+  if (enb_flagP)
+    T(T_ENB_RLC_MAC_DL, T_INT(module_idP), T_INT(rntiP),
+      T_INT(channel_idP), T_INT(ret));
+
+  return ret;
+}
+
+mac_rlc_status_resp_t mac_rlc_status_ind(
+  const module_id_t       module_idP,
+  const rnti_t            rntiP,
+  const eNB_index_t       eNB_index,
+  const frame_t           frameP,
+  const sub_frame_t       subframeP,
+  const eNB_flag_t        enb_flagP,
+  const MBMS_flag_t       MBMS_flagP,
+  const logical_chan_id_t channel_idP,
+  const tb_size_t         tb_sizeP
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+  ,const uint32_t sourceL2Id
+  ,const uint32_t destinationL2Id
+#endif
+  )
+{
+  nr_rlc_ue_t *ue;
+  mac_rlc_status_resp_t ret;
+  nr_rlc_entity_t *rb;
+
+  /* TODO: handle time a bit more properly */
+  if (nr_rlc_current_time_last_frame != frameP ||
+      nr_rlc_current_time_last_subframe != subframeP) {
+    nr_rlc_current_time++;
+    nr_rlc_current_time_last_frame = frameP;
+    nr_rlc_current_time_last_subframe = subframeP;
+  }
+
+  nr_rlc_manager_lock(nr_rlc_ue_manager);
+  ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rntiP);
+
+  switch (channel_idP) {
+  case 1 ... 2: rb = ue->srb[channel_idP - 1]; break;
+  case 3 ... 7: rb = ue->drb[channel_idP - 3]; break;
+  default:      rb = NULL;                     break;
+  }
+
+  if (rb != NULL) {
+    nr_rlc_entity_buffer_status_t buf_stat;
+    rb->set_time(rb, nr_rlc_current_time);
+    /* 36.321 deals with BSR values up to 3000000 bytes, after what it
+     * reports '> 3000000' (table 6.1.3.1-2). Passing 4000000 is thus
+     * more than enough.
+     */
+    buf_stat = rb->buffer_status(rb, 4000000);
+    ret.bytes_in_buffer = buf_stat.status_size
+                        + buf_stat.retx_size
+                        + buf_stat.tx_size;
+    ue->saved_status_ind_tb_size[channel_idP - 1] = tb_sizeP;
+  } else {
+    ret.bytes_in_buffer = 0;
+  }
+
+  nr_rlc_manager_unlock(nr_rlc_ue_manager);
+
+  ret.pdus_in_buffer = 0;
+  /* TODO: creation time may be important (unit: frame, as it seems) */
+  ret.head_sdu_creation_time = 0;
+  ret.head_sdu_remaining_size_to_send = 0;
+  ret.head_sdu_is_segmented = 0;
+  return ret;
+}
+
+int oai_emulation;
+
+rlc_op_status_t rlc_data_req     (const protocol_ctxt_t *const ctxt_pP,
+                                  const srb_flag_t   srb_flagP,
+                                  const MBMS_flag_t  MBMS_flagP,
+                                  const rb_id_t      rb_idP,
+                                  const mui_t        muiP,
+                                  confirm_t    confirmP,
+                                  sdu_size_t   sdu_sizeP,
+                                  mem_block_t *sdu_pP
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+  ,const uint32_t *const sourceL2Id
+  ,const uint32_t *const destinationL2Id
+#endif
+                                 )
+{
+  int rnti = ctxt_pP->rnti;
+  nr_rlc_ue_t *ue;
+  nr_rlc_entity_t *rb;
+
+  LOG_D(RLC, "%s rnti %d srb_flag %d rb_id %d mui %d confirm %d sdu_size %d MBMS_flag %d\n",
+        __FUNCTION__, rnti, srb_flagP, rb_idP, muiP, confirmP, sdu_sizeP,
+        MBMS_flagP);
+
+  if (ctxt_pP->enb_flag)
+    T(T_ENB_RLC_DL, T_INT(ctxt_pP->module_id),
+      T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_sizeP));
+
+  nr_rlc_manager_lock(nr_rlc_ue_manager);
+  ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti);
+
+  rb = NULL;
+
+  if (srb_flagP) {
+    if (rb_idP >= 1 && rb_idP <= 2)
+      rb = ue->srb[rb_idP - 1];
+  } else {
+    if (rb_idP >= 1 && rb_idP <= 5)
+      rb = ue->drb[rb_idP - 1];
+  }
+
+  if (rb != NULL) {
+    rb->set_time(rb, nr_rlc_current_time);
+    rb->recv_sdu(rb, (char *)sdu_pP->data, sdu_sizeP, muiP);
+  } else {
+    LOG_E(RLC, "%s:%d:%s: fatal: SDU sent to unknown RB\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  nr_rlc_manager_unlock(nr_rlc_ue_manager);
+
+  free_mem_block(sdu_pP, __func__);
+
+  return RLC_OP_STATUS_OK;
+}
+
+int rlc_module_init(int enb_flag)
+{
+  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+  static int inited = 0;
+
+  if (pthread_mutex_lock(&lock)) abort();
+
+  if (inited) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  inited = 1;
+
+  nr_rlc_ue_manager = new_nr_rlc_ue_manager(enb_flag);
+
+  if (pthread_mutex_unlock(&lock)) abort();
+
+  return 0;
+}
+
+void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP)
+{
+}
+
+static void deliver_sdu(void *_ue, nr_rlc_entity_t *entity, char *buf, int size)
+{
+  nr_rlc_ue_t *ue = _ue;
+  int is_srb;
+  int rb_id;
+  protocol_ctxt_t ctx;
+  mem_block_t *memblock;
+  int i;
+  int is_enb;
+
+  /* is it SRB? */
+  for (i = 0; i < 2; i++) {
+    if (entity == ue->srb[i]) {
+      is_srb = 1;
+      rb_id = i+1;
+      goto rb_found;
+    }
+  }
+
+  /* maybe DRB? */
+  for (i = 0; i < 5; i++) {
+    if (entity == ue->drb[i]) {
+      is_srb = 0;
+      rb_id = i+1;
+      goto rb_found;
+    }
+  }
+
+  LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n",
+        __FILE__, __LINE__, __FUNCTION__, ue->rnti);
+  exit(1);
+
+rb_found:
+  LOG_D(RLC, "%s:%d:%s: delivering SDU (rnti %d is_srb %d rb_id %d) size %d",
+        __FILE__, __LINE__, __FUNCTION__, ue->rnti, is_srb, rb_id, size);
+
+  memblock = get_free_mem_block(size, __func__);
+  if (memblock == NULL) {
+    LOG_E(RLC, "%s:%d:%s: ERROR: get_free_mem_block failed\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+  memcpy(memblock->data, buf, size);
+
+  /* unused fields? */
+  ctx.instance = 0;
+  ctx.frame = 0;
+  ctx.subframe = 0;
+  ctx.eNB_index = 0;
+  ctx.configured = 1;
+  ctx.brOption = 0;
+
+  /* used fields? */
+  ctx.module_id = 0;
+  ctx.rnti = ue->rnti;
+
+  is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager);
+  ctx.enb_flag = is_enb;
+
+  if (is_enb) {
+    T(T_ENB_RLC_UL,
+      T_INT(0 /*ctxt_pP->module_id*/),
+      T_INT(ue->rnti), T_INT(rb_id), T_INT(size));
+  }
+
+  if (!pdcp_data_ind(&ctx, is_srb, 0, rb_id, size, memblock)) {
+    LOG_E(RLC, "%s:%d:%s: ERROR: pdcp_data_ind failed\n", __FILE__, __LINE__, __FUNCTION__);
+    /* what to do in case of failure? for the moment: nothing */
+  }
+}
+
+static void successful_delivery(void *_ue, nr_rlc_entity_t *entity, int sdu_id)
+{
+  nr_rlc_ue_t *ue = _ue;
+  int i;
+  int is_srb;
+  int rb_id;
+#if 0
+  MessageDef *msg;
+#endif
+  int is_enb;
+
+  /* is it SRB? */
+  for (i = 0; i < 2; i++) {
+    if (entity == ue->srb[i]) {
+      is_srb = 1;
+      rb_id = i+1;
+      goto rb_found;
+    }
+  }
+
+  /* maybe DRB? */
+  for (i = 0; i < 5; i++) {
+    if (entity == ue->drb[i]) {
+      is_srb = 0;
+      rb_id = i+1;
+      goto rb_found;
+    }
+  }
+
+  LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n",
+        __FILE__, __LINE__, __FUNCTION__, ue->rnti);
+  exit(1);
+
+rb_found:
+  LOG_D(RLC, "sdu %d was successfully delivered on %s %d\n",
+        sdu_id,
+        is_srb ? "SRB" : "DRB",
+        rb_id);
+
+  /* TODO: do something for DRBs? */
+  if (is_srb == 0)
+    return;
+
+  is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager);
+  if (!is_enb)
+    return;
+
+#if 0
+  msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION);
+  RLC_SDU_INDICATION(msg).rnti          = ue->rnti;
+  RLC_SDU_INDICATION(msg).is_successful = 1;
+  RLC_SDU_INDICATION(msg).srb_id        = rb_id;
+  RLC_SDU_INDICATION(msg).message_id    = sdu_id;
+  /* TODO: accept more than 1 instance? here we send to instance id 0 */
+  itti_send_msg_to_task(TASK_RRC_ENB, 0, msg);
+#endif
+}
+
+static void max_retx_reached(void *_ue, nr_rlc_entity_t *entity)
+{
+  nr_rlc_ue_t *ue = _ue;
+  int i;
+  int is_srb;
+  int rb_id;
+#if 0
+  MessageDef *msg;
+#endif
+  int is_enb;
+
+  /* is it SRB? */
+  for (i = 0; i < 2; i++) {
+    if (entity == ue->srb[i]) {
+      is_srb = 1;
+      rb_id = i+1;
+      goto rb_found;
+    }
+  }
+
+  /* maybe DRB? */
+  for (i = 0; i < 5; i++) {
+    if (entity == ue->drb[i]) {
+      is_srb = 0;
+      rb_id = i+1;
+      goto rb_found;
+    }
+  }
+
+  LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n",
+        __FILE__, __LINE__, __FUNCTION__, ue->rnti);
+  exit(1);
+
+rb_found:
+  LOG_D(RLC, "max RETX reached on %s %d\n",
+        is_srb ? "SRB" : "DRB",
+        rb_id);
+
+  /* TODO: do something for DRBs? */
+  if (is_srb == 0)
+    return;
+
+  is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager);
+  if (!is_enb)
+    return;
+
+#if 0
+  msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION);
+  RLC_SDU_INDICATION(msg).rnti          = ue->rnti;
+  RLC_SDU_INDICATION(msg).is_successful = 0;
+  RLC_SDU_INDICATION(msg).srb_id        = rb_id;
+  RLC_SDU_INDICATION(msg).message_id    = -1;
+  /* TODO: accept more than 1 instance? here we send to instance id 0 */
+  itti_send_msg_to_task(TASK_RRC_ENB, 0, msg);
+#endif
+}
+
+static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s)
+{
+  nr_rlc_entity_t            *nr_rlc_am;
+  nr_rlc_ue_t                *ue;
+
+  struct LTE_SRB_ToAddMod__rlc_Config *r = s->rlc_Config;
+  struct LTE_SRB_ToAddMod__logicalChannelConfig *l = s->logicalChannelConfig;
+  int srb_id = s->srb_Identity;
+  int logical_channel_group;
+
+  //int t_reordering;
+  int t_status_prohibit;
+  int t_poll_retransmit;
+  int poll_pdu;
+  int poll_byte;
+  int max_retx_threshold;
+  int t_reassembly;
+  int sn_field_length;
+
+  if (srb_id != 1 && srb_id != 2) {
+    LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n",
+          __FILE__, __LINE__, __FUNCTION__, srb_id);
+    exit(1);
+  }
+
+  switch (l->present) {
+  case LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue:
+    logical_channel_group = *l->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup;
+    break;
+  case LTE_SRB_ToAddMod__logicalChannelConfig_PR_defaultValue:
+    /* default value from 36.331 9.2.1 */
+    logical_channel_group = 0;
+    break;
+  default:
+    LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  /* TODO: accept other values? */
+  if (logical_channel_group != 0) {
+    LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  switch (r->present) {
+  case LTE_SRB_ToAddMod__rlc_Config_PR_explicitValue: {
+    struct LTE_RLC_Config__am *am;
+    if (r->choice.explicitValue.present != LTE_RLC_Config_PR_am) {
+      LOG_E(RLC, "%s:%d:%s: fatal error, must be RLC AM\n",
+            __FILE__, __LINE__, __FUNCTION__);
+      exit(1);
+    }
+    am = &r->choice.explicitValue.choice.am;
+    //t_reordering       = decode_t_reordering(am->dl_AM_RLC.t_Reordering);
+    t_status_prohibit  = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit);
+    t_poll_retransmit  = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit);
+    poll_pdu           = decode_poll_pdu(am->ul_AM_RLC.pollPDU);
+    poll_byte          = decode_poll_byte(am->ul_AM_RLC.pollByte);
+    max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold);
+    break;
+  }
+  case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue:
+    /* default values from 36.331 9.2.1 */
+    //t_reordering       = 35;
+    t_status_prohibit  = 0;
+    t_poll_retransmit  = 45;
+    poll_pdu           = -1;
+    poll_byte          = -1;
+    max_retx_threshold = 4;
+    break;
+  default:
+    LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  nr_rlc_manager_lock(nr_rlc_ue_manager);
+  ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti);
+  if (ue->srb[srb_id-1] != NULL) {
+    LOG_D(RLC, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n",
+          __FILE__, __LINE__, __FUNCTION__, srb_id, rnti);
+  } else {
+    /* hack: hardcode values for NR */
+    t_poll_retransmit = 45;
+    t_reassembly = 35;
+    t_status_prohibit = 0;
+    poll_pdu = -1;
+    poll_byte = -1;
+    max_retx_threshold = 8;
+    sn_field_length = 12;
+    nr_rlc_am = new_nr_rlc_entity_am(100000,
+                                     100000,
+                                     deliver_sdu, ue,
+                                     successful_delivery, ue,
+                                     max_retx_reached, ue,
+                                     t_poll_retransmit,
+                                     t_reassembly, t_status_prohibit,
+                                     poll_pdu, poll_byte, max_retx_threshold,
+                                     sn_field_length);
+    nr_rlc_ue_add_srb_rlc_entity(ue, srb_id, nr_rlc_am);
+
+    LOG_D(RLC, "%s:%d:%s: added srb %d to ue %d\n",
+          __FILE__, __LINE__, __FUNCTION__, srb_id, rnti);
+  }
+  nr_rlc_manager_unlock(nr_rlc_ue_manager);
+}
+
+static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s)
+{
+  nr_rlc_entity_t            *nr_rlc_am;
+  nr_rlc_ue_t                *ue;
+
+  struct LTE_RLC_Config *r = s->rlc_Config;
+  struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig;
+  int drb_id = s->drb_Identity;
+  int channel_id = *s->logicalChannelIdentity;
+  int logical_channel_group;
+
+  //int t_reordering;
+  int t_status_prohibit;
+  int t_poll_retransmit;
+  int poll_pdu;
+  int poll_byte;
+  int max_retx_threshold;
+  int t_reassembly;
+  int sn_field_length;
+
+  if (!(drb_id >= 1 && drb_id <= 5)) {
+    LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n",
+          __FILE__, __LINE__, __FUNCTION__, drb_id);
+    exit(1);
+  }
+
+  if (channel_id != drb_id + 2) {
+    LOG_E(RLC, "%s:%d:%s: todo, remove this limitation\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup;
+
+  /* TODO: accept other values? */
+  if (logical_channel_group != 1) {
+    LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  switch (r->present) {
+  case LTE_RLC_Config_PR_am: {
+    struct LTE_RLC_Config__am *am;
+    am = &r->choice.am;
+    //t_reordering       = decode_t_reordering(am->dl_AM_RLC.t_Reordering);
+    t_status_prohibit  = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit);
+    t_poll_retransmit  = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit);
+    poll_pdu           = decode_poll_pdu(am->ul_AM_RLC.pollPDU);
+    poll_byte          = decode_poll_byte(am->ul_AM_RLC.pollByte);
+    max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold);
+    break;
+  }
+  default:
+    LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  nr_rlc_manager_lock(nr_rlc_ue_manager);
+  ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti);
+  if (ue->drb[drb_id-1] != NULL) {
+    LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n",
+          __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
+  } else {
+    /* hack: hardcode values for NR */
+    t_poll_retransmit = 45;
+    t_reassembly = 35;
+    t_status_prohibit = 0;
+    poll_pdu = -1;
+    poll_byte = -1;
+    max_retx_threshold = 8;
+    sn_field_length = 12;
+    nr_rlc_am = new_nr_rlc_entity_am(100000,
+                                     100000,
+                                     deliver_sdu, ue,
+                                     successful_delivery, ue,
+                                     max_retx_reached, ue,
+                                     t_poll_retransmit,
+                                     t_reassembly, t_status_prohibit,
+                                     poll_pdu, poll_byte, max_retx_threshold,
+                                     sn_field_length);
+    nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_am);
+
+    LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n",
+          __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
+  }
+  nr_rlc_manager_unlock(nr_rlc_ue_manager);
+}
+
+static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s)
+{
+  nr_rlc_entity_t            *nr_rlc_um;
+  nr_rlc_ue_t                *ue;
+
+  struct LTE_RLC_Config *r = s->rlc_Config;
+  struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig;
+  int drb_id = s->drb_Identity;
+  int channel_id = *s->logicalChannelIdentity;
+  int logical_channel_group;
+
+  //int t_reordering;
+  int sn_field_length;
+  int t_reassembly;
+
+  if (!(drb_id >= 1 && drb_id <= 5)) {
+    LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n",
+          __FILE__, __LINE__, __FUNCTION__, drb_id);
+    exit(1);
+  }
+
+  if (channel_id != drb_id + 2) {
+    LOG_E(RLC, "%s:%d:%s: todo, remove this limitation\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup;
+
+  /* TODO: accept other values? */
+  if (logical_channel_group != 1) {
+    LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  switch (r->present) {
+  case LTE_RLC_Config_PR_um_Bi_Directional: {
+    struct LTE_RLC_Config__um_Bi_Directional *um;
+    um = &r->choice.um_Bi_Directional;
+    //t_reordering    = decode_t_reordering(um->dl_UM_RLC.t_Reordering);
+    if (um->dl_UM_RLC.sn_FieldLength != um->ul_UM_RLC.sn_FieldLength) {
+      LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+      exit(1);
+    }
+    sn_field_length = decode_sn_field_length(um->dl_UM_RLC.sn_FieldLength);
+    break;
+  }
+  default:
+    LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  nr_rlc_manager_lock(nr_rlc_ue_manager);
+  ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti);
+  if (ue->drb[drb_id-1] != NULL) {
+    LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n",
+          __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
+  } else {
+    /* hack: hardcode values for NR */
+    t_reassembly = 35;
+    sn_field_length = 6;
+    nr_rlc_um = new_nr_rlc_entity_um(1000000,
+                                     1000000,
+                                     deliver_sdu, ue,
+                                     t_reassembly,
+                                     sn_field_length);
+    nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_um);
+
+    LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n",
+          __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
+  }
+  nr_rlc_manager_unlock(nr_rlc_ue_manager);
+}
+
+static void add_drb(int rnti, struct LTE_DRB_ToAddMod *s)
+{
+  switch (s->rlc_Config->present) {
+  case LTE_RLC_Config_PR_am:
+    add_drb_am(rnti, s);
+    break;
+  case LTE_RLC_Config_PR_um_Bi_Directional:
+    add_drb_um(rnti, s);
+    break;
+  default:
+    LOG_E(RLC, "%s:%d:%s: fatal: unhandled DRB type\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+}
+
+rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP,
+    const LTE_SRB_ToAddModList_t   * const srb2add_listP,
+    const LTE_DRB_ToAddModList_t   * const drb2add_listP,
+    const LTE_DRB_ToReleaseList_t  * const drb2release_listP
+#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+    ,const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP
+    ,const uint32_t sourceL2Id
+    ,const uint32_t destinationL2Id
+#endif
+                                        )
+{
+  int rnti = ctxt_pP->rnti;
+  int i;
+
+  if (/*ctxt_pP->enb_flag != 1 ||*/ ctxt_pP->module_id != 0 /*||
+      ctxt_pP->instance != 0 || ctxt_pP->eNB_index != 0 ||
+      ctxt_pP->configured != 1 || ctxt_pP->brOption != 0 */) {
+    LOG_E(RLC, "%s: ctxt_pP not handled (%d %d %d %d %d %d)\n", __FUNCTION__,
+          ctxt_pP->enb_flag , ctxt_pP->module_id, ctxt_pP->instance,
+          ctxt_pP->eNB_index, ctxt_pP->configured, ctxt_pP->brOption);
+    exit(1);
+  }
+
+  if (pmch_InfoList_r9_pP != NULL) {
+    LOG_E(RLC, "%s: pmch_InfoList_r9_pP not handled\n", __FUNCTION__);
+    exit(1);
+  }
+
+  if (drb2release_listP != NULL) {
+    LOG_E(RLC, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  if (srb2add_listP != NULL) {
+    for (i = 0; i < srb2add_listP->list.count; i++) {
+      add_srb(rnti, srb2add_listP->list.array[i]);
+    }
+  }
+
+  if (drb2add_listP != NULL) {
+    for (i = 0; i < drb2add_listP->list.count; i++) {
+      add_drb(rnti, drb2add_listP->list.array[i]);
+    }
+  }
+
+  return RLC_OP_STATUS_OK;
+}
+
+rlc_op_status_t rrc_rlc_config_req   (
+  const protocol_ctxt_t* const ctxt_pP,
+  const srb_flag_t      srb_flagP,
+  const MBMS_flag_t     mbms_flagP,
+  const config_action_t actionP,
+  const rb_id_t         rb_idP,
+  const rlc_info_t      rlc_infoP)
+{
+  nr_rlc_ue_t *ue;
+  int      i;
+
+  if (mbms_flagP) {
+    LOG_E(RLC, "%s:%d:%s: todo (MBMS NOT supported)\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+  if (actionP != CONFIG_ACTION_REMOVE) {
+    LOG_E(RLC, "%s:%d:%s: todo (only CONFIG_ACTION_REMOVE supported)\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+  if (ctxt_pP->module_id) {
+    LOG_E(RLC, "%s:%d:%s: todo (only module_id 0 supported)\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+  if ((srb_flagP && !(rb_idP >= 1 && rb_idP <= 2)) ||
+      (!srb_flagP && !(rb_idP >= 1 && rb_idP <= 5))) {
+    LOG_E(RLC, "%s:%d:%s: bad rb_id (%d) (is_srb %d)\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP);
+    exit(1);
+  }
+  nr_rlc_manager_lock(nr_rlc_ue_manager);
+  LOG_D(RLC, "%s:%d:%s: remove rb %d (is_srb %d) for UE %d\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP, ctxt_pP->rnti);
+  ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ctxt_pP->rnti);
+  if (srb_flagP) {
+    if (ue->srb[rb_idP-1] != NULL) {
+      ue->srb[rb_idP-1]->delete(ue->srb[rb_idP-1]);
+      ue->srb[rb_idP-1] = NULL;
+    } else
+      LOG_W(RLC, "removing non allocated SRB %d, do nothing\n", rb_idP);
+  } else {
+    if (ue->drb[rb_idP-1] != NULL) {
+      ue->drb[rb_idP-1]->delete(ue->drb[rb_idP-1]);
+      ue->drb[rb_idP-1] = NULL;
+    } else
+      LOG_W(RLC, "removing non allocated DRB %d, do nothing\n", rb_idP);
+  }
+  /* remove UE if it has no more RB configured */
+  for (i = 0; i < 2; i++)
+    if (ue->srb[i] != NULL)
+      break;
+  if (i == 2) {
+    for (i = 0; i < 5; i++)
+      if (ue->drb[i] != NULL)
+        break;
+    if (i == 5)
+      nr_rlc_manager_remove_ue(nr_rlc_ue_manager, ctxt_pP->rnti);
+  }
+  nr_rlc_manager_unlock(nr_rlc_ue_manager);
+  return RLC_OP_STATUS_OK;
+}
+
+void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t rrc_data_confP)
+{
+  /* nothing to do */
+}
+
+rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x)
+{
+  LOG_D(RLC, "%s:%d:%s: remove UE %d\n", __FILE__, __LINE__, __FUNCTION__, x->rnti);
+  nr_rlc_manager_lock(nr_rlc_ue_manager);
+  nr_rlc_manager_remove_ue(nr_rlc_ue_manager, x->rnti);
+  nr_rlc_manager_unlock(nr_rlc_ue_manager);
+
+  return RLC_OP_STATUS_OK;
+}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_pdu.c b/openair2/LAYER2/nr_rlc/nr_rlc_pdu.c
new file mode 100644
index 0000000000000000000000000000000000000000..b42410ab720d76d6c9820fb25476a94781c1bf1f
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_pdu.c
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "nr_rlc_pdu.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "LOG/log.h"
+
+/**************************************************************************/
+/* RX PDU management                                                      */
+/**************************************************************************/
+
+nr_rlc_pdu_t *nr_rlc_new_pdu(int sn, int so, int is_first,
+    int is_last, char *data, int size)
+{
+  nr_rlc_pdu_t *ret = malloc(sizeof(nr_rlc_pdu_t));
+  if (ret == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+  ret->sn = sn;
+  ret->so = so;
+  ret->size = size;
+  ret->is_first = is_first;
+  ret->is_last = is_last;
+  ret->next = NULL;
+
+  ret->data = malloc(size);
+  if (ret->data == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  memcpy(ret->data, data, size);
+
+  return ret;
+}
+
+void nr_rlc_free_pdu(nr_rlc_pdu_t *pdu)
+{
+  free(pdu->data);
+  free(pdu);
+}
+
+nr_rlc_pdu_t *nr_rlc_pdu_list_add(
+    int (*sn_compare)(void *, int, int), void *sn_compare_data,
+    nr_rlc_pdu_t *list, nr_rlc_pdu_t *pdu)
+{
+  nr_rlc_pdu_t head;
+  nr_rlc_pdu_t *cur;
+  nr_rlc_pdu_t *prev;
+
+  head.next = list;
+  cur = list;
+  prev = &head;
+
+  /* order is by 'sn', if 'sn' is the same then order is by 'so' */
+  while (cur != NULL) {
+    /* check if 'pdu' is before 'cur' in the list */
+    if (sn_compare(sn_compare_data, cur->sn, pdu->sn) > 0 ||
+        (cur->sn == pdu->sn && cur->so > pdu->so)) {
+      break;
+    }
+    prev = cur;
+    cur = cur->next;
+  }
+  prev->next = pdu;
+  pdu->next = cur;
+  return head.next;
+}
+
+/**************************************************************************/
+/* PDU decoder                                                            */
+/**************************************************************************/
+
+void nr_rlc_pdu_decoder_init(nr_rlc_pdu_decoder_t *decoder,
+                             char *buffer, int size)
+{
+  decoder->error = 0;
+  decoder->byte = 0;
+  decoder->bit = 0;
+  decoder->buffer = buffer;
+  decoder->size = size;
+}
+
+static int get_bit(nr_rlc_pdu_decoder_t *decoder)
+{
+  int ret;
+
+  if (decoder->byte >= decoder->size) {
+    decoder->error = 1;
+    return 0;
+  }
+
+  ret = (decoder->buffer[decoder->byte] >> (7 - decoder->bit)) & 1;
+
+  decoder->bit++;
+  if (decoder->bit == 8) {
+    decoder->bit = 0;
+    decoder->byte++;
+  }
+
+  return ret;
+}
+
+int nr_rlc_pdu_decoder_get_bits(nr_rlc_pdu_decoder_t *decoder, int count)
+{
+  int ret = 0;
+  int i;
+
+  if (count > 31) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  for (i = 0; i < count; i++) {
+    ret <<= 1;
+    ret |= get_bit(decoder);
+    if (decoder->error) return -1;
+  }
+
+  return ret;
+}
+
+/**************************************************************************/
+/* PDU encoder                                                            */
+/**************************************************************************/
+
+void nr_rlc_pdu_encoder_init(nr_rlc_pdu_encoder_t *encoder,
+                             char *buffer, int size)
+{
+  encoder->byte = 0;
+  encoder->bit = 0;
+  encoder->buffer = buffer;
+  encoder->size = size;
+}
+
+static void put_bit(nr_rlc_pdu_encoder_t *encoder, int bit)
+{
+  if (encoder->byte == encoder->size) {
+    LOG_E(RLC, "%s:%d:%s: fatal, buffer full\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  encoder->buffer[encoder->byte] <<= 1;
+  if (bit)
+    encoder->buffer[encoder->byte] |= 1;
+
+  encoder->bit++;
+  if (encoder->bit == 8) {
+    encoder->bit = 0;
+    encoder->byte++;
+  }
+}
+
+void nr_rlc_pdu_encoder_put_bits(nr_rlc_pdu_encoder_t *encoder,
+                                 int value, int count)
+{
+  int i;
+  int x;
+
+  if (count > 31) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  x = 1 << (count - 1);
+  for (i = 0; i < count; i++, x >>= 1)
+    put_bit(encoder, value & x);
+}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_pdu.h b/openair2/LAYER2/nr_rlc/nr_rlc_pdu.h
new file mode 100644
index 0000000000000000000000000000000000000000..8e9872522ffe2549ddf2570423aa176765a8cc4b
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_pdu.h
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _NR_RLC_PDU_H_
+#define _NR_RLC_PDU_H_
+
+/**************************************************************************/
+/* RX PDU management                                                      */
+/**************************************************************************/
+
+typedef struct nr_rlc_pdu_t {
+  int sn;
+  char *data;       /* contains only SDU bytes, no PDU header */
+  int size;         /* size of SDU data, no PDU header bytes counted */
+  int so;
+  int is_first;
+  int is_last;
+  struct nr_rlc_pdu_t *next;
+} nr_rlc_pdu_t;
+
+nr_rlc_pdu_t *nr_rlc_new_pdu(int sn, int so, int is_first,
+    int is_last, char *data, int size);
+
+void nr_rlc_free_pdu(nr_rlc_pdu_t *pdu);
+
+nr_rlc_pdu_t *nr_rlc_pdu_list_add(
+    int (*sn_compare)(void *, int, int), void *sn_compare_data,
+    nr_rlc_pdu_t *list, nr_rlc_pdu_t *pdu);
+
+/**************************************************************************/
+/* PDU decoder                                                            */
+/**************************************************************************/
+
+typedef struct {
+  int error;
+  int byte;           /* next byte to decode */
+  int bit;            /* next bit in next byte to decode */
+  char *buffer;
+  int size;
+} nr_rlc_pdu_decoder_t;
+
+void nr_rlc_pdu_decoder_init(nr_rlc_pdu_decoder_t *decoder,
+                             char *buffer, int size);
+
+#define nr_rlc_pdu_decoder_in_error(d) ((d)->error == 1)
+
+int nr_rlc_pdu_decoder_get_bits(nr_rlc_pdu_decoder_t *decoder, int count);
+
+/**************************************************************************/
+/* PDU encoder                                                            */
+/**************************************************************************/
+
+typedef struct {
+  int byte;           /* next byte to encode */
+  int bit;            /* next bit in next byte to encode */
+  char *buffer;
+  int size;
+} nr_rlc_pdu_encoder_t;
+
+void nr_rlc_pdu_encoder_init(nr_rlc_pdu_encoder_t *encoder,
+                             char *buffer, int size);
+
+void nr_rlc_pdu_encoder_put_bits(nr_rlc_pdu_encoder_t *encoder,
+                                 int value, int count);
+
+#endif /* _NR_RLC_PDU_H_ */
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_sdu.c b/openair2/LAYER2/nr_rlc/nr_rlc_sdu.c
new file mode 100644
index 0000000000000000000000000000000000000000..ef0d52558aa402c3701d72ab9f8e0d2a492a6d57
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_sdu.c
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "nr_rlc_sdu.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "LOG/log.h"
+
+nr_rlc_sdu_segment_t *nr_rlc_new_sdu(
+    char *buffer, int size,
+    int upper_layer_id)
+{
+  nr_rlc_sdu_t *sdu         = calloc(1, sizeof(nr_rlc_sdu_t));
+  nr_rlc_sdu_segment_t *ret = calloc(1, sizeof(nr_rlc_sdu_segment_t));
+  if (sdu == NULL || ret == NULL)
+    goto oom;
+
+  sdu->ref_count      = 1;
+  sdu->sn             = -1;                 /* set later */
+  sdu->upper_layer_id = upper_layer_id;
+  sdu->data           = malloc(size);
+  if (sdu->data == NULL)
+    goto oom;
+  memcpy(sdu->data, buffer, size);
+  sdu->size           = size;
+  sdu->retx_count     = -1;
+
+  ret->sdu      = sdu;
+  ret->size     = size;
+  ret->so       = 0;
+  ret->is_first = 1;
+  ret->is_last  = 1;
+
+  return ret;
+
+oom:
+  LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__,  __FUNCTION__);
+  exit(1);
+}
+
+void nr_rlc_free_sdu_segment(nr_rlc_sdu_segment_t *sdu)
+{
+  sdu->sdu->ref_count--;
+  if (sdu->sdu->ref_count == 0) {
+    free(sdu->sdu->data);
+    free(sdu->sdu);
+  }
+  free(sdu);
+}
+
+void nr_rlc_sdu_segment_list_append(nr_rlc_sdu_segment_t **list,
+                                    nr_rlc_sdu_segment_t **end,
+                                    nr_rlc_sdu_segment_t *sdu)
+{
+  if (*list == NULL) {
+    *list = sdu;
+    *end = sdu;
+    return;
+  }
+
+  (*end)->next = sdu;
+  *end = sdu;
+}
+
+nr_rlc_sdu_segment_t *nr_rlc_sdu_segment_list_add(
+    int (*sn_compare)(void *, int, int), void *sn_compare_data,
+    nr_rlc_sdu_segment_t *list, nr_rlc_sdu_segment_t *sdu_segment)
+{
+  nr_rlc_sdu_segment_t head;
+  nr_rlc_sdu_segment_t *cur;
+  nr_rlc_sdu_segment_t *prev;
+
+  head.next = list;
+  cur = list;
+  prev = &head;
+
+  /* order is by 'sn', if 'sn' is the same then order is by 'so' */
+  while (cur != NULL) {
+    /* check if 'sdu_segment' is before 'cur' in the list */
+    if (sn_compare(sn_compare_data, cur->sdu->sn, sdu_segment->sdu->sn) > 0 ||
+        (cur->sdu->sn == sdu_segment->sdu->sn && cur->so > sdu_segment->so)) {
+      break;
+    }
+    prev = cur;
+    cur = cur->next;
+  }
+  prev->next = sdu_segment;
+  sdu_segment->next = cur;
+  return head.next;
+}
+
+void nr_rlc_free_sdu_segment_list(nr_rlc_sdu_segment_t *l)
+{
+  nr_rlc_sdu_segment_t *cur;
+
+  while (l != NULL) {
+    cur = l;
+    l = l->next;
+    nr_rlc_free_sdu_segment(cur);
+  }
+}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_sdu.h b/openair2/LAYER2/nr_rlc/nr_rlc_sdu.h
new file mode 100644
index 0000000000000000000000000000000000000000..f4585fb7d62342f4b5a5065c1c778d05c27ff063
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_sdu.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.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _NR_RLC_SDU_H_
+#define _NR_RLC_SDU_H_
+
+typedef struct nr_rlc_sdu_t {
+  int sn;
+  int upper_layer_id;
+  char *data;
+  int size;
+  int retx_count;
+
+  int ref_count;      /* incremented each time the SDU is segmented */
+} nr_rlc_sdu_t;
+
+typedef struct nr_rlc_sdu_segment_t {
+  nr_rlc_sdu_t *sdu;
+  int size;
+  int so;
+  int is_first;
+  int is_last;
+  struct nr_rlc_sdu_segment_t *next;
+} nr_rlc_sdu_segment_t;
+
+nr_rlc_sdu_segment_t *nr_rlc_new_sdu(
+    char *buffer, int size,
+    int upper_layer_id);
+void nr_rlc_free_sdu_segment(nr_rlc_sdu_segment_t *sdu);
+void nr_rlc_sdu_segment_list_append(nr_rlc_sdu_segment_t **list,
+                                    nr_rlc_sdu_segment_t **end,
+                                    nr_rlc_sdu_segment_t *sdu);
+nr_rlc_sdu_segment_t *nr_rlc_sdu_segment_list_add(
+    int (*sn_compare)(void *, int, int), void *sn_compare_data,
+    nr_rlc_sdu_segment_t *list, nr_rlc_sdu_segment_t *sdu_segment);
+void nr_rlc_free_sdu_segment_list(nr_rlc_sdu_segment_t *l);
+
+#endif /* _NR_RLC_SDU_H_ */
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c
new file mode 100644
index 0000000000000000000000000000000000000000..09f1e4f599e5ca98389dc577782b35594671f130
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "nr_rlc_ue_manager.h"
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "LOG/log.h"
+
+typedef struct {
+  pthread_mutex_t lock;
+  nr_rlc_ue_t     **ue_list;
+  int             ue_count;
+  int             enb_flag;
+} nr_rlc_ue_manager_internal_t;
+
+nr_rlc_ue_manager_t *new_nr_rlc_ue_manager(int enb_flag)
+{
+  nr_rlc_ue_manager_internal_t *ret;
+
+  ret = calloc(1, sizeof(nr_rlc_ue_manager_internal_t));
+  if (ret == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  if (pthread_mutex_init(&ret->lock, NULL)) abort();
+  ret->enb_flag = enb_flag;
+
+  return ret;
+}
+
+int nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager_t *_m)
+{
+  nr_rlc_ue_manager_internal_t *m = _m;
+  return m->enb_flag;
+}
+
+void nr_rlc_manager_lock(nr_rlc_ue_manager_t *_m)
+{
+  nr_rlc_ue_manager_internal_t *m = _m;
+  if (pthread_mutex_lock(&m->lock)) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+}
+
+void nr_rlc_manager_unlock(nr_rlc_ue_manager_t *_m)
+{
+  nr_rlc_ue_manager_internal_t *m = _m;
+  if (pthread_mutex_unlock(&m->lock)) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+}
+
+/* must be called with lock acquired */
+nr_rlc_ue_t *nr_rlc_manager_get_ue(nr_rlc_ue_manager_t *_m, int rnti)
+{
+  /* TODO: optimze */
+  nr_rlc_ue_manager_internal_t *m = _m;
+  int i;
+
+  for (i = 0; i < m->ue_count; i++)
+    if (m->ue_list[i]->rnti == rnti)
+      return m->ue_list[i];
+
+  LOG_D(RLC, "%s:%d:%s: new UE %d\n", __FILE__, __LINE__, __FUNCTION__, rnti);
+
+  m->ue_count++;
+  m->ue_list = realloc(m->ue_list, sizeof(nr_rlc_ue_t *) * m->ue_count);
+  if (m->ue_list == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+  m->ue_list[m->ue_count-1] = calloc(1, sizeof(nr_rlc_ue_t));
+  if (m->ue_list[m->ue_count-1] == NULL) {
+    LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  m->ue_list[m->ue_count-1]->rnti = rnti;
+
+  return m->ue_list[m->ue_count-1];
+}
+
+/* must be called with lock acquired */
+void nr_rlc_manager_remove_ue(nr_rlc_ue_manager_t *_m, int rnti)
+{
+  nr_rlc_ue_manager_internal_t *m = _m;
+  nr_rlc_ue_t *ue;
+  int i;
+  int j;
+
+  for (i = 0; i < m->ue_count; i++)
+    if (m->ue_list[i]->rnti == rnti)
+      break;
+
+  if (i == m->ue_count) {
+    LOG_D(RLC, "%s:%d:%s: warning: ue %d not found\n",
+          __FILE__, __LINE__, __FUNCTION__,
+          rnti);
+    return;
+  }
+
+  ue = m->ue_list[i];
+
+  for (j = 0; j < 2; j++)
+    if (ue->srb[j] != NULL)
+      ue->srb[j]->delete(ue->srb[j]);
+
+  for (j = 0; j < 5; j++)
+    if (ue->drb[j] != NULL)
+      ue->drb[j]->delete(ue->drb[j]);
+
+  free(ue);
+
+  m->ue_count--;
+  if (m->ue_count == 0) {
+    free(m->ue_list);
+    m->ue_list = NULL;
+    return;
+  }
+
+  memmove(&m->ue_list[i], &m->ue_list[i+1],
+          (m->ue_count - i) * sizeof(nr_rlc_ue_t *));
+  m->ue_list = realloc(m->ue_list, m->ue_count * sizeof(nr_rlc_ue_t *));
+  if (m->ue_list == NULL) {
+    LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+}
+
+/* must be called with lock acquired */
+void nr_rlc_ue_add_srb_rlc_entity(nr_rlc_ue_t *ue, int srb_id, nr_rlc_entity_t *entity)
+{
+  if (srb_id < 1 || srb_id > 2) {
+    LOG_E(RLC, "%s:%d:%s: fatal, bad srb id\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  srb_id--;
+
+  if (ue->srb[srb_id] != NULL) {
+    LOG_E(RLC, "%s:%d:%s: fatal, srb already present\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  ue->srb[srb_id] = entity;
+}
+
+/* must be called with lock acquired */
+void nr_rlc_ue_add_drb_rlc_entity(nr_rlc_ue_t *ue, int drb_id, nr_rlc_entity_t *entity)
+{
+  if (drb_id < 1 || drb_id > 5) {
+    LOG_E(RLC, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  drb_id--;
+
+  if (ue->drb[drb_id] != NULL) {
+    LOG_E(RLC, "%s:%d:%s: fatal, drb already present\n",
+          __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  ue->drb[drb_id] = entity;
+}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..97da28cdce2136f01bef2d0c8625269e7ba5edf0
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _NR_RLC_UE_MANAGER_H_
+#define _NR_RLC_UE_MANAGER_H_
+
+#include "nr_rlc_entity.h"
+
+typedef void nr_rlc_ue_manager_t;
+
+typedef struct nr_rlc_ue_t {
+  int rnti;
+  /* due to openair calling status_ind/data_req, we need to keep this.
+   * To be considered 'hackish'.
+   */
+  int saved_status_ind_tb_size[2+5];
+  nr_rlc_entity_t *srb[2];
+  nr_rlc_entity_t *drb[5];
+} nr_rlc_ue_t;
+
+/***********************************************************************/
+/* manager functions                                                   */
+/***********************************************************************/
+
+nr_rlc_ue_manager_t *new_nr_rlc_ue_manager(int enb_flag);
+
+int nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager_t *m);
+
+void nr_rlc_manager_lock(nr_rlc_ue_manager_t *m);
+void nr_rlc_manager_unlock(nr_rlc_ue_manager_t *m);
+
+nr_rlc_ue_t *nr_rlc_manager_get_ue(nr_rlc_ue_manager_t *m, int rnti);
+void nr_rlc_manager_remove_ue(nr_rlc_ue_manager_t *m, int rnti);
+
+/***********************************************************************/
+/* ue functions                                                        */
+/***********************************************************************/
+
+void nr_rlc_ue_add_srb_rlc_entity(nr_rlc_ue_t *ue, int srb_id, nr_rlc_entity_t *entity);
+void nr_rlc_ue_add_drb_rlc_entity(nr_rlc_ue_t *ue, int drb_id, nr_rlc_entity_t *entity);
+
+#endif /* _NR_RLC_UE_MANAGER_H_ */
diff --git a/openair2/LAYER2/nr_rlc/test.c b/openair2/LAYER2/nr_rlc/test.c
new file mode 100644
index 0000000000000000000000000000000000000000..52b0891bc3037702e6eb2a78d213dc36a27daadc
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/test.c
@@ -0,0 +1,32 @@
+#include "nr_rlc_entity.h"
+
+#include <stdio.h>
+
+int main(void)
+{
+  char out[32768];
+  nr_rlc_entity_t *am;
+  int sdu_id = 0;
+  int size;
+  int i;
+
+  am = new_nr_rlc_entity_am(100000, 100000,
+                            0, 0,
+                            0, 0,
+                            0, 0,
+                            45, 35, 0,
+                            -1, -1, 8,
+                            12);
+
+  char data[8] = { 1, 2, 3, 4, 8, 7, 6, 5 };
+
+  am->recv_sdu(am, data, sizeof(data), sdu_id++);
+
+  size = am->generate_pdu(am, out, 32768);
+
+  printf("generate_pdu[%d]:", size);
+  for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)out[i]);
+  printf("\n");
+
+  return 0;
+}
diff --git a/openair2/LAYER2/nr_rlc/tests/LOG/log.h b/openair2/LAYER2/nr_rlc/tests/LOG/log.h
new file mode 100644
index 0000000000000000000000000000000000000000..5c9fcd643cfca036cc81eca221f4a5e818aee685
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/LOG/log.h
@@ -0,0 +1,10 @@
+#ifndef _LOG_H_
+#define _LOG_H_
+
+#include <stdio.h>
+
+#define LOG_E(x, ...) printf(__VA_ARGS__)
+#define LOG_D(x, ...) printf(__VA_ARGS__)
+#define LOG_W(x, ...) printf(__VA_ARGS__)
+
+#endif /* _LOG_H_ */
diff --git a/openair2/LAYER2/nr_rlc/tests/Makefile b/openair2/LAYER2/nr_rlc/tests/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..746d61483b6523ab708a861e25d0d884363b10e8
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/Makefile
@@ -0,0 +1,33 @@
+CC=gcc
+CFLAGS=-Wall -g --coverage -I.
+
+LIB=nr_rlc_entity.o nr_rlc_entity_am.o nr_rlc_entity_um.o nr_rlc_entity_tm.o \
+    nr_rlc_pdu.o nr_rlc_sdu.o
+
+tests:
+	@./run_tests.sh
+
+all: clean_run $(TEST).run
+
+%.run: $(TEST).bin
+	#valgrind ./$(TEST).bin > $(TEST).run_pre 2> $(TEST).valgrind
+	./$(TEST).bin > $(TEST).run_pre
+	grep ^TEST $(TEST).run_pre > $(TEST).run
+	gunzip -c $(TEST).txt.gz > $(TEST).txt
+	diff -q $(TEST).txt $(TEST).run
+
+$(TEST).bin: $(TEST).o $(LIB)
+	$(CC) $(CFLAGS) -o $@ $^
+
+%.o: ../%.c
+	$(CC) $(CFLAGS) -I.. -c -o $@ $<
+
+$(TEST).o: test.c
+	$(CC) $(CFLAGS) -c -o $@ $< -DTEST='"$(TEST).h"'
+
+clean_run:
+	rm -f $(TEST).run $(TEST).bin $(TEST).o
+
+clean:
+	rm -f *.o *.bin *.run *.run_pre *.gcov *.gcda *.gcno test*.txt a.out \
+		*.valgrind
diff --git a/openair2/LAYER2/nr_rlc/tests/run_tests.sh b/openair2/LAYER2/nr_rlc/tests/run_tests.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ac225160646d869235976445f35f9a4ec3cff52d
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/run_tests.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+test_count=13
+
+for i in `seq $test_count`
+do
+  make all TEST=test$i >/dev/null 2>/dev/null
+  if [ $? != 0 ]
+  then
+    echo TEST $i FAILURE
+  fi
+done
diff --git a/openair2/LAYER2/nr_rlc/tests/test.c b/openair2/LAYER2/nr_rlc/tests/test.c
new file mode 100644
index 0000000000000000000000000000000000000000..742e79ca2c1cf788a38e95b9b2f4457c3e6deeb9
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test.c
@@ -0,0 +1,483 @@
+#include "../nr_rlc_entity.h"
+#include "../nr_rlc_entity_am.h"
+#include "../nr_rlc_entity_um.h"
+#include "../nr_rlc_entity_tm.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+/*
+ * GNB_AM <rx_maxsize> <tx_maxsize> <t_poll_retransmit> <t_reassembly>
+ *       <t_status_prohibit> <poll_pdu> <poll_byte> <max_retx_threshold>
+ *       <sn_field_length>
+ *       create the gNB RLC AM entity with given parameters
+ *
+ * UE_AM <rx_maxsize> <tx_maxsize> <t_poll_retransmit> <t_reassembly>
+ *      <t_status_prohibit> <poll_pdu> <poll_byte> <max_retx_threshold>
+ *      <sn_field_length>
+ *       create the UE RLC AM entity with given parameters
+ *
+ * GNB_UM <rx_maxsize> <tx_maxsize> <t_reassembly> <sn_field_length>
+ *     create the eNB RLC UM entity with given parameters
+ *
+ * UE_UM <rx_maxsize> <tx_maxsize> <t_reassembly> <sn_field_length>
+ *     create the UE RLC UM entity with given parameters
+ *
+ * GNB_TM <tx_maxsize>
+ *     create the eNB RLC TM entity with given parameters
+ *
+ * UE_UM <tx_maxsize>
+ *     create the UE RLC TM entity with given parameters
+ *
+ * TIME <time>
+ *     following actions to be performed at time <time>
+ *     <time> starts at 1
+ *     You must end your test definition with a line 'TIME, -1'.
+ *
+ * GNB_SDU <id> <size>
+ *     send an SDU to eNB with id <i> and size <size>
+ *     the SDU is [00 01 ... ff 01 ...]
+ *     (ie. start byte is 00 then we increment for each byte, loop if needed)
+ *
+ * UE_SDU <id> <size>
+ *     same as GNB_SDU but the SDU is sent to the UE
+ *
+ * GNB_PDU <size> <'size' bytes>
+ *     send a custom PDU from eNB to UE (eNB does not see this PDU at all)
+ *
+ * UE_PDU <size> <'size' bytes>
+ *     send a custom PDU from UE to eNB (UE does not see this PDU at all)
+ *
+ * GNB_PDU_SIZE <size>
+ *     set 'gnb_pdu_size'
+ *
+ * UE_PDU_SIZE <size>
+ *     set 'ue_pdu_size'
+ *
+ * GNB_RECV_FAILS <fails>
+ *     set the 'gnb_recv_fails' flag to <fails>
+ *     (1: recv will fail, 0: recv will succeed)
+ *
+ * UE_RECV_FAILS <fails>
+ *     same as GNB_RECV_FAILS but for 'ue_recv_fails'
+ *
+ * MUST_FAIL
+ *     to be used as first command after the first TIME to indicate
+ *     that the test must fail (ie. exit with non zero, crash not allowed)
+ *
+ * GNB_BUFFER_STATUS
+ *     call buffer_status for eNB and print result
+ *
+ * UE_BUFFER_STATUS
+ *     call buffer_status for UE and print result
+ *
+ * GNB_DISCARD_SDU <sdu ID>
+ *     discards given SDU
+ *
+ * UE_DISCARD_SDU <sdu ID>
+ *     discards given SDU
+ *
+ * RE_ESTABLISH
+ *     re-establish both eNB and UE
+ */
+
+enum action {
+  GNB_AM, UE_AM,
+  GNB_UM, UE_UM,
+  GNB_TM, UE_TM,
+  TIME, GNB_SDU, UE_SDU, GNB_PDU, UE_PDU,
+  GNB_PDU_SIZE, UE_PDU_SIZE,
+  GNB_RECV_FAILS, UE_RECV_FAILS,
+  MUST_FAIL,
+  GNB_BUFFER_STATUS, UE_BUFFER_STATUS,
+  GNB_DISCARD_SDU, UE_DISCARD_SDU,
+  RE_ESTABLISH
+};
+
+int test[] = {
+/* TEST is defined at compilation time */
+#include TEST
+};
+
+void deliver_sdu_gnb_am(void *deliver_sdu_data,
+                        struct nr_rlc_entity_t *_entity,
+                        char *buf, int size)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  printf("TEST: GNB: %"PRIu64": deliver SDU size %d [",
+         entity->t_current, size);
+  for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
+  printf("]\n");
+}
+
+void deliver_sdu_gnb_um(void *deliver_sdu_data,
+                        struct nr_rlc_entity_t *_entity,
+                        char *buf, int size)
+{
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+  printf("TEST: GNB: %"PRIu64": deliver SDU size %d [",
+         entity->t_current, size);
+  for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
+  printf("]\n");
+}
+
+void deliver_sdu_gnb_tm(void *deliver_sdu_data,
+                        struct nr_rlc_entity_t *_entity,
+                        char *buf, int size)
+{
+  nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
+  printf("TEST: GNB: %"PRIu64": deliver SDU size %d [",
+         entity->t_current, size);
+  for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
+  printf("]\n");
+}
+
+void successful_delivery_gnb(void *successful_delivery_data,
+                             nr_rlc_entity_t *_entity, int sdu_id)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  printf("TEST: GNB: %"PRIu64": SDU %d was successfully delivered.\n",
+         entity->t_current, sdu_id);
+}
+
+void max_retx_reached_gnb(void *max_retx_reached_data,
+                          nr_rlc_entity_t *_entity)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  printf("TEST: GNB: %"PRIu64": max RETX reached! radio link failure!\n",
+         entity->t_current);
+  exit(1);
+}
+
+void deliver_sdu_ue_am(void *deliver_sdu_data,
+                       struct nr_rlc_entity_t *_entity,
+                       char *buf, int size)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  printf("TEST: UE: %"PRIu64": deliver SDU size %d [",
+         entity->t_current, size);
+  for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
+  printf("]\n");
+}
+
+void deliver_sdu_ue_um(void *deliver_sdu_data,
+                       struct nr_rlc_entity_t *_entity,
+                       char *buf, int size)
+{
+  nr_rlc_entity_um_t *entity = (nr_rlc_entity_um_t *)_entity;
+  printf("TEST: UE: %"PRIu64": deliver SDU size %d [",
+         entity->t_current, size);
+  for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
+  printf("]\n");
+}
+
+void deliver_sdu_ue_tm(void *deliver_sdu_data,
+                       struct nr_rlc_entity_t *_entity,
+                       char *buf, int size)
+{
+  nr_rlc_entity_tm_t *entity = (nr_rlc_entity_tm_t *)_entity;
+  printf("TEST: UE: %"PRIu64": deliver SDU size %d [",
+         entity->t_current, size);
+  for (int i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
+  printf("]\n");
+}
+
+void successful_delivery_ue(void *successful_delivery_data,
+                            nr_rlc_entity_t *_entity, int sdu_id)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  printf("TEST: UE: %"PRIu64": SDU %d was successfully delivered.\n",
+         entity->t_current, sdu_id);
+}
+
+void max_retx_reached_ue(void *max_retx_reached_data,
+                         nr_rlc_entity_t *_entity)
+{
+  nr_rlc_entity_am_t *entity = (nr_rlc_entity_am_t *)_entity;
+  printf("TEST: UE: %"PRIu64", max RETX reached! radio link failure!\n",
+         entity->t_current);
+  exit(1);
+}
+
+int test_main(void)
+{
+  nr_rlc_entity_t *gnb = NULL;
+  nr_rlc_entity_t *ue = NULL;
+  int i;
+  int k;
+  char *sdu;
+  char *pdu;
+  nr_rlc_entity_buffer_status_t buffer_status;
+  int gnb_do_buffer_status = 0;
+  int ue_do_buffer_status = 0;
+  int size;
+  int pos;
+  int next_byte_gnb = 0;
+  int next_byte_ue = 0;
+  int gnb_recv_fails = 0;
+  int ue_recv_fails = 0;
+  int gnb_pdu_size = 1000;
+  int ue_pdu_size = 1000;
+
+  printf("TEST: start\n");
+
+  sdu = malloc(16001);
+  pdu = malloc(3000);
+  if (sdu == NULL || pdu == NULL) {
+    printf("out of memory\n");
+    exit(1);
+  }
+
+  for (i = 0; i < 16001; i++)
+    sdu[i] = i & 255;
+
+  pos = 0;
+  if (test[pos] != TIME) {
+    printf("%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  for (i = 1; i < 1000; i++) {
+    if (i == test[pos+1]) {
+      pos += 2;
+      while (test[pos] != TIME)
+        switch (test[pos]) {
+        default: printf("fatal: unknown action\n"); exit(1);
+        case GNB_AM:
+          gnb = new_nr_rlc_entity_am(test[pos+1], test[pos+2],
+                                     deliver_sdu_gnb_am, NULL,
+                                     successful_delivery_gnb, NULL,
+                                     max_retx_reached_gnb, NULL,
+                                     test[pos+3], test[pos+4], test[pos+5],
+                                     test[pos+6], test[pos+7], test[pos+8],
+                                     test[pos+9]);
+          pos += 10;
+          break;
+        case UE_AM:
+          ue = new_nr_rlc_entity_am(test[pos+1], test[pos+2],
+                                    deliver_sdu_ue_am, NULL,
+                                    successful_delivery_ue, NULL,
+                                    max_retx_reached_ue, NULL,
+                                    test[pos+3], test[pos+4], test[pos+5],
+                                    test[pos+6], test[pos+7], test[pos+8],
+                                    test[pos+9]);
+          pos += 10;
+          break;
+        case GNB_UM:
+          gnb = new_nr_rlc_entity_um(test[pos+1], test[pos+2],
+                                     deliver_sdu_gnb_um, NULL,
+                                     test[pos+3], test[pos+4]);
+          pos += 5;
+          break;
+        case UE_UM:
+          ue = new_nr_rlc_entity_um(test[pos+1], test[pos+2],
+                                    deliver_sdu_ue_um, NULL,
+                                    test[pos+3], test[pos+4]);
+          pos += 5;
+          break;
+        case GNB_TM:
+          gnb = new_nr_rlc_entity_tm(test[pos+1], deliver_sdu_gnb_tm, NULL);
+          pos += 2;
+          break;
+        case UE_TM:
+          ue = new_nr_rlc_entity_tm(test[pos+1], deliver_sdu_ue_tm, NULL);
+          pos += 2;
+          break;
+        case GNB_SDU:
+          for (k = 0; k < test[pos+2]; k++, next_byte_gnb++)
+            sdu[k] = next_byte_gnb;
+          printf("TEST: GNB: %d: recv_sdu (id %d): size %d: [",
+                 i, test[pos+1], test[pos+2]);
+          for (k = 0; k < test[pos+2]; k++)
+            printf(" %2.2x", (unsigned char)sdu[k]);
+          printf("]\n");
+          gnb->recv_sdu(gnb, sdu, test[pos+2], test[pos+1]);
+          pos += 3;
+          break;
+        case UE_SDU:
+          for (k = 0; k < test[pos+2]; k++, next_byte_ue++)
+            sdu[k] = next_byte_ue;
+          printf("TEST: UE: %d: recv_sdu (id %d): size %d: [",
+                 i, test[pos+1], test[pos+2]);
+          for (k = 0; k < test[pos+2]; k++)
+            printf(" %2.2x", (unsigned char)sdu[k]);
+          printf("]\n");
+          ue->recv_sdu(ue, sdu, test[pos+2], test[pos+1]);
+          pos += 3;
+          break;
+        case GNB_PDU:
+          for (k = 0; k < test[pos+1]; k++)
+            pdu[k] = test[pos+2+k];
+          printf("TEST: GNB: %d: custom PDU: size %d: [", i, test[pos+1]);
+          for (k = 0; k < test[pos+1]; k++) printf(" %2.2x", (unsigned char)pdu[k]);
+          printf("]\n");
+          if (!ue_recv_fails)
+            ue->recv_pdu(ue, pdu, test[pos+1]);
+          pos += 2 + test[pos+1];
+          break;
+        case UE_PDU:
+          for (k = 0; k < test[pos+1]; k++)
+            pdu[k] = test[pos+2+k];
+          printf("TEST: UE: %d: custom PDU: size %d: [", i, test[pos+1]);
+          for (k = 0; k < test[pos+1]; k++) printf(" %2.2x", (unsigned char)pdu[k]);
+          printf("]\n");
+          if (!gnb_recv_fails)
+            gnb->recv_pdu(gnb, pdu, test[pos+1]);
+          pos += 2 + test[pos+1];
+          break;
+        case GNB_PDU_SIZE:
+          gnb_pdu_size = test[pos+1];
+          pos += 2;
+          break;
+        case UE_PDU_SIZE:
+          ue_pdu_size = test[pos+1];
+          pos += 2;
+          break;
+        case GNB_RECV_FAILS:
+          gnb_recv_fails = test[pos+1];
+          pos += 2;
+          break;
+        case UE_RECV_FAILS:
+          ue_recv_fails = test[pos+1];
+          pos += 2;
+          break;
+        case MUST_FAIL:
+          /* do nothing, only used by caller */
+          pos++;
+          break;
+        case GNB_BUFFER_STATUS:
+          gnb_do_buffer_status = 1;
+          pos++;
+          break;
+        case UE_BUFFER_STATUS:
+          ue_do_buffer_status = 1;
+          pos++;
+          break;
+        case GNB_DISCARD_SDU:
+          printf("TEST: GNB: %d: discard SDU %d\n", i, test[pos+1]);
+          gnb->discard_sdu(gnb, test[pos+1]);
+          pos += 2;
+          break;
+        case UE_DISCARD_SDU:
+          printf("TEST: UE: %d: discard SDU %d\n", i, test[pos+1]);
+          ue->discard_sdu(ue, test[pos+1]);
+          pos += 2;
+          break;
+        case RE_ESTABLISH:
+          printf("TEST: %d: re-establish eNB and UE\n", i);
+          gnb->reestablishment(gnb);
+          ue->reestablishment(ue);
+          pos++;
+          break;
+        }
+    }
+
+    gnb->set_time(gnb, i);
+    ue->set_time(ue, i);
+
+    if (gnb_do_buffer_status) {
+      gnb_do_buffer_status = 0;
+      buffer_status = gnb->buffer_status(gnb, gnb_pdu_size);
+      printf("TEST: GNB: %d: buffer_status: status_size %d tx_size %d retx_size %d\n",
+             i,
+             buffer_status.status_size,
+             buffer_status.tx_size,
+             buffer_status.retx_size);
+    }
+
+    size = gnb->generate_pdu(gnb, pdu, gnb_pdu_size);
+    if (size) {
+      printf("TEST: GNB: %d: generate_pdu: size %d: [", i, size);
+      for (k = 0; k < size; k++) printf(" %2.2x", (unsigned char)pdu[k]);
+      printf("]\n");
+      if (!ue_recv_fails)
+        ue->recv_pdu(ue, pdu, size);
+    }
+
+    if (ue_do_buffer_status) {
+      ue_do_buffer_status = 0;
+      buffer_status = ue->buffer_status(ue, ue_pdu_size);
+      printf("TEST: UE: %d: buffer_status: status_size %d tx_size %d retx_size %d\n",
+             i,
+             buffer_status.status_size,
+             buffer_status.tx_size,
+             buffer_status.retx_size);
+    }
+
+    size = ue->generate_pdu(ue, pdu, ue_pdu_size);
+    if (size) {
+      printf("TEST: UE: %d: generate_pdu: size %d: [", i, size);
+      for (k = 0; k < size; k++) printf(" %2.2x", (unsigned char)pdu[k]);
+      printf("]\n");
+      if (!gnb_recv_fails)
+        gnb->recv_pdu(gnb, pdu, size);
+    }
+  }
+
+  gnb->delete(gnb);
+  ue->delete(ue);
+
+  free(sdu);
+  free(pdu);
+
+  return 0;
+}
+
+void usage(void)
+{
+  printf("options:\n");
+  printf("    -no-fork\n");
+  printf("        don't fork (to ease debugging with gdb)\n");
+  exit(0);
+}
+
+int main(int n, char **v)
+{
+  int must_fail = 0;
+  int son;
+  int status;
+  int i;
+  int no_fork = 0;
+
+  for (i = 1; i < n; i++) {
+    if (!strcmp(v[i], "-no-fork")) { no_fork = 1; continue; }
+    usage();
+  }
+
+  if (test[2] == MUST_FAIL)
+    must_fail = 1;
+
+  if (no_fork) return test_main();
+
+  son = fork();
+  if (son == -1) {
+    perror("fork");
+    return 1;
+  }
+
+  if (son == 0)
+    return test_main();
+
+  if (wait(&status) == -1) {
+    perror("wait");
+    return 1;
+  }
+
+  /* child must quit properly */
+  if (!WIFEXITED(status))
+    return 1;
+
+  /* child must fail if expected to */
+  if (must_fail && WEXITSTATUS(status) == 0)
+    return 1;
+
+  /* child must not fail if not expected to */
+  if (!must_fail && WEXITSTATUS(status))
+    return 1;
+
+  return 0;
+}
diff --git a/openair2/LAYER2/nr_rlc/tests/test1.h b/openair2/LAYER2/nr_rlc/tests/test1.h
new file mode 100644
index 0000000000000000000000000000000000000000..3240ecfc3686092f446eea9c72e373d2a436db12
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test1.h
@@ -0,0 +1,14 @@
+/*
+ * basic am test (SN field size 12):
+ * at time 1, gNB receives an SDU of 10 bytes
+ * at time 10, UE receives an SDU of 5 bytes
+ */
+
+TIME, 1,
+    GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 12,
+    UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 12,
+    GNB_SDU, 0, 10,
+    UE_BUFFER_STATUS,
+TIME, 10,
+    UE_SDU, 0, 5,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test1.txt.gz b/openair2/LAYER2/nr_rlc/tests/test1.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..d3852d070cb17dae5f7db1678ef427b0e7f85a96
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test1.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test10.h b/openair2/LAYER2/nr_rlc/tests/test10.h
new file mode 100644
index 0000000000000000000000000000000000000000..1653736f2665229c70cbe3fbe797b934ee2fbfe7
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test10.h
@@ -0,0 +1,13 @@
+/*
+ * um test (SN field size 6):
+ * test reassembly
+ * at time 1, gNB receives an SDU of 50 bytes
+ * sends it in 3 parts
+ */
+
+TIME, 1,
+    GNB_UM, 100000, 100000, 35, 6,
+    UE_UM, 100000, 100000, 35, 6,
+    GNB_PDU_SIZE, 22,
+    GNB_SDU, 0, 50,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test10.txt.gz b/openair2/LAYER2/nr_rlc/tests/test10.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..12430b53c5647e7c17d1428aa1413ada5b7e5b67
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test10.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test11.h b/openair2/LAYER2/nr_rlc/tests/test11.h
new file mode 100644
index 0000000000000000000000000000000000000000..41465e09e1dcd41148814f0a84e34af22dabe61f
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test11.h
@@ -0,0 +1,13 @@
+/*
+ * um test (SN field size 12):
+ * test reassembly
+ * at time 1, gNB receives an SDU of 50 bytes
+ * sends it in 3 parts
+ */
+
+TIME, 1,
+    GNB_UM, 100000, 100000, 35, 12,
+    UE_UM, 100000, 100000, 35, 12,
+    GNB_PDU_SIZE, 22,
+    GNB_SDU, 0, 50,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test11.txt.gz b/openair2/LAYER2/nr_rlc/tests/test11.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..1a5294ffa023c3fa3a2b2853e0f846fbbc9d4807
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test11.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test12.h b/openair2/LAYER2/nr_rlc/tests/test12.h
new file mode 100644
index 0000000000000000000000000000000000000000..4ab28dd3f23901f665b66c7deb6eec44b9da1ce2
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test12.h
@@ -0,0 +1,18 @@
+/*
+ * um test (SN field size 6):
+ * test reassembly and timeout
+ * at time 1, gNB receives an SDU of 50 bytes
+ * sends it in 3 parts
+ * part 2 not received
+ */
+
+TIME, 1,
+    GNB_UM, 100000, 100000, 35, 6,
+    UE_UM, 100000, 100000, 35, 6,
+    GNB_PDU_SIZE, 22,
+    GNB_SDU, 0, 50,
+TIME, 2,
+    UE_RECV_FAILS, 1,
+TIME, 3,
+    UE_RECV_FAILS, 0,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test12.txt.gz b/openair2/LAYER2/nr_rlc/tests/test12.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..ac85aa89f39fb5c76f5e21b07d1658c461839e0c
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test12.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test13.h b/openair2/LAYER2/nr_rlc/tests/test13.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc973fdcff60c1fe3a1c8f32e698755edc89f15a
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test13.h
@@ -0,0 +1,18 @@
+/*
+ * um test (SN field size 12):
+ * test reassembly and timeout
+ * at time 1, gNB receives an SDU of 50 bytes
+ * sends it in 3 parts
+ * part 2 not received
+ */
+
+TIME, 1,
+    GNB_UM, 100000, 100000, 35, 12,
+    UE_UM, 100000, 100000, 35, 12,
+    GNB_PDU_SIZE, 22,
+    GNB_SDU, 0, 50,
+TIME, 2,
+    UE_RECV_FAILS, 1,
+TIME, 3,
+    UE_RECV_FAILS, 0,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test13.txt.gz b/openair2/LAYER2/nr_rlc/tests/test13.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..3838dcf15214dda2c8bbd7fba5e60c9016b4a8c2
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test13.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test2.h b/openair2/LAYER2/nr_rlc/tests/test2.h
new file mode 100644
index 0000000000000000000000000000000000000000..7adc349c1ea3765b7dc0e0293cd756139dd1f368
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test2.h
@@ -0,0 +1,14 @@
+/*
+ * basic am test (SN field size 18):
+ * at time 1, gNB receives an SDU of 10 bytes
+ * at time 10, UE receives an SDU of 5 bytes
+ */
+
+TIME, 1,
+    GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18,
+    UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18,
+    GNB_SDU, 0, 10,
+    UE_BUFFER_STATUS,
+TIME, 10,
+    UE_SDU, 0, 5,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test2.txt.gz b/openair2/LAYER2/nr_rlc/tests/test2.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..04092cdaa2d778f3a65dfbe26e9879a01c740428
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test2.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test3.h b/openair2/LAYER2/nr_rlc/tests/test3.h
new file mode 100644
index 0000000000000000000000000000000000000000..db5454f8de0dd9e66917df88134f03ddeca7c325
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test3.h
@@ -0,0 +1,14 @@
+/*
+ * basic um test (SN field size 6):
+ * at time 1, gNB receives an SDU of 10 bytes
+ * at time 10, UE receives an SDU of 5 bytes
+ */
+
+TIME, 1,
+    GNB_UM, 100000, 100000, 35, 6,
+    UE_UM, 100000, 100000, 35, 6,
+    GNB_SDU, 0, 10,
+    UE_BUFFER_STATUS,
+TIME, 10,
+    UE_SDU, 0, 5,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test3.txt.gz b/openair2/LAYER2/nr_rlc/tests/test3.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..070981d99126bc7e90585422defb1befa6f315bf
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test3.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test4.h b/openair2/LAYER2/nr_rlc/tests/test4.h
new file mode 100644
index 0000000000000000000000000000000000000000..1c9bcbc0b9823514177642acc82b78d9cdc4c200
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test4.h
@@ -0,0 +1,14 @@
+/*
+ * basic um test (SN field size 12):
+ * at time 1, gNB receives an SDU of 10 bytes
+ * at time 10, UE receives an SDU of 5 bytes
+ */
+
+TIME, 1,
+    GNB_UM, 100000, 100000, 35, 6,
+    UE_UM, 100000, 100000, 35, 6,
+    GNB_SDU, 0, 10,
+    UE_BUFFER_STATUS,
+TIME, 10,
+    UE_SDU, 0, 5,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test4.txt.gz b/openair2/LAYER2/nr_rlc/tests/test4.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..f4230c8522fe334bb0a8d294b36d62e70c761f88
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test4.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test5.h b/openair2/LAYER2/nr_rlc/tests/test5.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea090adcb53b19e3a7c2339a3318cc15047fc87b
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test5.h
@@ -0,0 +1,15 @@
+/*
+ * basic am test (SN field size 11, not exiting, test must fail):
+ * at time 1, gNB receives an SDU of 10 bytes
+ * at time 10, UE receives an SDU of 5 bytes
+ */
+
+TIME, 1,
+    MUST_FAIL,
+    GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 11,
+    UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 11,
+    GNB_SDU, 0, 10,
+    UE_BUFFER_STATUS,
+TIME, 10,
+    UE_SDU, 0, 5,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test5.txt.gz b/openair2/LAYER2/nr_rlc/tests/test5.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..812365c1e36f0b492cb94e3e45c4fe74f6d5888d
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test5.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test6.h b/openair2/LAYER2/nr_rlc/tests/test6.h
new file mode 100644
index 0000000000000000000000000000000000000000..86d7724dd2f733d320ef248852f8cfa6b3e41bfc
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test6.h
@@ -0,0 +1,15 @@
+/*
+ * basic um test (SN field size 19, bad size, test must fail):
+ * at time 1, gNB receives an SDU of 10 bytes
+ * at time 10, UE receives an SDU of 5 bytes
+ */
+
+TIME, 1,
+    MUST_FAIL,
+    GNB_UM, 100000, 100000, 35, 19,
+    UE_UM, 100000, 100000, 35, 19,
+    GNB_SDU, 0, 10,
+    UE_BUFFER_STATUS,
+TIME, 10,
+    UE_SDU, 0, 5,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test6.txt.gz b/openair2/LAYER2/nr_rlc/tests/test6.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..1d8575cef043478db1d98f22b0e1aa37dc578bdb
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test6.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test7.h b/openair2/LAYER2/nr_rlc/tests/test7.h
new file mode 100644
index 0000000000000000000000000000000000000000..4a380261f44365ba23588d70e51f9b98e713bc7a
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test7.h
@@ -0,0 +1,14 @@
+/*
+ * basic tm test:
+ * at time 1, gNB receives an SDU of 10 bytes
+ * at time 10, UE receives an SDU of 5 bytes
+ */
+
+TIME, 1,
+    GNB_TM, 100000,
+    UE_TM, 100000,
+    GNB_SDU, 0, 10,
+    UE_BUFFER_STATUS,
+TIME, 10,
+    UE_SDU, 0, 5,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test7.txt.gz b/openair2/LAYER2/nr_rlc/tests/test7.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..8689670886558883003d140847b37b2f6c723049
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test7.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test8.h b/openair2/LAYER2/nr_rlc/tests/test8.h
new file mode 100644
index 0000000000000000000000000000000000000000..c205f7ab57755d025108d1e432b04930226ab6b6
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test8.h
@@ -0,0 +1,20 @@
+/*
+ * am test (SN field size 12):
+ * test reassembly
+ * at time 1, gNB receives an SDU of 50 bytes
+ * sends 1st part, received by UE
+ * then sends 2nd part, not received
+ * then sends 3rd part, received
+ * then UE receives all
+ */
+
+TIME, 1,
+    GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 12,
+    UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 12,
+    GNB_PDU_SIZE, 22,
+    GNB_SDU, 0, 50,
+TIME, 2,
+    UE_RECV_FAILS, 1,
+TIME, 3,
+    UE_RECV_FAILS, 0,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test8.txt.gz b/openair2/LAYER2/nr_rlc/tests/test8.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..d69e43acdce5dd621905f0c2d731d189b0807e70
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test8.txt.gz differ
diff --git a/openair2/LAYER2/nr_rlc/tests/test9.h b/openair2/LAYER2/nr_rlc/tests/test9.h
new file mode 100644
index 0000000000000000000000000000000000000000..c3fb0e31d11b7dbe823d8bb5bd84abd23398622b
--- /dev/null
+++ b/openair2/LAYER2/nr_rlc/tests/test9.h
@@ -0,0 +1,20 @@
+/*
+ * am test (SN field size 18):
+ * test reassembly
+ * at time 1, gNB receives an SDU of 50 bytes
+ * sends 1st part, received by UE
+ * then sends 2nd part, not received
+ * then sends 3rd part, received
+ * then UE receives all
+ */
+
+TIME, 1,
+    GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18,
+    UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18,
+    GNB_PDU_SIZE, 22,
+    GNB_SDU, 0, 50,
+TIME, 2,
+    UE_RECV_FAILS, 1,
+TIME, 3,
+    UE_RECV_FAILS, 0,
+TIME, -1
diff --git a/openair2/LAYER2/nr_rlc/tests/test9.txt.gz b/openair2/LAYER2/nr_rlc/tests/test9.txt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..6def9c20f8dab3b8faa9284fc8cc24dc4201db2e
Binary files /dev/null and b/openair2/LAYER2/nr_rlc/tests/test9.txt.gz differ
diff --git a/openair2/NETWORK_DRIVER/MESH/common.c b/openair2/NETWORK_DRIVER/MESH/common.c
index 493236cb30ab790de117d89519633ce052abaa4d..c5b46440dcf2f24e442a45ef4c4cd767db98d6db 100644
--- a/openair2/NETWORK_DRIVER/MESH/common.c
+++ b/openair2/NETWORK_DRIVER/MESH/common.c
@@ -407,7 +407,7 @@ void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct class
 
   if (bytes_wrote != NAS_PDCPH_SIZE) {
     printk("NAS_COMMON_QOS_SEND: problem while writing PDCP's header (bytes wrote = %d )\n",bytes_wrote);
-    printk("rb_id %d, Wrote %d, Header Size %lu\n", pdcph.rb_id , bytes_wrote, NAS_PDCPH_SIZE);
+    printk("rb_id %ld, Wrote %d, Header Size %lu\n", pdcph.rb_id , bytes_wrote, NAS_PDCPH_SIZE);
 #ifndef PDCP_USE_NETLINK
     rtf_reset(NAS2PDCP_FIFO);
 #endif //PDCP_USE_NETLINK
@@ -421,7 +421,7 @@ void nas_COMMON_QOS_send(struct sk_buff *skb, struct cx_entity *cx, struct class
 #endif //PDCP_USE_NETLINK
 
   if (bytes_wrote != skb->len+NAS_PDCPH_SIZE) {
-    printk("NAS_COMMON_QOS_SEND: Inst %d, RB_ID %d: problem while writing PDCP's data, bytes_wrote = %d, Data_len %d, PDCPH_SIZE %lu\n",
+    printk("NAS_COMMON_QOS_SEND: Inst %d, RB_ID %ld: problem while writing PDCP's data, bytes_wrote = %d, Data_len %d, PDCPH_SIZE %lu\n",
            inst,
            pdcph.rb_id,
            bytes_wrote,
diff --git a/openair2/RRC/LTE/L2_interface.c b/openair2/RRC/LTE/L2_interface.c
index ac855a46e643ae49df4ed9842eb698882f0f5f9e..54dba6862883011e13e702d380e56bc01c202477 100644
--- a/openair2/RRC/LTE/L2_interface.c
+++ b/openair2/RRC/LTE/L2_interface.c
@@ -68,7 +68,7 @@ mac_rrc_data_req(
   uint8_t sfn                     = (uint8_t)((frameP>>2)&0xff);
 
   if (LOG_DEBUGFLAG(DEBUG_RRC)) {
-    LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%d\n",Mod_idP,Srb_id);
+    LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%ld\n",Mod_idP,Srb_id);
   }
 
   eNB_RRC_INST *rrc;
@@ -167,7 +167,7 @@ mac_rrc_data_req(
     if (ue_context_p == NULL) return(0);
 
     eNB_RRC_UE_t *ue_p = &ue_context_p->ue_context;
-    LOG_T(RRC,"[eNB %d] Frame %d CCCH request (Srb_id %d, rnti %x)\n",Mod_idP,frameP, Srb_id,rnti);
+    LOG_T(RRC,"[eNB %d] Frame %d CCCH request (Srb_id %ld, rnti %x)\n",Mod_idP,frameP, Srb_id,rnti);
     Srb_info=&ue_p->Srb0;
 
     // check if data is there for MAC
@@ -182,7 +182,7 @@ mac_rrc_data_req(
   }
 
   if( (Srb_id & RAB_OFFSET ) == PCCH) {
-    LOG_T(RRC,"[eNB %d] Frame %d PCCH request (Srb_id %d)\n",Mod_idP,frameP, Srb_id);
+    LOG_T(RRC,"[eNB %d] Frame %d PCCH request (Srb_id %ld)\n",Mod_idP,frameP, Srb_id);
 
     // check if data is there for MAC
     if(RC.rrc[Mod_idP]->carrier[CC_id].sizeof_paging[mbsfn_sync_area] > 0) { //Fill buffer
@@ -254,7 +254,7 @@ mac_rrc_data_ind(
 //--------------------------------------------------------------------------
 {
   if (NODE_IS_DU(RC.rrc[module_idP]->node_type)) {
-    LOG_W(RRC,"[DU %d][RAPROC] Received SDU for CCCH on SRB %d length %d for UE id %d RNTI %x \n",
+    LOG_W(RRC,"[DU %d][RAPROC] Received SDU for CCCH on SRB %ld length %d for UE id %d RNTI %x \n",
           module_idP, srb_idP, sdu_lenP, UE_id, rntiP);
     /* do ITTI message */
     DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(
@@ -279,7 +279,7 @@ mac_rrc_data_ind(
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, rntiP, frameP, sub_frameP,0);
 
   if((srb_idP & RAB_OFFSET) == CCCH) {
-    LOG_D(RRC, "[eNB %d] Received SDU for CCCH on SRB %d\n", module_idP, srb_idP);
+    LOG_D(RRC, "[eNB %d] Received SDU for CCCH on SRB %ld\n", module_idP, srb_idP);
     ctxt.brOption = brOption;
 
     /*Srb_info = &RC.rrc[module_idP]->carrier[CC_id].Srb0;
diff --git a/openair2/RRC/LTE/L2_interface_common.c b/openair2/RRC/LTE/L2_interface_common.c
index b5cc99bc3a78fa1fba0dfbb1d40ab9d15545f66c..20df462938f960f3f436d28c51bd97c8708c9e45 100644
--- a/openair2/RRC/LTE/L2_interface_common.c
+++ b/openair2/RRC/LTE/L2_interface_common.c
@@ -123,10 +123,10 @@ rrc_data_ind(
   rb_id_t    DCCH_index = Srb_id;
 
   if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
-    LOG_I(RRC, "[UE %x] Frame %d: received a DCCH %d message on SRB %d with Size %d from eNB %d\n",
+    LOG_I(RRC, "[UE %x] Frame %d: received a DCCH %ld message on SRB %ld with Size %d from eNB %d\n",
           ctxt_pP->module_id, ctxt_pP->frame, DCCH_index,Srb_id,sdu_sizeP,  ctxt_pP->eNB_index);
   } else {
-    LOG_D(RRC, "[eNB %d] Frame %d: received a DCCH %d message on SRB %d with Size %d from UE %x\n",
+    LOG_D(RRC, "[eNB %d] Frame %d: received a DCCH %ld message on SRB %ld with Size %d from UE %x\n",
           ctxt_pP->module_id,
           ctxt_pP->frame,
           DCCH_index,
diff --git a/openair2/RRC/LTE/L2_interface_ue.c b/openair2/RRC/LTE/L2_interface_ue.c
index a8a0086a4d832b795f9a5e3c2ddf9f19ea9d28d3..c9d4e61d0ae7a19ff251dd8903c67cf3fb1d9e69 100644
--- a/openair2/RRC/LTE/L2_interface_ue.c
+++ b/openair2/RRC/LTE/L2_interface_ue.c
@@ -59,8 +59,8 @@ mac_rrc_data_req_ue(
 )
 //--------------------------------------------------------------------------
 {
-  LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%d\n",Mod_idP,Srb_id);
-  LOG_D(RRC,"[UE %d] Frame %d Filling SL DISCOVERY SRB_ID %d\n",Mod_idP,frameP,Srb_id);
+  LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%ld\n",Mod_idP,Srb_id);
+  LOG_D(RRC,"[UE %d] Frame %d Filling SL DISCOVERY SRB_ID %ld\n",Mod_idP,frameP,Srb_id);
   LOG_D(RRC,"[UE %d] Frame %d buffer_pP status %d,\n",Mod_idP,frameP, UE_rrc_inst[Mod_idP].SL_Discovery[eNB_index].Tx_buffer.payload_size);
 
   //TTN (for D2D)
@@ -72,7 +72,7 @@ mac_rrc_data_req_ue(
     return(Ret_size);
   }
 
-  LOG_D(RRC,"[UE %d] Frame %d Filling CCCH SRB_ID %d\n",Mod_idP,frameP,Srb_id);
+  LOG_D(RRC,"[UE %d] Frame %d Filling CCCH SRB_ID %ld\n",Mod_idP,frameP,Srb_id);
   LOG_D(RRC,"[UE %d] Frame %d buffer_pP status %d,\n",Mod_idP,frameP, UE_rrc_inst[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size);
 
   if( (UE_rrc_inst[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size > 0) ) {
@@ -137,7 +137,7 @@ mac_rrc_data_ind_ue(
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, 0, rntiP, frameP, sub_frameP,eNB_indexP);
 
   if(srb_idP == BCCH_SI_MBMS) {
-    LOG_D(RRC,"[UE %d] Received SDU for BCCH on MBMS SRB %d from eNB %d\n",module_idP,srb_idP,eNB_indexP);
+    LOG_D(RRC,"[UE %d] Received SDU for BCCH on MBMS SRB %ld from eNB %d\n",module_idP,srb_idP,eNB_indexP);
 #if defined(ENABLE_ITTI)
     {
       MessageDef *message_p;
@@ -167,7 +167,7 @@ mac_rrc_data_ind_ue(
   }
 
   if(srb_idP == BCCH) {
-    LOG_D(RRC,"[UE %d] Received SDU for BCCH on SRB %d from eNB %d\n",module_idP,srb_idP,eNB_indexP);
+    LOG_D(RRC,"[UE %d] Received SDU for BCCH on SRB %ld from eNB %d\n",module_idP,srb_idP,eNB_indexP);
 #if defined(ENABLE_ITTI)
     {
       MessageDef *message_p;
@@ -197,13 +197,13 @@ mac_rrc_data_ind_ue(
   }
 
   if(srb_idP == PCCH) {
-    LOG_D(RRC,"[UE %d] Received SDU for PCCH on SRB %d from eNB %d\n",module_idP,srb_idP,eNB_indexP);
+    LOG_D(RRC,"[UE %d] Received SDU for PCCH on SRB %ld from eNB %d\n",module_idP,srb_idP,eNB_indexP);
     decode_PCCH_DLSCH_Message(&ctxt,eNB_indexP,(uint8_t *)sduP,sdu_lenP);
   }
 
   if((srb_idP & RAB_OFFSET) == CCCH) {
     if (sdu_lenP>0) {
-      LOG_T(RRC,"[UE %d] Received SDU for CCCH on SRB %d from eNB %d\n",module_idP,srb_idP & RAB_OFFSET,eNB_indexP);
+      LOG_T(RRC,"[UE %d] Received SDU for CCCH on SRB %ld from eNB %d\n",module_idP,srb_idP & RAB_OFFSET,eNB_indexP);
 #if defined(ENABLE_ITTI)
       {
         MessageDef *message_p;
@@ -237,7 +237,7 @@ mac_rrc_data_ind_ue(
   }
 
   if ((srb_idP & RAB_OFFSET) == MCCH) {
-    LOG_T(RRC,"[UE %d] Frame %d: Received SDU on MBSFN sync area %d for MCCH on SRB %d from eNB %d\n",
+    LOG_T(RRC,"[UE %d] Frame %d: Received SDU on MBSFN sync area %d for MCCH on SRB %ld from eNB %d\n",
           module_idP,frameP, mbsfn_sync_areaP, srb_idP & RAB_OFFSET,eNB_indexP);
 #if defined(ENABLE_ITTI)
     {
@@ -266,7 +266,7 @@ mac_rrc_data_ind_ue(
 
   //TTN (for D2D)
   if(srb_idP == SL_DISCOVERY) {
-    LOG_I(RRC,"[UE %d] Received SDU (%d bytes) for SL_DISCOVERY on SRB %d from eNB %d\n",module_idP, sdu_lenP, srb_idP,eNB_indexP);
+    LOG_I(RRC,"[UE %d] Received SDU (%d bytes) for SL_DISCOVERY on SRB %ld from eNB %d\n",module_idP, sdu_lenP, srb_idP,eNB_indexP);
     decode_SL_Discovery_Message(&ctxt, eNB_indexP, sduP, sdu_lenP);
   }
 
@@ -350,7 +350,7 @@ rrc_data_ind_ue(
 //------------------------------------------------------------------------------
 {
   rb_id_t    DCCH_index = Srb_id;
-  LOG_I(RRC, "[UE %x] Frame %d: received a DCCH %d message on SRB %d with Size %d from eNB %d\n",
+  LOG_I(RRC, "[UE %x] Frame %d: received a DCCH %ld message on SRB %ld with Size %d from eNB %d\n",
         ctxt_pP->module_id, ctxt_pP->frame, DCCH_index,Srb_id,sdu_sizeP,  ctxt_pP->eNB_index);
 #if defined(ENABLE_ITTI)
   {
diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c
index 17cef8112e79b34605954c5c80d4fd3cb9b074d8..66c4401e57c66238b25bd2214f4c2899312c9e4f 100644
--- a/openair2/RRC/LTE/rrc_UE.c
+++ b/openair2/RRC/LTE/rrc_UE.c
@@ -1307,7 +1307,7 @@ rrc_ue_process_radioResourceConfigDedicated(
       // 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);
+      LOG_I(RRC,"[UE %d] default DRB = %ld\n",ctxt_pP->module_id, *UE_rrc_inst[ctxt_pP->module_id].defaultDRB);
     }
 
     uint8_t *kUPenc = NULL;
@@ -1889,7 +1889,7 @@ rrc_ue_decode_dcch(
   MessageDef *msg_p;
 
   if (Srb_id != 1) {
-    LOG_E(RRC,"[UE %d] Frame %d: Received message on DL-DCCH (SRB%d), should not have ...\n",
+    LOG_E(RRC,"[UE %d] Frame %d: Received message on DL-DCCH (SRB%ld), should not have ...\n",
           ctxt_pP->module_id, ctxt_pP->frame, Srb_id);
     return;
   }
diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c
index 3751f2ddfb3a3d0ec3fd4c866c010d454e50f162..dbeaa9f6a548c2d329e5fbd4a9ece1c9f90c61c8 100644
--- a/openair2/RRC/LTE/rrc_eNB.c
+++ b/openair2/RRC/LTE/rrc_eNB.c
@@ -4774,7 +4774,7 @@ check_handovers(
                 GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).frame,
                 0,
                 GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).eNB_index);
-              LOG_D(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
+              LOG_D(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %d, rb_id %ld, muiP %d, confirmP %d, mode %d\n",
                     PROTOCOL_CTXT_ARGS(&ctxt),
                     ITTI_MSG_NAME (msg_p),
                     ITTI_MSG_ORIGIN_NAME(msg_p),
@@ -4783,7 +4783,7 @@ check_handovers(
                     GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).muip,
                     GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).confirmp,
                     GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).mode);
-              LOG_I(RRC, "Before calling pdcp_data_req from check_handovers! GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id: %d \n", GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id);
+              LOG_I(RRC, "Before calling pdcp_data_req from check_handovers! GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id: %ld \n", GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id);
               result = pdcp_data_req (&ctxt,
                                       SRB_FLAG_NO,
                                       GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id,
@@ -4842,7 +4842,7 @@ check_handovers(
                 GTPV1U_ENB_END_MARKER_IND (msg_p).frame,
                 0,
                 GTPV1U_ENB_END_MARKER_IND (msg_p).eNB_index);
-              LOG_I(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
+              LOG_I(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %d, rb_id %ld, muiP %d, confirmP %d, mode %d\n",
                     PROTOCOL_CTXT_ARGS(&ctxt),
                     ITTI_MSG_NAME (msg_p),
                     ITTI_MSG_ORIGIN_NAME(msg_p),
@@ -4851,7 +4851,7 @@ check_handovers(
                     GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).muip,
                     GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).confirmp,
                     GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).mode);
-              LOG_D(RRC, "Before calling pdcp_data_req from check_handovers! GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id: %d \n", GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id);
+              LOG_D(RRC, "Before calling pdcp_data_req from check_handovers! GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id: %ld \n", GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id);
               result = pdcp_data_req (&ctxt,
                                       SRB_FLAG_NO,
                                       GTPV1U_ENB_END_MARKER_IND (msg_p).rb_id,
@@ -7144,11 +7144,11 @@ rrc_eNB_decode_dcch(
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
 
   if ((Srb_id != 1) && (Srb_id != 2)) {
-    LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received message on SRB%d, should not have ...\n",
+    LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received message on SRB%ld, should not have ...\n",
           PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
           Srb_id);
   } else {
-    LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received message on SRB%d\n",
+    LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received message on SRB%ld\n",
           PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
           Srb_id);
   }
diff --git a/openair2/RRC/LTE/rrc_eNB_GTPV1U.c b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c
index d873a825ba9ee2661c5c88ec4dab6c876a4955cf..749dff3acedf0832f1a737e5382ad66dcdba601a 100644
--- a/openair2/RRC/LTE/rrc_eNB_GTPV1U.c
+++ b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c
@@ -112,7 +112,7 @@ gtpv_data_req(
     LOG_I(GTPU,"gtpv_data_req sdu_sizeP == 0");
     return FALSE;
   }
-  LOG_D(GTPU,"gtpv_data_req ue rnti %x sdu_sizeP %d rb id %d", ctxt_pP->rnti, sdu_sizeP, rb_idP);
+  LOG_D(GTPU,"gtpv_data_req ue rnti %x sdu_sizeP %d rb id %ld", ctxt_pP->rnti, sdu_sizeP, rb_idP);
 #if defined(ENABLE_ITTI)
   {
     MessageDef *message_p;
diff --git a/openair2/RRC/NR/L2_nr_interface.c b/openair2/RRC/NR/L2_nr_interface.c
index 00282c5dfa8f58531597a3c060448eba8a26398c..86cff69517f31df92d4fd9c65496cdf30c27f5f9 100644
--- a/openair2/RRC/NR/L2_nr_interface.c
+++ b/openair2/RRC/NR/L2_nr_interface.c
@@ -58,7 +58,7 @@ int8_t mac_rrc_nr_data_req(const module_id_t Mod_idP,
   uint8_t sfn_msb                     = (uint8_t)((frameP>>4)&0x3f);
   
 #ifdef DEBUG_RRC
-  LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%d\n",Mod_idP,Srb_id);
+  LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%ld\n",Mod_idP,Srb_id);
 #endif
 
   gNB_RRC_INST *rrc;
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c
index 78f0529512f0c2f59bc87b8fc1d5c114ede3a073..d9829a46dc48d03cf184c856004dfa85c95316f8 100644
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c
@@ -519,8 +519,6 @@ void do_SERVINGCELLCONFIGCOMMON(uint8_t Mod_id,
     bwp_dl_searchspace->monitoringSymbolsWithinSlot->buf                            = MALLOC(2);
     bwp_dl_searchspace->nrofCandidates                                              = CALLOC(1,sizeof(struct NR_SearchSpace__nrofCandidates));
     bwp_dl_searchspace->searchSpaceType                                             = CALLOC(1,sizeof(struct NR_SearchSpace__searchSpaceType));
-    bwp_dl_searchspace->searchSpaceType->choice.common                              = CALLOC(1,sizeof(struct NR_SearchSpace__searchSpaceType__common));
-    bwp_dl_searchspace->searchSpaceType->choice.ue_Specific                         = CALLOC(1,sizeof(struct NR_SearchSpace__searchSpaceType__ue_Specific));
     bwp_dl_timedomainresourceallocation->k0 = CALLOC(1,sizeof(long));
     pusch_configcommontimedomainresourceallocation      = CALLOC(1,sizeof(NR_PUSCH_TimeDomainResourceAllocation_t));
     pusch_configcommontimedomainresourceallocation->k2  = CALLOC(1,sizeof(long));
@@ -647,6 +645,7 @@ void do_SERVINGCELLCONFIGCOMMON(uint8_t Mod_id,
   bwp_dl_searchspace->searchSpaceType->present = configuration->SearchSpace_searchSpaceType[CC_id];
 
   if(bwp_dl_searchspace->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common) {
+    bwp_dl_searchspace->searchSpaceType->choice.common                              = CALLOC(1,sizeof(struct NR_SearchSpace__searchSpaceType__common));
     bwp_dl_searchspace->searchSpaceType->choice.common->dci_Format2_0                                           = CALLOC(1,sizeof(struct NR_SearchSpace__searchSpaceType__common__dci_Format2_0));
     bwp_dl_searchspace->searchSpaceType->choice.common->dci_Format2_0->nrofCandidates_SFI.aggregationLevel1     = CALLOC(1,sizeof(long));
     bwp_dl_searchspace->searchSpaceType->choice.common->dci_Format2_0->nrofCandidates_SFI.aggregationLevel2     = CALLOC(1,sizeof(long));
@@ -663,6 +662,7 @@ void do_SERVINGCELLCONFIGCOMMON(uint8_t Mod_id,
     *(bwp_dl_searchspace->searchSpaceType->choice.common->dci_Format2_3->dummy1)                                = configuration->Common_dci_Format2_3_monitoringPeriodicity[CC_id];
     bwp_dl_searchspace->searchSpaceType->choice.common->dci_Format2_3->dummy2                                   = configuration->Common_dci_Format2_3_nrofPDCCH_Candidates[CC_id];
   } else if (bwp_dl_searchspace->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
+    bwp_dl_searchspace->searchSpaceType->choice.ue_Specific                         = CALLOC(1,sizeof(struct NR_SearchSpace__searchSpaceType__ue_Specific));
     bwp_dl_searchspace->searchSpaceType->choice.ue_Specific->dci_Formats = configuration->ue_Specific__dci_Formats[CC_id];
   }
 
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h
index 10935ddf89f200ce6c7cec42e333f4bb1baac12d..c3154b708eda2581fff0093af7f7c13a70a52e7a 100644
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.h
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h
@@ -74,7 +74,7 @@ uint8_t do_MIB_NR(rrc_gNB_carrier_data_t *carrier,
 /**
 \brief Generate configuration for SIB1 (gNB).
 @param carrier pointer to Carrier information
-@param configuration Pointer Configuration Request structure
+@param configuration Pointer Configuration Request structure  
 @return size of encoded bit stream in bytes*/
 uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier
 #if defined(ENABLE_ITTI)
diff --git a/openair2/UTIL/FIFO/pad_list.c b/openair2/UTIL/FIFO/pad_list.c
index e15041118d0f182492d34f596c829c988c0dd371..124893a756c5c9533378f34af8e56a64235209d4 100644
--- a/openair2/UTIL/FIFO/pad_list.c
+++ b/openair2/UTIL/FIFO/pad_list.c
@@ -591,7 +591,7 @@ void pkt_list_display (Packet_OTG_List_t *listP) {
 
     if (cursor) {
       while (cursor != NULL) {
-        printf ("Pkt (DST %d, RB %d)\n", (cursor->otg_pkt).dst_id, (cursor->otg_pkt).rb_id);
+        printf ("Pkt (DST %d, RB %ld)\n", (cursor->otg_pkt).dst_id, (cursor->otg_pkt).rb_id);
         //msg ("From (%d,%d) To (%d,%d)\n", (cursor->job).node1, (cursor->job).master1, (cursor->job).node2, (cursor->job).master2);
         cursor = cursor->next;
         nb_elements++;
diff --git a/openair2/UTIL/MEM/mem_block.h b/openair2/UTIL/MEM/mem_block.h
index 4d8ed4e89bc9e881ca0a6a346a3f2d97f36e0b61..f40566f6ed2d8051e5cfb8bae9220f1f531e2bec 100644
--- a/openair2/UTIL/MEM/mem_block.h
+++ b/openair2/UTIL/MEM/mem_block.h
@@ -180,8 +180,6 @@ typedef struct {
 
 } mem_pool;
 
-mem_pool  *memBlockVar;
-#define mem_block_var (*memBlockVar)
 
 #ifdef __cplusplus
 }
diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c
index 54c4153e46d753e1d1c27c95f7faa5dd5752e38a..f15f295548e9e4a474479f12501df1a99ad3ef75 100644
--- a/openair3/GTPV1-U/gtpv1u_eNB.c
+++ b/openair3/GTPV1-U/gtpv1u_eNB.c
@@ -831,7 +831,7 @@ int gtpv1u_delete_x2u_tunnel(
       if (hash_rc == HASH_TABLE_OK) {
         for (erab_index = 0; erab_index < ue_context_p->ue_context.nb_x2u_e_rabs; erab_index++) {
           eps_bearer_id = ue_context_p->ue_context.enb_gtp_x2u_ebi[erab_index];
-          LOG_I(GTPU, "gtpv1u_delete_x2u_tunnel user rnti %x teNB X2U teid %u eps bearer id %u\n",
+          LOG_I(GTPU, "gtpv1u_delete_x2u_tunnel user rnti %x teNB X2U teid %u eps bearer id %ld\n",
                 req_pP->rnti,
                 gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_teNB,
                 ue_context_p->ue_context.enb_gtp_x2u_ebi[erab_index]);
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index 10e591294b727eedac9e57b1e823e19a86cc8d3c..8cfa398615b3e27323d6cee4ae6ec87f64cf79f9 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -455,14 +455,14 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
 #if defined(__x86_64) || defined(__i386__)
   #ifdef __AVX2__
       nsamps2 = (nsamps+7)>>3;
-      __m256i buff_tx[2][nsamps2];
+      __m256i buff_tx[8][nsamps2];
   #else
     nsamps2 = (nsamps+3)>>2;
-    __m128i buff_tx[2][nsamps2];
+    __m128i buff_tx[8][nsamps2];
   #endif
 #elif defined(__arm__)
     nsamps2 = (nsamps+3)>>2;
-    int16x8_t buff_tx[2][nsamps2];
+    int16x8_t buff_tx[8][nsamps2];
 #else
     #error Unsupported CPU architecture, USRP device cannot be built
 #endif
@@ -566,14 +566,14 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
 #if defined(__x86_64) || defined(__i386__)
 #ifdef __AVX2__
     nsamps2 = (nsamps+7)>>3;
-    __m256i buff_tmp[2][nsamps2];
+    __m256i buff_tmp[8][nsamps2];
 #else
     nsamps2 = (nsamps+3)>>2;
-    __m128i buff_tmp[2][nsamps2];
+    __m128i buff_tmp[8][nsamps2];
 #endif
 #elif defined(__arm__)
     nsamps2 = (nsamps+3)>>2;
-    int16x8_t buff_tmp[2][nsamps2];
+    int16x8_t buff_tmp[8][nsamps2];
 #endif
 
     if (device->type == USRP_B200_DEV) {
diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c
index 76d0ad667478d89899063a7f9676156d9af7981d..cfaa7b8f5353f0adad589e875e3b44fced9c9d5b 100644
--- a/targets/ARCH/rfsimulator/simulator.c
+++ b/targets/ARCH/rfsimulator/simulator.c
@@ -276,7 +276,7 @@ sin_addr:
   };
   bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr));
   AssertFatal(listen(t->listen_sock, 5) == 0, "");
-  struct epoll_event ev;
+  struct epoll_event ev={0};
   ev.events = EPOLLIN;
   ev.data.fd = t->listen_sock;
   AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD,  t->listen_sock, &ev) != -1, "");
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
index 2a2ebd45fda3da67c1ea99d875f7d44b907aa38a..b98adf5a95eebd1b02476d7bebac3f977c7991e0 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -246,15 +246,16 @@ L1s = (
 RUs = (
     {		  
        local_rf       = "yes"
-         nb_tx          = 1
-         nb_rx          = 1
-         att_tx         = 0
+         nb_tx          = 1; 
+         nb_rx          = 1; 
+         att_tx         = 0; 
          att_rx         = 0;
          bands          = [7];
          max_pdschReferenceSignalPower = -27;
          max_rxgain                    = 114;
          eNB_instances  = [0];
-	 sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,mgmt_addr=192.168.10.2,clock_source=external,time_source=external";
+
+	 sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,clock_source=external,time_source=external";
 
     }
 );  
@@ -284,9 +285,9 @@ NETWORK_CONTROLLER :
        global_log_verbosity                  ="medium";
        hw_log_level                          ="info";
        hw_log_verbosity                      ="medium";
-       phy_log_level                         ="debug";
+       phy_log_level                         ="info";
        phy_log_verbosity                     ="medium";
-       mac_log_level                         ="debug";
+       mac_log_level                         ="info";
        mac_log_verbosity                     ="high";
        rlc_log_level                         ="info";
        rlc_log_verbosity                     ="medium";
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
index a11bf9d515bfa11106f25ce5a2b2d3ae9652482e..420188b80e8d4d280263e0b52b7d54bd4b76813a 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
@@ -70,7 +70,7 @@ gNBs =
       UL_BWP_prefix_type                                            = "NORMAL";
       UL_timeAlignmentTimerCommon                                   = "infinity";
       ServingCellConfigCommon_n_TimingAdvanceOffset                 = "n0"
-      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x01;
+      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x01;#####
       ServingCellConfigCommon_ssb_periodicityServingCell            = 10;
       ServingCellConfigCommon_dmrs_TypeA_Position                   = 2;
       NIA_SubcarrierSpacing                                         = "kHz15"; 
@@ -246,7 +246,7 @@ L1s = (
 RUs = (
     {		  
        local_rf       = "yes"
-         nb_tx          = 1
+         nb_tx          = 1 
          nb_rx          = 1
          att_tx         = 0
          att_rx         = 0;
@@ -264,7 +264,7 @@ THREAD_STRUCT = (
     #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
     parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
     #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
-    worker_config      = "WORKER_DISABLE";
+    worker_config      = "WORKER_ENABLE";
   }
 );
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf
index 73f2214baf684154dccf9d075de50d0165934f62..691224b8835a9c3da20dd71b8643477a90c95267 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf
@@ -70,7 +70,7 @@ gNBs =
       UL_BWP_prefix_type                                            = "NORMAL";
       UL_timeAlignmentTimerCommon                                   = "infinity";
       ServingCellConfigCommon_n_TimingAdvanceOffset                 = "n0"
-      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x01;
+      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x0ff;
       ServingCellConfigCommon_ssb_periodicityServingCell            = 10;
       ServingCellConfigCommon_dmrs_TypeA_Position                   = 2;
       NIA_SubcarrierSpacing                                         = "kHz15"; 
@@ -246,7 +246,7 @@ L1s = (
 RUs = (
     {		  
        local_rf       = "yes"
-         nb_tx          = 1
+         nb_tx          = 8
          nb_rx          = 1
          att_tx         = 0
          att_rx         = 0;
@@ -264,7 +264,7 @@ THREAD_STRUCT = (
     #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
     parallel_config    = "PARALLEL_SINGLE_THREAD";
     #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
-    worker_config      = "WORKER_DISABLE";
+    worker_config      = "WORKER_ENABLE";
   }
 );
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.beamw.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.beamw.usrpn300.conf
new file mode 100644
index 0000000000000000000000000000000000000000..a9d251efa2dc5d826ad34bd00d81d333ea3ce0b7
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.beamw.usrpn300.conf
@@ -0,0 +1,291 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});	 
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function                                                 = "3GPP_gNODEB";
+      node_timing                                                   = "synch_to_ext_device";
+      node_synch_ref                                                = 0;
+      frame_type                                                    = "TDD";
+      DL_prefix_type                                                = "NORMAL";
+      UL_prefix_type                                                = "NORMAL";
+      eutra_band                                                    = 78;
+      downlink_frequency                                            = 3510000000L;
+      uplink_frequency_offset                                       = -120000000;
+      Nid_cell                                                      = 0;
+      N_RB_DL                                                       = 217;
+      nb_antenna_ports                                              = 1;
+      nb_antennas_tx                                                = 1;
+      nb_antennas_rx                                                = 1;
+      tx_gain                                                       = 90;
+      rx_gain                                                       = 125;
+      MIB_subCarrierSpacingCommon                                   = 30;
+      MIB_ssb_SubcarrierOffset                                      = 0;
+      MIB_dmrs_TypeA_Position                                       = 2;
+      pdcch_ConfigSIB1                                              = 0;
+      SIB1_frequencyOffsetSSB                                       = "khz5";
+      SIB1_ssb_PeriodicityServingCell                               = 5;
+      SIB1_ss_PBCH_BlockPower                                       = -60;
+      absoluteFrequencySSB                                          = 0;
+      DL_FreqBandIndicatorNR                                        = 15;
+      DL_absoluteFrequencyPointA                                    = 15;
+      DL_offsetToCarrier                                            = 15;
+      DL_SCS_SubcarrierSpacing                                      = "kHz30";
+      DL_SCS_SpecificCarrier_k0                                     = 0;
+      DL_carrierBandwidth                                           = 15;
+      DL_locationAndBandwidth                                       = 15;
+      DL_BWP_SubcarrierSpacing                                      = "kHz30";
+      DL_BWP_prefix_type                                            = "NORMAL";
+      UL_FreqBandIndicatorNR                                        = 15;
+      UL_absoluteFrequencyPointA                                    = 13;
+      UL_additionalSpectrumEmission                                 = 3;
+      UL_p_Max                                                      = -1;
+      UL_frequencyShift7p5khz                                       = "TRUE";
+      UL_offsetToCarrier                                            = 10;
+      UL_SCS_SubcarrierSpacing                                      = "kHz30";
+      UL_SCS_SpecificCarrier_k0                                     = 0;
+      UL_carrierBandwidth                                           = 15;
+      UL_locationAndBandwidth                                       = 15;
+      UL_BWP_SubcarrierSpacing                                      = "kHz30";
+      UL_BWP_prefix_type                                            = "NORMAL";
+      UL_timeAlignmentTimerCommon                                   = "infinity";
+      ServingCellConfigCommon_n_TimingAdvanceOffset                 = "n0"
+      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x03;
+      ServingCellConfigCommon_ssb_periodicityServingCell            = 10;
+      ServingCellConfigCommon_dmrs_TypeA_Position                   = 2;
+      NIA_SubcarrierSpacing                                         = "kHz15"; 
+      ServingCellConfigCommon_ss_PBCH_BlockPower                    = -60;
+      referenceSubcarrierSpacing                                    = "kHz15";
+      dl_UL_TransmissionPeriodicity                                 = "ms0p5";
+      nrofDownlinkSlots                                             = 10;
+      nrofDownlinkSymbols                                           = 10;
+      nrofUplinkSlots                                               = 10;
+      nrofUplinkSymbols                                             = 10;
+      rach_totalNumberOfRA_Preambles                                = 63;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice         = "oneEighth";
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneEighth      = 4;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneFourth      = 8;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneHalf        = 16;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_one            = 24;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_two            = 32;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_four           = 8;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_eight          = 4;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_sixteen        = 2;
+      rach_groupBconfigured                                         = "ENABLE";
+      rach_ra_Msg3SizeGroupA                                        = 56;
+      rach_messagePowerOffsetGroupB                                 = "dB0";
+      rach_numberOfRA_PreamblesGroupA                               = 32;
+      rach_ra_ContentionResolutionTimer                             = 8;
+      rsrp_ThresholdSSB                                             = 64;
+      rsrp_ThresholdSSB_SUL                                         = 64;
+      prach_RootSequenceIndex_choice                                = "l839";
+      prach_RootSequenceIndex_l839                                  = 0;
+      prach_RootSequenceIndex_l139                                  = 0;
+      prach_msg1_SubcarrierSpacing                                  = "kHz30";
+      restrictedSetConfig                                           = "unrestrictedSet";
+      msg3_transformPrecoding                                       = "ENABLE";
+      prach_ConfigurationIndex                                      = 10;
+      prach_msg1_FDM                                                = "one";
+      prach_msg1_FrequencyStart                                     = 10;
+      zeroCorrelationZoneConfig                                     = 10;
+      preambleReceivedTargetPower                                   = -150;
+      preambleTransMax                                              = 6;
+      powerRampingStep                                              = "dB0";
+      ra_ResponseWindow                                             = 8;
+      groupHoppingEnabledTransformPrecoding                         = "ENABLE";
+      msg3_DeltaPreamble                                            = 0;
+      p0_NominalWithGrant                                           = 0;
+      PUSCH_TimeDomainResourceAllocation_k2                         = 0;
+      PUSCH_TimeDomainResourceAllocation_mappingType                = "typeA";
+      PUSCH_TimeDomainResourceAllocation_startSymbolAndLength       = 0;
+      pucch_ResourceCommon                                          = 0;
+      pucch_GroupHopping                                            = "neither";
+      hoppingId                                                     = 0;
+      p0_nominal                                                    = -30;
+      PDSCH_TimeDomainResourceAllocation_k0                         = 2;
+      PDSCH_TimeDomainResourceAllocation_mappingType                = "typeA";
+      PDSCH_TimeDomainResourceAllocation_startSymbolAndLength       = 0;
+      rateMatchPatternId                                            = 0;
+      RateMatchPattern_patternType                                  = "bitmaps";
+      symbolsInResourceBlock                                        = "oneSlot";
+      periodicityAndPattern                                         = 2;
+      RateMatchPattern_controlResourceSet                           = 5;
+      RateMatchPattern_subcarrierSpacing                            = "kHz30";
+      RateMatchPattern_mode                                         = "dynamic";
+      controlResourceSetZero                                        = 0;
+      searchSpaceZero                                               = 0;
+      searchSpaceSIB1                                               = 10;
+      searchSpaceOtherSystemInformation                             = 10;
+      pagingSearchSpace                                             = 10;
+      ra_SearchSpace                                                = 10;
+      PDCCH_common_controlResourceSetId                             = 5;
+      PDCCH_common_ControlResourceSet_duration                      = 2;
+      PDCCH_cce_REG_MappingType                                     = "nonInterleaved";
+      PDCCH_reg_BundleSize                                          = 3;
+      PDCCH_interleaverSize                                         = 3;
+      PDCCH_shiftIndex                                              = 10;  
+      PDCCH_precoderGranularity                                     = "sameAsREG-bundle";
+      PDCCH_TCI_StateId                                             = 32;
+      tci_PresentInDCI                                              = "ENABLE";
+      PDCCH_DMRS_ScramblingID                                       = 0;
+      SearchSpaceId                                                 = 10;
+      commonSearchSpaces_controlResourceSetId                       = 5;
+      SearchSpace_monitoringSlotPeriodicityAndOffset_choice         = "sl1";
+      SearchSpace_monitoringSlotPeriodicityAndOffset_value          = 0;
+      SearchSpace_duration                                          = 2;
+      SearchSpace_nrofCandidates_aggregationLevel1                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel2                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel4                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel8                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel16                 = 0;
+      SearchSpace_searchSpaceType                                   = "common";
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel1     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel2     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel4     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel8     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel16    = 1; 
+      Common_dci_Format2_3_monitoringPeriodicity                    = 1;
+      Common_dci_Format2_3_nrofPDCCH_Candidates                     = 1;
+      ue_Specific__dci_Formats                                      = "formats0-0-And-1-0";
+      RateMatchPatternLTE_CRS_carrierFreqDL                         = 6;
+      RateMatchPatternLTE_CRS_carrierBandwidthDL                    = 6;
+      RateMatchPatternLTE_CRS_nrofCRS_Ports                         = 1;
+      RateMatchPatternLTE_CRS_v_Shift                               = 0;
+      RateMatchPatternLTE_CRS_radioframeAllocationPeriod            = 1;
+      RateMatchPatternLTE_CRS_radioframeAllocationOffset            = 0;
+      RateMatchPatternLTE_CRS_subframeAllocation_choice             = "oneFrame";
+      }
+    );
+
+
+    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.26";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
+        GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        }  
+);
+
+RUs = (
+    {		  
+       local_rf       = "yes"
+         nb_tx          = 2
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 114;
+         eNB_instances  = [0];
+	 sdr_addrs = "addr=192.168.10.2";
+         # beamforming weights for static beams each of them is a int32 composed by two int16 representing imaginary and real part of the weight
+         # weights are input in an array, starting with the weights associated to first logical beam for all nb_tx , than the weights for 2nd logical beam and so on
+         # the list size is (nb_tx) X (number of logical beams) 
+   	 bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+     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/RT/USER/gNB_usrp.gtkw b/targets/RT/USER/gNB_usrp.gtkw
index 069d1765a95358b9f4875addcac6bb9277a712e4..416dd3b62ba48806e7df7fdf43f1dd6d265ae09d 100644
--- a/targets/RT/USER/gNB_usrp.gtkw
+++ b/targets/RT/USER/gNB_usrp.gtkw
@@ -1,19 +1,19 @@
 [*]
-[*] GTKWave Analyzer v3.3.61 (w)1999-2014 BSI
-[*] Sat May 18 17:25:11 2019
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Fri Sep  6 15:01:30 2019
 [*]
-[dumpfile] "/tmp/openair_dump_gNB40.vcd"
-[dumpfile_mtime] "Sat May 18 17:11:31 2019"
-[dumpfile_size] 53148516
-[savefile] "/home/caracal/raymond/openairinterface5g/targets/RT/USER/gNB_usrp.gtkw"
-[timestart] 11552775390
-[size] 1840 795
+[dumpfile] "/tmp/gNB_prec.vcd"
+[dumpfile_mtime] "Fri Sep  6 14:59:50 2019"
+[dumpfile_size] 13106022
+[savefile] "/homes/wangts/openairinterface5g/targets/RT/USER/gNB_usrp.gtkw"
+[timestart] 2183320000
+[size] 1920 1018
 [pos] -1 -1
-*-13.848083 11552814436 -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
+*-18.423141 -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
 [sst_width] 386
 [signals_width] 344
 [sst_expanded] 1
-[sst_vpaned_height] 197
+[sst_vpaned_height] 267
 @28
 functions.trx_read
 functions.trx_write
@@ -24,9 +24,8 @@ variables.frame_number_TX1_UE[63:0]
 functions.ue_gain_control
 @420
 variables.frame_number_RX1_UE[63:0]
-@25
-variables.trx_ts_ue[63:0]
 @24
+variables.trx_ts_ue[63:0]
 variables.trx_ts[63:0]
 variables.trx_tst[63:0]
 variables.frame_number_RX0_RU[63:0]
@@ -63,5 +62,7 @@ functions.phy_procedures_ru_feptx_ofdm0
 functions.phy_procedures_ru_feptx_ofdm1
 functions.phy_procedures_ru_feptx_prec0
 functions.phy_procedures_ru_feptx_prec1
+@23
+variables.ru_tx_ofdm_mask[63:0]
 [pattern_trace] 1
 [pattern_trace] 0
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index dea8c7a2b521399e1af66ac7f60a25566879d7e9..af96fa68dc998f59171e2d79a8475252388240d7 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -81,6 +81,7 @@
 /* these variables have to be defined before including ENB_APP/enb_paramdef.h */
 static int DEFBANDS[] = {7};
 static int DEFENBS[] = {0};
+static int DEFBFW[] = {0x00007fff};
 
 #include "ENB_APP/enb_paramdef.h"
 #include "common/config/config_userapi.h"
diff --git a/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c b/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c
index 9f28fd7c78a6c3182fec9f763676e2e68ecd6dac..378ee95c3bea10fbf8b4a019fb788dd4208184fa 100644
--- a/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c
+++ b/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c
@@ -226,7 +226,7 @@ int main(int argc, char **argv)
   mac_xface = malloc(sizeof(MAC_xface));
   Mac_rlc_xface = (MAC_RLC_XFACE*)malloc16(sizeof(MAC_RLC_XFACE));
 
-  rlc_module_init ();
+  rlc_module_init (1);
   pdcp_module_init();
   logInit();