diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index bd2d8e3b1e587a6f9cf3866e03e749561907c18d..e11c850b8e732a85c262062b531160a2ffc3b5b8 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1968,6 +1968,7 @@ set(NR_PDCP_SRC
   ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c
   ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c
   ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
+  ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c
   ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
   )
 
diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml
index 6d3424b42024109d74b0f43a28fb1d19fb68d30c..089d0503fdf02a7b0726223adec38c78e343a7c5 100644
--- a/cmake_targets/autotests/test_case_list.xml
+++ b/cmake_targets/autotests/test_case_list.xml
@@ -1292,7 +1292,9 @@
                                  (Test8: DMRS Type B, 3 DMRS, 2 PTRS, 3 Interpolated Symbols),
                                  (Test9: SC-FDMA, 50 PRBs),
                                  (Test10: SC-FDMA, 75 PRBs),
-                                 (Test11: SC-FDMA, 3 DMRS)</desc>
+                                 (Test11: SC-FDMA, 216 PRBs),
+                                 (Test12: SC-FDMA, 273 PRBs),
+                                 (Test13: SC-FDMA, 3 DMRS)</desc>
       <pre_compile_prog></pre_compile_prog>
       <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog>
       <compile_prog_args> --phy_simulators  -c </compile_prog_args>
@@ -1307,10 +1309,13 @@
                       -n100 -s5 -T 2 1 2 -U 2 0 2
                       -n100 -s5 -T 2 2 2 -U 2 1 2
                       -n100 -s5 -a4 -b8 -T 2 1 2 -U 2 1 3
-                      -n100 -s20 -Z
-                      -n100 -s20 -Z -r75
-                      -n100 -s20 -Z -U 2 0 2</main_exec_args>
-      <tags>nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11</tags>
+                      -n100 -s2 -Z
+                      -n100 -s2 -Z -r75
+                      -n100 -s2 -Z -r216 -R217
+                      -n100 -s2 -Z -r270 -R273
+                      -n100 -s2 -Z -U 2 0 2</main_exec_args>
+
+      <tags>nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13</tags>
       <search_expr_true>PUSCH test OK</search_expr_true>
       <search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
       <nruns>3</nruns>
diff --git a/common/config/config_load_configmodule.c b/common/config/config_load_configmodule.c
index 03b380ee2fc8246fc7c5b529c19f37baadbf4ccc..740c6e240bc77c61c99fbc08982d83ec30ba3fcd 100644
--- a/common/config/config_load_configmodule.c
+++ b/common/config/config_load_configmodule.c
@@ -331,9 +331,10 @@ void end_configmodule(void) {
     printf ("[CONFIG] free %u config value pointers\n",cfgptr->numptrs);
 
     for(int i=0; i<cfgptr->numptrs ; i++) {
-      if (cfgptr->ptrs[i] != NULL) {
+      if (cfgptr->ptrs[i] != NULL && cfgptr->ptrsAllocated[i] == true) {
         free(cfgptr->ptrs[i]);
         cfgptr->ptrs[i]=NULL;
+	cfgptr->ptrsAllocated[i] = false;
       }
     }
 
diff --git a/common/config/config_load_configmodule.h b/common/config/config_load_configmodule.h
index d0309c62c3b66fde19ac8ea6338ce7f05993cef2..8baaa99bb8074f90e9fa42aac5d18506c65a2f40 100644
--- a/common/config/config_load_configmodule.h
+++ b/common/config/config_load_configmodule.h
@@ -36,6 +36,8 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
 #include "common/config/config_paramdesc.h"
 #include "common/utils/T/T.h"
 #define CONFIG_MAX_OOPT_PARAMS    10     // maximum number of parameters in the -O option (-O <cfgmode>:P1:P2...
@@ -74,6 +76,7 @@ typedef struct configmodule_interface {
   uint32_t numptrs;
   uint32_t rtflags;
   char     *ptrs[CONFIG_MAX_ALLOCATEDPTRS];
+  bool ptrsAllocated[CONFIG_MAX_ALLOCATEDPTRS];
 } configmodule_interface_t;
 
 #ifdef CONFIG_LOADCONFIG_MAIN
diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c
index 33d6408828439cd4b596255d49cc83178fa088ae..af70cae71eccf889a3618ed152f5f1138ac28627 100644
--- a/common/config/config_userapi.c
+++ b/common/config/config_userapi.c
@@ -62,6 +62,7 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) {
 
       if ( (cfgoptions->paramflags & PARAMFLAG_NOFREE) == 0) {
         config_get_if()->ptrs[config_get_if()->numptrs] = (char *)ptr;
+	config_get_if()->ptrsAllocated[config_get_if()->numptrs] = true;
         config_get_if()->numptrs++;
       }
     } else {
@@ -82,7 +83,9 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) {
   }
 
   if (*ptr == NULL) {
-    *ptr = malloc(length>40?length:40); // LTS: dummy fix, waiting Francois full fix in 4G branch
+    *ptr = malloc(length>40?length:40);
+    // LTS: dummy fix, waiting Francois full fix in 4G branch
+    // the issue is we don't know at this point the size we will get
 
     if ( *ptr != NULL) {
       memset(*ptr,0,length);
diff --git a/common/config/libconfig/config_libconfig.c b/common/config/libconfig/config_libconfig.c
index 2e9fd614c504e286f5eeb728a4b03ab198ec1cf0..eb08a70183f5f699253450d460be22e607938c59 100644
--- a/common/config/libconfig/config_libconfig.c
+++ b/common/config/libconfig/config_libconfig.c
@@ -346,6 +346,7 @@ int config_libconfig_init(char *cfgP[], int numP) {
   libconfig_privdata.configfile = strdup((char *)cfgP[0]);
   config_get_if()->numptrs=0;
   memset(config_get_if()->ptrs,0,sizeof(void *) * CONFIG_MAX_ALLOCATEDPTRS);
+  memset(config_get_if()->ptrsAllocated, 0, sizeof(config_get_if()->ptrsAllocated));
 
   /* Read the file. If there is an error, report it and exit. */
   if(! config_read_file(&(libconfig_privdata.cfg), libconfig_privdata.configfile)) {
diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c
index 2340c78bf18f4ea1cc56bc65ef6d4fd4950b3f9c..9fd67a6dbb9cf6a0f3f385b4df81788c465601b9 100644
--- a/common/utils/LOG/log.c
+++ b/common/utils/LOG/log.c
@@ -88,16 +88,19 @@ int write_file_matlab(const char *fname,
 					  void *data,
 					  int length,
 					  int dec,
-					  char format)
+					  unsigned int format)
 {
   FILE *fp=NULL;
   int i;
 
+  AssertFatal((format&~MATLAB_RAW) <16,"");
+
   if (data == NULL)
     return -1;
 
   //printf("Writing %d elements of type %d to %s\n",length,format,fname);
 
+
   if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) {
     fp = fopen(fname,"a+");
   } else if (format != 10 && format !=11  && format != 12 && format != 13 && format != 14) {
@@ -109,6 +112,32 @@ int write_file_matlab(const char *fname,
     return(-1);
   }
 
+  if ( (format&MATLAB_RAW) == MATLAB_RAW ) {
+    int sz[16]={sizeof(short), 2*sizeof(short),
+		sizeof(int), 2*sizeof(int),
+		sizeof(char), 2*sizeof(char),
+		sizeof(long long), 
+		sizeof(double), 2*sizeof(double),
+		sizeof(unsigned char),
+		sizeof(short),
+		sizeof(short),
+		sizeof(short),
+		sizeof(short),
+		sizeof(short),
+		sizeof(short)
+    };
+    int eltSz= sz[format&~MATLAB_RAW];
+    if (dec==1) 
+      fwrite(data, eltSz, length, fp);
+    else 
+      for (i=0; i<length; i+=dec)
+	fwrite(data+i*eltSz, eltSz, 1, fp);
+    
+    fclose(fp);
+    return(0);	
+  }
+
+
   if (format != 10 && format !=11  && format != 12 && format != 13 && format != 14)
     fprintf(fp,"%s = [",vname);
 
@@ -214,6 +243,8 @@ int write_file_matlab(const char *fname,
     case 12 : // case eren for log2_maxh real unsigned 8 bit
       fprintf(fp,"%d \n",((unsigned char *)&data)[0]);
       break;
+  default:
+    AssertFatal(false, "unknown dump format: %d\n", format);
   }
 
   if (format != 10 && format !=11 && format !=12 && format != 13 && format != 15) {
diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h
index d893708a8b5327d6af0fdd72852c6d374eb832d4..49c6bdfd4c32bf696995dd66192fef781125b7f2 100644
--- a/common/utils/LOG/log.h
+++ b/common/utils/LOG/log.h
@@ -336,7 +336,25 @@ typedef struct {
 @param dec    decimation level
 @param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit)
 */
-int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format);
+#define MATLAB_RAW (1<<31)
+#define MATLAB_SHORT 0
+#define MATLAB_CSHORT 1
+#define MATLAB_INT 2
+#define MATLAB_CINT 3
+#define MATLAB_INT8 4
+#define MATLAB_CINT8 5
+#define MATLAB_LLONG 6
+#define MATLAB_DOUBLE 7
+#define MATLAB_CDOUBLE 8
+#define MATLAB_UINT8 9
+#define MATLEB_EREN1 10
+#define MATLEB_EREN2 11
+#define MATLEB_EREN3 12
+#define MATLAB_CSHORT_BRACKET1 13
+#define MATLAB_CSHORT_BRACKET2 14
+#define MATLAB_CSHORT_BRACKET3 15
+  
+int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format);
 
 /*----------------macro definitions for reading log configuration from the config module */
 #define CONFIG_STRING_LOG_PREFIX                           "log_config"
diff --git a/common/utils/T/T_defs.h b/common/utils/T/T_defs.h
index 7b5304b1cb144fdeb3ffdac617c27a45d398aba1..11c816f002a409c8befb42ff7381126a5e3b00a9 100644
--- a/common/utils/T/T_defs.h
+++ b/common/utils/T/T_defs.h
@@ -44,7 +44,7 @@
    /* let's have 100 RBs functional for the basic simulator */
 #  define T_BUFFER_MAX (1024*64*2)
 #else
-#  define T_BUFFER_MAX (1024*64)
+#  define T_BUFFER_MAX (1024*64*2)
 #endif
 
 /* size of the local cache for messages (must be pow(2,something)) */
@@ -52,7 +52,7 @@
    /* we don't need much space for the basic simulator */
 #  define T_CACHE_SIZE 1024
 #else
-#  define T_CACHE_SIZE (8192 * 2)
+#  define T_CACHE_SIZE (8192)
 #endif
 
 /* maximum number of bytes a message can contain */
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 06ee5bf12bb6d43a254f215419f29c74d0293298..bad6444e1303d385c9808608a599cf6e43330bab 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -1,3 +1,7 @@
+ID = BENETEL
+  GROUP = ALL
+  FORMAT = int,frame : int,slot : buffer,rxdataF
+
 #general logs
 ID = ENB_MASTER_TICK
     DESC = eNodeB master tick - one tick per ms, to be used as "reference clock", mostly for ticktime view
diff --git a/doc/TESTING_GNB_W_COTS_UE.md b/doc/TESTING_GNB_W_COTS_UE.md
index 610cc5bdd47539b823c00917c530911fc211b093..73ae18351f2f1458a687ea41408321c3cc36180f 100644
--- a/doc/TESTING_GNB_W_COTS_UE.md
+++ b/doc/TESTING_GNB_W_COTS_UE.md
@@ -30,8 +30,6 @@ http://www.saelig.com/MFR00066/ste2300.htm
 ## Configuration Overview
 
 * Non Standalone (NSA) configuration  : initial Control Plane established between UE and RAN eNB, then User Plane established between UE and gNB, Core network is 4G based supporting rel 15
-
-* Commercial UE: Oppo Reno 5G
 * OAI Software Defined gNB and eNB
 * eNB RF front end: USRP (ETTUS) B200 Mini or B210
 * gNB RF front end: USRP (ETTUS) B200 Mini or B210 (N310 will be needed for MIMO and wider BW's)
@@ -40,6 +38,17 @@ http://www.saelig.com/MFR00066/ste2300.htm
 * BW: 40MHz
 * Antenna scheme: SISO
 
+## COTS UEs 
+
+Our code might not work with all 5G phones yet, but we are constantly improving it. Here is a list of COTS UEs that we know that work with OAI. 
+
+*  Oppo Reno 5G
+*  Samsung A90 5G
+*  Google Pixel 5G
+*  Simcom SIMCOM8200EA 
+*  Quectel RM500Q-GL
+
+
 ## Repository
 
 https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index 8ed4ac2e1cc21693316440175040f904299ef005..5a53c69063f64d069af19ec29af340b062f9b61b 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -1026,7 +1026,13 @@ void init_eNB_afterRU(void) {
       for (i=0; i<gNB->RU_list[ru_id]->nb_rx; aa++,i++) {
 	LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n",gNB->RU_list[ru_id]->idx,i,aa);
 	gNB->prach_vars.rxsigF[aa]    =  gNB->RU_list[ru_id]->prach_rxsigF[0][i];
+#if 0
+printf("before %p\n", gNB->common_vars.rxdataF[aa]);
+#endif
 	gNB->common_vars.rxdataF[aa]     =  gNB->RU_list[ru_id]->common.rxdataF[i];
+#if 0
+printf("after %p\n", gNB->common_vars.rxdataF[aa]);
+#endif
       }
     }
 
diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c
index 87cd157948d5aac3a843daa3f432317d88f4ddd1..5d651344d608e606bb6d7d76512c9fe730edd99d 100644
--- a/executables/nr-uesoftmodem.c
+++ b/executables/nr-uesoftmodem.c
@@ -557,11 +557,14 @@ int main( int argc, char **argv ) {
 
   
   init_NR_UE_threads(1);
-  config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
   printf("UE threads created by %ld\n", gettid());
   
   // wait for end of program
   printf("TYPE <CTRL-C> TO TERMINATE\n");
+  // Sleep a while before checking all parameters have been used
+  // Some are used directly in external threads, asynchronously
+  sleep(20);
+  config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
 
   while(true)
     sleep(3600);
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
index ebe5c26bf6617c0a95101f94fdbac0fcac8efb71..bc5e7af45fb98e4c50c938457fed1afec386e7f0 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
@@ -715,8 +715,10 @@ typedef struct {
   uint16_t prgSize;
   /// Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255
   uint8_t digBFInterfaces;
+  // Depends on numPRGs
   uint16_t PMIdx[275];
-  uint16_t *beamIdx[275];
+  // Depends on digBFInterfaces
+  uint16_t beamIdx[256];
 } nfapi_nr_tx_precoding_and_beamforming_t;
 
 //table 3-37 
diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c
index 0a7088ba398a1ef814e79084ba77e4dff72714d4..ed9a859fb64673c67faded9b0e33d4948b567a22 100644
--- a/openair1/PHY/MODULATION/nr_modulation.c
+++ b/openair1/PHY/MODULATION/nr_modulation.c
@@ -325,10 +325,10 @@ void nr_ue_layer_mapping(NR_UE_ULSCH_t **ulsch_ue,
 
 void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH)
 {
-#if defined(__x86_64__) || defined(__i386__)
-  __m128i dft_in128[1][1200], dft_out128[1][1200];
+#if defined(__x86_64__) || +defined(__i386__)
+  __m128i dft_in128[1][3240], dft_out128[1][3240];
 #elif defined(__arm__)
-  int16x8_t dft_in128[1][1200], dft_out128[1][1200];
+  int16x8_t dft_in128[1][3240], dft_out128[1][3240];
 #endif
   uint32_t *dft_in0 = (uint32_t*)dft_in128[0], *dft_out0 = (uint32_t*)dft_out128[0];
 
@@ -340,8 +340,10 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH)
   int16x8_t norm128;
 #endif
 
-  for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
-    dft_in0[ip] = d[i];
+  if ((Msc_PUSCH % 1536) > 0) {
+    for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
+      dft_in0[ip] = d[i];
+    }
   }
 
   switch (Msc_PUSCH) {
@@ -480,7 +482,7 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH)
       break;
 
     case 972:
-      dft(DFT_960,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      dft(DFT_972,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
       break;
 
     case 1080:
@@ -494,11 +496,98 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH)
     case 1200:
       dft(DFT_1200,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
       break;
+
+    case 1296:
+      dft(DFT_1296,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1440:
+      dft(DFT_1440,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1500:
+      dft(DFT_1500,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1536:
+      //dft(DFT_1536,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      dft(DFT_1536,(int16_t*)d, (int16_t*)z, 1);
+      break;
+
+    case 1620:
+      dft(DFT_1620,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1728:
+      dft(DFT_1728,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1800:
+      dft(DFT_1800,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1920:
+      dft(DFT_1920,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1944:
+      dft(DFT_1944,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 2160:
+      dft(DFT_2160,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 2304:
+      dft(DFT_2304,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 2400:
+      dft(DFT_2400,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 2592:
+      dft(DFT_2592,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 2700:
+      dft(DFT_2700,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 2880:
+      dft(DFT_2880,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 2916:
+      dft(DFT_2916,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 3000:
+      dft(DFT_3000,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 3072:
+      //dft(DFT_3072,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      dft(DFT_3072,(int16_t*)d, (int16_t*)z, 1);
+      break;
+
+    case 3240:
+      dft(DFT_3240,(int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    default:
+      // should not be reached
+      LOG_E( PHY, "Unsupported Msc_PUSCH value of %"PRIu16"\n", Msc_PUSCH );
+      return;
+
   }
 
-  for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
-    z[i] = dft_out0[ip];
+
+  if ((Msc_PUSCH % 1536) > 0) {
+    for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4)
+      z[i] = dft_out0[ip];
   }
+
 }
 
 
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
index 713e71674b979f47fb4040a7712d7a875a1afc51..38b35dcf6d39a93969b7b3f1ee3cbb73158e7622 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
@@ -158,6 +158,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
 #endif
   for (aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
 
+    re_offset = k;   /* Initializing the Resource element offset for each Rx antenna */
+
     pil   = (int16_t *)&pilot[0];
     rxF   = (int16_t *)&rxdataF[aarx][(symbol_offset+k+nushift)];
     ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset];
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
index 7e6becb4a8b1213ccb062e7847517179d7210478..42d6cfad7a3e7ac19c3128fe86317628bc46269c 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
@@ -16,10 +16,10 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
 {
 
 #if defined(__x86_64__) || defined(__i386__)
-  __m128i idft_in128[1][1200], idft_out128[1][1200];
+  __m128i idft_in128[1][3240], idft_out128[1][3240];
   __m128i norm128;
 #elif defined(__arm__)
-  int16x8_t idft_in128[1][1200], idft_out128[1][1200];
+  int16x8_t idft_in128[1][3240], idft_out128[1][3240];
   int16x8_t norm128;
 #endif
   int16_t *idft_in0 = (int16_t*)idft_in128[0], *idft_out0 = (int16_t*)idft_out128[0];
@@ -28,20 +28,19 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
 
   LOG_T(PHY,"Doing lte_idft for Msc_PUSCH %d\n",Msc_PUSCH);
 
-  // conjugate input
-  for (i = 0; i < (Msc_PUSCH>>2); i++) {
+  if ((Msc_PUSCH % 1536) > 0) {
+    // conjugate input
+    for (i = 0; i < (Msc_PUSCH>>2); i++) {
 #if defined(__x86_64__)||defined(__i386__)
-    *&(((__m128i*)z)[i]) = _mm_sign_epi16(*&(((__m128i*)z)[i]), *(__m128i*)&conjugate2[0]);
+      *&(((__m128i*)z)[i]) = _mm_sign_epi16(*&(((__m128i*)z)[i]), *(__m128i*)&conjugate2[0]);
 #elif defined(__arm__)
-    *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]);
+      *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]);
 #endif
+    }
+    for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4)
+      ((uint32_t*)idft_in0)[ip+0] = z[i];
   }
 
-  for (i=0,ip=0; i<Msc_PUSCH; i++, ip+=4) {
-    ((int32_t*)idft_in0)[ip+0] = z[i];
-  }
-
-
   switch (Msc_PUSCH) {
     case 12:
       dft(DFT_12,(int16_t *)idft_in0, (int16_t *)idft_out0,0);
@@ -194,25 +193,102 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
       dft(DFT_1200,idft_in0, idft_out0, 1);
       break;
 
+    case 1296:
+      dft(DFT_1296,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1440:
+      dft(DFT_1440,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1500:
+      dft(DFT_1500,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1536:
+      //dft(DFT_1536,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      idft(IDFT_1536,(int16_t*)z, (int16_t*)z, 1);
+      break;
+
+    case 1620:
+      dft(DFT_1620,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1728:
+      dft(DFT_1728,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1800:
+      dft(DFT_1800,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1920:
+      dft(DFT_1920,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1944:
+      dft(DFT_1944,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 2160:
+      dft(DFT_2160,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 2304:
+      dft(DFT_2304,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 2400:
+      dft(DFT_2400,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 2592:
+      dft(DFT_2592,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 2700:
+      dft(DFT_2700,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 2880:
+      dft(DFT_2880,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 2916:
+      dft(DFT_2916,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 3000:
+      dft(DFT_3000,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 3072:
+      //dft(DFT_3072,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      idft(IDFT_3072,(int16_t*)z, (int16_t*)z, 1);
+      break;
+
+    case 3240:
+      dft(DFT_3240,(int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
     default:
       // should not be reached
       LOG_E( PHY, "Unsupported Msc_PUSCH value of %"PRIu16"\n", Msc_PUSCH );
       return;
   }
 
+  if ((Msc_PUSCH % 1536) > 0) {
+    for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4)
+      z[i] = ((uint32_t*)idft_out0)[ip];
 
-
-  for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
-    z[i] = ((int32_t*)idft_out0)[ip];
-  }
-
-  // conjugate output
-  for (i = 0; i < (Msc_PUSCH>>2); i++) {
+    // conjugate output
+    for (i = 0; i < (Msc_PUSCH>>2); i++) {
 #if defined(__x86_64__) || defined(__i386__)
-    ((__m128i*)z)[i] = _mm_sign_epi16(((__m128i*)z)[i], *(__m128i*)&conjugate2[0]);
+      ((__m128i*)z)[i] = _mm_sign_epi16(((__m128i*)z)[i], *(__m128i*)&conjugate2[0]);
 #elif defined(__arm__)
-    *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]);
+      *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]);
 #endif
+    }
   }
 
 #if defined(__x86_64__) || defined(__i386__)
@@ -222,6 +298,7 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH)
 
 }
 
+
 void nr_ulsch_extract_rbs_single(int32_t **rxdataF,
                                  NR_gNB_PUSCH *pusch_vars,
                                  unsigned char symbol,
diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c
index f6cb93ed037dbc9e93fdfea1eca32e506ec54728..cb6152385260942df9ebe89fd11ae3bd0f5cafa0 100644
--- a/openair1/PHY/TOOLS/nr_phy_scope.c
+++ b/openair1/PHY/TOOLS/nr_phy_scope.c
@@ -225,6 +225,8 @@ static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int laye
 }
 
 static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize, const int divisions, const char *label) {
+  if ( values == NULL )
+     return;
   fl_winset(FL_ObjWin(graph->graph));
   const int samplesPerPixel=datasize/graph->w;
   int displayPart=graph->waterFallh-ScaleZone;
diff --git a/openair1/PHY/TOOLS/oai_dfts.c b/openair1/PHY/TOOLS/oai_dfts.c
index e4e85f7ba9ce3207a2ef8a70b45f87153b2060ce..6569f7eab5be3b4b92c92b951bd73ef360fd1329 100644
--- a/openair1/PHY/TOOLS/oai_dfts.c
+++ b/openair1/PHY/TOOLS/oai_dfts.c
@@ -5952,8 +5952,6 @@ void idft32768(int16_t *x,int16_t *y,unsigned char scale)
 
 
 #endif
-
-
 int16_t twa1536[1024],twb1536[1024];
 
 // 512 x 3
@@ -9471,145 +9469,1058 @@ void dft1200(int16_t *x,int16_t *y,unsigned char scale_flag)
 
 }
 
-void init_rad4(int N,int16_t *tw) {
 
-  int16_t *twa = tw;
-  int16_t *twb = twa+(N/2);
-  int16_t *twc = twb+(N/2);
-  int i;
+static int16_t twa1296[431*2*4];
+static int16_t twb1296[431*2*4];
 
-  for (i=0;i<(N/4);i++) {
-    *twa = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa++;
-    *twa = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twa++;
-    *twb = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb++;
-    *twb = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); twb++;
-    *twc = (int16_t)round(32767.0*cos(2*M_PI*3*i/N)); twc++;
-    *twc = -(int16_t)round(32767.0*sin(2*M_PI*3*i/N)); twc++;
-  }
-}
-void init_rad4_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc) {
+void dft1296(int16_t *x,int16_t *y,unsigned char scale_flag) //432 * 3
+{
 
   int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa1296[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb1296[0];
+  simd_q15_t x2128[1296];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[1296];//=&ytmp128array3[0];
 
-  for (i=1;i<(N/4);i++) {
-    twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); 
-    twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N));
-    twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N));
-    twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N));
-    twc[0] = (int16_t)round(32767.0*cos(2*M_PI*3*i/N));
-    twc[1] = -(int16_t)round(32767.0*sin(2*M_PI*3*i/N));
-    for (j=1;j<4;j++) {
-      ((int32_t*)twa)[j]=((int32_t*)twa)[0];
-      ((int32_t*)twb)[j]=((int32_t*)twb)[0];
-      ((int32_t*)twc)[j]=((int32_t*)twc)[0];
-    }
-    twa+=8;
-    twb+=8;
-    twc+=8;
+
+
+  for (i=0,j=0; i<432; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+432] = x128[j+1];
+    x2128[i+864] = x128[j+2];
   }
-}
 
-void init_rad2(int N,int16_t *tw) {
+  dft432((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft432((int16_t *)(x2128+432),(int16_t *)(ytmp128+432),1);
+  dft432((int16_t *)(x2128+864),(int16_t *)(ytmp128+864),1);
 
-  int16_t *twa = tw;
-  int i;
+  bfly3_tw1(ytmp128,ytmp128+432,ytmp128+864,y128,y128+432,y128+864);
 
-  for (i=0;i<(N>>1);i++) {
-    *twa = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa++;
-    *twa = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twa++;
+  for (i=1,j=0; i<432; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+432+i,
+          ytmp128+864+i,
+          y128+i,
+          y128+432+i,
+          y128+864+i,
+          twa128+j,
+          twb128+j);
   }
-}
 
-void init_rad2_rep(int N,int16_t *twa) {
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<1296; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
 
+static int16_t twa1440[479*2*4];
+static int16_t twb1440[479*2*4];
+
+void dft1440(int16_t *x,int16_t *y,unsigned char scale_flag)  // 480 x 3
+{
   int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa1440[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb1440[0];
+  simd_q15_t x2128[1440];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[1440];//=&ytmp128array3[0];
 
-  for (i=1;i<(N/2);i++) {
-    twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); 
-    twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N));
-    for (j=1;j<4;j++) {
-      ((int32_t*)twa)[j]=((int32_t*)twa)[0];
+
+
+  for (i=0,j=0; i<480; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+480] = x128[j+1];
+    x2128[i+960] = x128[j+2];
+  }
+
+  dft480((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft480((int16_t *)(x2128+480),(int16_t *)(ytmp128+480),1);
+  dft480((int16_t *)(x2128+960),(int16_t *)(ytmp128+960),1);
+
+  bfly3_tw1(ytmp128,ytmp128+480,ytmp128+960,y128,y128+480,y128+960);
+
+  for (i=1,j=0; i<480; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+480+i,
+          ytmp128+960+i,
+          y128+i,
+          y128+480+i,
+          y128+960+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<1440; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
     }
-    twa+=8;
   }
-}
 
-void init_rad3(int N,int16_t *twa,int16_t *twb) {
+  _mm_empty();
+  _m_empty();
 
-  int i;
+};
 
-  for (i=0;i<(N/3);i++) {
-    *twa = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa++;
-    *twa = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twa++;
-    *twb = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb++;
-    *twb = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); twb++;
+static int16_t twa1500[2392]__attribute__((aligned(32)));
+static int16_t twb1500[2392]__attribute__((aligned(32)));
+static int16_t twc1500[2392]__attribute__((aligned(32)));
+static int16_t twd1500[2392]__attribute__((aligned(32)));
+
+void dft1500(int16_t *x,int16_t *y,unsigned char scale_flag)
+{
+
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa1500[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb1500[0];
+  simd_q15_t *twc128=(simd_q15_t *)&twc1500[0];
+  simd_q15_t *twd128=(simd_q15_t *)&twd1500[0];
+  simd_q15_t x2128[1500];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[1500];//=&ytmp128array2[0];
+
+
+
+  for (i=0,j=0; i<300; i++,j+=5) {
+    x2128[i]    = x128[j];
+    x2128[i+300] = x128[j+1];
+    x2128[i+600] = x128[j+2];
+    x2128[i+900] = x128[j+3];
+    x2128[i+1200] = x128[j+4];
+  }
+
+  dft300((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft300((int16_t *)(x2128+300),(int16_t *)(ytmp128+300),1);
+  dft300((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1);
+  dft300((int16_t *)(x2128+900),(int16_t *)(ytmp128+900),1);
+  dft300((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1);
+
+  bfly5_tw1(ytmp128,ytmp128+300,ytmp128+600,ytmp128+900,ytmp128+1200,y128,y128+300,y128+600,y128+900,y128+1200);
+
+  for (i=1,j=0; i<300; i++,j++) {
+    bfly5(ytmp128+i,
+          ytmp128+300+i,
+          ytmp128+600+i,
+          ytmp128+900+i,
+          ytmp128+1200+i,
+          y128+i,
+          y128+300+i,
+          y128+600+i,
+          y128+900+i,
+          y128+1200+i,
+          twa128+j,
+          twb128+j,
+          twc128+j,
+          twd128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[15]);
+
+    for (i=0; i<1500; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
   }
+
+  _mm_empty();
+  _m_empty();
+
 }
 
-void init_rad3_rep(int N,int16_t *twa,int16_t *twb) {
+static int16_t twa1620[539*2*4];
+static int16_t twb1620[539*2*4];
 
+void dft1620(int16_t *x,int16_t *y,unsigned char scale_flag)  // 540 x 3
+{
   int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa1620[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb1620[0];
+  simd_q15_t x2128[1620];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[1620];//=&ytmp128array3[0];
 
-  for (i=1;i<(N/3);i++) {
-    twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); 
-    twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N));
-    twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N));
-    twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N));
-    for (j=1;j<4;j++) {
-      ((int32_t*)twa)[j]=((int32_t*)twa)[0];
-      ((int32_t*)twb)[j]=((int32_t*)twb)[0];
+
+
+  for (i=0,j=0; i<540; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+540] = x128[j+1];
+    x2128[i+1080] = x128[j+2];
+  }
+
+  dft540((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft540((int16_t *)(x2128+540),(int16_t *)(ytmp128+540),1);
+  dft540((int16_t *)(x2128+1080),(int16_t *)(ytmp128+1080),1);
+
+  bfly3_tw1(ytmp128,ytmp128+540,ytmp128+1080,y128,y128+540,y128+1080);
+
+  for (i=1,j=0; i<540; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+540+i,
+          ytmp128+1080+i,
+          y128+i,
+          y128+540+i,
+          y128+1080+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<1620; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
     }
-    twa+=8;
-    twb+=8;
   }
-}
 
-void init_rad5_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc,int16_t *twd) {
+  _mm_empty();
+  _m_empty();
+
+};
 
+static int16_t twa1728[575*2*4];
+static int16_t twb1728[575*2*4];
+
+void dft1728(int16_t *x,int16_t *y,unsigned char scale_flag)  // 576 x 3
+{
   int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa1728[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb1728[0];
+  simd_q15_t x2128[1728];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[1728];//=&ytmp128array3[0];
 
-  for (i=1;i<(N/5);i++) {
-    twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); 
-    twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N));
-    twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N));
-    twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N));
-    twc[0] = (int16_t)round(32767.0*cos(2*M_PI*3*i/N));
-    twc[1] = -(int16_t)round(32767.0*sin(2*M_PI*3*i/N));
-    twd[0] = (int16_t)round(32767.0*cos(2*M_PI*4*i/N));
-    twd[1] = -(int16_t)round(32767.0*sin(2*M_PI*4*i/N));
-    for (j=1;j<4;j++) {
-      ((int32_t*)twa)[j]=((int32_t*)twa)[0];
-      ((int32_t*)twb)[j]=((int32_t*)twb)[0];
-      ((int32_t*)twc)[j]=((int32_t*)twc)[0];
-      ((int32_t*)twd)[j]=((int32_t*)twd)[0];
+
+
+  for (i=0,j=0; i<576; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+576] = x128[j+1];
+    x2128[i+1152] = x128[j+2];
+  }
+
+  dft576((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft576((int16_t *)(x2128+576),(int16_t *)(ytmp128+576),1);
+  dft576((int16_t *)(x2128+1152),(int16_t *)(ytmp128+1152),1);
+
+  bfly3_tw1(ytmp128,ytmp128+576,ytmp128+1152,y128,y128+576,y128+1152);
+
+  for (i=1,j=0; i<576; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+576+i,
+          ytmp128+1152+i,
+          y128+i,
+          y128+576+i,
+          y128+1152+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<1728; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
     }
-    twa+=8;
-    twb+=8;
-    twc+=8;
-    twd+=8;                  
   }
-}
-/*----------------------------------------------------------------*/
-/* dft library entry points:                                      */
 
-int dfts_autoinit(void)
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa1800[599*2*4];
+static int16_t twb1800[599*2*4];
+
+void dft1800(int16_t *x,int16_t *y,unsigned char scale_flag)  // 600 x 3
 {
-  init_rad4(1024,tw1024);
-  init_rad2(2048,tw2048);
-  init_rad4(4096,tw4096);
-  init_rad2(8192,tw8192);
-  init_rad4(16384,tw16384);
-  init_rad2(32768,tw32768);
-  
-  init_rad3(1536,twa1536,twb1536);
-  init_rad3(3072,twa3072,twb3072);
-  init_rad3(6144,twa6144,twb6144);
-  init_rad3(12288,twa12288,twb12288);
-  init_rad3(18432,twa18432,twb18432);
-  init_rad3(24576,twa24576,twb24576);
-  init_rad3(36864,twa36864,twb36864);
-  init_rad3(49152,twa49152,twb49152);
-  init_rad3(98304,twa98304,twb98304);
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa1800[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb1800[0];
+  simd_q15_t x2128[1800];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[1800];//=&ytmp128array3[0];
+
+
+
+  for (i=0,j=0; i<600; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+600] = x128[j+1];
+    x2128[i+1200] = x128[j+2];
+  }
+
+  dft600((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft600((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1);
+  dft600((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1);
+
+  bfly3_tw1(ytmp128,ytmp128+600,ytmp128+1200,y128,y128+600,y128+1200);
+
+  for (i=1,j=0; i<600; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+600+i,
+          ytmp128+1200+i,
+          y128+i,
+          y128+600+i,
+          y128+1200+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<1800; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa1920[479*2*4];
+static int16_t twb1920[479*2*4];
+static int16_t twc1920[479*2*4];
+
+void dft1920(int16_t *x,int16_t *y,unsigned char scale_flag)  // 480 x 4
+{
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa1920[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb1920[0];
+  simd_q15_t *twc128=(simd_q15_t *)&twc1920[0];
+  simd_q15_t x2128[1920];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[1920];//=&ytmp128array2[0];
+
+
+
+  for (i=0,j=0; i<480; i++,j+=4) {
+    x2128[i]    = x128[j];
+    x2128[i+480] = x128[j+1];
+    x2128[i+960] = x128[j+2];
+    x2128[i+1440] = x128[j+3];
+  }
+
+  dft480((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft480((int16_t *)(x2128+480),(int16_t *)(ytmp128+480),1);
+  dft480((int16_t *)(x2128+960),(int16_t *)(ytmp128+960),1);
+  dft480((int16_t *)(x2128+1440),(int16_t *)(ytmp128+1440),1);
+
+  bfly4_tw1(ytmp128,ytmp128+480,ytmp128+960,ytmp128+1440,y128,y128+480,y128+960,y128+1440);
+
+  for (i=1,j=0; i<480; i++,j++) {
+    bfly4(ytmp128+i,
+          ytmp128+480+i,
+          ytmp128+960+i,
+          ytmp128+1440+i,
+          y128+i,
+          y128+480+i,
+          y128+960+i,
+          y128+1440+i,
+          twa128+j,
+          twb128+j,
+          twc128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[13]);
+    for (i=0; i<1920; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa1944[647*2*4];
+static int16_t twb1944[647*2*4];
+
+void dft1944(int16_t *x,int16_t *y,unsigned char scale_flag)  // 648 x 3
+{
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa1944[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb1944[0];
+  simd_q15_t x2128[1944];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[1944];//=&ytmp128array3[0];
+
+
+
+  for (i=0,j=0; i<648; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+648] = x128[j+1];
+    x2128[i+1296] = x128[j+2];
+  }
+
+  dft648((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft648((int16_t *)(x2128+648),(int16_t *)(ytmp128+648),1);
+  dft648((int16_t *)(x2128+1296),(int16_t *)(ytmp128+1296),1);
+
+  bfly3_tw1(ytmp128,ytmp128+648,ytmp128+1296,y128,y128+648,y128+1296);
+
+  for (i=1,j=0; i<648; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+648+i,
+          ytmp128+1296+i,
+          y128+i,
+          y128+648+i,
+          y128+1296+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<1944; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa2160[719*2*4];
+static int16_t twb2160[719*2*4];
+
+void dft2160(int16_t *x,int16_t *y,unsigned char scale_flag)  // 720 x 3
+{
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa2160[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb2160[0];
+  simd_q15_t x2128[2160];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[2160];//=&ytmp128array3[0];
+
+
+
+  for (i=0,j=0; i<720; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+720] = x128[j+1];
+    x2128[i+1440] = x128[j+2];
+  }
+
+  dft720((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft720((int16_t *)(x2128+720),(int16_t *)(ytmp128+720),1);
+  dft720((int16_t *)(x2128+1440),(int16_t *)(ytmp128+1440),1);
+
+  bfly3_tw1(ytmp128,ytmp128+720,ytmp128+1440,y128,y128+720,y128+1440);
+
+  for (i=1,j=0; i<720; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+720+i,
+          ytmp128+1440+i,
+          y128+i,
+          y128+720+i,
+          y128+1440+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<2160; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa2304[767*2*4];
+static int16_t twb2304[767*2*4];
+
+void dft2304(int16_t *x,int16_t *y,unsigned char scale_flag)  // 768 x 3
+{
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa2304[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb2304[0];
+  simd_q15_t x2128[2304];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[2304];//=&ytmp128array3[0];
+
+
+
+  for (i=0,j=0; i<768; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+768] = x128[j+1];
+    x2128[i+1536] = x128[j+2];
+  }
+
+  dft768((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft768((int16_t *)(x2128+768),(int16_t *)(ytmp128+768),1);
+  dft768((int16_t *)(x2128+1536),(int16_t *)(ytmp128+1536),1);
+
+  bfly3_tw1(ytmp128,ytmp128+768,ytmp128+1536,y128,y128+768,y128+1536);
+
+  for (i=1,j=0; i<768; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+768+i,
+          ytmp128+1536+i,
+          y128+i,
+          y128+768+i,
+          y128+1536+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<2304; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa2400[599*2*4];
+static int16_t twb2400[599*2*4];
+static int16_t twc2400[599*2*4];
+
+void dft2400(int16_t *x,int16_t *y,unsigned char scale_flag)  // 600 x 4
+{
+
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa2400[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb2400[0];
+  simd_q15_t *twc128=(simd_q15_t *)&twc2400[0];
+  simd_q15_t x2128[2400];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[2400];//=&ytmp128array2[0];
+
+
+
+  for (i=0,j=0; i<600; i++,j+=4) {
+    x2128[i]    = x128[j];
+    x2128[i+600] = x128[j+1];
+    x2128[i+1200] = x128[j+2];
+    x2128[i+1800] = x128[j+3];
+  }
+
+  dft600((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft600((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1);
+  dft600((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1);
+  dft600((int16_t *)(x2128+1800),(int16_t *)(ytmp128+1800),1);
+
+  bfly4_tw1(ytmp128,ytmp128+600,ytmp128+1200,ytmp128+1800,y128,y128+600,y128+1200,y128+1800);
+
+  for (i=1,j=0; i<600; i++,j++) {
+    bfly4(ytmp128+i,
+          ytmp128+600+i,
+          ytmp128+1200+i,
+          ytmp128+1800+i,
+          y128+i,
+          y128+600+i,
+          y128+1200+i,
+          y128+1800+i,
+          twa128+j,
+          twb128+j,
+          twc128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[13]);
+    for (i=0; i<2400; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa2592[863*2*4];
+static int16_t twb2592[863*2*4];
+
+void dft2592(int16_t *x,int16_t *y,unsigned char scale_flag)  // 864 x 3
+{
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa2592[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb2592[0];
+  simd_q15_t x2128[2592];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[2592];//=&ytmp128array3[0];
+
+
+
+  for (i=0,j=0; i<864; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+864] = x128[j+1];
+    x2128[i+1728] = x128[j+2];
+  }
+
+  dft864((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft864((int16_t *)(x2128+864),(int16_t *)(ytmp128+864),1);
+  dft864((int16_t *)(x2128+1728),(int16_t *)(ytmp128+1728),1);
+
+  bfly3_tw1(ytmp128,ytmp128+864,ytmp128+1728,y128,y128+864,y128+1728);
+
+  for (i=1,j=0; i<864; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+864+i,
+          ytmp128+1728+i,
+          y128+i,
+          y128+864+i,
+          y128+1728+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<2592; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa2700[899*2*4];
+static int16_t twb2700[899*2*4];
+
+void dft2700(int16_t *x,int16_t *y,unsigned char scale_flag)  // 900 x 3
+{
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa2700[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb2700[0];
+  simd_q15_t x2128[2700];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[2700];//=&ytmp128array3[0];
+
+
+
+  for (i=0,j=0; i<900; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+900] = x128[j+1];
+    x2128[i+1800] = x128[j+2];
+  }
+
+  dft900((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft900((int16_t *)(x2128+900),(int16_t *)(ytmp128+900),1);
+  dft900((int16_t *)(x2128+1800),(int16_t *)(ytmp128+1800),1);
+
+  bfly3_tw1(ytmp128,ytmp128+900,ytmp128+1800,y128,y128+900,y128+1800);
+
+  for (i=1,j=0; i<900; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+900+i,
+          ytmp128+1800+i,
+          y128+i,
+          y128+900+i,
+          y128+1800+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<2700; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa2880[959*2*4];
+static int16_t twb2880[959*2*4];
+
+void dft2880(int16_t *x,int16_t *y,unsigned char scale_flag)  // 960 x 3
+{
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa2880[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb2880[0];
+  simd_q15_t x2128[2880];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[2880];//=&ytmp128array3[0];
+
+
+
+  for (i=0,j=0; i<960; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+960] = x128[j+1];
+    x2128[i+1920] = x128[j+2];
+  }
+
+  dft960((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft960((int16_t *)(x2128+960),(int16_t *)(ytmp128+960),1);
+  dft960((int16_t *)(x2128+1920),(int16_t *)(ytmp128+1920),1);
+
+  bfly3_tw1(ytmp128,ytmp128+960,ytmp128+1920,y128,y128+960,y128+1920);
+
+  for (i=1,j=0; i<960; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+960+i,
+          ytmp128+1920+i,
+          y128+i,
+          y128+960+i,
+          y128+1920+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<2880; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa2916[971*2*4];
+static int16_t twb2916[971*2*4];
+
+void dft2916(int16_t *x,int16_t *y,unsigned char scale_flag)  // 972 x 3
+{
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa2916[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb2916[0];
+  simd_q15_t x2128[2916];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[2916];//=&ytmp128array3[0];
+
+
+
+  for (i=0,j=0; i<972; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+972] = x128[j+1];
+    x2128[i+1944] = x128[j+2];
+  }
+
+  dft972((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft972((int16_t *)(x2128+972),(int16_t *)(ytmp128+972),1);
+  dft972((int16_t *)(x2128+1944),(int16_t *)(ytmp128+1944),1);
+
+  bfly3_tw1(ytmp128,ytmp128+972,ytmp128+1944,y128,y128+972,y128+1944);
+
+  for (i=1,j=0; i<972; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+972+i,
+          ytmp128+1944+i,
+          y128+i,
+          y128+972+i,
+          y128+1944+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<2916; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+static int16_t twa3000[599*8]__attribute__((aligned(32)));
+static int16_t twb3000[599*8]__attribute__((aligned(32)));
+static int16_t twc3000[599*8]__attribute__((aligned(32)));
+static int16_t twd3000[599*8]__attribute__((aligned(32)));
+
+void dft3000(int16_t *x,int16_t *y,unsigned char scale_flag) // 600 * 5
+{
+
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa3000[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb3000[0];
+  simd_q15_t *twc128=(simd_q15_t *)&twc3000[0];
+  simd_q15_t *twd128=(simd_q15_t *)&twd3000[0];
+  simd_q15_t x2128[3000];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[3000];//=&ytmp128array2[0];
+
+
+
+  for (i=0,j=0; i<600; i++,j+=5) {
+    x2128[i]    = x128[j];
+    x2128[i+600] = x128[j+1];
+    x2128[i+1200] = x128[j+2];
+    x2128[i+1800] = x128[j+3];
+    x2128[i+2400] = x128[j+4];
+  }
+
+  dft600((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft600((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1);
+  dft600((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1);
+  dft600((int16_t *)(x2128+1800),(int16_t *)(ytmp128+1800),1);
+  dft600((int16_t *)(x2128+2400),(int16_t *)(ytmp128+2400),1);
+
+  bfly5_tw1(ytmp128,ytmp128+600,ytmp128+1200,ytmp128+1800,ytmp128+2400,y128,y128+600,y128+1200,y128+1800,y128+2400);
+
+  for (i=1,j=0; i<600; i++,j++) {
+    bfly5(ytmp128+i,
+          ytmp128+600+i,
+          ytmp128+1200+i,
+          ytmp128+1800+i,
+          ytmp128+2400+i,
+          y128+i,
+          y128+600+i,
+          y128+1200+i,
+          y128+1800+i,
+          y128+2400+i,
+          twa128+j,
+          twb128+j,
+          twc128+j,
+          twd128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[15]);
+
+    for (i=0; i<3000; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+}
+
+static int16_t twa3240[1079*2*4];
+static int16_t twb3240[1079*2*4];
+
+void dft3240(int16_t *x,int16_t *y,unsigned char scale_flag)  // 1080 x 3
+{
+  int i,j;
+  simd_q15_t *x128=(simd_q15_t *)x;
+  simd_q15_t *y128=(simd_q15_t *)y;
+  simd_q15_t *twa128=(simd_q15_t *)&twa3240[0];
+  simd_q15_t *twb128=(simd_q15_t *)&twb3240[0];
+  simd_q15_t x2128[3240];// = (simd_q15_t *)&x2128array[0];
+  simd_q15_t ytmp128[3240];//=&ytmp128array3[0];
+
+
+
+  for (i=0,j=0; i<1080; i++,j+=3) {
+    x2128[i]    = x128[j];
+    x2128[i+1080] = x128[j+1];
+    x2128[i+2160] = x128[j+2];
+  }
+
+  dft1080((int16_t *)x2128,(int16_t *)ytmp128,1);
+  dft1080((int16_t *)(x2128+1080),(int16_t *)(ytmp128+1080),1);
+  dft1080((int16_t *)(x2128+2160),(int16_t *)(ytmp128+2160),1);
+
+  bfly3_tw1(ytmp128,ytmp128+1080,ytmp128+2160,y128,y128+1080,y128+2160);
+
+  for (i=1,j=0; i<1080; i++,j++) {
+    bfly3(ytmp128+i,
+          ytmp128+1080+i,
+          ytmp128+2160+i,
+          y128+i,
+          y128+1080+i,
+          y128+2160+i,
+          twa128+j,
+          twb128+j);
+  }
+
+  if (scale_flag==1) {
+    norm128 = set1_int16(dft_norm_table[14]);
+
+    for (i=0; i<3240; i++) {
+      y128[i] = mulhi_int16(y128[i],norm128);
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+};
+
+void init_rad4(int N,int16_t *tw) {
+
+  int16_t *twa = tw;
+  int16_t *twb = twa+(N/2);
+  int16_t *twc = twb+(N/2);
+  int i;
+
+  for (i=0;i<(N/4);i++) {
+    *twa = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa++;
+    *twa = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twa++;
+    *twb = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb++;
+    *twb = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); twb++;
+    *twc = (int16_t)round(32767.0*cos(2*M_PI*3*i/N)); twc++;
+    *twc = -(int16_t)round(32767.0*sin(2*M_PI*3*i/N)); twc++;
+  }
+}
+void init_rad4_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc) {
+
+  int i,j;
+
+  for (i=1;i<(N/4);i++) {
+    twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N));
+    twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N));
+    twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N));
+    twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N));
+    twc[0] = (int16_t)round(32767.0*cos(2*M_PI*3*i/N));
+    twc[1] = -(int16_t)round(32767.0*sin(2*M_PI*3*i/N));
+    for (j=1;j<4;j++) {
+      ((int32_t*)twa)[j]=((int32_t*)twa)[0];
+      ((int32_t*)twb)[j]=((int32_t*)twb)[0];
+      ((int32_t*)twc)[j]=((int32_t*)twc)[0];
+    }
+    twa+=8;
+    twb+=8;
+    twc+=8;
+  }
+}
+
+void init_rad2(int N,int16_t *tw) {
+
+  int16_t *twa = tw;
+  int i;
+
+  for (i=0;i<(N>>1);i++) {
+    *twa = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa++;
+    *twa = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twa++;
+  }
+}
+
+void init_rad2_rep(int N,int16_t *twa) {
+
+  int i,j;
+
+  for (i=1;i<(N/2);i++) {
+    twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N));
+    twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N));
+    for (j=1;j<4;j++) {
+      ((int32_t*)twa)[j]=((int32_t*)twa)[0];
+    }
+    twa+=8;
+  }
+}
+
+void init_rad3(int N,int16_t *twa,int16_t *twb) {
+
+  int i;
+
+  for (i=0;i<(N/3);i++) {
+    *twa = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa++;
+    *twa = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twa++;
+    *twb = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb++;
+    *twb = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); twb++;
+  }
+}
+
+void init_rad3_rep(int N,int16_t *twa,int16_t *twb) {
+
+  int i,j;
+
+  for (i=1;i<(N/3);i++) {
+    twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N));
+    twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N));
+    twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N));
+    twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N));
+    for (j=1;j<4;j++) {
+      ((int32_t*)twa)[j]=((int32_t*)twa)[0];
+      ((int32_t*)twb)[j]=((int32_t*)twb)[0];
+    }
+    twa+=8;
+    twb+=8;
+  }
+}
+
+void init_rad5_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc,int16_t *twd) {
+
+  int i,j;
+
+  for (i=1;i<(N/5);i++) {
+    twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N));
+    twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N));
+    twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N));
+    twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N));
+    twc[0] = (int16_t)round(32767.0*cos(2*M_PI*3*i/N));
+    twc[1] = -(int16_t)round(32767.0*sin(2*M_PI*3*i/N));
+    twd[0] = (int16_t)round(32767.0*cos(2*M_PI*4*i/N));
+    twd[1] = -(int16_t)round(32767.0*sin(2*M_PI*4*i/N));
+    for (j=1;j<4;j++) {
+      ((int32_t*)twa)[j]=((int32_t*)twa)[0];
+      ((int32_t*)twb)[j]=((int32_t*)twb)[0];
+      ((int32_t*)twc)[j]=((int32_t*)twc)[0];
+      ((int32_t*)twd)[j]=((int32_t*)twd)[0];
+    }
+    twa+=8;
+    twb+=8;
+    twc+=8;
+    twd+=8;
+  }
+}
+/*----------------------------------------------------------------*/
+/* dft library entry points:                                      */
+
+int dfts_autoinit(void)
+{
+  init_rad4(1024,tw1024);
+  init_rad2(2048,tw2048);
+  init_rad4(4096,tw4096);
+  init_rad2(8192,tw8192);
+  init_rad4(16384,tw16384);
+  init_rad2(32768,tw32768);
+
+  init_rad3(1536,twa1536,twb1536);
+  init_rad3(3072,twa3072,twb3072);
+  init_rad3(6144,twa6144,twb6144);
+  init_rad3(12288,twa12288,twb12288);
+  init_rad3(18432,twa18432,twb18432);
+  init_rad3(24576,twa24576,twb24576);
+  init_rad3(36864,twa36864,twb36864);
+  init_rad3(49152,twa49152,twb49152);
+  init_rad3(98304,twa98304,twb98304);
 
 
   init_rad2_rep(24,tw24);
@@ -9645,6 +10556,24 @@ int dfts_autoinit(void)
   init_rad3_rep(1080,twa1080,twb1080);
   init_rad4_rep(1152,twa1152,twb1152,twc1152);
   init_rad4_rep(1200,twa1200,twb1200,twc1200);
+  init_rad3_rep(1296,twa1296,twb1296);
+  init_rad3_rep(1440,twa1440,twb1440);
+  init_rad5_rep(1500,twa1500,twb1500,twc1500,twd1500);
+  init_rad3_rep(1620,twa1620,twb1620);
+  init_rad3_rep(1728,twa1728,twb1728);
+  init_rad3_rep(1800,twa1800,twb1800);
+  init_rad4_rep(1920,twa1920,twb1920, twc1920);
+  init_rad3_rep(1944,twa1944,twb1944);
+  init_rad3_rep(2160,twa2160,twb2160);
+  init_rad3_rep(2304,twa2304,twb2304);
+  init_rad4_rep(2400,twa2400,twb2400,twc2400);
+  init_rad3_rep(2592,twa2592,twb2592);
+  init_rad3_rep(2700,twa2700,twb2700);
+  init_rad3_rep(2880,twa2880,twb2880);
+  init_rad3_rep(2916,twa2916,twb2916);
+  init_rad5_rep(3000,twa3000,twb3000,twc3000,twd3000);
+  init_rad3_rep(3240,twa3240,twb3240);
+
   return 0;
 }
 
diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h
index 12467e1fdc226fe701827223deaf964c4ae47413..db7ac3d813cb6266cc99b41dd0681db4a70d3d7c 100644
--- a/openair1/PHY/TOOLS/tools_defs.h
+++ b/openair1/PHY/TOOLS/tools_defs.h
@@ -226,9 +226,26 @@ void dft1024(int16_t *x,int16_t *y,uint8_t scale_flag);
 void dft1080(int16_t *x,int16_t *y,uint8_t scale_flag);
 void dft1152(int16_t *x,int16_t *y,uint8_t scale_flag);
 void dft1200(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft1296(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft1440(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft1500(int16_t *x,int16_t *y,uint8_t scale_flag);
 void dft1536(int16_t *sigF,int16_t *sig,uint8_t scale_flag);
+void dft1620(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft1728(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft1800(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft1920(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft1944(int16_t *x,int16_t *y,uint8_t scale_flag);
 void dft2048(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft2160(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft2304(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft2400(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft2592(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft2700(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft2880(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft2916(int16_t *x,int16_t *y,uint8_t scale_flag);
+void dft3000(int16_t *x,int16_t *y,uint8_t scale_flag);
 void dft3072(int16_t *sigF,int16_t *sig,uint8_t scale_flag);
+void dft3240(int16_t *x,int16_t *y,uint8_t scale_flag);
 void dft4096(int16_t *x,int16_t *y,uint8_t scale_flag);
 void dft6144(int16_t *sigF,int16_t *sig,uint8_t scale_flag);
 void dft8192(int16_t *x,int16_t *y,uint8_t scale_flag);
@@ -283,21 +300,25 @@ typedef enum DFT_size_idx {
 	DFT_108,   DFT_120,   DFT_128,  DFT_144,    DFT_180,  DFT_192,  DFT_216,   DFT_240,
 	DFT_256,   DFT_288,   DFT_300,  DFT_324,    DFT_360,  DFT_384,  DFT_432,   DFT_480,
 	DFT_512,   DFT_540,   DFT_576,  DFT_600,    DFT_648,  DFT_720,  DFT_768,   DFT_864,
-	DFT_900,   DFT_960,   DFT_972,  DFT_1024,   DFT_1080, DFT_1152, DFT_1200,  DFT_1536,
-	DFT_2048,  DFT_3072,  DFT_4096, DFT_6144,   DFT_8192, DFT_9216, DFT_12288, DFT_18432, 
-	DFT_24576, DFT_36864, DFT_49152, DFT_73728, DFT_98304,
+	DFT_900,   DFT_960,   DFT_972,  DFT_1024,   DFT_1080, DFT_1152, DFT_1200,  DFT_1296,
+	DFT_1440,  DFT_1500,  DFT_1536, DFT_1620,   DFT_1728, DFT_1800, DFT_1920,  DFT_1944,
+	DFT_2048,  DFT_2160,  DFT_2304, DFT_2400,   DFT_2592, DFT_2700, DFT_2880,  DFT_2916,
+	DFT_3000,  DFT_3072,  DFT_3240, DFT_4096,   DFT_6144, DFT_8192, DFT_9216,  DFT_12288,
+	DFT_18432, DFT_24576, DFT_36864, DFT_49152, DFT_73728, DFT_98304,
 	DFT_SIZE_IDXTABLESIZE
 } dft_size_idx_t;
 
 #ifdef OAIDFTS_MAIN
 adftfunc_t dft_ftab[]={
 	dft12,    dft24,    dft36,    dft48,    dft60,   dft72,   dft96,
-	dft108,   dft120,   dft128,   dft144,   dft180,  dft192,  dft216,   dft240,   
+	dft108,   dft120,   dft128,   dft144,   dft180,  dft192,  dft216,   dft240,
 	dft256,   dft288,   dft300,   dft324,   dft360,  dft384,  dft432,   dft480,
 	dft512,   dft540,   dft576,   dft600,   dft648,  dft720,  dft768,   dft864,
-	dft900,   dft960,   dft972,   dft1024,  dft1080, dft1152, dft1200,  dft1536,
-	dft2048,  dft3072,  dft4096,  dft6144,  dft8192, dft9216, dft12288, dft18432, 
-	dft24576, dft36864, dft49152, dft73728, dft98304
+	dft900,   dft960,   dft972,   dft1024,  dft1080, dft1152, dft1200,  dft1296,
+	dft1440,  dft1500,  dft1536,  dft1620,  dft1728, dft1800, dft1920,  dft1944,
+	dft2048,  dft2160,  dft2304,  dft2400,  dft2592, dft2700, dft2880,  dft2916,
+	dft3000,  dft3072,  dft3240,  dft4096,  dft6144, dft8192, dft9216,  dft12288,
+	dft18432, dft24576, dft36864, dft49152, dft73728, dft98304
 };
 #endif
 
@@ -309,9 +330,9 @@ typedef enum idft_size_idx {
 } idft_size_idx_t;
 #ifdef OAIDFTS_MAIN
 aidftfunc_t idft_ftab[]={
-        idft128,   idft256,  idft512,   idft1024,  idft1536,  idft2048,  idft3072,  idft4096,
-	    idft6144,  idft8192, idft9216,  idft12288, idft18432, idft24576, idft36864, idft49152, 
-	    idft73728, idft98304
+	idft128,   idft256,  idft512,   idft1024,  idft1536,  idft2048,  idft3072,  idft4096,
+	idft6144,  idft8192, idft9216,  idft12288, idft18432, idft24576, idft36864, idft49152,
+	idft73728, idft98304
 };
 #endif
 
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 55626e386ecd361dd6ec2608c8d3274339a2cc06..9f97b7eadf30232bb3281a811b99a616aa3ea060 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -552,6 +552,11 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
 
   gNB_I0_measurements(gNB);
 
+  // measure enegry in SS=10 L=4, nb_rb = 18, first_rb = 0 (corresponds to msg3)
+  int offset = 10*gNB->frame_parms.ofdm_symbol_size + gNB->frame_parms.first_carrier_offset;
+  int power_rxF = signal_energy_nodc(&gNB->common_vars.rxdataF[0][offset],12*18);
+  LOG_D(PHY,"frame %d, slot %d: UL signal energy %d\n",frame_rx,slot_rx,power_rxF);
+
   for (int i=0;i<NUMBER_OF_NR_PUCCH_MAX;i++){
     NR_gNB_PUCCH_t *pucch = gNB->pucch[i];
     if (pucch) {
@@ -647,6 +652,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
           }
 #endif
 
+T(T_BENETEL, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], 2048*4*14));
+
           uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index;
           uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols;
           VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,1);
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index babcf67227d6ece10ee453615841de7d3229a3e3..678453539143a1a76faaccfaecc1d674fc9124c6 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -151,6 +151,12 @@ nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
   return 0;
 }
 
+int nr_derive_key(int alg_type, uint8_t alg_id,
+               const uint8_t key[32], uint8_t **out)
+{
+  return 0;
+}
+
 void config_common(int Mod_idP,
                    int pdsch_AntennaPorts, 
 		   NR_ServingCellConfigCommon_t *scc
diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c
index 3fce86c88019bf424243876683a1473c268263f5..c90bcf1395d9dbd7755b30a3bd3b0b8c503de9e9 100644
--- a/openair1/SIMULATION/NR_PHY/prachsim.c
+++ b/openair1/SIMULATION/NR_PHY/prachsim.c
@@ -142,6 +142,12 @@ int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index
   return 0;
 }
 
+int nr_derive_key(int alg_type, uint8_t alg_id,
+               const uint8_t key[32], uint8_t **out)
+{
+  return 0;
+}
+
 int main(int argc, char **argv){
 
   char c;
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index 997e2ba4008d71c4b935c530f3b9716104f8bb19..443ee6e1c0ccef6c04e347c99f8365902dc456ee 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -165,6 +165,12 @@ int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index
   return 0;
 }
 
+int nr_derive_key(int alg_type, uint8_t alg_id,
+               const uint8_t key[32], uint8_t **out)
+{
+  return 0;
+}
+
 // needed for some functions
 uint16_t n_rnti = 0x1234;
 openair0_config_t openair0_cfg[MAX_CARDS];
diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h
index f6b4f3c4e2a99dae1df8a3942a45e23a866db2ef..bd0788d2d0efd6353df7ea996e78dfddcbe62fa0 100644
--- a/openair2/COMMON/s1ap_messages_types.h
+++ b/openair2/COMMON/s1ap_messages_types.h
@@ -155,6 +155,11 @@ typedef struct security_capabilities_s {
   uint16_t integrity_algorithms;
 } security_capabilities_t;
 
+typedef struct nr_security_capabilities_s {
+  uint16_t encryption_algorithms;
+  uint16_t integrity_algorithms;
+} nr_security_capabilities_t;
+
 /* Provides the establishment cause for the RRC connection request as provided
  * by the upper layers. W.r.t. the cause value names: highPriorityAccess
  * concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for
@@ -538,6 +543,9 @@ typedef struct s1ap_initial_context_setup_req_s {
   uint8_t  nb_of_e_rabs;
   /* list of e_rab to be setup by RRC layers */
   e_rab_t  e_rab_param[S1AP_MAX_E_RAB];
+
+  /* NR Security algorithms (if any, set to 0 if not present) */
+  nr_security_capabilities_t nr_security_capabilities;
 } s1ap_initial_context_setup_req_t;
 
 typedef struct tai_plmn_identity_s {
diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h
index 0c55764d6e2602b9dd94948e0fcc1960e150df6a..f4911c47dc6bf112c06ba2df289785d95f89da71 100644
--- a/openair2/COMMON/x2ap_messages_types.h
+++ b/openair2/COMMON/x2ap_messages_types.h
@@ -338,7 +338,7 @@ typedef struct x2ap_ENDC_sgnb_addition_req_s {
   /* used for RRC->X2AP in source eNB */
   int rnti;
 
-  security_capabilities_t security_capabilities;
+  nr_security_capabilities_t security_capabilities;
 
   /* SgNB Security Key */
   uint8_t      kgnb[32];
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 4ee676a49e8344514cb6b0e47def35458838e904..957485a9923341f75b8373efc4a05fbd3a183d66 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -163,6 +163,8 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) {
   //  scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB_SUL        = CALLOC(1,sizeof(NR_RSRP_Range_t));
   scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing       = CALLOC(1,sizeof(NR_SubcarrierSpacing_t));
   scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder       = CALLOC(1,sizeof(long));
+  // 0 - ENABLE, 1 - DISABLE, hence explicitly setting to DISABLED.
+  *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder       = NR_PUSCH_Config__transformPrecoder_disabled;
   scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon                 = CALLOC(1,sizeof(NR_SetupRelease_PUSCH_ConfigCommon_t)); 
   scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->present        = NR_SetupRelease_PUSCH_ConfigCommon_PR_setup;
   scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup   = CALLOC(1,sizeof(struct NR_PUSCH_ConfigCommon));
@@ -513,6 +515,101 @@ void RCconfig_nr_macrlc() {
 
 }
 
+void config_security(gNB_RRC_INST *rrc)
+{
+  paramdef_t logparams_defaults[] = SECURITY_GLOBALPARAMS_DESC;
+  int ret = config_get(logparams_defaults,
+                       sizeof(logparams_defaults) / sizeof(paramdef_t),
+                       CONFIG_STRING_SECURITY);
+  int i;
+
+  if (ret < 0) {
+    LOG_W(RRC, "configuration file does not contain a \"security\" section, applying default parameters (no security)\n");
+    rrc->security.ciphering_algorithms[0]    = 0;  /* nea0 = no ciphering */
+    rrc->security.ciphering_algorithms_count = 1;
+    rrc->security.integrity_algorithms[0]    = 0;  /* nia0 = no integrity */
+    rrc->security.integrity_algorithms_count = 1;
+    return;
+  }
+
+  if (logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].numelt > 4) {
+    LOG_E(RRC, "too much ciphering algorithms in section \"security\" of the configuration file, maximum is 4\n");
+    exit(1);
+  }
+  if (logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].numelt > 4) {
+    LOG_E(RRC, "too much integrity algorithms in section \"security\" of the configuration file, maximum is 4\n");
+    exit(1);
+  }
+
+  /* get ciphering algorithms */
+  rrc->security.ciphering_algorithms_count = 0;
+  for (i = 0; i < logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].numelt; i++) {
+    if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea0")) {
+      rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 0;
+      rrc->security.ciphering_algorithms_count++;
+      continue;
+    }
+    if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea1")) {
+      rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 1;
+      rrc->security.ciphering_algorithms_count++;
+      continue;
+    }
+    if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea2")) {
+      rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 2;
+      rrc->security.ciphering_algorithms_count++;
+      continue;
+    }
+    if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea3")) {
+      rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 3;
+      rrc->security.ciphering_algorithms_count++;
+      continue;
+    }
+    LOG_E(RRC, "unknown ciphering algorithm \"%s\" in section \"security\" of the configuration file\n",
+          logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i]);
+    exit(1);
+  }
+
+  /* get integrity algorithms */
+  rrc->security.integrity_algorithms_count = 0;
+  for (i = 0; i < logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].numelt; i++) {
+    if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia0")) {
+      rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 0;
+      rrc->security.integrity_algorithms_count++;
+      continue;
+    }
+    if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia1")) {
+      rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 1;
+      rrc->security.integrity_algorithms_count++;
+      continue;
+    }
+    if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia2")) {
+      rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 2;
+      rrc->security.integrity_algorithms_count++;
+      continue;
+    }
+    if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia3")) {
+      rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 3;
+      rrc->security.integrity_algorithms_count++;
+      continue;
+    }
+    LOG_E(RRC, "unknown integrity algorithm \"%s\" in section \"security\" of the configuration file\n",
+          logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i]);
+    exit(1);
+  }
+
+  if (rrc->security.ciphering_algorithms_count == 0) {
+    LOG_W(RRC, "no preferred ciphering algorithm set in configuration file, applying default parameters (no security)\n");
+    rrc->security.ciphering_algorithms[0]    = 0;  /* nea0 = no ciphering */
+    rrc->security.ciphering_algorithms_count = 1;
+  }
+
+  if (rrc->security.integrity_algorithms_count == 0) {
+    LOG_W(RRC, "no preferred integrity algorithm set in configuration file, applying default parameters (no security)\n");
+    rrc->security.integrity_algorithms[0]    = 0;  /* nia0 = no integrity */
+    rrc->security.integrity_algorithms_count = 1;
+  }
+}
+
 void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
 
   int                    num_gnbs                                                      = 0;
@@ -679,7 +776,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
     }//End for (k=0; k <num_gnbs ; k++)
   }//End if (num_gnbs>0)
 
-
+  config_security(rrc);
 }//End RCconfig_NRRRC function
 
 int RCconfig_nr_gtpu(void ) {
diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h
index f1fe0c97c9128be73e3758fe0e0eacfcac73eeb2..403602c109ff6ce4899c02268223bee6b610be44 100644
--- a/openair2/GNB_APP/gnb_paramdef.h
+++ b/openair2/GNB_APP/gnb_paramdef.h
@@ -452,4 +452,27 @@ typedef enum {
 #define CONFIG_HLP_WORKER                          "coding and FEP worker thread WORKER_DISABLE or WORKER_ENABLE\n"
 #define CONFIG_HLP_PARALLEL                        "PARALLEL_SINGLE_THREAD, PARALLEL_RU_L1_SPLIT, or PARALLEL_RU_L1_TRX_SPLIT(RU_L1_TRX_SPLIT by defult)\n"
 /*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* security configuration                                                                                                                                                           */
+/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+#define CONFIG_STRING_SECURITY      "security"
+
+#define SECURITY_CONFIG_CIPHERING   "ciphering_algorithms"
+#define SECURITY_CONFIG_INTEGRITY   "integrity_algorithms"
+
+/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*   security configuration                                                                                                                                                         */
+/*   optname                               help                                          paramflags         XXXptr               defXXXval                 type              numelt */
+/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+#define SECURITY_GLOBALPARAMS_DESC { \
+    {SECURITY_CONFIG_CIPHERING,            "preferred ciphering algorithms\n",            0,                strlistptr:NULL,      defstrlistval:NULL,       TYPE_STRINGLIST,  0}, \
+    {SECURITY_CONFIG_INTEGRITY,            "preferred integrity algorithms\n",            0,                strlistptr:NULL,      defstrlistval:NULL,       TYPE_STRINGLIST,  0}, \
+}
+
+#define SECURITY_CONFIG_CIPHERING_IDX   0
+#define SECURITY_CONFIG_INTEGRITY_IDX   1
+/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+
 #endif
diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index efdc031038f9bea5e767b9e980d28657e6f99cc5..bce07195562851925fb7901b74f79f6c9bb9a55a 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -401,21 +401,37 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
       const int UE_id = add_new_nr_ue(Mod_idP, rnti, secondaryCellGroup);
       LOG_I(PHY,"Added new UE_id %d/%x with initial secondaryCellGroup\n",UE_id,rnti);
     } else if (add_ue == 1 && !get_softmodem_params()->phy_test) {
-      /* TODO: should check for free RA process */
       const int CC_id = 0;
-      NR_RA_t *ra = &RC.nrmac[Mod_idP]->common_channels[CC_id].ra[0];
-      ra->state = RA_IDLE;
+      NR_COMMON_channels_t *cc = &RC.nrmac[Mod_idP]->common_channels[CC_id];
+      uint8_t ra_index = 0;
+      /* checking for free RA process */
+      for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) {
+        if((cc->ra[ra_index].state == RA_IDLE) && (!cc->ra[ra_index].cfra)) break;
+      }
+      if (ra_index == NR_NB_RA_PROC_MAX) {
+        LOG_E(MAC, "%s() %s:%d RA processes are not available for CFRA RNTI :%x\n", __FUNCTION__, __FILE__, __LINE__, rnti);
+        return -1;
+      }	
+      NR_RA_t *ra = &cc->ra[ra_index];
       ra->secondaryCellGroup = secondaryCellGroup;
       if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated!=NULL) {
         if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) {
           ra->cfra = true;
           ra->rnti = rnti;
-          struct NR_CFRA cfra = *secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra;
-          uint8_t num_preamble = cfra.resources.choice.ssb->ssb_ResourceList.list.count;
+          struct NR_CFRA *cfra = secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra;
+          uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count;
           ra->preambles.num_preambles = num_preamble;
           ra->preambles.preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t));
-          for (int i = 0; i < num_preamble; i++)
-            ra->preambles.preamble_list[i] = cfra.resources.choice.ssb->ssb_ResourceList.list.array[i]->ra_PreambleIndex;
+          for(int i=0; i<cc->num_active_ssb; i++) {
+            for(int j=0; j<num_preamble; j++) {
+              if (cc->ssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) {
+                // one dedicated preamble for each beam
+                ra->preambles.preamble_list[i] =
+                    cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ra_PreambleIndex;
+                break;
+              }
+            }
+          }
         }
       }
       LOG_I(PHY,"Added new RA process for UE RNTI %04x with initial secondaryCellGroup\n", rnti);
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index e356afb339b41379bfc824b5abd6da7c0e41c213..e2d5db0799ee61a84f8fb87629d92e93e4504a0d 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -372,7 +372,13 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
 #define BIT(x) (1 << (x))
   const uint64_t dlsch_in_slot_bitmap = BIT( 1) | BIT( 2) | BIT( 3) | BIT( 4) | BIT( 5) | BIT( 6)
                                       | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16);
-  const uint64_t ulsch_in_slot_bitmap = BIT( 8) | BIT(18);
+
+  uint8_t prach_config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
+  uint64_t ulsch_in_slot_bitmap;
+  if (prach_config_index==4) //this is the PRACH config used in the Benetel RRU. TODO: make this generic for any PRACH config. 
+    ulsch_in_slot_bitmap = BIT( 8) | BIT( 9);
+  else
+    ulsch_in_slot_bitmap = BIT( 8) | BIT(18);
 
   memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0
   memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index b914e80d23bc04ebd13e8ba268bc9df1dc9633b2..ac3a4e77d236626f371e93313d1c6105008da7bc 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -151,6 +151,38 @@ void find_SSB_and_RO_available(module_id_t module_idP) {
   uint8_t num_active_ssb = 0;
   uint8_t max_association_period = 1;
 
+  struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *ssb_perRACH_OccasionAndCB_PreamblesPerSSB = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB;
+
+  switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present){
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
+      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
+      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
+      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
+      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
+      cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
+      cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four;
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
+      cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight;
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
+      cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen;
+      break;
+    default:
+      AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present);
+      break;
+    }
+
   if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
     mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
   else
@@ -181,25 +213,28 @@ void find_SSB_and_RO_available(module_id_t module_idP) {
     }
   }
 
-  for(int i = 1; (1 << (i-1)) <= max_association_period;i++) {
+  cc->total_prach_occasions_per_config_period = total_RA_occasions;
+  for(int i=1; (1 << (i-1)) < max_association_period; i++) {
+    cc->max_association_period = (1 <<(i-1));
+    total_RA_occasions = total_RA_occasions * cc->max_association_period;
     if(total_RA_occasions >= (int) (num_active_ssb/num_ssb_per_RO)) {
       repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb);
       break;
     }
-    else {
-      total_RA_occasions = total_RA_occasions * i;
-      cc->max_association_period = i;
-    }
   }
-  if(cc->max_association_period == 0)
-    cc->max_association_period = 1;
 
   unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO);
   cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion;
   cc->num_active_ssb = num_active_ssb;
 
-  LOG_I(MAC, "Total available RO %d, num of active SSB %d: unused RO = %d max_association_period %u N_RA_sfn %u \n",
-        cc->total_prach_occasions, cc->num_active_ssb, unused_RA_occasion, max_association_period, N_RA_sfn);
+  LOG_I(MAC,
+        "Total available RO %d, num of active SSB %d: unused RO = %d association_period %u N_RA_sfn %u total_prach_occasions_per_config_period %u\n",
+        cc->total_prach_occasions,
+        cc->num_active_ssb,
+        unused_RA_occasion,
+        cc->max_association_period,
+        N_RA_sfn,
+        cc->total_prach_occasions_per_config_period);
 }		
 		
 void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
@@ -439,139 +474,167 @@ void nr_initiate_ra_proc(module_id_t module_idP,
   gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
   NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
   NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
-  NR_RA_t *ra = &cc->ra[0];
-
-  uint16_t ra_rnti;
-
-  // ra_rnti from 5.1.3 in 38.321
-  // FK: in case of long PRACH the phone seems to expect the subframe number instead of the slot number here. 
-  if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present==NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l839) 
-   ra_rnti=1+symbol+(9/*slotP*/*14)+(freq_index*14*80)+(ul_carrier_id*14*80*8);
-  else
-   ra_rnti=1+symbol+(slotP*14)+(freq_index*14*80)+(ul_carrier_id*14*80*8);
-
 
-  // if the preamble received correspond to one of the listed
-  // the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries
-  int pr_found=0;
-  for (int i = 0; i < ra->preambles.num_preambles; i++) {
-    if (preamble_index == ra->preambles.preamble_list[i]) {
-      pr_found=1;
-      break;
-    }
-  }
-
-  if (!pr_found) {
-    LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n",
-          module_idP, preamble_index);
+  uint8_t total_RApreambles = 64;
+  uint8_t  num_ssb_per_RO = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;	
+  int pr_found;
 
-    return; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
+  if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL)
+    total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles;	
+  
+  if(num_ssb_per_RO > 3) { /*num of ssb per RO >= 1*/
+    num_ssb_per_RO -= 3;
+    total_RApreambles = total_RApreambles/num_ssb_per_RO ;
   }
-  // This should be handled differently when we use the initialBWP for RA
-  ra->bwp_id=1;
-  NR_BWP_Downlink_t *bwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1];
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1);
-
-  LOG_I(MAC, "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d  Initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, slotP, preamble_index);
-
-  if (ra->state == RA_IDLE) {
 
-    uint8_t beam_index = ssb_index_from_prach(module_idP,
-		                              frameP,
-					      slotP,
-					      preamble_index,
-					      freq_index,
-					      symbol);
-    int loop = 0;
-    LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP);
-    ra->state = Msg2;
-    ra->timing_offset = timing_offset;
-    ra->preamble_slot = slotP;
-
-    struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
-    AssertFatal(commonSearchSpaceList->list.count>0,
-	        "common SearchSpace list has 0 elements\n");
-    // Common searchspace list
-    for (int i=0;i<commonSearchSpaceList->list.count;i++) {
-      ss=commonSearchSpaceList->list.array[i];
-      if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)
-        ra->ra_ss=ss;
-    }
-
-    // retrieving ra pdcch monitoring period and offset
-    find_monitoring_periodicity_offset_common(ra->ra_ss,
-                                              &monitoring_slot_period,
-                                              &monitoring_offset);
+  for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
+    NR_RA_t *ra = &cc->ra[i];
+    pr_found = 0;
+    if (ra->state == RA_IDLE) {
+      for(int j = 0; j < ra->preambles.num_preambles; j++) {
+        //check if the preamble received correspond to one of the listed or configured preambles
+        if (preamble_index == ra->preambles.preamble_list[j]) {
+          pr_found=1;
+          break;
+        }
+      }
 
-    nr_schedule_msg2(frameP, slotP, &msg2_frame, &msg2_slot, scc, monitoring_slot_period, monitoring_offset,beam_index,cc->num_active_ssb);
+      if (pr_found == 0) {
+         continue;
+      }
 
-    ra->Msg2_frame = msg2_frame;
-    ra->Msg2_slot = msg2_slot;
+      uint16_t ra_rnti;
 
-    LOG_I(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
-    if (!ra->cfra) {
-      do {
-        ra->rnti = (taus() % 65518) + 1;
-        loop++;
+      // ra_rnti from 5.1.3 in 38.321
+      // FK: in case of long PRACH the phone seems to expect the subframe number instead of the slot number here.
+      if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present
+          == NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l839)
+        ra_rnti = 1 + symbol + (9 /*slotP*/ * 14) + (freq_index * 14 * 80) + (ul_carrier_id * 14 * 80 * 8);
+      else
+        ra_rnti = 1 + symbol + (slotP * 14) + (freq_index * 14 * 80) + (ul_carrier_id * 14 * 80 * 8);
+
+      // This should be handled differently when we use the initialBWP for RA
+      ra->bwp_id = 1;
+      NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList
+                                   ->list.array[ra->bwp_id - 1];
+
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1);
+
+      LOG_I(MAC,
+            "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d  Initiating RA procedure for preamble index %d\n",
+            module_idP,
+            CC_id,
+            frameP,
+            slotP,
+            preamble_index);
+
+      uint8_t beam_index = ssb_index_from_prach(module_idP, frameP, slotP, preamble_index, freq_index, symbol);
+
+      // the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries
+      if (ra->cfra) {
+        // if the preamble received correspond to one of the listed
+        if (!(preamble_index == ra->preambles.preamble_list[beam_index])) {
+          LOG_E(
+              MAC,
+              "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n",
+              module_idP,
+              preamble_index);
+          continue; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
+        }
       }
-      while (loop != 100 && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1) && ra->rnti >= 1 && ra->rnti <= 65519));
-      if (loop == 100) {
-        LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
-        abort();
+      int loop = 0;
+      LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP);
+      ra->state = Msg2;
+      ra->timing_offset = timing_offset;
+      ra->preamble_slot = slotP;
+
+      struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList =
+          bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
+      AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n");
+      // Common searchspace list
+      for (int i = 0; i < commonSearchSpaceList->list.count; i++) {
+        ss = commonSearchSpaceList->list.array[i];
+        if (ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)
+          ra->ra_ss = ss;
       }
-    }
-    ra->RA_rnti = ra_rnti;
-    ra->preamble_index = preamble_index;
-    ra->beam_id = beam_index;
-
-    LOG_I(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB index %u\n",
-      module_idP,
-      CC_id,
-      frameP,
-      ra->Msg2_frame,
-      ra->Msg2_slot,
-      ra->RA_rnti,
-      cc->ssb_index[beam_index]);
 
-    return;
+      // retrieving ra pdcch monitoring period and offset
+      find_monitoring_periodicity_offset_common(ra->ra_ss, &monitoring_slot_period, &monitoring_offset);
+
+      nr_schedule_msg2(frameP,
+                       slotP,
+                       &msg2_frame,
+                       &msg2_slot,
+                       scc,
+                       monitoring_slot_period,
+                       monitoring_offset,
+                       beam_index,
+                       cc->num_active_ssb);
+
+      ra->Msg2_frame = msg2_frame;
+      ra->Msg2_slot = msg2_slot;
+
+      LOG_I(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
+      if (!ra->cfra) {
+        do {
+          ra->rnti = (taus() % 65518) + 1;
+          loop++;
+        } while (loop != 100
+                 && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1)
+                      && ra->rnti >= 1 && ra->rnti <= 65519));
+        if (loop == 100) {
+          LOG_E(MAC, "%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
+          abort();
+        }
+      }
+      ra->RA_rnti = ra_rnti;
+      ra->preamble_index = preamble_index;
+      ra->beam_id = beam_index;
+
+      LOG_I(MAC,
+            "[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB "
+            "index %u\n",
+            module_idP,
+            CC_id,
+            frameP,
+            ra->Msg2_frame,
+            ra->Msg2_slot,
+            ra->RA_rnti,
+            cc->ssb_index[beam_index]);
+
+      return;
+    }
   }
   LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d Frame %d initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, preamble_index);
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0);
 }
 
-void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
-
-  //uint8_t i = 0;
-  int CC_id = 0;
+void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
+{
   gNB_MAC_INST *mac = RC.nrmac[module_idP];
-  NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
 
   start_meas(&mac->schedule_ra);
-
-//  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
-//    for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
-  
-//	NR_RA_t *ra = &cc->ra[i];
-	NR_RA_t *ra = &cc->ra[0];
-
-  LOG_D(MAC,"RA[state:%d]\n",ra->state);
-  switch (ra->state){
-    case Msg2:
-      nr_generate_Msg2(module_idP, CC_id, frameP, slotP);
-      break;
-    case Msg4:
-      //generate_Msg4(module_idP, CC_id, frameP, slotP);
-      break;
-    case WAIT_Msg4_ACK:
-      //check_Msg4_retransmission(module_idP, CC_id, frameP, slotP);
-      break;
-    default:
-    break;
+  for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
+    NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
+    for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
+      NR_RA_t *ra = &cc->ra[i];
+      LOG_D(MAC, "RA[state:%d]\n", ra->state);
+      switch (ra->state) {
+        case Msg2:
+          nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra);
+          break;
+        case Msg4:
+          // generate_Msg4(module_idP, CC_id, frameP, slotP);
+          break;
+        case WAIT_Msg4_ACK:
+          // check_Msg4_retransmission(module_idP, CC_id, frameP, slotP);
+          break;
+        default:
+          break;
+      }
+    }
   }
-//    }
-//  }
   stop_meas(&mac->schedule_ra);
 }
 
@@ -632,12 +695,11 @@ void nr_get_Msg3alloc(module_id_t module_id,
   ra->msg3_first_rb = rbStart;
 }
 
-void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP){
-
+void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu)
+{
   gNB_MAC_INST                                   *mac = RC.nrmac[module_idP];
   NR_COMMON_channels_t                            *cc = &mac->common_channels[CC_id];
   NR_ServingCellConfigCommon_t                   *scc = cc->ServingCellConfigCommon;
-  NR_RA_t                                         *ra = &cc->ra[0];
 
   if (ra->state == RA_IDLE) {
     LOG_W(MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti);
@@ -752,27 +814,25 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t
                                                  pusch_pdu->nrOfLayers = 1)>>3;
 
   // calling function to fill rar message
-  nr_fill_rar(module_idP, ra, cc->RAR_pdu.payload, pusch_pdu);
-
+  nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu);
 }
 
-// WIP
-// todo:
-// - fix me
-// - get msg3 alloc (see nr_process_rar)
-void nr_generate_Msg2(module_id_t module_idP,
-                      int CC_id,
-                      frame_t frameP,
-                      sub_frame_t slotP)
+void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra)
 {
-
   int mcsIndex;
   int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment = 0;
   gNB_MAC_INST                      *nr_mac = RC.nrmac[module_idP];
   NR_COMMON_channels_t                  *cc = &nr_mac->common_channels[CC_id];
-  NR_RA_t                               *ra = &cc->ra[CC_id];
   NR_SearchSpace_t *ss = ra->ra_ss;
 
+  // This code from this point on will not work on initialBWP or CORESET0
+  AssertFatal(ra->bwp_id > 0, "cannot work on initialBWP for now\n");
+
+  AssertFatal(ra->secondaryCellGroup, "no secondaryCellGroup for RNTI %04x\n", ra->crnti);
+  AssertFatal(ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
+              "downlinkBWP_ToAddModList has %d BWP!\n",
+              ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
+
   uint16_t RA_rnti = ra->RA_rnti;
   long locationAndBandwidth;
 
@@ -780,7 +840,7 @@ void nr_generate_Msg2(module_id_t module_idP,
   // get the BW of the PDCCH for PDCCH size and RAR PDSCH size
 
   NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
-  int dci10_bw;
+  int dci10_bw = 0;
 
   if (ra->coreset0_configured == 1) {
     AssertFatal(1==0,"This is a standalone condition\n");
@@ -792,8 +852,24 @@ void nr_generate_Msg2(module_id_t module_idP,
 
   if ((ra->Msg2_frame == frameP) && (ra->Msg2_slot == slotP)) {
 
+    uint16_t *vrb_map = cc[CC_id].vrb_map;
+    int rbStart = 0, rbSize = 6;
+    for (int i = 0; (i < rbSize) && (rbStart <= (dci10_bw - rbSize)); i++) {
+      if (vrb_map[rbStart + i]) {
+        rbStart += i;
+        i = 0;
+      }
+    }
+    if (rbStart > (dci10_bw - rbSize)) {
+      LOG_E(MAC, "%s(): cannot find free vrb_map for RA RNTI %04x!\n", __func__, ra->RA_rnti);
+      return;
+    }
+
     nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body;
-    // Checking if the DCI allocation is feasible in current subframe
+    // Checking if the DCI allocation is feasible in current subframe: we might
+    // need to need up to two (PDCCH + PDSCH) messages, so check that we can
+    // always allocate both (this might be an overestimation, since the PDCCH
+    // message might already exist)
     if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
       LOG_I(MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, RA_rnti);
       return;
@@ -816,8 +892,6 @@ void nr_generate_Msg2(module_id_t module_idP,
       return;
     }
 
-    nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs];
-
     /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not
      * exist, create it. This is especially important if we have multiple RAs,
      * and the DLSCH has to reuse them, so we need to mark them */
@@ -844,14 +918,6 @@ void nr_generate_Msg2(module_id_t module_idP,
 
     LOG_I(MAC,"[gNB %d] [RAPROC] CC_id %d Frame %d, slotP %d: Generating RAR DCI, state %d\n", module_idP, CC_id, frameP, slotP, ra->state);
 
-    // This code from this point on will not work on initialBWP or CORESET0
-    AssertFatal(ra->bwp_id>0,"cannot work on initialBWP for now\n");
-
-    AssertFatal(ra->secondaryCellGroup,
-                "no secondaryCellGroup for RNTI %04x\n",
-                ra->crnti);
-    AssertFatal(ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
-      "downlinkBWP_ToAddModList has %d BWP!\n", ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
     NR_BWP_Uplink_t *ubwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1];
 
     LOG_I(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw);
@@ -898,8 +964,8 @@ void nr_generate_Msg2(module_id_t module_idP,
     pdsch_pdu_rel15->numDmrsCdmGrpsNoData = 2;
     pdsch_pdu_rel15->dmrsPorts = 1;
     pdsch_pdu_rel15->resourceAlloc = 1;
-    pdsch_pdu_rel15->rbStart = 0;
-    pdsch_pdu_rel15->rbSize = 6;
+    pdsch_pdu_rel15->rbStart = rbStart;
+    pdsch_pdu_rel15->rbSize = rbSize;
     pdsch_pdu_rel15->VRBtoPRBMapping = 0; // non interleaved
 
     for (int i=0; i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count; i++) {
@@ -974,17 +1040,8 @@ void nr_generate_Msg2(module_id_t module_idP,
                        dci10_bw,
                        ra->bwp_id);
 
-    // Program UL processing for Msg3
-    nr_get_Msg3alloc(module_idP, CC_id, scc, ubwp, slotP, frameP, ra);
-    LOG_I(MAC, "Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot);
-    nr_add_msg3(module_idP, CC_id, frameP, slotP);
-    ra->state = WAIT_Msg3;
-    LOG_I(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
-
-    x_Overhead = 0;
-    nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_payload.tb_scaling);
-
     // DL TX request
+    nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs];
     tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0];
     tx_req->PDU_index = pduindex;
     tx_req->num_TLV = 1;
@@ -992,16 +1049,24 @@ void nr_generate_Msg2(module_id_t module_idP,
     nr_mac->TX_req[CC_id].SFN = frameP;
     nr_mac->TX_req[CC_id].Number_of_PDUs++;
     nr_mac->TX_req[CC_id].Slot = slotP;
-    memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length);
+
+    // Program UL processing for Msg3
+    nr_get_Msg3alloc(module_idP, CC_id, scc, ubwp, slotP, frameP, ra);
+    LOG_I(MAC, "Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot);
+    nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *) &tx_req->TLVs[0].value.direct[0]);
+    ra->state = WAIT_Msg3;
+    LOG_I(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
+
+    x_Overhead = 0;
+    nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_payload.tb_scaling);
 
     T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id),
       T_INT(RA_rnti), T_INT(frameP), T_INT(slotP), T_INT(0) /* harq pid, meaningful? */,
-      T_BUFFER(&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length));
+      T_BUFFER(&tx_req->TLVs[0].value.direct[0], tx_req->TLVs[0].length));
 
     /* mark the corresponding RBs as used */
-    uint16_t *vrb_map = cc[CC_id].vrb_map;
-    for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++)
-      vrb_map[rb + pdsch_pdu_rel15->rbStart] = 1;
+    for (int rb = 0; rb < rbSize; rb++)
+      vrb_map[rb + rbStart] = 1;
   }
 }
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
index 9587e3b0bb8c717a7ed92864c81de44e34a89d4f..6487f391b9198bfb489dba0471ba670f53e3fa84 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
@@ -245,7 +245,9 @@ void nr_schedule_css_dlsch_phytest(module_id_t   module_idP,
     TX_req->PDU_index = nr_mac->pdu_index[CC_id]++;
     TX_req->num_TLV = 1;
     TX_req->TLVs[0].length = 8;
-    memcpy((void*)&TX_req->TLVs[0].value.direct[0],(void*)&cc[CC_id].RAR_pdu.payload[0],TX_req->TLVs[0].length);
+    // why do we copy from RAR_pdu here? Shouldn't we fill some more or less
+    // meaningful data, e.g., padding + random data?
+    //memcpy((void *)&TX_req->TLVs[0].value.direct[0], (void *)&cc[CC_id].RAR_pdu[0].payload[0], TX_req->TLVs[0].length);
     nr_mac->TX_req[CC_id].Number_of_PDUs++;
     nr_mac->TX_req[CC_id].SFN=frameP;
     nr_mac->TX_req[CC_id].Slot=slotP;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 4a47e4d894600601026384aa48988d41f8ea8692..db7dde014034c74352921098c32a63a14aa924d5 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -396,7 +396,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
         T_BUFFER(sduP, sdu_lenP));
 
     UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP;
-    LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d\n",
+    LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d sduP %p\n",
           gnb_mod_idP,
           harq_pid,
           CC_idP,
@@ -404,7 +404,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
           slotP,
           current_rnti,
           UE_id,
-          ul_cqi);
+          ul_cqi,
+          sduP);
 
     // if not missed detection (10dB threshold for now)
     if (UE_scheduling_control->ul_rssi < (100+rssi)) {
@@ -433,7 +434,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
     if (sduP != NULL){
       LOG_D(MAC, "Received PDU at MAC gNB \n");
 
-      UE_scheduling_control->sched_ul_bytes -= UE_info->mac_stats[UE_id].ulsch_current_bytes;
+      const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size;
+      UE_scheduling_control->sched_ul_bytes -= tb_size;
       if (UE_scheduling_control->sched_ul_bytes < 0)
         UE_scheduling_control->sched_ul_bytes = 0;
 
@@ -443,7 +445,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
       NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
       /* reduce sched_ul_bytes when cur_harq->round == 3 */
       if (cur_harq->round == 3){
-        UE_scheduling_control->sched_ul_bytes -= UE_info->mac_stats[UE_id].ulsch_current_bytes;
+        const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size;
+        UE_scheduling_control->sched_ul_bytes -= tb_size;
         if (UE_scheduling_control->sched_ul_bytes < 0)
           UE_scheduling_control->sched_ul_bytes = 0;
       }
@@ -863,7 +866,7 @@ void nr_schedule_ulsch(module_id_t module_id,
   /* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each
    * allocated PDCCH so we can easily allocate UE's DCIs independent of any
    * CORESET order */
-  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_bwp_coreset[MAX_NUM_BWP][MAX_NUM_CORESET] = {0};
+  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_bwp_coreset[MAX_NUM_BWP][MAX_NUM_CORESET] = {{0}};
 
   NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon;
   NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
@@ -919,6 +922,7 @@ void nr_schedule_ulsch(module_id_t module_id,
       /* Save information on MCS, TBS etc for the current initial transmission
        * so we have access to it when retransmitting */
       cur_harq->sched_pusch = *sched_pusch;
+      sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
     } else {
       LOG_D(MAC,
             "%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n",
@@ -932,7 +936,6 @@ void nr_schedule_ulsch(module_id_t module_id,
             cur_harq->ndi);
     }
     UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size;
-    sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
 
     LOG_D(MAC,
           "%4d.%2d RNTI %04x UL sched %4d.%2d start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 26d29f9412815a4e778887a9cd909869bb1cda10..3502a11580cf75af67805070267e34d5044f1b0c 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -346,11 +346,7 @@ void config_nr_mib(int Mod_idP,
                    int cellBarred,
                    int intraFreqReselection);
 
-
-void nr_generate_Msg2(module_id_t module_idP,
-                      int CC_id,
-                      frame_t frameP,
-                      sub_frame_t slotP);
+void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra);
 
 void nr_process_mac_pdu(
     module_id_t module_idP,
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index bca974a00f08644028788cbc97a99cc67844c293..63587d58a4f118935ff4f0e38477e25c8e46e3ec 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -194,8 +194,6 @@ typedef struct {
   uint32_t PCCH_alloc_pdu;
   /// Outgoing PCCH pdu for PHY
   PCCH_PDU PCCH_pdu;
-  /// Outgoing RAR pdu for PHY
-  RAR_PDU RAR_pdu;
   /// Template for RA computations
   NR_RA_t ra[NR_NB_RA_PROC_MAX];
   /// VRB map for common channels
@@ -215,6 +213,8 @@ typedef struct {
   uint8_t max_association_period;
   //SSB index
   uint8_t ssb_index[MAX_NUM_OF_SSB];
+  //CB preambles for each SSB
+  uint8_t cb_preambles_per_ssb;
 } NR_COMMON_channels_t;
 
 
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
index f3d4b1613099765430c8825047d0686f7cdfde82..ffc669a46169740fdaf7cab79921a4864165f9e7 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
@@ -22,11 +22,12 @@
 #include "nr_pdcp_entity.h"
 
 #include "nr_pdcp_entity_drb_am.h"
+#include "nr_pdcp_security_nea2.h"
 
 #include "LOG/log.h"
 
 nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
-    int rb_id,
+    int is_gnb, int rb_id,
     void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
                         char *buf, int size),
     void *deliver_sdu_data,
@@ -38,7 +39,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
 }
 
 nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
-    int rb_id,
+    int is_gnb, int rb_id,
     void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
                         char *buf, int size),
     void *deliver_sdu_data,
@@ -47,7 +48,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
     void *deliver_pdu_data,
     int sn_size,
     int t_reordering,
-    int discard_timer)
+    int discard_timer,
+    int ciphering_algorithm,
+    int integrity_algorithm,
+    unsigned char *ciphering_key,
+    unsigned char *integrity_key)
 {
   nr_pdcp_entity_drb_am_t *ret;
 
@@ -76,5 +81,25 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
 
   ret->common.maximum_nr_pdcp_sn = (1 << sn_size) - 1;
 
+  if (ciphering_key != NULL && ciphering_algorithm != 0) {
+    if (ciphering_algorithm != 2) {
+      LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n");
+      exit(1);
+    }
+    ret->common.has_ciphering = 1;
+    ret->common.ciphering_algorithm = ciphering_algorithm;
+    memcpy(ret->common.ciphering_key, ciphering_key, 16);
+
+    ret->common.security_context = nr_pdcp_security_nea2_init(ciphering_key);
+    ret->common.cipher = nr_pdcp_security_nea2_cipher;
+    ret->common.free_security = nr_pdcp_security_nea2_free_security;
+  }
+  ret->common.is_gnb = is_gnb;
+
+  if (integrity_key != NULL) {
+    printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
   return (nr_pdcp_entity_t *)ret;
 }
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h
index ce5dd300e96c2dc28ba7a42f03d903a495a80720..58d79835ecbc588524526887624ecea47c15632e 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h
@@ -42,10 +42,28 @@ typedef struct nr_pdcp_entity_t {
   int tx_hfn;
   int next_nr_pdcp_tx_sn;
   int maximum_nr_pdcp_sn;
+
+  /* security */
+  int has_ciphering;
+  int has_integrity;
+  int ciphering_algorithm;
+  int integrity_algorithm;
+  unsigned char ciphering_key[16];
+  unsigned char integrity_key[16];
+  void *security_context;
+  void (*cipher)(void *security_context,
+                 unsigned char *buffer, int length,
+                 int bearer, int count, int direction);
+  void (*free_security)(void *security_context);
+  /* security algorithms need to know uplink/downlink information
+   * which is reverse for gnb and ue, so we need to know if this
+   * pdcp entity is for a gnb or an ue
+   */
+  int is_gnb;
 } nr_pdcp_entity_t;
 
 nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
-    int rb_id,
+    int is_gnb, int rb_id,
     void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
                         char *buf, int size),
     void *deliver_sdu_data,
@@ -54,7 +72,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
     void *deliver_pdu_data);
 
 nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
-    int rb_id,
+    int is_gnb, int rb_id,
     void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
                         char *buf, int size),
     void *deliver_sdu_data,
@@ -63,7 +81,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
     void *deliver_pdu_data,
     int sn_size,
     int t_reordering,
-    int discard_timer);
+    int discard_timer,
+    int ciphering_algorithm,
+    int integrity_algorithm,
+    unsigned char *ciphering_key,
+    unsigned char *integrity_key);
 
 void nr_DRB_preconfiguration(uint16_t crnti);
 
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
index f2f849b9e36e301eafd17688381de37da4400259..62881c184e8cf3f35198b54f2893e2b4c4bb3eeb 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
@@ -29,12 +29,21 @@
 void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size)
 {
   nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
+  int sn;
 
   if (size < 3) abort();
 
   if (!(buffer[0] & 0x80))
     LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
 
+  sn = (((unsigned char)buffer[0] & 0x3) << 16) |
+        ((unsigned char)buffer[1]        <<  8) |
+         (unsigned char)buffer[2];
+
+  if (entity->common.has_ciphering)
+    entity->common.cipher(entity->common.security_context, (unsigned char *)buffer+3, size-3,
+                          entity->rb_id, sn, entity->common.is_gnb ? 0 : 1);
+
   entity->common.deliver_sdu(entity->common.deliver_sdu_data,
                              (nr_pdcp_entity_t *)entity, buffer+3, size-3);
 }
@@ -59,6 +68,10 @@ void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int
   buf[2] = sn & 0xff;
   memcpy(buf+3, buffer, size);
 
+  if (entity->common.has_ciphering)
+    entity->common.cipher(entity->common.security_context, (unsigned char *)buf+3, size,
+                          entity->rb_id, sn, entity->common.is_gnb ? 1 : 0);
+
   entity->common.deliver_pdu(entity->common.deliver_pdu_data,
                              (nr_pdcp_entity_t *)entity, buf, size+3, sdu_id);
 }
@@ -71,5 +84,7 @@ void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *ke
 void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity)
 {
   nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
+  if (entity->common.free_security != NULL)
+    entity->common.free_security(entity->common.security_context);
   free(entity);
 }
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
index 6195a91ea26037c7585768b6fde262223d24c8ee..f14d25b145a72c4b3534e05ff46cce5752478edc 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
@@ -591,7 +591,11 @@ static void add_srb(int rnti, struct NR_SRB_ToAddMod *s)
   TODO;
 }
 
-static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s)
+static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
+                       int ciphering_algorithm,
+                       int integrity_algorithm,
+                       unsigned char *ciphering_key,
+                       unsigned char *integrity_key)
 {
   nr_pdcp_entity_t *pdcp_drb;
   nr_pdcp_ue_t *ue;
@@ -621,8 +625,11 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s)
     LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n",
           __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
   } else {
-    pdcp_drb = new_nr_pdcp_entity_drb_am(drb_id, deliver_sdu_drb, ue, deliver_pdu_drb, ue,
-                                         sn_size_dl, t_reordering, discard_timer);
+    pdcp_drb = new_nr_pdcp_entity_drb_am(is_gnb, drb_id,
+                                         deliver_sdu_drb, ue, deliver_pdu_drb, ue,
+                                         sn_size_dl, t_reordering, discard_timer,
+                                         ciphering_algorithm, integrity_algorithm,
+                                         ciphering_key, integrity_key);
     nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
 
     LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
@@ -630,16 +637,23 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s)
   nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
 }
 
-static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_Config_t *rlc_Config)
+static void add_drb(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
+                    NR_RLC_Config_t *rlc_Config,
+                    int ciphering_algorithm,
+                    int integrity_algorithm,
+                    unsigned char *ciphering_key,
+                    unsigned char *integrity_key)
 {
   switch (rlc_Config->present) {
   case NR_RLC_Config_PR_am:
-    add_drb_am(rnti, s);
+    add_drb_am(is_gnb, rnti, s, ciphering_algorithm, integrity_algorithm,
+               ciphering_key, integrity_key);
     break;
   case NR_RLC_Config_PR_um_Bi_Directional:
     //add_drb_um(rnti, s);
     /* hack */
-    add_drb_am(rnti, s);
+    add_drb_am(is_gnb, rnti, s, ciphering_algorithm, integrity_algorithm,
+               ciphering_key, integrity_key);
     break;
   default:
     LOG_E(PDCP, "%s:%d:%s: fatal: unhandled DRB type\n",
@@ -657,7 +671,8 @@ boolean_t nr_rrc_pdcp_config_asn1_req(
   const uint8_t                   security_modeP,
   uint8_t                  *const kRRCenc,
   uint8_t                  *const kRRCint,
-  uint8_t                  *const kUPenc
+  uint8_t                  *const kUPenc,
+  uint8_t                  *const kUPint
 #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
   ,LTE_PMCH_InfoList_r9_t  *pmch_InfoList_r9
 #endif
@@ -676,7 +691,7 @@ boolean_t nr_rrc_pdcp_config_asn1_req(
       //srb2add_list == NULL ||
       //drb2add_list != NULL ||
       drb2release_list != NULL ||
-      security_modeP != 255 ||
+      //security_modeP != 255 ||
       //kRRCenc != NULL ||
       //kRRCint != NULL ||
       //kUPenc != NULL ||
@@ -693,7 +708,10 @@ boolean_t nr_rrc_pdcp_config_asn1_req(
 
   if (drb2add_list != NULL) {
     for (i = 0; i < drb2add_list->list.count; i++) {
-      add_drb(rnti, drb2add_list->list.array[i], rlc_bearer2add_list->list.array[i]->rlc_Config);
+      add_drb(ctxt_pP->enb_flag, rnti, drb2add_list->list.array[i],
+              rlc_bearer2add_list->list.array[i]->rlc_Config,
+              security_modeP & 0x0f, (security_modeP >> 4) & 0x0f,
+              kUPenc, kUPint);
     }
   }
 
@@ -705,6 +723,7 @@ boolean_t nr_rrc_pdcp_config_asn1_req(
   free(kRRCenc);
   free(kRRCint);
   free(kUPenc);
+  free(kUPint);
 
   return 0;
 }
@@ -805,6 +824,7 @@ void nr_DRB_preconfiguration(uint16_t crnti)
     NULL,
     NULL,
     NULL,
+    NULL,
     Rlc_Bearer_ToAdd_list);
 
   nr_rrc_rlc_config_asn1_req (&ctxt,
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c
new file mode 100644
index 0000000000000000000000000000000000000000..fc07f661dd590ee486a2a5d850a2256a66e62ceb
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c
@@ -0,0 +1,65 @@
+/*
+ * 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_pdcp_security_nea2.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <nettle/nettle-meta.h>
+#include <nettle/aes.h>
+#include <nettle/ctr.h>
+
+void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key)
+{
+  void *ctx = calloc(1, nettle_aes128.context_size);
+  if (ctx == NULL) exit(1);
+
+#if NETTLE_VERSION_MAJOR < 3
+  nettle_aes128.set_encrypt_key(ctx, 16, ciphering_key);
+#else
+  nettle_aes128.set_encrypt_key(ctx, ciphering_key);
+#endif
+
+  return ctx;
+}
+
+void nr_pdcp_security_nea2_cipher(void *security_context,
+                                  unsigned char *buffer, int length,
+                                  int bearer, int count, int direction)
+{
+  unsigned char t[16];
+
+  t[0] = (count >> 24) & 255;
+  t[1] = (count >> 16) & 255;
+  t[2] = (count >>  8) & 255;
+  t[3] = (count      ) & 255;
+  t[4] = ((bearer-1) << 3) | (direction << 2);
+  memset(&t[5], 0, 16-5);
+
+  nettle_ctr_crypt(security_context, nettle_aes128.encrypt,
+                   nettle_aes128.block_size, t,
+                   length, buffer, buffer);
+}
+
+void nr_pdcp_security_nea2_free_security(void *security_context)
+{
+  free(security_context);
+}
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h
new file mode 100644
index 0000000000000000000000000000000000000000..c3667c93d4c850dac7e5da0d82ef1c56e60b3a0e
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.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 _NR_PDCP_SECURITY_NEA2_H_
+#define _NR_PDCP_SECURITY_NEA2_H_
+
+void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key);
+
+void nr_pdcp_security_nea2_cipher(void *security_context,
+                                  unsigned char *buffer, int length,
+                                  int bearer, int count, int direction);
+
+void nr_pdcp_security_nea2_free_security(void *security_context);
+
+#endif /* _NR_PDCP_SECURITY_NEA2_H_ */
diff --git a/openair2/NETWORK_DRIVER/UE_IP/device.c b/openair2/NETWORK_DRIVER/UE_IP/device.c
index 63184eb6da60ff04fbde92ce2e4217a07fc28593..0ff9a73925789f7f26be0f0e6a6e5226a10bf305 100644
--- a/openair2/NETWORK_DRIVER/UE_IP/device.c
+++ b/openair2/NETWORK_DRIVER/UE_IP/device.c
@@ -302,6 +302,7 @@ void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP) {
 }
 
 //---------------------------------------------------------------------------
+
 #if  LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
 void ue_ip_tx_timeout(struct net_device *dev_pP, unsigned int txqueue)
 #else
diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h
index 7602e9ca64b61291e4bbf1c7910e654b131ddaca..4f55f94121f1b63c0e64978de42b9cd6aba1652a 100644
--- a/openair2/RRC/LTE/rrc_defs.h
+++ b/openair2/RRC/LTE/rrc_defs.h
@@ -546,6 +546,13 @@ typedef struct rrc_gummei_s {
   uint16_t mme_group_id;
 } rrc_gummei_t;
 
+typedef struct {
+  uint16_t ciphering_algorithms;
+  uint16_t integrity_algorithms;
+  uint16_t sk_counter;
+  uint8_t  kgNB[32];
+} lte_rrc_nr_security_t;
+
 typedef struct eNB_RRC_UE_s {
   uint8_t                            primaryCC_id;
   LTE_SCellToAddMod_r10_t            sCell_config[2];
@@ -615,6 +622,9 @@ typedef struct eNB_RRC_UE_s {
 
   security_capabilities_t            security_capabilities;
 
+  /* security capabilities and settings for an UE in ENDC mode */
+  lte_rrc_nr_security_t              nr_security;
+
   int                                next_hop_chain_count;
 
   uint8_t                            next_security_key[SECURITY_KEY_LENGTH];
diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c
index 6d39fb222112148ecc55b6d27d5b9517369ddc7d..526ce129b1e43302ab8e5161e4282c0baba224e9 100644
--- a/openair2/RRC/LTE/rrc_eNB.c
+++ b/openair2/RRC/LTE/rrc_eNB.c
@@ -4426,69 +4426,11 @@ static int encode_CG_ConfigInfo(
   struct NR_RadioBearerConfig *rb_config = NULL;
   asn_enc_rval_t enc_rval;
   int RRC_OK = 1;
-  int index = 0;
   char temp_buff[ASN_MAX_ENCODE_SIZE];
   NR_UE_CapabilityRAT_ContainerList_t *ue_cap_rat_container_list = NULL;
   NR_UE_CapabilityRAT_Container_t *ue_cap_rat_container_MRDC = NULL;
   NR_UE_CapabilityRAT_Container_t *ue_cap_rat_container_nr = NULL;
   int RAT_Container_count = 0;
-  rb_config = calloc(1,sizeof(struct NR_RadioBearerConfig));
-  AssertFatal(rb_config != NULL,"failed to allocate memory for rb_config");
-
-  if(ue_context_pP->ue_context.DRB_configList->list.count != 0) {
-    rb_config->drb_ToAddModList = calloc(1,sizeof(struct NR_DRB_ToAddModList ));
-    AssertFatal(rb_config->drb_ToAddModList != NULL,"failed to allocated memory for drbtoaddmodlist");
-    rb_config->drb_ToAddModList->list.count = NUMBEROF_DRBS_TOBE_ADDED;
-    rb_config->drb_ToAddModList->list.array
-      = calloc(NUMBEROF_DRBS_TOBE_ADDED, sizeof(struct NR_DRB_ToAddMod *));
-    AssertFatal( rb_config->drb_ToAddModList->list.array != NULL,
-                 "falied to allocate memory for list.array");
-
-    for(index = 0; index < NUMBEROF_DRBS_TOBE_ADDED; index++) {
-      rb_config->drb_ToAddModList->list.array[index]
-        = calloc(1,sizeof(struct NR_DRB_ToAddMod));
-      AssertFatal(rb_config->drb_ToAddModList->list.array[index] != NULL,
-                  "failed to allocate memory for drb_toaddmod");
-      rb_config->drb_ToAddModList->list.array[index]->drb_Identity
-        = ue_context_pP->ue_context.DRB_configList->list.array[index]->drb_Identity;
-
-      if(ue_context_pP->ue_context.DRB_configList->list.array[index]->eps_BearerIdentity) {
-        rb_config->drb_ToAddModList->list.array[index]->cnAssociation
-          = calloc(1,sizeof(struct NR_DRB_ToAddMod__cnAssociation));
-        AssertFatal(rb_config->drb_ToAddModList->list.array[index]->cnAssociation != NULL,
-                    "failed to allocate memory cnAssociation");
-        rb_config->drb_ToAddModList->list.array[index]->cnAssociation->present
-          = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity;
-        rb_config->drb_ToAddModList->list.array[index]->cnAssociation->choice.eps_BearerIdentity
-          = *(ue_context_pP->ue_context.DRB_configList->list.array[index]->eps_BearerIdentity);
-      }
-
-      rb_config->drb_ToAddModList->list.array[index]->pdcp_Config = calloc(1,sizeof(struct NR_PDCP_Config));
-      rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb = calloc(1,sizeof(struct NR_PDCP_Config__drb));
-      rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->discardTimer = calloc(1,sizeof(long));
-      *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->discardTimer
-        = *(ue_context_pP->ue_context.DRB_configList->list.array[index]->pdcp_Config->discardTimer);
-      rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(long));
-      *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeUL
-        = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
-      rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(long));
-      *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeDL
-        = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits;
-      rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->headerCompression.present
-        = NR_PDCP_Config__drb__headerCompression_PR_notUsed;
-      rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->headerCompression.choice.notUsed = 0;
-      rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->t_Reordering = calloc(1,sizeof(long));
-      *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->t_Reordering
-        = NR_PDCP_Config__t_Reordering_ms0;
-    }
-
-    rb_config->securityConfig = calloc(1,sizeof(struct NR_SecurityConfig ));
-    rb_config->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(struct NR_SecurityAlgorithmConfig));
-    rb_config->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0;
-    rb_config->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm = NULL;
-    rb_config->securityConfig->keyToUse = calloc(1,sizeof(long));
-    *rb_config->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master;
-  }
 
   cg_configinfo = calloc(1,sizeof(struct NR_CG_ConfigInfo));
   AssertFatal(cg_configinfo != NULL,"failed to allocate memory for cg_configinfo");
@@ -4548,15 +4490,6 @@ static int encode_CG_ConfigInfo(
                          (const char *)temp_buff, (enc_rval.encoded+7)>>3);
   }
 
-  cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->mcg_RB_Config
-    = calloc(1,sizeof(OCTET_STRING_t));
-  AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->
-              mcg_RB_Config != NULL, "failed to allocate memory for mcg_rb_config");
-  enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RadioBearerConfig,NULL,(void *)rb_config,temp_buff,ASN_MAX_ENCODE_SIZE);
-  AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
-              enc_rval.failed_type->name, enc_rval.encoded);
-  OCTET_STRING_fromBuf(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->mcg_RB_Config,
-                       (const char *)temp_buff, (enc_rval.encoded+7)>>3);
   // this xer_fprint can be enabled for additional debugging messages
   // xer_fprint(stdout,&asn_DEF_NR_CG_ConfigInfo,(void *)cg_configinfo);
   enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo,NULL,(void *)cg_configinfo,
@@ -4665,11 +4598,20 @@ rrc_eNB_process_MeasurementReport(
 
         msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ);
         memset(&(X2AP_ENDC_SGNB_ADDITION_REQ(msg)), 0, sizeof(x2ap_ENDC_sgnb_addition_req_t));
+
         X2AP_ENDC_SGNB_ADDITION_REQ(msg).rnti = ctxt_pP->rnti;
+
+        X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.encryption_algorithms = ue_context_pP->ue_context.nr_security.ciphering_algorithms;
+        X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.integrity_algorithms = ue_context_pP->ue_context.nr_security.integrity_algorithms;
+
+        memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).kgnb, ue_context_pP->ue_context.nr_security.kgNB, 32);
+
         memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer,enc_buf,enc_size);
         X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer_size = enc_size;
+
         X2AP_ENDC_SGNB_ADDITION_REQ(msg).target_physCellId
           = measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[0]->physCellId;
+
         //For the moment we have a single E-RAB which will be the one to be added to the gNB
         //Not sure how to select bearers to be added if there are multiple.
         X2AP_ENDC_SGNB_ADDITION_REQ(msg).nb_e_rabs_tobeadded = 1;
diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c
index 320004a361409ebc0dcd2cb0ac68badd3dadd4ba..d34b4164a204dbf299f28b6e02f15c5dd03beda8 100644
--- a/openair2/RRC/LTE/rrc_eNB_S1AP.c
+++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c
@@ -1045,6 +1045,15 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
       }
     }
 
+    ue_context_p->ue_context.nr_security.ciphering_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.encryption_algorithms;
+    ue_context_p->ue_context.nr_security.integrity_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.integrity_algorithms;
+    /* let's initialize sk_counter to 0 */
+    ue_context_p->ue_context.nr_security.sk_counter = 0;
+    /* let's compute kgNB */
+    derive_skgNB(ue_context_p->ue_context.kenb,
+                 ue_context_p->ue_context.nr_security.sk_counter,
+                 ue_context_p->ue_context.nr_security.kgNB);
+
     // in case, send the S1SP initial context response if it is not sent with the attach complete message
     if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) {
       LOG_I(RRC, "Sending rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP, cause %ld\n", ue_context_p->ue_context.reestablishment_cause);
diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h
index c53d44983cb9a6166f61d704156f71130de293e3..36d9bdee60c44f18ed419aa729ca5881685ffd6c 100644
--- a/openair2/RRC/NR/nr_rrc_defs.h
+++ b/openair2/RRC/NR/nr_rrc_defs.h
@@ -447,6 +447,15 @@ typedef struct {
 //---------------------------------------------------
 
 
+typedef struct {
+  /* nea0 = 0, nea1 = 1, ... */
+  int ciphering_algorithms[4];
+  int ciphering_algorithms_count;
+
+  /* nia0 = 0, nia1 = 1, ... */
+  int integrity_algorithms[4];
+  int integrity_algorithms_count;
+} nr_security_configuration_t;
 
 //---NR---(completely change)---------------------
 typedef struct gNB_RRC_INST_s {
@@ -479,6 +488,8 @@ typedef struct gNB_RRC_INST_s {
   int srb1_timer_status_prohibit;
   int srs_enable[MAX_NUM_CCs];
 
+  // security configuration (preferred algorithms)
+  nr_security_configuration_t security;
 } gNB_RRC_INST;
 
 #include "nr_rrc_proto.h" //should be put here otherwise compilation error
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 9b7d734e2c0c587a21ae24834e8a299bb1bb3d66..6d876a0eefacbfa7dcb94474849e2a40fa186025 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -39,6 +39,7 @@
 #include "LTE_UE-CapabilityRAT-ContainerList.h"
 #include "NR_CG-Config.h"
 #include "NR_CG-ConfigInfo.h"
+#include "NR_SecurityConfig.h"
 
 int rrc_init_nr_global_param(void);
 
@@ -90,7 +91,10 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
 			   int n_physical_antenna_ports,
 			   int initial_csi_index);
 
-void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig);
+void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
+                           int eps_bearer_id, int rb_id,
+                           e_NR_CipheringAlgorithm ciphering_algorithm,
+                           e_NR_SecurityConfig__keyToUse key_to_use);
 
 int generate_CG_Config(gNB_RRC_INST *rrc, 
 		       NR_CG_Config_t *cg_Config,
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index abf85a805b6b1e7f67bc3b73099d973be350d779..6d430d722370c71d0c0351e0a87fade5d2f49d2d 100755
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -103,7 +103,8 @@ extern boolean_t nr_rrc_pdcp_config_asn1_req(
     const uint8_t                   security_modeP,
     uint8_t                  *const kRRCenc,
     uint8_t                  *const kRRCint,
-    uint8_t                  *const kUPenc
+    uint8_t                  *const kUPenc,
+    uint8_t                  *const kUPint
   #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
     ,LTE_PMCH_InfoList_r9_t  *pmch_InfoList_r9
   #endif
@@ -887,6 +888,7 @@ rrc_gNB_process_RRCReconfigurationComplete(
                               kUPenc,
                               NULL,
                               NULL,
+                              NULL,
                               NULL);
   /* Refresh SRBs/DRBs */
   nr_rrc_rlc_config_asn1_req(ctxt_pP,
@@ -1702,6 +1704,7 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t    *const ctxt_pP,
           //                         NULL,
           //                         NULL,
           //                         NULL,
+          //                         NULL,
           //                         NULL);
 
           // if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) {
diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c
index a390d05a0894f6efcfc46fe5612478b8e8ad867b..5ea02c78322f1b9d377f9d127baf6f1d9a20e2e6 100644
--- a/openair2/RRC/NR/rrc_gNB_nsa.c
+++ b/openair2/RRC/NR/rrc_gNB_nsa.c
@@ -39,6 +39,7 @@
 #include "openair2/RRC/LTE/rrc_eNB_GTPV1U.h"
 #include "executables/softmodem-common.h"
 #include <openair2/RRC/NR/rrc_gNB_UE_context.h>
+#include "UTIL/OSA/osa_defs.h"
 
 extern boolean_t nr_rrc_pdcp_config_asn1_req(
     const protocol_ctxt_t *const  ctxt_pP,
@@ -48,7 +49,8 @@ extern boolean_t nr_rrc_pdcp_config_asn1_req(
     const uint8_t                   security_modeP,
     uint8_t                  *const kRRCenc,
     uint8_t                  *const kRRCint,
-    uint8_t                  *const kUPenc
+    uint8_t                  *const kUPenc,
+    uint8_t                  *const kUPint
   #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
     ,LTE_PMCH_InfoList_r9_t  *pmch_InfoList_r9
   #endif
@@ -115,28 +117,14 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, NR_UE_CapabilityRAT_ContainerL
 
   // dump ue_capabilities
 
-  if ( LOG_DEBUGFLAG(DEBUG_ASN1 && ueCapabilityRAT_Container_nr != NULL) ) {
+  if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_nr != NULL ) {
     xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, ue_context_p->ue_context.UE_Capability_nr);
   }
 
-  if ( LOG_DEBUGFLAG(DEBUG_ASN1 && ueCapabilityRAT_Container_MRDC != NULL) ) {
+  if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_MRDC != NULL ) {
     xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, ue_context_p->ue_context.UE_Capability_MRDC);
   }
 
-  if(cg_config_info && cg_config_info->mcg_RB_Config) {
-    asn_dec_rval_t dec_rval = uper_decode(NULL,
-                                          &asn_DEF_NR_RadioBearerConfig,
-                                          (void **)&ue_context_p->ue_context.rb_config,
-                                          cg_config_info->mcg_RB_Config->buf,
-                                          cg_config_info->mcg_RB_Config->size, 0, 0);
-
-    if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
-      AssertFatal(1==0,"[InterNode] Failed to decode mcg_rb_config (%zu bits), size of OCTET_STRING %lu\n",
-                  dec_rval.consumed, cg_config_info->mcg_RB_Config->size);
-    }
-  }
-
-  xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)ue_context_p->ue_context.rb_config);
   rrc_add_nsa_user(rrc,ue_context_p, m);
 }
 
@@ -152,6 +140,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
   gtpv1u_enb_create_tunnel_req_t  create_tunnel_req;
   gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
   protocol_ctxt_t ctxt={0};
+  unsigned char *kUPenc = NULL;
+  int i;
   // NR RRCReconfiguration
   AssertFatal(rrc->Nb_ue < MAX_NR_RRC_UE_CONTEXTS,"cannot add another UE\n");
   ue_context_p->ue_context.reconfig = calloc(1,sizeof(NR_RRCReconfiguration_t));
@@ -162,9 +152,91 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
   NR_RRCReconfiguration_IEs_t *reconfig_ies=calloc(1,sizeof(NR_RRCReconfiguration_IEs_t));
   ue_context_p->ue_context.reconfig->criticalExtensions.choice.rrcReconfiguration = reconfig_ies;
   carrier->initial_csi_index[rrc->Nb_ue] = 0;
+  ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t));
   if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1 || get_softmodem_params()->sa == 1){
-    ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t));
-    fill_default_rbconfig(ue_context_p->ue_context.rb_config);
+    fill_default_rbconfig(ue_context_p->ue_context.rb_config,
+                          5 /* EPS bearer ID */,
+                          1 /* drb ID */,
+                          NR_CipheringAlgorithm_nea0,
+                          NR_SecurityConfig__keyToUse_master);
+  } else {
+    /* TODO: handle more than one bearer */
+    if (m == NULL) {
+      LOG_E(RRC, "fatal: m==NULL\n");
+      exit(1);
+    }
+    if (m->nb_e_rabs_tobeadded != 1) {
+      LOG_E(RRC, "fatal: m->nb_e_rabs_tobeadded = %d, should be 1\n", m->nb_e_rabs_tobeadded);
+      exit(1);
+    }
+
+    /* store security key and security capabilities */
+    memcpy(ue_context_p->ue_context.kgnb, m->kgnb, 32);
+    ue_context_p->ue_context.security_capabilities.nRencryption_algorithms = m->security_capabilities.encryption_algorithms;
+    ue_context_p->ue_context.security_capabilities.nRintegrity_algorithms = m->security_capabilities.integrity_algorithms;
+
+    /* Select ciphering algorithm based on gNB configuration file and
+     * UE's supported algorithms.
+     * We take the first from the list that is supported by the UE.
+     * The ordering of the list comes from the configuration file.
+     */
+    /* preset nea0 as fallback */
+    ue_context_p->ue_context.ciphering_algorithm = 0;
+    for (i = 0; i < rrc->security.ciphering_algorithms_count; i++) {
+      int nea_mask[4] = {
+        0,
+        0x8000,  /* nea1 */
+        0x4000,  /* nea2 */
+        0x2000   /* nea3 */
+      };
+      if (rrc->security.ciphering_algorithms[i] == 0) {
+        /* nea0 already preselected */
+        break;
+      }
+      if (ue_context_p->ue_context.security_capabilities.nRencryption_algorithms & nea_mask[rrc->security.ciphering_algorithms[i]]) {
+        ue_context_p->ue_context.ciphering_algorithm = rrc->security.ciphering_algorithms[i];
+        break;
+      }
+    }
+
+    LOG_I(RRC, "selecting ciphering algorithm %d\n", (int)ue_context_p->ue_context.ciphering_algorithm);
+
+    /* integrity: no integrity protection for DRB in ENDC mode
+     * as written in 38.331: "If UE is connected to E-UTRA/EPC, this field
+     * indicates the integrity protection algorithm to be used for SRBs
+     * configured with NR PDCP, as specified in TS 33.501"
+     * So nothing for DRB. Plus a test with a COTS UE revealed that it
+     * did not apply integrity on the DRB.
+     */
+    ue_context_p->ue_context.integrity_algorithm = 0;
+
+    LOG_I(RRC, "selecting integrity algorithm %d\n", ue_context_p->ue_context.integrity_algorithm);
+
+    /* derive UP security key */
+    unsigned char *kUPenc_kdf;
+    nr_derive_key_up_enc(ue_context_p->ue_context.ciphering_algorithm,
+                         ue_context_p->ue_context.kgnb,
+                         &kUPenc_kdf);
+    /* kUPenc: last 128 bits of key derivation function which returns 256 bits */
+    kUPenc = malloc(16);
+    if (kUPenc == NULL) exit(1);
+    memcpy(kUPenc, kUPenc_kdf+16, 16);
+    free(kUPenc_kdf);
+
+    e_NR_CipheringAlgorithm cipher_algo;
+    switch (ue_context_p->ue_context.ciphering_algorithm) {
+    case 0: cipher_algo = NR_CipheringAlgorithm_nea0; break;
+    case 1: cipher_algo = NR_CipheringAlgorithm_nea1; break;
+    case 2: cipher_algo = NR_CipheringAlgorithm_nea2; break;
+    case 3: cipher_algo = NR_CipheringAlgorithm_nea3; break;
+    default: LOG_E(RRC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1);
+    }
+
+    fill_default_rbconfig(ue_context_p->ue_context.rb_config,
+                          m->e_rabs_tobeadded[0].e_rab_id,
+                          m->e_rabs_tobeadded[0].drb_ID,
+                          cipher_algo,
+                          NR_SecurityConfig__keyToUse_secondary);
   }
   fill_default_reconfig(carrier->servingcellconfigcommon,
                         reconfig_ies,
@@ -285,10 +357,11 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
     (NR_SRB_ToAddModList_t *) NULL,
     ue_context_p->ue_context.rb_config->drb_ToAddModList ,
     ue_context_p->ue_context.rb_config->drb_ToReleaseList,
-    0xff,
-    NULL,
-    NULL,
-    NULL,
+    (ue_context_p->ue_context.integrity_algorithm << 4) | ue_context_p->ue_context.ciphering_algorithm,
+    NULL,          /* kRRCenc - unused */
+    NULL,          /* kRRCint - unused */
+    kUPenc,        /* kUPenc  */
+    NULL,          /* kUPint  - unused */
     NULL,
     NULL,
     ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList);
diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c
index aebdc2f1cc9b260dda194bbae0fcc96e3461ab87..ab3f19227622cbcb9b26f3339bfc448fcdc32997 100644
--- a/openair2/RRC/NR/rrc_gNB_reconfig.c
+++ b/openair2/RRC/NR/rrc_gNB_reconfig.c
@@ -1329,7 +1329,10 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
   reconfig->nonCriticalExtension = NULL;
 }
 
-void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) {
+void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
+                          int eps_bearer_id, int rb_id,
+                           e_NR_CipheringAlgorithm ciphering_algorithm,
+                           e_NR_SecurityConfig__keyToUse key_to_use) {
 
   rbconfig->srb_ToAddModList = NULL;
   rbconfig->srb3_ToRelease = NULL;
@@ -1337,8 +1340,8 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) {
   NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod));
   drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation));
   drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity;
-  drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 5;
-  drb_ToAddMod->drb_Identity = 1;
+  drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= eps_bearer_id;
+  drb_ToAddMod->drb_Identity = rb_id;
   drb_ToAddMod->reestablishPDCP = NULL;
   drb_ToAddMod->recoverPDCP = NULL;
   drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config));
@@ -1367,12 +1370,12 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) {
 
   rbconfig->securityConfig = calloc(1,sizeof(*rbconfig->securityConfig));
   rbconfig->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(*rbconfig->securityConfig->securityAlgorithmConfig));
-  rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0;
+  rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = ciphering_algorithm;
   rbconfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm=NULL;
   rbconfig->securityConfig->keyToUse = calloc(1,sizeof(*rbconfig->securityConfig->keyToUse));
-  *rbconfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master;
+  *rbconfig->securityConfig->keyToUse = key_to_use;
 
-  xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig);
+//  xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig);
 }
 /* Function to set or overwrite PTRS DL RRC parameters */
 void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset)
diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c
index b6c0ae4b453cd57f82c4450bb85e470a2d87d070..460dbf1d22b5f06a6ff41b9da7f2d2d370cec00a 100644
--- a/openair2/RRC/NR_UE/rrc_UE.c
+++ b/openair2/RRC/NR_UE/rrc_UE.c
@@ -186,7 +186,8 @@ extern boolean_t nr_rrc_pdcp_config_asn1_req(
     const uint8_t                   security_modeP,
     uint8_t                  *const kRRCenc,
     uint8_t                  *const kRRCint,
-    uint8_t                  *const kUPenc
+    uint8_t                  *const kUPenc,
+    uint8_t                  *const kUPint
   #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
     ,LTE_PMCH_InfoList_r9_t  *pmch_InfoList_r9
   #endif
@@ -2085,6 +2086,7 @@ nr_sa_rrc_ue_process_radioBearerConfig(
     //                             NULL,
     //                             NULL,
     //                             NULL,
+    //                             NULL,
     //                             NULL);
     // Refresh SRBs
     // nr_rrc_rlc_config_asn1_req(ctxt_pP,
@@ -2176,6 +2178,7 @@ nr_sa_rrc_ue_process_radioBearerConfig(
       //                             NULL,
       //                             kUPenc,
       //                             NULL,
+      //                             NULL,
       //                             NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB,
       //                             NULL);
       // Refresh DRBs
diff --git a/openair2/UTIL/OSA/osa_defs.h b/openair2/UTIL/OSA/osa_defs.h
index 304dd07042d4dca0259a6164014b2ddf371f07b6..633465868380bba098f25dfbe385873baa050765 100644
--- a/openair2/UTIL/OSA/osa_defs.h
+++ b/openair2/UTIL/OSA/osa_defs.h
@@ -53,6 +53,8 @@ typedef enum {
 
 //int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB);
 
+int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB);
+
 int derive_key(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
                const uint8_t key[32], uint8_t **out);
 int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
diff --git a/openair2/UTIL/OSA/osa_key_deriver.c b/openair2/UTIL/OSA/osa_key_deriver.c
index 71c7793fa084c451a73223218b95e133f9602d0e..159ee7f159b93f9ce1c791edc263ff5787a247eb 100644
--- a/openair2/UTIL/OSA/osa_key_deriver.c
+++ b/openair2/UTIL/OSA/osa_key_deriver.c
@@ -159,3 +159,27 @@ int derive_keNB(const uint8_t key[32], const uint32_t nas_count, uint8_t **keNB)
     return 0;
 }
 */
+
+int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB)
+{
+  uint8_t *out;
+  uint8_t s[5];
+
+  /* FC is 0x1c (see 3gpp 33.401 annex A.15) */
+  s[0] = 0x1c;
+
+  /* put sk_counter */
+  s[1] = (sk_counter >> 8) & 0xff;
+  s[2] = sk_counter & 0xff;
+
+  /* put length of sk_counter (2) */
+  s[3] = 0x00;
+  s[4] = 0x02;
+
+  kdf(s, 5, keNB, 32, &out, 32);
+
+  memcpy(skgNB, out, 32);
+  free(out);
+
+  return 0;
+}
diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c
index 7c233d9e14d83e4a1a7c592a49643c40be391d1f..370d34868b577e7428a68d5e70ac49dad397124a 100644
--- a/openair3/S1AP/s1ap_eNB_handlers.c
+++ b/openair3/S1AP/s1ap_eNB_handlers.c
@@ -864,22 +864,36 @@ int s1ap_eNB_handle_initial_context_request(uint32_t   assoc_id,
       BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms);
     S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms =
       BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms);
-    /* id-SecurityKey : Copy the security key */
   } else {/* ie != NULL */
     return -1;
   }
 
+  /* id-SecurityKey : Copy the security key */
   S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                              S1AP_ProtocolIE_ID_id_SecurityKey, true);
 
   if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
     memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key,
            ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size);
-    itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
   } else {/* ie != NULL */
     return -1;
   }
 
+  /* id-NRUESecurityCapabilities */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
+                             S1AP_ProtocolIE_ID_id_NRUESecurityCapabilities, false);
+  if (ie != NULL) {
+    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms =
+      BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRencryptionAlgorithms);
+    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms =
+      BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRintegrityProtectionAlgorithms);
+  } else {
+    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = 0;
+    S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = 0;
+  }
+
+  itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
+
   return 0;
 }
 
diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h
index 85ee80ea7cdf443a01559cb27cdc265f09ababa2..93e9ffb52f8d908c5f6da1dbcf56bdd68db50aad 100644
--- a/targets/ARCH/COMMON/common_lib.h
+++ b/targets/ARCH/COMMON/common_lib.h
@@ -105,9 +105,10 @@ typedef enum {
   ADRV9371_ZC706_DEV,
   /*!\brief device is UEDv2 */
   UEDv2_DEV,
+  RFSIMULATOR,
   MAX_RF_DEV_TYPE
 } dev_type_t;
-#define DEVTYPE_NAMES {"","EXMIMO","USRP B200","USRP X300","USRP N300","BLADERF","LMSSDR","IRIS","No HW","ADRV9371_ZC706","UEDv2"} 
+#define DEVTYPE_NAMES {"","EXMIMO","USRP B200","USRP X300","USRP N300","BLADERF","LMSSDR","IRIS","No HW","ADRV9371_ZC706","UEDv2", "RFSIMULATOR"} 
 /*!\brief transport protocol types
  */
 typedef enum {
@@ -491,15 +492,11 @@ struct openair0_device_t {
 typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg);
 /* type of transport init function, implemented in shared lib */
 typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params);
-#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5  // UE DL FDD record
-#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A  // UE UL FDD record
-#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6  // UE DL TDD record
-#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A  // UE UL TDD record
+#define UE_MAGICDL 0xA5A5A5A5A5A5A5A5  // UE DL FDD record
+#define UE_MAGICUL 0x5A5A5A5A5A5A5A5A  // UE UL FDD record
 
-#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5  // eNB DL FDD record
-#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B  // eNB UL FDD record
-#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6  // eNB DL TDD record
-#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B  // eNB UL TDD record
+#define ENB_MAGICDL 0xB5B5B5B5B5B5B5B5  // eNB DL FDD record
+#define ENB_MAGICUL 0x5B5B5B5B5B5B5B5B  // eNB UL FDD record
 
 #define OPTION_LZ4  0x00000001          // LZ4 compression (option_value is set to compressed size)
 
@@ -516,19 +513,6 @@ typedef struct {
   uint32_t option_flag;    // Option flag
 } samplesBlockHeader_t;
 
-#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5  // UE DL FDD record
-#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A  // UE UL FDD record
-#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6  // UE DL TDD record
-#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A  // UE UL TDD record
-
-#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5  // eNB DL FDD record
-#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B  // eNB UL FDD record
-#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6  // eNB DL TDD record
-#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B  // eNB UL TDD record
-
-#define OPTION_LZ4  0x00000001          // LZ4 compression (option_value is set to compressed size)
-
-
 #ifdef __cplusplus
 extern "C"
 {
diff --git a/targets/ARCH/ETHERNET/benetel/4g/benetel.c b/targets/ARCH/ETHERNET/benetel/4g/benetel.c
index 76855111e11828389e24b04aa0b59cbaa4a44a0c..d3b72463b495a1cfd4579cf770350a12f94dd5c1 100644
--- a/targets/ARCH/ETHERNET/benetel/4g/benetel.c
+++ b/targets/ARCH/ETHERNET/benetel/4g/benetel.c
@@ -163,8 +163,8 @@ int trx_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len)
     cap->FH_fmt                           = OAI_IF4p5_only;
     cap->num_bands                        = 1;
     cap->band_list[0]                     = 7;
-    cap->nb_rx[0]                         = 1;
-    cap->nb_tx[0]                         = 1;
+    cap->nb_rx[0]                         = device->openair0_cfg->rx_num_channels;
+    cap->nb_tx[0]                         = device->openair0_cfg->tx_num_channels;
     cap->max_pdschReferenceSignalPower[0] = -27;
     cap->max_rxgain[0]                    = 90;
 
@@ -194,11 +194,12 @@ void benetel_fh_if4p5_south_in(RU_t *ru,
   LTE_DL_FRAME_PARMS *fp;
   int symbol;
   int32_t *rxdata;
-  int antenna = 0;
+  int antenna;
 
   lock_ul_buffer(&s->buffers, *subframe);
 next:
-  while (!(s->buffers.ul_busy[*subframe] == 0x3fff ||
+  while (!((s->buffers.ul_busy[0][*subframe] == 0x3fff &&
+            s->buffers.ul_busy[1][*subframe] == 0x3fff) ||
            s->buffers.prach_busy[*subframe] == 1))
     wait_ul_buffer(&s->buffers, *subframe);
   if (s->buffers.prach_busy[*subframe] == 1) {
@@ -217,24 +218,27 @@ next:
 
   eNB = eNB_list[0];
   fp  = &eNB->frame_parms;
-  for (symbol = 0; symbol < 14; symbol++) {
-    int i;
-    uint16_t *p = (uint16_t *)(&s->buffers.ul[*subframe][symbol*1200*4]);
-    for (i = 0; i < 1200*2; i++) {
-      p[i] = htons(p[i]);
-    }
-    rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size];
+  for (antenna = 0; antenna < ru->nb_rx; antenna++) {
+    for (symbol = 0; symbol < 14; symbol++) {
+      int i;
+      uint16_t *p = (uint16_t *)(&s->buffers.ul[antenna][*subframe][symbol*1200*4]);
+      for (i = 0; i < 1200*2; i++) {
+        p[i] = htons(p[i]);
+      }
+      rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size];
 #if 1
-    memcpy(rxdata + 2048 - 600,
-           &s->buffers.ul[*subframe][symbol*1200*4],
-           600 * 4);
-    memcpy(rxdata,
-           &s->buffers.ul[*subframe][symbol*1200*4] + 600*4,
-           600 * 4);
+      memcpy(rxdata + 2048 - 600,
+             &s->buffers.ul[antenna][*subframe][symbol*1200*4],
+             600 * 4);
+      memcpy(rxdata,
+             &s->buffers.ul[antenna][*subframe][symbol*1200*4] + 600*4,
+             600 * 4);
 #endif
+    }
   }
 
-  s->buffers.ul_busy[*subframe] = 0;
+  s->buffers.ul_busy[0][*subframe] = 0;
+  s->buffers.ul_busy[1][*subframe] = 0;
   signal_ul_buffer(&s->buffers, *subframe);
   unlock_ul_buffer(&s->buffers, *subframe);
 
@@ -272,45 +276,49 @@ void benetel_fh_if4p5_south_out(RU_t *ru,
   LTE_DL_FRAME_PARMS *fp;
   int symbol;
   int32_t *txdata;
-  int aa = 0;
+  int aa;
 
   //printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, subframe, timestamp);
 
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
 
   lock_dl_buffer(&s->buffers, subframe);
-  if (s->buffers.dl_busy[subframe]) {
+  if (s->buffers.dl_busy[0][subframe] ||
+      s->buffers.dl_busy[1][subframe]) {
     printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, subframe);
      unlock_dl_buffer(&s->buffers, subframe);
     return;
   }
   eNB = eNB_list[0];
   fp  = &eNB->frame_parms;
-  if (ru->num_eNB != 1 || ru->nb_tx != 1 || fp->ofdm_symbol_size != 2048 ||
+  if (ru->num_eNB != 1 || fp->ofdm_symbol_size != 2048 ||
       fp->Ncp != NORMAL || fp->symbols_per_tti != 14) {
     printf("%s:%d:%s: unsupported configuration\n",
            __FILE__, __LINE__, __FUNCTION__);
     exit(1);
   }
 
-  for (symbol = 0; symbol < 14; symbol++) {
-    txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size];
+  for (aa = 0; aa < ru->nb_tx; aa++) {
+    for (symbol = 0; symbol < 14; symbol++) {
+      txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size];
 #if 1
-    memcpy(&s->buffers.dl[subframe][symbol*1200*4],
-           txdata + 2048 - 600,
-           600 * 4);
-    memcpy(&s->buffers.dl[subframe][symbol*1200*4] + 600*4,
-           txdata + 1,
-           600 * 4);
+      memcpy(&s->buffers.dl[aa][subframe][symbol*1200*4],
+             txdata + 2048 - 600,
+             600 * 4);
+      memcpy(&s->buffers.dl[aa][subframe][symbol*1200*4] + 600*4,
+             txdata + 1,
+             600 * 4);
 #endif
-    int i;
-    uint16_t *p = (uint16_t *)(&s->buffers.dl[subframe][symbol*1200*4]);
-    for (i = 0; i < 1200*2; i++) {
-      p[i] = htons(p[i]);
+      int i;
+      uint16_t *p = (uint16_t *)(&s->buffers.dl[aa][subframe][symbol*1200*4]);
+      for (i = 0; i < 1200*2; i++) {
+        p[i] = htons(p[i]);
+      }
     }
   }
 
-  s->buffers.dl_busy[subframe] = 0x3fff;
+  s->buffers.dl_busy[0][subframe] = 0x3fff;
+  s->buffers.dl_busy[1][subframe] = 0x3fff;
   unlock_dl_buffer(&s->buffers, subframe);
 
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx, ru->proc.frame_tx);
diff --git a/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c b/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c
index 42953d1d4a8be829135d4c80332f6b253fbf9270..2b6ef37e6fa0c242688a9f9f6598b8f1cc9ef9b6 100644
--- a/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c
+++ b/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c
@@ -233,19 +233,20 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs)
 	}
 
 
-	if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && ANT_NUM == 0x00) {
+	if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce) {
           p.frame = FRAME;
           p.subframe = SUBFRAME >> 4;
           p.slot = 0; /* unused */
           p.symbol = SYMBOL;
-          p.antenna = 0;
+          p.antenna = ANT_NUM;
           memcpy(p.iq, IQ_ptr, 4800);
           store_ul(bs, &p);
         }
 
-	// U-PLANE UL ANT_0 PROCESSING
-	if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && ANT_NUM == 0x00 && dl_start == 1)
+	// U-PLANE UL PROCESSING
+	if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && dl_start == 1)
 	{
+                int a = ANT_NUM;
                 int tx_frame = FRAME;
                 int tx_subframe = SUBFRAME >> 4;
                 int tx_symbol = SYMBOL + 5;
@@ -266,33 +267,20 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs)
                 SUBFRAME = tx_subframe << 4;
                 SYMBOL = tx_symbol;
 
-                /* antenna 0 - send actual DL data (if available) */
+                /* send actual DL data (if available) */
                 lock_dl_buffer(bs->buffers, tx_subframe);
-                if (!(bs->buffers->dl_busy[tx_subframe] & (1 << tx_symbol))) {
-                  printf("%s: warning, DL underflow (sf.symbol %d.%d)\n", __FUNCTION__,
+                if (!(bs->buffers->dl_busy[a][tx_subframe] & (1 << tx_symbol))) {
+                  printf("%s: warning, DL underflow (antenna %d sf.symbol %d.%d)\n",
+                         __FUNCTION__,
+                         a,
                          tx_subframe, tx_symbol);
                   memset(IQ_ptr, 0, 1200 * 4);
                 } else {
-                  memcpy(IQ_ptr, bs->buffers->dl[tx_subframe] + tx_symbol * 1200*4,
+                  memcpy(IQ_ptr, bs->buffers->dl[a][tx_subframe] + tx_symbol * 1200*4,
                          1200*4);
                 }
-                bs->buffers->dl_busy[tx_subframe] &= ~(1 << tx_symbol);
+                bs->buffers->dl_busy[a][tx_subframe] &= ~(1 << tx_symbol);
                 unlock_dl_buffer(bs->buffers, tx_subframe);
-
-		// fill DL Data for ant 0 with 0 value
-//		memset(IQ_ptr, 0, 4800);
-	}
-
-	// U-PLANE UL ANT_1 PROCESSING
-	else if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && ANT_NUM == 0x01 && dl_start == 1)
-	{
-
-//		ANT_NUM = 0x01;
-		SYMBOL = (SYMBOL + 5) % 14;
-		PAYLOAD_2 = 0xc8;
-
-		// fill DL Data for ant 1 with 0 value
-		memset(IQ_ptr, 0, 4800);
 	}
 
 	// U-PLANE PRACH PROCESSING
diff --git a/targets/ARCH/ETHERNET/benetel/4g/low.c b/targets/ARCH/ETHERNET/benetel/4g/low.c
index 038592d596c4cac0d21a4f1a79afe1014174f59c..14783a700b46a97dd6d02cd3fae2959a2b0c89f6 100644
--- a/targets/ARCH/ETHERNET/benetel/4g/low.c
+++ b/targets/ARCH/ETHERNET/benetel/4g/low.c
@@ -27,37 +27,36 @@
 
 void store_ul(benetel_t *bs, ul_packet_t *ul)
 {
-  /* only antenna 0 for the moment */
-  if (ul->antenna != 0)
-    return;
+  int a = ul->antenna;
 
-  if (ul->subframe != bs->next_subframe ||
-      ul->symbol != bs->next_symbol) {
-    printf("%s: fatal, expected frame.sf.symbol %d.%d.%d, got %d.%d.%d\n",
+  if (ul->subframe != bs->next_subframe[a] ||
+      ul->symbol != bs->next_symbol[a]) {
+    printf("%s: fatal, antenna %d expected frame.sf.symbol %d.%d.%d, got %d.%d.%d\n",
            __FUNCTION__,
-           bs->expected_benetel_frame, bs->next_subframe, bs->next_symbol,
+           a,
+           bs->expected_benetel_frame[a], bs->next_subframe[a], bs->next_symbol[a],
            ul->frame, ul->subframe, ul->symbol);
     exit(1);
   }
 
-  lock_ul_buffer(bs->buffers, bs->next_subframe);
-  if (bs->buffers->ul_busy[bs->next_subframe] & (1 << bs->next_symbol)) {
+  lock_ul_buffer(bs->buffers, bs->next_subframe[a]);
+  if (bs->buffers->ul_busy[a][bs->next_subframe[a]] & (1 << bs->next_symbol[a])) {
     printf("%s: warning, UL overflow (sf.symbol %d.%d)\n", __FUNCTION__,
-           bs->next_subframe, bs->next_symbol);
+           bs->next_subframe[a], bs->next_symbol[a]);
   }
-  memcpy(bs->buffers->ul[bs->next_subframe] + bs->next_symbol * 1200*4,
+  memcpy(bs->buffers->ul[a][bs->next_subframe[a]] + bs->next_symbol[a] * 1200*4,
          ul->iq, 1200*4);
-  bs->buffers->ul_busy[bs->next_subframe] |= (1 << bs->next_symbol);
-  signal_ul_buffer(bs->buffers, bs->next_subframe);
-  unlock_ul_buffer(bs->buffers, bs->next_subframe);
+  bs->buffers->ul_busy[a][bs->next_subframe[a]] |= (1 << bs->next_symbol[a]);
+  signal_ul_buffer(bs->buffers, bs->next_subframe[a]);
+  unlock_ul_buffer(bs->buffers, bs->next_subframe[a]);
 
-  bs->next_symbol++;
-  if (bs->next_symbol == 14) {
-    bs->next_symbol = 0;
-    bs->next_subframe = (bs->next_subframe + 1) % 10;
-    if (bs->next_subframe == 0) {
-      bs->expected_benetel_frame++;
-      bs->expected_benetel_frame &= 255;
+  bs->next_symbol[a]++;
+  if (bs->next_symbol[a] == 14) {
+    bs->next_symbol[a] = 0;
+    bs->next_subframe[a] = (bs->next_subframe[a] + 1) % 10;
+    if (bs->next_subframe[a] == 0) {
+      bs->expected_benetel_frame[a]++;
+      bs->expected_benetel_frame[a] &= 255;
     }
   }
 }
diff --git a/targets/ARCH/ETHERNET/benetel/4g/low.h b/targets/ARCH/ETHERNET/benetel/4g/low.h
index 5e75d9181e84f06447a6631373c043fe3d9779eb..e74bf89163bc54d2a34a0cfb7e9d065fbd2b47eb 100644
--- a/targets/ARCH/ETHERNET/benetel/4g/low.h
+++ b/targets/ARCH/ETHERNET/benetel/4g/low.h
@@ -26,9 +26,10 @@
 
 typedef struct {
   shared_buffers *buffers;
-  int            next_subframe;
-  int            next_symbol;
-  int            expected_benetel_frame;
+  /* [2] is for two antennas */
+  int            next_subframe[2];
+  int            next_symbol[2];
+  int            expected_benetel_frame[2];
   char           *dpdk_main_command_line;
 } benetel_t;
 
diff --git a/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c b/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c
index ecff473010c34f1bfae5ab166ca3c83f663cb5b8..edf62a67e07ab71cda2f6e3f32e9d70ac9c2f565 100644
--- a/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c
+++ b/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c
@@ -68,7 +68,8 @@ void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_
 
   bs->buffers = buffers;
 
-  bs->expected_benetel_frame = 255;
+  bs->expected_benetel_frame[0] = 255;
+  bs->expected_benetel_frame[1] = 255;
 
   bs->dpdk_main_command_line = dpdk_main_command_line;
 
diff --git a/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c
index 492a15dfc3833e85b38d196b32903615f8618114..380cbabc73bf618201f7e4864c24afec9521e156 100644
--- a/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c
+++ b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c
@@ -44,9 +44,12 @@ void init_buffers(shared_buffers *s)
   /* in FDD the eNB's first transmitted DL subframe is 4 but the device
    * needs to have subframes 1, 2 and 3 ready. Let's pretend there are ready.
    */
-  s->dl_busy[1] = 0x3fff;
-  s->dl_busy[2] = 0x3fff;
-  s->dl_busy[3] = 0x3fff;
+  s->dl_busy[0][1] = 0x3fff;
+  s->dl_busy[0][2] = 0x3fff;
+  s->dl_busy[0][3] = 0x3fff;
+  s->dl_busy[1][1] = 0x3fff;
+  s->dl_busy[1][2] = 0x3fff;
+  s->dl_busy[1][3] = 0x3fff;
 }
 
 void lock_dl_buffer(shared_buffers *s, int subframe)
diff --git a/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h
index 1d5040b95b55d3ef76fd6d40ede97f7ea686acca..ed174265c5d4fbff11f212b2ae2b0eb1883c5e66 100644
--- a/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h
+++ b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h
@@ -26,10 +26,11 @@
 #include <stdint.h>
 
 typedef struct {
-  unsigned char dl[10][14*1200*4];
-  unsigned char ul[10][14*1200*4];
-  uint16_t dl_busy[10];
-  uint16_t ul_busy[10];
+  /* [2] is for two antennas */
+  unsigned char dl[2][10][14*1200*4];
+  unsigned char ul[2][10][14*1200*4];
+  uint16_t dl_busy[2][10];
+  uint16_t ul_busy[2][10];
 
   pthread_mutex_t m_ul[10];
   pthread_cond_t  c_ul[10];
diff --git a/targets/ARCH/ETHERNET/benetel/5g/benetel.c b/targets/ARCH/ETHERNET/benetel/5g/benetel.c
index 2f60e7dc49efe15a25325565744cd916744d3bdc..cededa968eddd8c06bfdfcb1f44a8dcf86cfb362 100644
--- a/targets/ARCH/ETHERNET/benetel/5g/benetel.c
+++ b/targets/ARCH/ETHERNET/benetel/5g/benetel.c
@@ -162,8 +162,9 @@ int trx_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len)
     cap->FH_fmt                           = OAI_IF4p5_only;
     cap->num_bands                        = 1;
     cap->band_list[0]                     = 78;
-    cap->nb_rx[0]                         = 1;
-    cap->nb_tx[0]                         = 1;
+    /* TODO: hardcoded to 1 for the moment, get the real value somehow... */
+    cap->nb_rx[0]                         = 1; //device->openair0_cfg->rx_num_channels;
+    cap->nb_tx[0]                         = 1; //device->openair0_cfg->tx_num_channels;
     cap->max_pdschReferenceSignalPower[0] = -27;
     cap->max_rxgain[0]                    = 90;
 
@@ -201,12 +202,13 @@ void benetel_fh_if4p5_south_in(RU_t *ru,
   NR_DL_FRAME_PARMS *fp;
   int symbol;
   int32_t *rxdata;
-  int antenna = 0;
+  int antenna;
 
   lock_ul_buffer(&s->buffers, *slot);
 #if 1
 next:
-  while (!(s->buffers.ul_busy[*slot] == 0x3fff ||
+  while (!((s->buffers.ul_busy[0][*slot] == 0x3fff &&
+            s->buffers.ul_busy[1][*slot] == 0x3fff) ||
            s->buffers.prach_busy[*slot] == 1))
     wait_ul_buffer(&s->buffers, *slot);
   if (s->buffers.prach_busy[*slot] == 1) {
@@ -226,24 +228,31 @@ next:
 #endif
 
   fp = ru->nr_frame_parms;
-  for (symbol = 0; symbol < 14; symbol++) {
-    int i;
-    uint16_t *p = (uint16_t *)(&s->buffers.ul[*slot][symbol*1272*4]);
-    for (i = 0; i < 1272*2; i++) {
-      p[i] = htons(p[i]);
-    }
-    rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size];
+  for (antenna = 0; antenna < ru->nb_rx; antenna++) {
+    for (symbol = 0; symbol < 14; symbol++) {
+      int i;
+      int16_t *p = (int16_t *)(&s->buffers.ul[antenna][*slot][symbol*1272*4]);
+      for (i = 0; i < 1272*2; i++) {
+        p[i] = (int16_t)(ntohs(p[i])) / 16;
+      }
+      rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size];
+#if 0
+if (*slot == 0 && symbol == 0)
+printf("rxdata in benetel_fh_if4p5_south_in %p\n", &ru->common.rxdataF[antenna][0]);
+#endif
 #if 1
-    memcpy(rxdata + 2048 - 1272/2,
-           &s->buffers.ul[*slot][symbol*1272*4],
-           (1272/2) * 4);
-    memcpy(rxdata,
-           &s->buffers.ul[*slot][symbol*1272*4] + (1272/2)*4,
-           (1272/2) * 4);
+      memcpy(rxdata + 2048 - 1272/2,
+             &s->buffers.ul[antenna][*slot][symbol*1272*4],
+             (1272/2) * 4);
+      memcpy(rxdata,
+             &s->buffers.ul[antenna][*slot][symbol*1272*4] + (1272/2)*4,
+             (1272/2) * 4);
 #endif
+    }
   }
 
-  s->buffers.ul_busy[*slot] = 0;
+  s->buffers.ul_busy[0][*slot] = 0;
+  s->buffers.ul_busy[1][*slot] = 0;
   signal_ul_buffer(&s->buffers, *slot);
   unlock_ul_buffer(&s->buffers, *slot);
 
@@ -281,43 +290,47 @@ void benetel_fh_if4p5_south_out(RU_t *ru,
   NR_DL_FRAME_PARMS *fp;
   int symbol;
   int32_t *txdata;
-  int aa = 0;
+  int aa;
 
   //printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, slot, timestamp);
 
   lock_dl_buffer(&s->buffers, slot);
-  if (s->buffers.dl_busy[slot]) {
+  if (s->buffers.dl_busy[0][slot] ||
+      s->buffers.dl_busy[1][slot]) {
     printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, slot);
     unlock_dl_buffer(&s->buffers, slot);
     return;
   }
 
   fp = ru->nr_frame_parms;
-  if (ru->num_gNB != 1 || ru->nb_tx != 1 || fp->ofdm_symbol_size != 2048 ||
+  if (ru->num_gNB != 1 || fp->ofdm_symbol_size != 2048 ||
       fp->Ncp != NORMAL || fp->symbols_per_slot != 14) {
     printf("%s:%d:%s: unsupported configuration\n",
            __FILE__, __LINE__, __FUNCTION__);
     exit(1);
   }
 
-  for (symbol = 0; symbol < 14; symbol++) {
-    txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size];
+  for (aa = 0; aa < ru->nb_tx; aa++) {
+    for (symbol = 0; symbol < 14; symbol++) {
+      txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size];
 #if 1
-    memcpy(&s->buffers.dl[slot][symbol*1272*4],
-           txdata + 2048 - (1272/2),
-           (1272/2) * 4);
-    memcpy(&s->buffers.dl[slot][symbol*1272*4] + (1272/2)*4,
-           txdata,
-           (1272/2) * 4);
+      memcpy(&s->buffers.dl[aa][slot][symbol*1272*4],
+             txdata + 2048 - (1272/2),
+             (1272/2) * 4);
+      memcpy(&s->buffers.dl[aa][slot][symbol*1272*4] + (1272/2)*4,
+             txdata,
+             (1272/2) * 4);
 #endif
-    int i;
-    uint16_t *p = (uint16_t *)(&s->buffers.dl[slot][symbol*1272*4]);
-    for (i = 0; i < 1272*2; i++) {
-      p[i] = htons(p[i]);
+      int i;
+      uint16_t *p = (uint16_t *)(&s->buffers.dl[aa][slot][symbol*1272*4]);
+      for (i = 0; i < 1272*2; i++) {
+        p[i] = htons(p[i]);
+      }
     }
   }
 
-  s->buffers.dl_busy[slot] = 0x3fff;
+  s->buffers.dl_busy[0][slot] = 0x3fff;
+  s->buffers.dl_busy[1][slot] = 0x3fff;
   unlock_dl_buffer(&s->buffers, slot);
 }
 
diff --git a/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c b/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c
index dd50603ec544fc91868c1735d23dd3003863d404..88f4ecb4cdebde52d1f8ce2997ad34762c1b5364 100644
--- a/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c
+++ b/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c
@@ -243,21 +243,22 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs)
 	}
 
 
-	if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && ANT_NUM == 0x00) {
+	if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4) {
           int subframe = SUBFRAME >> 4;
           int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03);
           p.frame = FRAME;
           p.slot = subframe * 2 + slot;
           p.symbol = SYMBOL & 0x3f;
-          p.antenna = 0;
+          p.antenna = ANT_NUM;
           memcpy(p.iq, IQ_ptr, 5088);
           store_ul(bs, &p);
      //     if (p.symbol==0) printf("store ul f.sl.sy %d.%d.%d\n", p.frame, p.slot, p.symbol);
         }
 
-	// U-PLANE UL ANT_0 PROCESSING
-	if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && ANT_NUM == 0x00 && dl_start == 1)
+	// U-PLANE UL PROCESSING
+	if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && dl_start == 1)
 	{
+                int a        = ANT_NUM & 0x01;
                 int frame    = FRAME;
                 int subframe = SUBFRAME >> 4;
                 int slot     = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03);
@@ -282,66 +283,45 @@ l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs)
                   }
                 }
 
-		ANT_NUM = 0x00;
-
 		// Mask the symbol bits from UL packet received and apply the shift.
 		SYMBOL = ((SYMBOL & 0b00111111) + 10) % 14;
 
-		ANT_NUM = 0x00;
+                ANT_NUM = a;
 		SUBFRAME = sf;
 
+                if (a == 1)
+                  slot_id_ctrl++;
+
 		// Slot id control for DL
-		if(slot_id_ctrl > 13){
-			SYMBOL = SYMBOL | 0b01000000;
+		if (slot_id_ctrl > 13) {
+                  SYMBOL = SYMBOL | 0b01000000;
+
+                  if (a == 1) {
+                    if (slot_id_ctrl > 27) {
+                      slot_id_ctrl = 0;
+                      sf = sf + 0x10;
+
+                      if (sf > 0x90){
+                        sf = 0;
+                      }
+                    }
+                  }
 		}
 
-                /* antenna 0 - send actual DL data (if available) */
+                /* send actual DL data (if available) */
                 oai_slot = tx_subframe * 2 + tx_slot;
                 lock_dl_buffer(bs->buffers, oai_slot);
-                if (!(bs->buffers->dl_busy[oai_slot] & (1 << tx_symbol))) {
-                  printf("%s: warning, DL underflow (sl.symbol %d.%d)\n", __FUNCTION__,
-                         oai_slot, tx_symbol);
+                if (!(bs->buffers->dl_busy[a][oai_slot] & (1 << tx_symbol))) {
+                  printf("%s: warning, DL underflow (antenna %d sl.symbol %d.%d)\n", __FUNCTION__,
+                         a, oai_slot, tx_symbol);
                   memset(IQ_ptr, 0, 1272 * 4);
                 } else {
-                  memcpy(IQ_ptr, bs->buffers->dl[oai_slot] + tx_symbol * 1272*4,
+                  memcpy(IQ_ptr, bs->buffers->dl[a][oai_slot] + tx_symbol * 1272*4,
                          1272*4);
                 }
 //printf("DL buffer f sf slot symbol %d %d %d %d (sf %d)\n", tx_frame, tx_subframe, tx_slot, tx_symbol, (int)sf);
-                bs->buffers->dl_busy[oai_slot] &= ~(1 << tx_symbol);
+                bs->buffers->dl_busy[a][oai_slot] &= ~(1 << tx_symbol);
                 unlock_dl_buffer(bs->buffers, oai_slot);
-
-		// fill DL Data for ant 0 with 0 value
-//		memset(IQ_ptr, 0, 5088);
-	}
-
-	// U-PLANE UL ANT_1 PROCESSING
-	if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && ANT_NUM == 0x01 && dl_start == 1)
-	{
-
-		// Mask the symbol bits from UL packet received and apply the shift.
-		SYMBOL = ((SYMBOL & 0b00111111) +10) % 14;
-
-		ANT_NUM = 0x01;
-		SUBFRAME = sf;
-
-		slot_id_ctrl++;
-
-		// Slot id control for DL
-		if(slot_id_ctrl > 13){
-			SYMBOL = SYMBOL | 0b01000000;
-
-			if(slot_id_ctrl > 27){
-				slot_id_ctrl = 0;
-				sf = sf + 0x10;
-
-				if (sf >0x90){
-					sf = 0;
-				}
-			}
-		}
-
-		// fill DL Data for ant 1 with 0 value
-		memset(IQ_ptr, 0, 5088);
 	}
 
 	// U-PLANE PRACH PROCESSING
diff --git a/targets/ARCH/ETHERNET/benetel/5g/low.c b/targets/ARCH/ETHERNET/benetel/5g/low.c
index 52c9f24127ce279d67b82cfa3f4fae4b22de852e..b34d69784f119db177c144c4d42542a798eccdd4 100644
--- a/targets/ARCH/ETHERNET/benetel/5g/low.c
+++ b/targets/ARCH/ETHERNET/benetel/5g/low.c
@@ -35,63 +35,61 @@ printf("store_ul %d.%ld (%ld)\n", (int)(t.tv_sec % 60), t.tv_nsec, t.tv_nsec - o
 old = t;
 #endif
 
-  /* only antenna 0 for the moment */
-  if (ul->antenna != 0)
-    return;
+  int a = ul->antenna;
 
-  if (ul->slot != bs->next_slot ||
-      ul->symbol != bs->next_symbol) {
-    printf("%s: error, expected frame.sl.symbol %d.%d.%d, got %d.%d.%d\n",
+  if (ul->slot != bs->next_slot[a] ||
+      ul->symbol != bs->next_symbol[a]) {
+    printf("%s: error, antenna %d expected frame.sl.symbol %d.%d.%d, got %d.%d.%d\n",
            __FUNCTION__,
-           bs->expected_benetel_frame, bs->next_slot, bs->next_symbol,
+           a, bs->expected_benetel_frame[a], bs->next_slot[a], bs->next_symbol[a],
            ul->frame, ul->slot, ul->symbol);
   }
 
   /* fill missing data with 0s */
-  while (ul->slot != bs->next_slot ||
-         ul->symbol != bs->next_symbol) {
-    lock_ul_buffer(bs->buffers, bs->next_slot);
-    if (bs->buffers->ul_busy[bs->next_slot] & (1 << bs->next_symbol)) {
-      printf("%s: warning, UL overflow (sl.symbol %d.%d)\n", __FUNCTION__,
-             bs->next_slot, bs->next_symbol);
+  while (ul->slot != bs->next_slot[a] ||
+         ul->symbol != bs->next_symbol[a]) {
+    lock_ul_buffer(bs->buffers, bs->next_slot[a]);
+    if (bs->buffers->ul_busy[a][bs->next_slot[a]] & (1 << bs->next_symbol[a])) {
+      printf("%s: warning, antenna %d UL overflow (sl.symbol %d.%d)\n", __FUNCTION__,
+             a, bs->next_slot[a], bs->next_symbol[a]);
     }
 
-    memset(bs->buffers->ul[bs->next_slot] + bs->next_symbol * 1272*4,
+    memset(bs->buffers->ul[a][bs->next_slot[a]] + bs->next_symbol[a] * 1272*4,
            0, 1272*4);
-    bs->buffers->ul_busy[bs->next_slot] |= (1 << bs->next_symbol);
-    signal_ul_buffer(bs->buffers, bs->next_slot);
-    unlock_ul_buffer(bs->buffers, bs->next_slot);
-
-    bs->next_symbol++;
-    if (bs->next_symbol == 14) {
-      bs->next_symbol = 0;
-      bs->next_slot = (bs->next_slot + 1) % 20;
-      if (bs->next_slot == 0) {
-        bs->expected_benetel_frame++;
-        bs->expected_benetel_frame &= 255;
+    bs->buffers->ul_busy[a][bs->next_slot[a]] |= (1 << bs->next_symbol[a]);
+    signal_ul_buffer(bs->buffers, bs->next_slot[a]);
+    unlock_ul_buffer(bs->buffers, bs->next_slot[a]);
+
+    bs->next_symbol[a]++;
+    if (bs->next_symbol[a] == 14) {
+      bs->next_symbol[a] = 0;
+      bs->next_slot[a] = (bs->next_slot[a] + 1) % 20;
+      if (bs->next_slot[a] == 0) {
+        bs->expected_benetel_frame[a]++;
+        bs->expected_benetel_frame[a] &= 255;
       }
     }
   }
 
-  lock_ul_buffer(bs->buffers, bs->next_slot);
-  if (bs->buffers->ul_busy[bs->next_slot] & (1 << bs->next_symbol)) {
-    printf("%s: warning, UL overflow (sl.symbol %d.%d)\n", __FUNCTION__,
-           bs->next_slot, bs->next_symbol);
+  lock_ul_buffer(bs->buffers, bs->next_slot[a]);
+  if (bs->buffers->ul_busy[a][bs->next_slot[a]] & (1 << bs->next_symbol[a])) {
+    printf("%s: warning, antenna %d UL overflow (sl.symbol %d.%d)\n", __FUNCTION__,
+           a, bs->next_slot[a], bs->next_symbol[a]);
   }
 
-  memcpy(bs->buffers->ul[bs->next_slot] + bs->next_symbol * 1272*4,
+  memcpy(bs->buffers->ul[a][bs->next_slot[a]] + bs->next_symbol[a] * 1272*4,
          ul->iq, 1272*4);
-  bs->buffers->ul_busy[bs->next_slot] |= (1 << bs->next_symbol);
-  signal_ul_buffer(bs->buffers, bs->next_slot);
-  unlock_ul_buffer(bs->buffers, bs->next_slot);
-
-  bs->next_symbol++;
-  if (bs->next_symbol == 14) {
-    bs->next_symbol = 0;
-    bs->next_slot = (bs->next_slot + 1) % 20;
-    if (bs->next_slot == 0) {
-      bs->expected_benetel_frame++;
-      bs->expected_benetel_frame &= 255;
+  bs->buffers->ul_busy[a][bs->next_slot[a]] |= (1 << bs->next_symbol[a]);
+  signal_ul_buffer(bs->buffers, bs->next_slot[a]);
+  unlock_ul_buffer(bs->buffers, bs->next_slot[a]);
+
+  bs->next_symbol[a]++;
+  if (bs->next_symbol[a] == 14) {
+    bs->next_symbol[a] = 0;
+    bs->next_slot[a] = (bs->next_slot[a] + 1) % 20;
+    if (bs->next_slot[a] == 0) {
+      bs->expected_benetel_frame[a]++;
+      bs->expected_benetel_frame[a] &= 255;
     }
   }
 }
diff --git a/targets/ARCH/ETHERNET/benetel/5g/low.h b/targets/ARCH/ETHERNET/benetel/5g/low.h
index 5e1daee9d1ceaf005e957426526a752291ecaeda..659819296af298b3cdc86e99df4d64238e1c4671 100644
--- a/targets/ARCH/ETHERNET/benetel/5g/low.h
+++ b/targets/ARCH/ETHERNET/benetel/5g/low.h
@@ -26,9 +26,10 @@
 
 typedef struct {
   shared_buffers *buffers;
-  int            next_slot;
-  int            next_symbol;
-  int            expected_benetel_frame;
+  /* [2] is for two antennas */
+  int            next_slot[2];
+  int            next_symbol[2];
+  int            expected_benetel_frame[2];
   char           *dpdk_main_command_line;
 } benetel_t;
 
diff --git a/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c b/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c
index 5e26f6782ea737e0b6b18c23b39bc86a01d74839..b26df0772375afebb7cf327f8fd3546348ef4a08 100644
--- a/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c
+++ b/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c
@@ -68,7 +68,8 @@ void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_
 
   bs->buffers = buffers;
 
-  bs->expected_benetel_frame = 255;
+  bs->expected_benetel_frame[0] = 255;
+  bs->expected_benetel_frame[1] = 255;
 
   bs->dpdk_main_command_line = dpdk_main_command_line;
 
diff --git a/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c
index b9da10b380687819a643f0593c152e6879ab9e69..a302400eb41c835e3820c5cb2ae6d5a375ef090c 100644
--- a/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c
+++ b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c
@@ -45,11 +45,16 @@ void init_buffers(shared_buffers *s)
    * needs to have slots 1, 2 and 3, 4 and 5 ready. Let's pretend
    * they are ready.
    */
-  s->dl_busy[1] = 0x3fff;
-  s->dl_busy[2] = 0x3fff;
-  s->dl_busy[3] = 0x3fff;
-  s->dl_busy[4] = 0x3fff;
-  s->dl_busy[5] = 0x3fff;
+  s->dl_busy[0][1] = 0x3fff;
+  s->dl_busy[0][2] = 0x3fff;
+  s->dl_busy[0][3] = 0x3fff;
+  s->dl_busy[0][4] = 0x3fff;
+  s->dl_busy[0][5] = 0x3fff;
+  s->dl_busy[1][1] = 0x3fff;
+  s->dl_busy[1][2] = 0x3fff;
+  s->dl_busy[1][3] = 0x3fff;
+  s->dl_busy[1][4] = 0x3fff;
+  s->dl_busy[1][5] = 0x3fff;
 }
 
 void lock_dl_buffer(shared_buffers *s, int slot)
diff --git a/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h
index ca7dbd9c8f92aef059813f721462812f8e87efc1..9d51b8138dafb5721462c730256c8db3e0d6095a 100644
--- a/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h
+++ b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h
@@ -26,10 +26,11 @@
 #include <stdint.h>
 
 typedef struct {
-  unsigned char dl[20][14*1272*4];
-  unsigned char ul[20][14*1272*4];
-  uint16_t dl_busy[20];
-  uint16_t ul_busy[20];
+  /* [2] is for two antennas */
+  unsigned char dl[2][20][14*1272*4];
+  unsigned char ul[2][20][14*1272*4];
+  uint16_t dl_busy[2][20];
+  uint16_t ul_busy[2][20];
 
   pthread_mutex_t m_ul[20];
   pthread_cond_t  c_ul[20];
diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c
index 79bf3dd0772f7c5dbdc61505b3cdb33201884cf4..cd35c46a15a40c882e7c393adbe55ea527599792 100644
--- a/targets/ARCH/rfsimulator/simulator.c
+++ b/targets/ARCH/rfsimulator/simulator.c
@@ -76,15 +76,16 @@ extern RAN_CONTEXT_t RC;
 /*                                            configuration parameters for the rfsimulator device                                                                              */
 /*   optname                     helpstr                     paramflags           XXXptr                               defXXXval                          type         numelt  */
 /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
-#define RFSIMULATOR_PARAMS_DESC {\
-    {"serveraddr",             "<ip address to connect to>\n",          0,         strptr:&(rfsimulator->ip),              defstrval:"127.0.0.1",           TYPE_STRING,    0 },\
-    {"serverport",             "<port to connect to>\n",                0,         u16ptr:&(rfsimulator->port),            defuintval:PORT,                 TYPE_UINT16,    0 },\
-    {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS,               0,         strlistptr:NULL,                        defstrlistval:NULL,              TYPE_STRINGLIST,0 },\
-    {"IQfile",                 "<file path to use when saving IQs>\n",  0,         strptr:&(saveF),                        defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING,    0 },\
-    {"modelname",              "<channel model name>\n",                0,         strptr:&(modelname),                    defstrval:"AWGN",                TYPE_STRING,    0 },\
-    {"ploss",                  "<channel path loss in dB>\n",           0,         dblptr:&(rfsimulator->chan_pathloss),   defdblval:0,                     TYPE_DOUBLE,    0 },\
-    {"forgetfact",             "<channel forget factor ((0 to 1)>\n",   0,         dblptr:&(rfsimulator->chan_forgetfact), defdblval:0,                     TYPE_DOUBLE,    0 },\
-    {"offset",                 "<channel offset in samps>\n",           0,         iptr:&(rfsimulator->chan_offset),       defintval:0,                     TYPE_INT,       0 }\
+#define simOpt PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED
+#define RFSIMULATOR_PARAMS_DESC {					\
+    {"serveraddr",             "<ip address to connect to>\n",    simOpt   ,  strptr:&(rfsimulator->ip),              defstrval:"127.0.0.1",           TYPE_STRING,    0 },\
+    {"serverport",             "<port to connect to>\n",             simOpt,  u16ptr:&(rfsimulator->port),            defuintval:PORT,                 TYPE_UINT16,    0 },\
+    {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS,            0,       strlistptr:NULL,                        defstrlistval:NULL,              TYPE_STRINGLIST,0 },\
+    {"IQfile",                 "<file path to use when saving IQs>\n",simOpt, strptr:&(saveF),                        defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING,    0 },\
+    {"modelname",              "<channel model name>\n",              simOpt, strptr:&(modelname),                    defstrval:"AWGN",                TYPE_STRING,    0 },\
+    {"ploss",                  "<channel path loss in dB>\n",         simOpt, dblptr:&(rfsimulator->chan_pathloss),   defdblval:0,                     TYPE_DOUBLE,    0 },\
+    {"forgetfact",             "<channel forget factor ((0 to 1)>\n", simOpt, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0,                     TYPE_DOUBLE,    0 },\
+    {"offset",                 "<channel offset in samps>\n",         simOpt, iptr:&(rfsimulator->chan_offset),       defintval:0,                     TYPE_INT,       0 }\
   };
 
 
@@ -137,7 +138,7 @@ typedef struct {
 } rfsimulator_state_t;
 
 
-void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
+static void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
   buffer_t *ptr=&bridge->buf[sock];
   AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
   ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
@@ -195,7 +196,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
   }
 }
 
-void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
+static void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
   AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL,  sock, NULL) != -1, "");
   close(sock);
   free(bridge->buf[sock].circularBuf);
@@ -206,12 +207,12 @@ void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
   bridge->buf[sock].conn_sock=-1;
 }
 
-void socketError(rfsimulator_state_t *bridge, int sock) {
+static void socketError(rfsimulator_state_t *bridge, int sock) {
   if (bridge->buf[sock].conn_sock!=-1) {
     LOG_W(HW,"Lost socket \n");
     removeCirBuf(bridge, sock);
 
-    if (bridge->typeStamp==UE_MAGICDL_FDD)
+    if (bridge->typeStamp==UE_MAGICDL)
       exit(1);
   }
 }
@@ -229,7 +230,7 @@ enum  blocking_t {
   blocking
 };
 
-void setblocking(int sock, enum blocking_t active) {
+static void setblocking(int sock, enum blocking_t active) {
   int opts;
   AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,"");
 
@@ -243,7 +244,7 @@ void setblocking(int sock, enum blocking_t active) {
 
 static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps);
 
-void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
+static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
   if (t->saveIQfile != -1) {
     if (write(t->saveIQfile, _buf, count) != count )
       LOG_E(HW,"write in save iq file failed (%s)\n",strerror(errno));
@@ -277,7 +278,7 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
   }
 }
 
-void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
+static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
   char *saveF=NULL;
   char *modelname=NULL;
   paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC;
@@ -312,9 +313,9 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
 
   if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 ||
        strncasecmp(rfsimulator->ip,"server",3) == 0 )
-    rfsimulator->typeStamp = ENB_MAGICDL_FDD;
+    rfsimulator->typeStamp = ENB_MAGICDL;
   else
-    rfsimulator->typeStamp = UE_MAGICDL_FDD;
+    rfsimulator->typeStamp = UE_MAGICDL;
 }
 
 static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) {
@@ -358,9 +359,9 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt,
   return CMDSTATUS_FOUND;
 }
 
-int server_start(openair0_device *device) {
+static int startServer(openair0_device *device) {
   rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
-  t->typeStamp=ENB_MAGICDL_FDD;
+  t->typeStamp=ENB_MAGICDL;
   AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
   int enable = 1;
   AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, "");
@@ -381,9 +382,9 @@ sin_addr:
   return 0;
 }
 
-int start_ue(openair0_device *device) {
+static int startClient(openair0_device *device) {
   rfsimulator_state_t *t = device->priv;
-  t->typeStamp=UE_MAGICDL_FDD;
+  t->typeStamp=UE_MAGICDL;
   int sock;
   AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
   struct sockaddr_in addr = {
@@ -458,7 +459,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp
   return nsamps;
 }
 
-int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
+static int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
   return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags, false);
 }
 
@@ -483,7 +484,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
       AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, "");
       setblocking(conn_sock, notBlocking);
       allocCirBuf(t, conn_sock);
-      LOG_I(HW,"A ue connected, sending the current time\n");
+      LOG_I(HW,"A client connected, sending the current time\n");
       struct complex16 v= {0};
       void *samplesVoid[t->tx_num_channels];
 
@@ -534,8 +535,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
 
       // check the header and start block transfer
       if ( b->headerMode==true && b->remainToTransfer==0) {
-        AssertFatal( (t->typeStamp == UE_MAGICDL_FDD  && b->th.magic==ENB_MAGICDL_FDD) ||
-                     (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol");
+        AssertFatal( (t->typeStamp == UE_MAGICDL  && b->th.magic==ENB_MAGICDL) ||
+                     (t->typeStamp == ENB_MAGICDL && b->th.magic==UE_MAGICDL), "Socket Error in protocol");
         b->headerMode=false;
 
         if ( t->nextTimestamp == 0 ) { // First block in UE, resync with the eNB current TS
@@ -606,7 +607,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
   return nfds>0;
 }
 
-int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) {
+static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) {
   if (nbAnt != 1) {
     LOG_W(HW, "rfsimulator: only 1 antenna tested\n");
   }
@@ -748,31 +749,24 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
         signal_energy(samplesVoid[0], nsamps));
   return nsamps;
 }
-int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) {
-  abort();
-  return 0;
-}
-int rfsimulator_reply(openair0_device *device, void *msg, ssize_t msg_len) {
-  abort();
-  return 0;
-}
-int rfsimulator_get_stats(openair0_device *device) {
+
+static int rfsimulator_get_stats(openair0_device *device) {
   return 0;
 }
-int rfsimulator_reset_stats(openair0_device *device) {
+static int rfsimulator_reset_stats(openair0_device *device) {
   return 0;
 }
-void rfsimulator_end(openair0_device *device) {}
-int rfsimulator_stop(openair0_device *device) {
+static void rfsimulator_end(openair0_device *device) {}
+static int rfsimulator_stop(openair0_device *device) {
   return 0;
 }
-int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
+static int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
   return 0;
 }
-int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
+static int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
   return 0;
 }
-int rfsimulator_write_init(openair0_device *device) {
+static int rfsimulator_write_init(openair0_device *device) {
   return 0;
 }
 __attribute__((__visibility__("default")))
@@ -782,10 +776,10 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
   rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
   rfsimulator_readconfig(rfsimulator);
   pthread_mutex_init(&Sockmutex, NULL);
-  LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE");
-  device->trx_start_func       = rfsimulator->typeStamp == ENB_MAGICDL_FDD ?
-                                 server_start :
-                                 start_ue;
+  LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL ? "server waiting opposite rfsimulators to connect" : "client: will connect to a rfsimulator server side");
+  device->trx_start_func       = rfsimulator->typeStamp == ENB_MAGICDL ?
+                                 startServer :
+                                 startClient;
   device->trx_get_stats_func   = rfsimulator_get_stats;
   device->trx_reset_stats_func = rfsimulator_reset_stats;
   device->trx_end_func         = rfsimulator_end;
@@ -795,7 +789,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
   device->trx_write_func       = rfsimulator_write;
   device->trx_read_func      = rfsimulator_read;
   /* let's pretend to be a b2x0 */
-  device->type = USRP_B200_DEV;
+  device->type = RFSIMULATOR;
   device->openair0_cfg=&openair0_cfg[0];
   device->priv = rfsimulator;
   device->trx_write_init = rfsimulator_write_init;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf
index 49b4e4441e298b5cb2283a5e5bccbff249630921..aab3876d96355f60c890815876e06132544b4809 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf
@@ -230,12 +230,12 @@ RUs = (
         local_if_name  = "dpdk";
         sdr_addrs      = "softmodem -m 2048 -l 35 -n 2 -b 0000:81:00.3 --proc-type auto --file-prefix ggg -- -p 0x1";
         #sdr_addrs      = "softmodem -l 8 -n 2 -- -p 0x2";
-        remote_address = "127.0.0.2";
-        local_address  = "127.0.0.1";
-        local_portc    = 50000;
-        remote_portc   = 50000;
-        local_portd    = 50001;
-        remote_portd   = 50001;
+        #remote_address = "127.0.0.2";
+        #local_address  = "127.0.0.1";
+        #local_portc    = 50000;
+        #remote_portc   = 50000;
+        #local_portd    = 50001;
+        #remote_portd   = 50001;
         local_rf       = "no"
         tr_preference  = "raw_if4p5"
         nb_tx          = 1
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf
index 037de199dfdc18af5e7f1df666d8d46f6e9e3e93..504d5e7b349d48fb9c047cbcd196d4da020158ee 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf
@@ -23,6 +23,8 @@ gNBs =
 
     ssb_SubcarrierOffset                                      = 31; //0;
     pdsch_AntennaPorts                                        = 1;
+    #pusch_TargetSNRx10                                        = 200;
+    #pucch_TargetSNRx10                                        = 200;
     pusch_TargetSNRx10                                        = 200;
     pucch_TargetSNRx10                                        = 200;
 	
@@ -102,8 +104,9 @@ gNBs =
           prach_msg1_FDM                                            = 0;
           prach_msg1_FrequencyStart                                 = 74;
           zeroCorrelationZoneConfig                                 = 13;
-          #preambleReceivedTargetPower                               = -118;
-          preambleReceivedTargetPower                               = -104;
+          preambleReceivedTargetPower                               = -118;
+          #preambleReceivedTargetPower                               = -104;
+          #preambleReceivedTargetPower                               = -108;
 #preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
           preambleTransMax                                          = 6;
 #powerRampingStep
@@ -149,14 +152,16 @@ gNBs =
         initialULBWPstartSymbolAndLength_2    = 52;
 
         msg3_DeltaPreamble                                          = 1;
-        p0_NominalWithGrant                                         =-90;
+        #p0_NominalWithGrant                                         =-90;
+        p0_NominalWithGrant                                         =-118;
 
 # pucch-ConfigCommon setup :
 # pucchGroupHopping
 # 0 = neither, 1= group hopping, 2=sequence hopping
         pucchGroupHopping                                           = 0;
         hoppingId                                                   = 40;
-        p0_nominal                                                  = -90;
+        #p0_nominal                                                  = -90;
+        p0_nominal                                                  = -118;
 # ssb_PositionsInBurs_BitmapPR
 # 1=short, 2=medium, 3=long
       ssb_PositionsInBurst_PR                                       = 2;
@@ -189,7 +194,7 @@ gNBs =
       nrofUplinkSymbols                                             = 4; //0; //4;
 
   #ssPBCH_BlockPower                                             = 10;
-  ssPBCH_BlockPower                                             = 10;
+  ssPBCH_BlockPower                                             = -35;
   }
 
   );
@@ -229,9 +234,9 @@ gNBs =
     {
 
         GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
-        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.18.195/24";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.18.187/24";
         GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
-        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.18.195/24";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.18.187/24";
         GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
         GNB_IPV4_ADDRESS_FOR_X2C                 = "127.0.0.2/24";
         GNB_PORT_FOR_X2C                         = 36422; # Spec 36422
@@ -251,6 +256,7 @@ L1s = (
     	{
 	num_cc = 1;
 	tr_n_preference = "local_mac";
+	pusch_proc_threads = 8;
         }  
 );
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf
index 0659641607ec43618b5a3d992b7fb37942ff0714..40361aaf4e8ffa042fec8f82965afe156c668bbc 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf
@@ -33,7 +33,7 @@ gNBs =
 #  downlinkConfigCommon
     #frequencyInfoDL
       # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP)
-      absoluteFrequencySSB                                          = 642364;
+      absoluteFrequencySSB                                          = 642016;#642364;
       dl_frequencyBand                                                 = 78;
       # this is 3600 MHz
       dl_absoluteFrequencyPointA                                       = 640000;
@@ -130,16 +130,21 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 6; #2;
         initialULBWPmappingType_0             = 1
         # this is SS=0 L=11
         initialULBWPstartSymbolAndLength_0    = 55;
  	
-	initialULBWPk2_1                      = 2;
+	initialULBWPk2_1                      = 6; #2;
         initialULBWPmappingType_1             = 1;
         # this is SS=0 L=12
         initialULBWPstartSymbolAndLength_1    = 69;
 
+        initialULBWPk2_2                      = 7;
+        initialULBWPmappingType_2             = 1;
+        # this is SS=10 L=4
+        initialULBWPstartSymbolAndLength_2    = 52;
+
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf
index 0a6268f8a85b856ac572f95db8c7874363130389..a899845cb8913e82a529bed2b0809215be7c3f6e 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf
@@ -130,16 +130,21 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 6;#2;
         initialULBWPmappingType_0             = 1
         # this is SS=0 L=11
         initialULBWPstartSymbolAndLength_0    = 55;
  	
-	initialULBWPk2_1                      = 2;
+	initialULBWPk2_1                      = 6;#2;
         initialULBWPmappingType_1             = 1;
         # this is SS=0 L=12
         initialULBWPstartSymbolAndLength_1    = 69;
 
+        initialULBWPk2_2                      = 7;
+        initialULBWPmappingType_2             = 1;
+        # this is SS=10 L=4
+        initialULBWPstartSymbolAndLength_2    = 52;
+
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
index 555af5835d368647559077be618610c792dfe52a..c46ea98ec24cb204ca326f25d25b9fb1815a39d8 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
@@ -278,6 +278,18 @@ THREAD_STRUCT = (
   }
 );
 
+security = {
+  # preferred ciphering algorithms
+  # the first one of the list that an UE supports in chosen
+  # valid values: nea0, nea1, nea2, nea3
+  ciphering_algorithms = ( "nea0", "nea2" );
+
+  # preferred integrity algorithms
+  # the first one of the list that an UE supports in chosen
+  # valid values: nia0, nia1, nia2, nia3
+  integrity_algorithms = ( "nia0" );
+};
+
      log_config :
      {
        global_log_level                      ="info";
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index 56c2cb23dd43114975300a5c41b160c38c6a8551..368fd78f9e8c01230ef5f957efb2398e64c03b32 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -2986,6 +2986,7 @@ void RCconfig_RU(void) {
             RC.ru[j]->if_south                        = LOCAL_RF;
             RC.ru[j]->function                        = NGFI_RRU_IF4p5;
             RC.ru[j]->eth_params.transp_preference    = ETH_RAW_IF4p5_MODE;
+            RC.ru[j]->has_ctrl_prt                   =1;
             LOG_I(PHY,"Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j);
           }
 
@@ -3039,6 +3040,7 @@ else {
 	  RC.ru[j]->if_south                     = REMOTE_IF4p5;
 	  RC.ru[j]->function                     = NGFI_RAU_IF4p5;
 	  RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE;
+	  RC.ru[j]->has_ctrl_prt                 = 1;
 	
           if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) RC.ru[j]->is_slave=1;
           else RC.ru[j]->is_slave=0;