diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container
index f4b99e7f9246928a38d555b585aaab75bd9201d0..a6621afe25e217f668f6595380919178f0a6d4de 100644
--- a/ci-scripts/Jenkinsfile-GitLab-Container
+++ b/ci-scripts/Jenkinsfile-GitLab-Container
@@ -220,6 +220,21 @@ pipeline {
         }
       }
     }
+    stage ("Images Push to Registries") {
+      when { expression {"PUSH".equals(env.gitlabActionType)} }
+      steps {
+        script {
+          triggerSlaveJob ('RAN-DockerHub-Push', 'Push-to-Docker-Hub')
+        }
+        post {
+          failure {
+            script {
+              currentBuild.result = 'FAILURE'
+            }
+          }
+        }
+      }
+    }
   }
   post {
     always {
diff --git a/ci-scripts/Jenkinsfile-push-registry b/ci-scripts/Jenkinsfile-push-registry
new file mode 100644
index 0000000000000000000000000000000000000000..91d6136e0a55824cff05cc10f36419e815a6dfb0
--- /dev/null
+++ b/ci-scripts/Jenkinsfile-push-registry
@@ -0,0 +1,86 @@
+#!/bin/groovy
+/*
+ * 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
+ */
+
+// Location of the python executor node shall be in the same subnet as the others servers
+def nodeExecutor = params.nodeExecutor
+
+// Name of the phone resource
+def ciServerResource = params.serverResource
+
+pipeline {
+  agent {
+    label nodeExecutor
+  }
+  options {
+    disableConcurrentBuilds()
+    ansiColor('xterm')
+    lock (ciServerResource)
+  }
+  stages {
+    stage ("Verify Parameters") {
+      steps {
+        script {
+          echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
+          def allParametersPresent = true
+
+          // It is already to late to check it
+          if (params.nodeExecutor != null) {
+            echo "Docker Push executor node  :   ${nodeExecutor}"
+          }
+          if (params.serverResource == null) {
+            allParametersPresent = false
+          }
+        }
+      }
+    }
+    stage ("Push to DockerHub") {
+      steps {
+        script {
+          WEEK_TAG = sh returnStdout: true, script: 'date +"%Y.w%U"'
+          WEEK_TAG = WEEK_TAG.trim()
+
+          withCredentials([
+            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.DH_Credentials}", usernameVariable: 'DH_Username', passwordVariable: 'DH_Password']
+          ]) {
+            def listOfImages = ["oai-enb", "oai-gnb", "oai-lte-ue", "oai-nr-ue"]
+            sh "docker login -u ${DH_Username} -p ${DH_Password} > /dev/null 2>&1"
+            listOfImages.eachWithIndex { item, iindex ->
+              sh "docker image tag ${item}:develop ${DH_Username}/${item}:develop"
+              sh "docker image tag ${item}:develop ${DH_Username}/${item}:${WEEK_TAG}"
+              sh "docker push --quiet ${DH_Username}/${item}:${WEEK_TAG}"
+              sh "docker push --quiet ${DH_Username}/${item}:develop"
+              sh "docker rmi ${DH_Username}/${item}:${WEEK_TAG} ${DH_Username}/${item}:develop"
+            }
+            sh "docker logout > /dev/null 2>&1"
+          }
+        }
+      }
+    }
+  }
+  post {
+    always {
+      script {
+        echo "End of Registry Push"
+      }
+    }
+  }
+}
diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa
index 95aa4046d7edc7311efd54082b7ab6376763fd37..3243d1645d8d929d4d79cd54de447552d89e6a14 100644
--- a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa
+++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa
@@ -265,6 +265,21 @@ pipeline {
                             if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
                                 archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
                             }
+                        }
+                    }
+                }
+                stage('Log Collection (CN)') {
+                    steps {
+                        withCredentials([
+                             [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
+                        ]) {
+                            echo '\u2705 \u001B[32mLog Transfer (CN)\u001B[0m'
+                            sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/logs/oai-cn5g.log.zip ./oai-cn5g.log.${env.BUILD_ID}.zip || true"
+                        }
+                        script {
+                            if(fileExists("oai-cn5g.log.${env.BUILD_ID}.zip")) {
+                                archiveArtifacts "oai-cn5g.log.${env.BUILD_ID}.zip"
+                            }
                             if(fileExists("ci-scripts/test_results.html")) {
                                 sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
                                 sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
diff --git a/ci-scripts/Jenkinsfile-trig-nsa b/ci-scripts/Jenkinsfile-trig-nsa
index 2dcaf1a04fef5fa7eac155d0e9098d4eaef547bd..f4db9fd19be015c40f3d566b987ea7081ddf558a 100644
--- a/ci-scripts/Jenkinsfile-trig-nsa
+++ b/ci-scripts/Jenkinsfile-trig-nsa
@@ -47,30 +47,30 @@ pipeline {
                         COMMIT_ID=sh returnStdout: true, script:  """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".sha" || true """
                         COMMIT_ID=COMMIT_ID.trim()
                         echo "Testing NSA on : ${MR} ${SRC_BRANCH} ${COMMIT_ID}"
-                        //calling NSA sub job
-                        build job: "RAN-NSA-Mini-Module", wait : true, propagate : false, parameters: [
+                        //calling NSA B200
+                        build job: "RAN-NSA-B200-Module-LTEBOX", wait : true, propagate : false, parameters: [
                             string(name: 'eNB_MR', value: String.valueOf(MR)),                          
                             string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
                             string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
                             string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
                             booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE))
                         ]
-                        //calling NSA long sub job
-//                        build job: "RAN-NSA-Mini-Module-Long", wait : true, propagate : false, parameters: [
-//                            string(name: 'eNB_MR', value: String.valueOf(MR)),
-//                            string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
-//                            string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
-//                            string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
-//                            booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE))
-//                        ]
-                        //calling NSA attach/detach job
-//                        build job: "RAN-NSA-Mini-Module-Attach-Detach", wait : true, propagate : false, parameters: [
-//                            string(name: 'eNB_MR', value: String.valueOf(MR)),
-//                            string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
-//                            string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
-//                            string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
-//                            booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE))
-//                        ]
+                        //calling NSA 2x2
+                        build job: "RAN-NSA-2x2-Module-OAIEPC", wait : true, propagate : false, parameters: [
+                            string(name: 'eNB_MR', value: String.valueOf(MR)),
+                            string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
+                            string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
+                            string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
+                            booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE))
+                        ]
+                        //calling LTE 2x2
+                        build job: "RAN-LTE-2x2-Module-OAIEPC", wait : true, propagate : false, parameters: [
+                            string(name: 'eNB_MR', value: String.valueOf(MR)),
+                            string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
+                            string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
+                            string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
+                            booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE))
+                        ]
 
                     }
                 }                                  
diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml
index 619e8fba15bfeaae26831327696a9ff600d1d73c..0957a1e465fd8e4ccd21abd815d60a6c6af3dbec 100644
--- a/ci-scripts/ci_ueinfra.yaml
+++ b/ci-scripts/ci_ueinfra.yaml
@@ -4,7 +4,9 @@ idefix:
   Kind : quectel
   Process : 
     Name : quectel-CM
-    Cmd : /home/oaicicd/quectel-CM/quectel-CM -s oai.ipv4 -4
+    Cmd : /home/oaicicd/quectel-CM/quectel-CM -4 -s
+    Apn :
+      ltebox : oai.ipv4
   WakeupScript : ci_ctl_qtel.py /dev/ttyUSB2 wup
   DetachScript : ci_ctl_qtel.py /dev/ttyUSB2 detach
   LogStore : /media/usb-drive/ci_qlogs
@@ -20,16 +22,22 @@ nrmodule2_quectel:
   Kind : quectel
   Process :
     Name : quectel-CM
-    Cmd : /home/nrmodule2/quectel-CM/quectel-CM -s oai.ipv4 -4
+    Cmd : /home/nrmodule2/quectel-CM/quectel-CM -4 -s
+    Apn :
+      OAICN5G : oai
+      OAI-Rel14-Docker : oai.ipv4
   WakeupScript : ci_ctl_qtel.py /dev/ttyUSB7 wup
   DetachScript : ci_ctl_qtel.py /dev/ttyUSB7 detach
   LogStore : /media/ci_qlogs  
-  PLMN : 20899 
+  PLMN : 20897
   UENetwork : wwan1
   HostIPAddress : 192.168.18.189
   HostUsername : nrmodule2 
   HostPassword : linux 
   HostSourceCodePath : none
+  StartCommands :
+    - sudo -S ip link set dev wwan1 mtu 1500
+  MTU : 1500
 dummy:
   ID: ''
   State : ''
diff --git a/ci-scripts/cls_module_ue.py b/ci-scripts/cls_module_ue.py
index 96d4e0310ef99bae7be74ca607be4cd91f008554..74ae9c207e7e0e2bcc97e4bf642f0b915602fbec 100644
--- a/ci-scripts/cls_module_ue.py
+++ b/ci-scripts/cls_module_ue.py
@@ -61,7 +61,7 @@ class Module_UE:
 
 	#this method checks if the specified Process is running on the server hosting the module
 	#if not it will be started
-	def CheckCMProcess(self):
+	def CheckCMProcess(self,CNType):
 		HOST=self.HostUsername+'@'+self.HostIPAddress
 		COMMAND="ps aux | grep " + self.Process['Name'] + " | grep -v grep "
 		logging.debug(COMMAND)
@@ -76,7 +76,7 @@ class Module_UE:
 			logging.debug('Starting ' + self.Process['Name'])
 			mySSH = sshconnection.SSHConnection()
 			mySSH.open(self.HostIPAddress, self.HostUsername, self.HostPassword)
-			mySSH.command('echo $USER; echo ' + self.HostPassword + ' | nohup sudo -S ' + self.Process['Cmd'] + ' &','\$',5)
+			mySSH.command('echo $USER; echo ' + self.HostPassword + ' | nohup sudo -S ' + self.Process['Cmd'] + ' ' +  self.Process['Apn'][CNType]  + ' &','\$',5)
 			mySSH.close()
 			#checking the process
 			time.sleep(5)
@@ -131,6 +131,33 @@ class Module_UE:
 				logging.debug('\u001B[1;37;41m Module IP Address Not Found! \u001B[0m')
 				return -1
 
+	def CheckModuleMTU(self):
+		HOST=self.HostUsername+'@'+self.HostIPAddress
+		response= []
+		tentative = 3 
+		while (len(response)==0) and (tentative>0):
+			COMMAND="ip a show dev " + self.UENetwork + " | grep mtu"
+			logging.debug(COMMAND)
+			ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
+			response = ssh.stdout.readlines()
+			tentative-=1
+			time.sleep(10)
+		if (tentative==0) and (len(response)==0):
+			logging.debug('\u001B[1;37;41m Module NIC MTU Not Found! Time expired \u001B[0m')
+			return -1
+		else: #check response
+			result = re.search('mtu (?P<mtu>[0-9]+)', response[0].decode("utf-8") )
+			if result is not None: 
+				if (result.group('mtu') is not None) and (str(result.group('mtu'))==str(self.MTU)) : 
+					logging.debug('\u001B[1mUE Module NIC MTU is ' + str(self.MTU) + ' as expected\u001B[0m')
+					return 0
+				else:
+					logging.debug('\u001B[1;37;41m Incorrect Module NIC MTU ' + str(result.group('mtu')) + '! Expected : ' + str(self.MTU) + '\u001B[0m')
+					return -1
+			else:
+				logging.debug('\u001B[1;37;41m Module NIC MTU Not Found! \u001B[0m')
+				return -1
+
 	def EnableTrace(self):
 		if self.ue_trace=="yes":
 			mySSH = sshconnection.SSHConnection()
diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py
index f1ab8c106fbc51a0c8d33ffec48eb0bcdf3c44ab..8bda1fa202185e2adb6a51831b1f67306597b7ea 100644
--- a/ci-scripts/cls_oaicitest.py
+++ b/ci-scripts/cls_oaicitest.py
@@ -388,7 +388,7 @@ class OaiCiTest():
 			#RH
 			Module_UE = cls_module_ue.Module_UE(InfraUE.ci_ue_infra[self.ue_id])
 			Module_UE.ue_trace=ue_trace
-			is_module=Module_UE.CheckCMProcess()
+			is_module=Module_UE.CheckCMProcess(EPC.Type)
 			if is_module:
 				Module_UE.EnableTrace()
 				time.sleep(5)
@@ -400,10 +400,20 @@ class OaiCiTest():
 				if status==0:
 					HTML.CreateHtmlTestRow(Module_UE.UEIPAddress, 'OK', CONST.ALL_PROCESSES_OK)	
 					logging.debug('UE IP addresss : '+ Module_UE.UEIPAddress)
+					#execute additional commands from yaml file after UE attach
+					SSH = sshconnection.SSHConnection()
+					SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
+					for startcommand in Module_UE.StartCommands:
+						cmd = 'echo ' + Module_UE.HostPassword + ' | ' + startcommand 
+					SSH.command(cmd,'\$',5)	
+					SSH.close()
+					#check that the MTU is as expected / requested
+					Module_UE.CheckModuleMTU()
 				else: #status==-1 failed to retrieve IP address
 					HTML.CreateHtmlTestRow('N/A', 'KO', CONST.UE_IP_ADDRESS_ISSUE)
 					self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE)
 					return
+			
 
 
 	def InitializeOAIUE(self,HTML,RAN,EPC,COTS_UE,InfraUE):
@@ -1539,6 +1549,8 @@ class OaiCiTest():
 					#target address is different depending on EPC type
 					if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE):
 						Target = EPC.MmeIPAddress
+					elif re.match('OAICN5G', EPC.Type, re.IGNORECASE):
+						Target = '8.8.8.8'
 					else:
 						Target = EPC.IPAddress
 					#ping from module NIC rather than IP address to make sure round trip is over the air	
@@ -1986,7 +1998,7 @@ class OaiCiTest():
 			if type==0:
 				result = re.search('(?P<bitrate>[0-9\.]+ [KMG]bits\/sec) +(?P<jitter>[0-9\.]+ ms) +(?P<lostPack>[0-9]+)/ +(?P<sentPack>[0-9]+)', str(line))
 			else:
-				result = re.search('^\[  \d\].+ +(?P<bitrate>[0-9\.]+ [KMG]bits\/sec) +(?P<jitter>[0-9\.]+ ms) +(?P<lostPack>[0-9]+)\/(?P<sentPack>[0-9]+)', str(line))
+				result = re.search('^\[\s+\d\].+  (?P<bitrate>[0-9\.]+ [KMG]bits\/sec) +(?P<jitter>[0-9\.]+ ms) +(?P<lostPack>[0-9]+)\/\s*(?P<sentPack>[0-9]+)', str(line))
 
 			if result is not None:
 				bitrate = result.group('bitrate')
@@ -2230,85 +2242,157 @@ class OaiCiTest():
 
 
 	def Iperf_Module(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue,EPC, Module_UE):
-		SSH = sshconnection.SSHConnection()
-		#RH temporary quick n dirty for test
-		SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
-		cmd = 'echo ' + EPC.Password + ' | sudo -S ip link set dev tun5 mtu 1358'
-		SSH.command(cmd,'\$',5)	
-		SSH.close()
-			
+		if (re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE)) or (re.match('OAICN5G', EPC.Type, re.IGNORECASE)):
+			#retrieve trf-gen container IP address
+			SSH = sshconnection.SSHConnection()
+			SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
+			SSH.command('docker inspect --format="TRF_IP_ADDR = {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" prod-trf-gen', '\$', 5)
+			result = re.search('TRF_IP_ADDR = (?P<trf_ip_addr>[0-9\.]+)', SSH.getBefore())
+			if result is not None:
+				trf_gen_IP = result.group('trf_ip_addr')
+			SSH.close()
+			#kill iperf processes on UE side before (in case there are still some remaining)
+			SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
+			cmd = 'killall --signal=SIGKILL iperf'
+			SSH.command(cmd,'\$',5)
+			SSH.close()
 
-		#kill iperf processes before (in case there are still some remaining)
-		SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
-		cmd = 'killall --signal=SIGKILL iperf'
-		SSH.command(cmd,'\$',5)
-		SSH.close()
-		SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
-		cmd = 'killall --signal=SIGKILL iperf'
-		SSH.command(cmd,'\$',5)
-		SSH.close()
+			iperf_time = self.Iperf_ComputeTime()	
+			if self.iperf_direction=="DL":
+				logging.debug("Iperf for Module in DL mode detected")
+				#server side UE
+				server_filename='iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
+				SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
+				cmd = 'rm ' + server_filename
+				SSH.command(cmd,'\$',5)
+				cmd = 'echo $USER; nohup iperf -s -B ' + UE_IPAddress + ' -u  2>&1 > ' + server_filename
+				SSH.command(cmd,'\$',5)
+				SSH.close()
+				#client side EPC
+				SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
+				client_filename = 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log'
+				SSH.command('docker exec -it prod-trf-gen /bin/bash -c "killall --signal SIGKILL iperf"', '\$', 5)
+				iperf_cmd = 'bin/iperf -c ' + UE_IPAddress + ' ' + self.iperf_args + ' 2>&1 > ' + client_filename
+				cmd = 'docker exec -it prod-trf-gen /bin/bash -c \"' + iperf_cmd + '\"' 
+				SSH.command(cmd,'\$',int(iperf_time)*5.0)
+				SSH.command('docker cp prod-trf-gen:/iperf-2.0.13/'+ client_filename + ' ' + EPC.SourceCodePath, '\$', 5)
+				SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath + '/' + client_filename, '.')
+				SSH.close()
 
+				#copy the 2 resulting files locally
+				SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, server_filename, '.')
+				SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, client_filename, '.')
+				#send for analysis
+				self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,server_filename,1)	
 
-		iperf_time = self.Iperf_ComputeTime()	
-		if self.iperf_direction=="DL":
-			logging.debug("Iperf for Module in DL mode detected")
-			#server side UE
+			elif self.iperf_direction=="UL":
+				logging.debug("Iperf for Module in UL mode detected")
+				#server side EPC
+				SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
+				server_filename = 'iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
+				SSH.command('docker exec -it prod-trf-gen /bin/bash -c "killall --signal SIGKILL iperf"', '\$', 5)
+				iperf_cmd = 'echo $USER; nohup bin/iperf -s -u 2>&1 > ' + server_filename
+				cmd = 'docker exec -it prod-trf-gen /bin/bash -c \"' + iperf_cmd + '\"' 
+				SSH.command(cmd,'\$',5)
+				SSH.close()
+
+				#client side UE
+				SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
+				client_filename = 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log'
+				cmd = 'rm '+ client_filename
+				SSH.command(cmd,'\$',5)
+				SSH.command('iperf -B ' + UE_IPAddress + ' -c ' +  trf_gen_IP + ' '  + self.iperf_args + ' 2>&1 > ' + client_filename, '\$', int(iperf_time)*5.0)
+				SSH.close()
+
+				#once client is done, retrieve the server file from container to EPC Host
+				SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
+				SSH.command('docker cp prod-trf-gen:/iperf-2.0.13/' + server_filename + ' ' + EPC.SourceCodePath, '\$', 5)
+				SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath + '/' + server_filename, '.')
+				SSH.close()
+
+				#copy the 2 resulting files locally 
+				SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, client_filename, '.')
+				SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, server_filename, '.')
+				#send for analysis
+				self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,server_filename,1)
+			else :
+				logging.debug("Incorrect or missing IPERF direction in XML")
+
+		else: 		#default is ltebox
+
+			SSH = sshconnection.SSHConnection()
+
+			#kill iperf processes before (in case there are still some remaining)
 			SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
-			cmd = 'rm iperf_server_' +  self.testCase_id + '_' + self.ue_id + '.log'
-			SSH.command(cmd,'\$',5)
-			cmd = 'echo $USER; nohup /opt/iperf-2.0.10/iperf -s -B ' + UE_IPAddress + ' -u  2>&1 > iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log' 
+			cmd = 'killall --signal=SIGKILL iperf'
 			SSH.command(cmd,'\$',5)
 			SSH.close()
-			#client side EPC
 			SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
-			cmd = 'rm iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log'
-			SSH.command(cmd,'\$',5)
-			cmd = 'iperf -c ' + UE_IPAddress + ' ' + self.iperf_args + ' 2>&1 > iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log' 
-			SSH.command(cmd,'\$',int(iperf_time)*5.0)
-			SSH.close()
-			#copy the 2 resulting files locally
-			SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, 'iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log', '.')
-			SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log', '.')
-			#send for analysis
-			filename='iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
-			self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,filename,1)	
-
-		elif self.iperf_direction=="UL":#does not work at the moment
-			logging.debug("Iperf for Module in UL mode detected")
-			#server side EPC
-			SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
-			cmd = 'rm iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
-			SSH.command(cmd,'\$',5)
-			cmd = 'echo $USER; nohup iperf -s -u 2>&1 > iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
+			cmd = 'killall --signal=SIGKILL iperf'
 			SSH.command(cmd,'\$',5)
 			SSH.close()
 
-			#client side UE
+
+			iperf_time = self.Iperf_ComputeTime()	
+			if self.iperf_direction=="DL":
+				logging.debug("Iperf for Module in DL mode detected")
+				#server side UE
+				SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
+				cmd = 'rm iperf_server_' +  self.testCase_id + '_' + self.ue_id + '.log'
+				SSH.command(cmd,'\$',5)
+				cmd = 'echo $USER; nohup /opt/iperf-2.0.10/iperf -s -B ' + UE_IPAddress + ' -u  2>&1 > iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log' 
+				SSH.command(cmd,'\$',5)
+				SSH.close()
+				#client side EPC
+				SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
+				cmd = 'rm iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log'
+				SSH.command(cmd,'\$',5)
+				cmd = 'iperf -c ' + UE_IPAddress + ' ' + self.iperf_args + ' 2>&1 > iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log' 
+				SSH.command(cmd,'\$',int(iperf_time)*5.0)
+				SSH.close()
+				#copy the 2 resulting files locally
+				SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, 'iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log', '.')
+				SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log', '.')
+				#send for analysis
+				filename='iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
+				self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,filename,1)	
+
+			elif self.iperf_direction=="UL":
+				logging.debug("Iperf for Module in UL mode detected")
+				#server side EPC
+				SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
+				cmd = 'rm iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
+				SSH.command(cmd,'\$',5)
+				cmd = 'echo $USER; nohup iperf -s -u 2>&1 > iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
+				SSH.command(cmd,'\$',5)
+				SSH.close()
+
+				#client side UE
+				SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
+				cmd = 'rm iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log'
+				SSH.command(cmd,'\$',5)
+				SSH.command('/opt/iperf-2.0.10/iperf -c 192.172.0.1 ' + self.iperf_args + ' 2>&1 > iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log', '\$', int(iperf_time)*5.0)
+				SSH.close()
+
+				#copy the 2 resulting files locally
+				SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log', '.')
+				SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log', '.')
+				#send for analysis
+				filename='iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
+				self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,filename,1)
+			else :
+				logging.debug("Incorrect or missing IPERF direction in XML")
+
+			#kill iperf processes after to be clean
 			SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
-			cmd = 'rm iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log'
+			cmd = 'killall --signal=SIGKILL iperf'
 			SSH.command(cmd,'\$',5)
-			SSH.command('/opt/iperf-2.0.10/iperf -c 192.172.0.1 ' + self.iperf_args + ' 2>&1 > iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log', '\$', int(iperf_time)*5.0)
 			SSH.close()
-
-			#copy the 2 resulting files locally
-			SSH.copyin(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword, 'iperf_client_' + self.testCase_id + '_' + self.ue_id + '.log', '.')
-			SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log', '.')
-			#send for analysis
-			filename='iperf_server_' + self.testCase_id + '_' + self.ue_id + '.log'
-			self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, self.iperf_args,filename,1)
-		else :
-			logging.debug("Incorrect or missing IPERF direction in XML")
-
-		#kill iperf processes after to be clean
-		SSH.open(Module_UE.HostIPAddress, Module_UE.HostUsername, Module_UE.HostPassword)
-		cmd = 'killall --signal=SIGKILL iperf'
-		SSH.command(cmd,'\$',5)
-		SSH.close()
-		SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
-		cmd = 'killall --signal=SIGKILL iperf'
-		SSH.command(cmd,'\$',5)
-		SSH.close()
-		return
+			SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password)
+			cmd = 'killall --signal=SIGKILL iperf'
+			SSH.command(cmd,'\$',5)
+			SSH.close()
+			return
 
 	def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue,EPC):
 		try:
diff --git a/ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf
index db0802fdd7fcac457580b53bb54c8b02cad0b113..3460b82ac5ce501b4075d3325e4d9e48652f092d 100644
--- a/ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf
+++ b/ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf
@@ -14,7 +14,7 @@ eNBs =
 
     // Tracking area code, 0x0000 and 0xfffe are reserved values
     tracking_area_code = 1;
-    plmn_list = ( { mcc = 208; mnc = 99; mnc_length = 2; } );
+    plmn_list = ( { mcc = 208; mnc = 97; mnc_length = 2; } );
 
     tr_s_preference     = "local_mac"
 
@@ -31,6 +31,7 @@ eNBs =
       prefix_type             			      = "NORMAL";
       eutra_band              			      = 38;
       downlink_frequency      			      = 2605000000L;
+      nr_scg_ssb_freq                                 = 624608;
       uplink_frequency_offset 			      = 0;
       Nid_cell					      = 0;
       N_RB_DL                 			      = 100;
@@ -209,8 +210,8 @@ MACRLCs = (
         scheduler_mode = "fairRR";
         bler_target_upper = 20.0;
         bler_target_lower = 10.0;
-        max_ul_rb_index   = 24;
-        puSch10xSnr     =  100;
+        max_ul_rb_index   = 27;
+        puSch10xSnr     =  200;
         puCch10xSnr     =  150;
         }  
 );
diff --git a/ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf
index 5780a1c14c79f0ec38c221c01707068bdd776d5f..e6fafd1ef2967b06563c918021532bb976cde896 100644
--- a/ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf
+++ b/ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf
@@ -13,7 +13,7 @@ gNBs =
 
     // Tracking area code, 0x0000 and 0xfffe are reserved values
     tracking_area_code  =  1;
-    plmn_list = ({mcc = 208; mnc = 99; mnc_length = 2;});	 
+    plmn_list = ({mcc = 208; mnc = 97; mnc_length = 2;});	 
 
     tr_s_preference     = "local_mac"
 
@@ -24,6 +24,7 @@ gNBs =
     pusch_AntennaPorts                                        = 2;
     pusch_TargetSNRx10                                        = 200;
     pucch_TargetSNRx10                                        = 200;
+    ul_prbblacklist                                           = "51,52,53,54"
 
     servingCellConfigCommon = (
     {
@@ -33,11 +34,11 @@ gNBs =
 
 #  downlinkConfigCommon
     #frequencyInfoDL
-      # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP)
-      absoluteFrequencySSB                                          = 641272; //641032;      #641968; 641968=start of ssb at 3600MHz + 82 RBs    641032=center of SSB at center of cell
+      # this is 3350.04 MHz + 53 PRBs@30kHz SCS (same as initial BWP)
+      absoluteFrequencySSB                                             = 624608;
       dl_frequencyBand                                                 = 78;
-      # this is 3600 MHz
-      dl_absoluteFrequencyPointA                                       = 640000;
+      # this is 3350.04 MHz
+      dl_absoluteFrequencyPointA                                       = 623336;
       #scs-SpecificCarrierList
         dl_offstToCarrier                                              = 0;
 # subcarrierSpacing
@@ -46,7 +47,7 @@ gNBs =
         dl_carrierBandwidth                                            = 106;
      #initialDownlinkBWP
       #genericParameters
-        # this is RBstart=84,L=13 (275*(L-1))+RBstart
+        # this is RBstart=43,L=24 (275*(L-1))+RBstart
         initialDLBWPlocationAndBandwidth                                        = 6368;
 # subcarrierSpacing
 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
@@ -233,7 +234,7 @@ L1s = (
 	num_cc = 1;
 	tr_n_preference = "local_mac";
 	pusch_proc_threads = 8;
-        prach_dtx_threshold = 100;
+        prach_dtx_threshold = 120;
         }  
 );
 
diff --git a/ci-scripts/datalog_rt_stats.yaml b/ci-scripts/datalog_rt_stats.yaml
index 548caa0bddbb201fc14fdf6c6f66a142d40a5ace..507ea5d182f2f2c849fd8ae497a7ada7cf0c395b 100644
--- a/ci-scripts/datalog_rt_stats.yaml
+++ b/ci-scripts/datalog_rt_stats.yaml
@@ -12,7 +12,8 @@ Ref :
   feptx_prec : 8.0
   feptx_ofdm : 50.0
   feptx_total : 75.0
-  L1 Tx processing : 300.0
+  L1 Tx processing thread 0 : 300.0
+  L1 Tx processing thread 1 : 300.0
   DLSCH encoding : 230.0
   L1 Rx processing : 175.0
   PUSCH inner-receiver : 100.0
@@ -24,7 +25,8 @@ Threshold :
   feptx_prec : 1.25
   feptx_ofdm : 1.25
   feptx_total : 1.25
-  L1 Tx processing : 1.25
+  L1 Tx processing thread 0 : 1.25
+  L1 Tx processing thread 1 : 1.25
   DLSCH encoding : 1.25
   L1 Rx processing : 1.25
   PUSCH inner-receiver : 1.25
diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py
index 1c202438d2a3f337bab4e2207a53cea6ca7ce868..baae5644a1f27f6e1ecce441e7fe25bd8db42c27 100644
--- a/ci-scripts/epc.py
+++ b/ci-scripts/epc.py
@@ -220,7 +220,7 @@ class EPCManagement():
 		mySSH = SSH.SSHConnection()
 		mySSH.open(self.IPAddress, self.UserName, self.Password)
 		if re.match('ltebox', self.Type, re.IGNORECASE):
-			logging.debug('Using the sabox simulated HSS')
+			logging.debug('Using the SABOX simulated HSS')
 			mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5)
 			mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts', '\$', 5)
 			mySSH.command('cd /opt/hss_sim0609', '\$', 5)
@@ -229,6 +229,12 @@ class EPCManagement():
 			logging.debug('Using the sabox')
 			mySSH.command('cd /opt/ltebox/tools', '\$', 5)
 			mySSH.command('echo ' + self.Password + ' | sudo -S ./start_sabox', '\$', 5)
+		elif re.match('OAICN5G', self.Type, re.IGNORECASE):
+			logging.debug('Starting OAI CN5G')
+			mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5)
+			mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts', '\$', 5)
+			mySSH.command('cd /opt/oai-cn5g-fed/docker-compose', '\$', 5)
+			mySSH.command('./core-network.sh start nrf spgwu', '\$', 60)
 		else:
 			logging.error('This option should not occur!')
 		mySSH.close()
@@ -242,6 +248,16 @@ class EPCManagement():
 			return
 		if re.match('ltebox', self.Type, re.IGNORECASE):
 			self.MmeIPAddress = self.IPAddress
+		elif re.match('OAICN5G', self.Type, re.IGNORECASE):
+			mySSH = SSH.SSHConnection()
+			mySSH.open(self.IPAddress, self.UserName, self.Password)
+			response=mySSH.command3('docker container ls -f name=oai-amf', 10)
+			if len(response)>1:
+				response=mySSH.command3('docker inspect --format=\'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}\' oai-amf', 10)
+				tmp = str(response[0],'utf-8')
+				self.MmeIPAddress = tmp.rstrip()
+				logging.debug('AMF IP Address ' + self.MmeIPAddress)
+			mySSH.close()
 
 	def CheckHSSProcess(self, status_queue):
 		try:
@@ -433,6 +449,7 @@ class EPCManagement():
 		mySSH = SSH.SSHConnection()
 		mySSH.open(self.IPAddress, self.UserName, self.Password)
 		if re.match('ltebox', self.Type, re.IGNORECASE):
+			logging.debug('Terminating SA BOX')
 			mySSH.command('cd /opt/ltebox/tools', '\$', 5)
 			mySSH.command('echo ' + self.Password + ' | sudo -S ./stop_sabox', '\$', 5)
 			time.sleep(1)
@@ -440,6 +457,12 @@ class EPCManagement():
 			mySSH.command('cd scripts', '\$', 5)
 			time.sleep(1)
 			mySSH.command('echo ' + self.Password + ' | sudo -S screen -S simulated_5g_hss -X quit', '\$', 5)
+		elif re.match('OAICN5G', self.Type, re.IGNORECASE):
+			self.LogCollectOAICN5G()
+			logging.debug('Terminating OAI CN5G')
+			mySSH.command('cd /opt/oai-cn5g-fed/docker-compose', '\$', 5)
+			mySSH.command('docker-compose down', '\$', 5)
+			mySSH.command('./core-network.sh stop nrf spgwu', '\$', 60)
 		else:
 			logging.error('This should not happen!')
 		mySSH.close()
@@ -679,3 +702,16 @@ class EPCManagement():
 			logging.error('This option should not occur!')
 		mySSH.close()
 
+	def LogCollectOAICN5G(self):
+		mySSH = SSH.SSHConnection()
+		mySSH.open(self.IPAddress, self.UserName, self.Password)
+		logging.debug('OAI CN5G Collecting Log files to workspace')
+		mySSH.command('echo ' + self.Password + ' | sudo rm -rf ' + self.SourceCodePath + '/logs', '\$', 5)
+		mySSH.command('mkdir ' + self.SourceCodePath + '/logs','\$', 5)	
+		containers_list=['oai-smf','oai-spgwu','oai-amf','oai-nrf']
+		for c in containers_list:
+			mySSH.command('docker logs ' + c + ' > ' + self.SourceCodePath + '/logs/' + c + '.log', '\$', 5)
+		mySSH.command('cd ' + self.SourceCodePath + '/logs', '\$', 5)		
+		mySSH.command('zip oai-cn5g.log.zip *.log', '\$', 60)
+		mySSH.close()
+
diff --git a/ci-scripts/main.py b/ci-scripts/main.py
index d66c0c630578310bff402a62f525ab5ebf1e059b..9923d515a47e7568fa333817ecde12408d0085fd 100644
--- a/ci-scripts/main.py
+++ b/ci-scripts/main.py
@@ -154,6 +154,7 @@ def GetParametersFromXML(action):
 
 	elif action == 'Initialize_eNB':
 		RAN.eNB_Trace=test.findtext('eNB_Trace')
+		RAN.eNB_Stats=test.findtext('eNB_Stats')
 		RAN.Initialize_eNB_args=test.findtext('Initialize_eNB_args')
 		eNB_instance=test.findtext('eNB_instance')
 		USRPIPAddress=test.findtext('USRP_IPAddress')
diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py
index 5e3d8e388f8feca72c0aadbf3613554f9c90970e..d7328825724449536e85d9bf78fb0a4398e65b74 100644
--- a/ci-scripts/ran.py
+++ b/ci-scripts/ran.py
@@ -39,7 +39,6 @@ import time
 from multiprocessing import Process, Lock, SimpleQueue
 import yaml
 
-
 #-----------------------------------------------------------
 # OAI Testing modules
 #-----------------------------------------------------------
@@ -94,6 +93,7 @@ class RANManagement():
 		self.runtime_stats= ''
 		self.datalog_rt_stats={}
 		self.eNB_Trace = '' #if 'yes', Tshark will be launched at initialization
+		self.eNB_Stats = '' #if 'yes', Statistics Monitor will be launched at initialization		
 		self.USRPIPAddress = ''
 
 
@@ -341,6 +341,8 @@ class RANManagement():
 
 		self.testCase_id = HTML.testCase_id
 		mySSH = SSH.SSHConnection()
+		cwd = os.getcwd()
+		mySSH.copyout(lIpAddr,lUserName,lPassWord, cwd + "/active_net_interfaces.awk", "/tmp")
 		
 		#reboot USRP if requested in xml
 		if self.USRPIPAddress!='':
@@ -461,10 +463,36 @@ class RANManagement():
 			mySSH.command('if [ -e rbconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm rbconfig.raw; fi', '\$', 5)
 			mySSH.command('if [ -e reconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm reconfig.raw; fi', '\$', 5)
 		# NOTE: WE SHALL do a check if the executable is present (in case build went wrong)
-		mySSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface[self.eNB_instance] + ' -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
+
+		#hack UHD_RFNOC_DIR variable for gNB / N310 on RHEL8 server:
+		#if the USRP address is in the xml then we are using an eth USRP (N3xx)
+		if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'):
+			gNB = False
+		else:
+			gNB = True
+		if ((self.USRPIPAddress!='') and (gNB==True)):
+			mySSH.command('echo ' + lPassWord + ' | echo "ulimit -c unlimited && sudo UHD_RFNOC_DIR=/usr/local/share/uhd/rfnoc ./ran_build/build/' + self.air_interface[self.eNB_instance] + ' -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
+		#otherwise the regular command is ok
+		else:
+			mySSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface[self.eNB_instance] + ' -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
+
 		mySSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
 		mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5)
 		mySSH.command('echo $USER; nohup sudo -E ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10)
+
+
+		#stats monitoring during runtime
+		time.sleep(20)
+		monitor_file='../ci-scripts/stats_monitor.py'
+		conf_file='../ci-scripts/stats_monitor_conf.yaml'
+		if self.eNB_Stats=='yes':
+			if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'):
+				mySSH.command('echo $USER; nohup python3 ' + monitor_file + ' ' + conf_file + ' enb 2>&1 > enb_stats_monitor_execution.log &', '\$', 5)
+			else:
+				mySSH.command('echo $USER; nohup python3 ' + monitor_file + ' ' + conf_file + ' gnb 2>&1 > gnb_stats_monitor_execution.log &', '\$', 5)
+
+
+
 		self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log'
 		if extra_options != '':
 			self.eNBOptions[int(self.eNB_instance)] = extra_options
@@ -539,6 +567,8 @@ class RANManagement():
 			self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId[self.eNB_instance])
 
 		mySSH.close()
+
+
 		HTML.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK)
 		logging.debug('\u001B[1m Initialize eNB/gNB/ocp-eNB Completed\u001B[0m')
 
@@ -657,6 +687,11 @@ class RANManagement():
 				fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)]
 				self.eNBLogFiles[int(self.eNB_instance)] = ''
 			if analyzeFile:
+				#*stats.log files + pickle + png
+				mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/*stats.log', '.')
+				mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/*.pickle', '.')
+				mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/*.png', '.')
+				#
 				copyin_res = mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.')
 				if (copyin_res == -1):
 					logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m')
@@ -665,12 +700,20 @@ class RANManagement():
 					self.eNBmbmsEnables[int(self.eNB_instance)] = False
 					return
 				if self.eNB_serverId[self.eNB_instance] != '0':
+					#*stats.log files + pickle + png
+
+					#debug / tentative
+					mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './nrL1_stats.log', self.eNBSourceCodePath + '/cmake_targets/')
+					mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './nrMAC_stats.log', self.eNBSourceCodePath + '/cmake_targets/')
+					mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './gnb_stats_monitor.pickle.pickle', self.eNBSourceCodePath + '/cmake_targets/')
+					mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './gnb_stats_monitor.png', self.eNBSourceCodePath + '/cmake_targets/')
+					#
 					mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/')
 				logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze)
 				logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze, HTML)
 				if (logStatus < 0):
 					HTML.CreateHtmlTestRow('N/A', 'KO', logStatus)
-					self.preamtureExit = True
+					self.prematureExit = True
 					self.eNBmbmsEnables[int(self.eNB_instance)] = False
 					return
 				else:
@@ -691,8 +734,8 @@ class RANManagement():
 		mySSH.command('echo ' + self.eNBPassword + ' | sudo -S mv /tmp/enb_*.pcap .','\$',20)
 		mySSH.command('echo ' + self.eNBPassword + ' | sudo -S mv /tmp/gnb_*.pcap .','\$',20)
 		mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5)
-		mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap gnb_*.pcap enb_*txt physim_*.log *stats.log', '\$', 60)
-		mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap gnb_*.pcap enb_*txt physim_*.log *stats.log', '\$', 5)
+		mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap gnb_*.pcap enb_*txt physim_*.log *stats.log *monitor.pickle *monitor.png', '\$', 60)
+		mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap gnb_*.pcap enb_*txt physim_*.log *stats.log *.pickle *.png', '\$', 5)
 		mySSH.close()
 
 	def AnalyzeLogFile_eNB(self, eNBlogFile, HTML):
@@ -1032,7 +1075,7 @@ class RANManagement():
 				for k in datalog_rt_stats['Data']:
 					if float(datalog_rt_stats['Data'][k][2])> datalog_rt_stats['Threshold'][k]: #condition for fail : avg/ref is greater than the fixed threshold
 						#setting prematureExit is ok although not the best option
-						self.prematureExit=True
+						self.prematureExit=False #temp for debug : do not stop the test if RT stats are excedeed
 			else:
 				statMsg = 'No real time stats found in the log file\n'
 				logging.debug('No real time stats found in the log file')
diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py
index b4087c9695900422b107227c3bc60b0fae23c1f4..b85c40a0bea56e7b8ce2bf4b7d7a3ddf47f55ce1 100644
--- a/ci-scripts/sshconnection.py
+++ b/ci-scripts/sshconnection.py
@@ -163,6 +163,18 @@ class SSHConnection():
 		lSsh = subprocess.Popen(["ssh", "%s" % myHost, commandline],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
 		self.cmd2Results = str(lSsh.stdout.readlines())
 
+	def command3(self, commandline, timeout, silent=False):
+		if not silent:
+			logging.debug(commandline)
+		self.cmd2Results = ''
+		myHost = self.username + '@' + self.ipaddress
+		# CAUTION: THIS METHOD IMPLIES THAT THERE ARE VALID SSH KEYS
+		# BETWEEN THE PYTHON EXECUTOR NODE AND THE REMOTE HOST
+		# OTHERWISE IT WON'T WORK
+		lSsh = subprocess.Popen(["ssh", "%s" % myHost, commandline],shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
+		return lSsh.stdout.readlines()
+
+		
 	def close(self):
 		self.ssh.timeout = 5
 		self.ssh.sendline('exit')
diff --git a/ci-scripts/stats_monitor.py b/ci-scripts/stats_monitor.py
new file mode 100755
index 0000000000000000000000000000000000000000..877194de5944bf6932aa239e6942bbed9f2b2479
--- /dev/null
+++ b/ci-scripts/stats_monitor.py
@@ -0,0 +1,102 @@
+"""
+To create graphs and pickle from runtime statistics in L1,MAC,RRC,PDCP files
+"""
+
+import subprocess
+import time
+import shlex
+import re
+import sys
+import pickle
+import matplotlib.pyplot as plt
+import numpy as np
+import yaml
+
+
+class StatMonitor():
+    def __init__(self,cfg_file):
+        with open(cfg_file,'r') as file:
+            self.d = yaml.load(file)
+        for node in self.d:
+            for metric in self.d[node]:
+                self.d[node][metric]=[]
+
+
+    def process_gnb (self,node_type,output):
+        for line in output:
+            tmp=line.decode("utf-8")
+            result=re.match(r'^.*\bdlsch_rounds\b ([0-9]+)\/([0-9]+).*\bdlsch_errors\b ([0-9]+)',tmp)
+            if result is not None:
+                self.d[node_type]['dlsch_err'].append(int(result.group(3)))
+                percentage=float(result.group(2))/float(result.group(1))
+                self.d[node_type]['dlsch_err_perc_round_1'].append(percentage)
+            result=re.match(r'^.*\bulsch_rounds\b ([0-9]+)\/([0-9]+).*\bulsch_errors\b ([0-9]+)',tmp)
+            if result is not None:
+                self.d[node_type]['ulsch_err'].append(int(result.group(3)))
+                percentage=float(result.group(2))/float(result.group(1))
+                self.d[node_type]['ulsch_err_perc_round_1'].append(percentage)
+
+
+    def process_enb (self,node_type,output):
+        for line in output:
+            tmp=line.decode("utf-8")
+            result=re.match(r'^.*\bPHR\b ([0-9]+).+\bbler\b ([0-9]+\.[0-9]+).+\bmcsoff\b ([0-9]+).+\bmcs\b ([0-9]+)',tmp)
+            if result is not None:
+                self.d[node_type]['PHR'].append(int(result.group(1)))
+                self.d[node_type]['bler'].append(float(result.group(2)))
+                self.d[node_type]['mcsoff'].append(int(result.group(3)))
+                self.d[node_type]['mcs'].append(int(result.group(4)))
+
+
+    def collect(self,node_type):
+        if node_type=='enb':
+            cmd='cat L1_stats.log MAC_stats.log PDCP_stats.log RRC_stats.log'
+        else: #'gnb'
+            cmd='cat nrL1_stats.log nrMAC_stats.log nrPDCP_stats.log nrRRC_stats.log'
+        process=subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE)
+        output = process.stdout.readlines()
+        if node_type=='enb':
+            self.process_enb(node_type,output)
+        else: #'gnb'
+            self.process_gnb(node_type,output)
+
+
+    def graph(self,node_type):
+        col = 1
+        figure, axis = plt.subplots(len(self.d[node_type]), col ,figsize=(10, 10))
+        i=0
+        for metric in self.d[node_type]:
+            major_ticks = np.arange(0, len(self.d[node_type][metric])+1, 1)
+            axis[i].set_xticks(major_ticks)
+            axis[i].set_xticklabels([])
+            axis[i].plot(self.d[node_type][metric],marker='o')
+            axis[i].set_xlabel('time')
+            axis[i].set_ylabel(metric)
+            axis[i].set_title(metric)
+            i+=1
+
+        plt.tight_layout()
+        # Combine all the operations and display
+        plt.savefig(node_type+'_stats_monitor.png')
+        plt.show()
+
+
+if __name__ == "__main__":
+
+    cfg_filename = sys.argv[1] #yaml file as metrics config
+    node = sys.argv[2]#enb or gnb
+    mon=StatMonitor(cfg_filename)
+
+    #collecting stats when modem process is stopped
+    CMD='ps aux | grep mode | grep -v grep'
+    process=subprocess.Popen(CMD, shell=True, stdout=subprocess.PIPE)
+    output = process.stdout.readlines()
+    while len(output)!=0 :
+        mon.collect(node)
+        process=subprocess.Popen(CMD, shell=True, stdout=subprocess.PIPE)
+        output = process.stdout.readlines()
+        time.sleep(1)
+    print('Process stopped')
+    with open(node+'_stats_monitor.pickle', 'wb') as handle:
+        pickle.dump(mon.d, handle, protocol=pickle.HIGHEST_PROTOCOL)
+    mon.graph(node)
diff --git a/ci-scripts/stats_monitor.py.old b/ci-scripts/stats_monitor.py.old
new file mode 100755
index 0000000000000000000000000000000000000000..ae9b39bfa632c5b85d24d494464b2ae001040cb3
--- /dev/null
+++ b/ci-scripts/stats_monitor.py.old
@@ -0,0 +1,94 @@
+import subprocess
+import time
+import shlex
+import re
+import sys
+import matplotlib.pyplot as plt
+import pickle
+import numpy as np
+import os
+
+def collect(d, node_type):
+    if node_type=='enb':
+        cmd='cat L1_stats.log MAC_stats.log PDCP_stats.log RRC_stats.log'
+    else: #'gnb'
+        cmd='cat nrL1_stats.log nrMAC_stats.log nrPDCP_stats.log nrRRC_stats.log'
+    process=subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE)
+    output = process.stdout.readlines()
+    for l in output:
+        tmp=l.decode("utf-8")
+        result=re.match(rf'^.*\bPHR\b ([0-9]+).+\bbler\b ([0-9]+\.[0-9]+).+\bmcsoff\b ([0-9]+).+\bmcs\b ([0-9]+)',tmp)
+        if result is not None:
+            d['PHR'].append(int(result.group(1)))
+            d['bler'].append(float(result.group(2)))
+            d['mcsoff'].append(int(result.group(3)))
+            d['mcs'].append(int(result.group(4)))
+
+
+def graph(d, node_type):
+
+
+    figure, axis = plt.subplots(4, 1,figsize=(10, 10)) 
+
+    major_ticks = np.arange(0, len(d['PHR'])+1, 1)
+    axis[0].set_xticks(major_ticks)
+    axis[0].set_xticklabels([])
+    axis[0].plot(d['PHR'],marker='o')
+    axis[0].set_xlabel('time')
+    axis[0].set_ylabel('PHR')
+    axis[0].set_title("PHR")
+  
+    major_ticks = np.arange(0, len(d['bler'])+1, 1)
+    axis[1].set_xticks(major_ticks)
+    axis[1].set_xticklabels([])
+    axis[1].plot(d['bler'],marker='o')
+    axis[1].set_xlabel('time')
+    axis[1].set_ylabel('bler')
+    axis[1].set_title("bler")
+
+    major_ticks = np.arange(0, len(d['mcsoff'])+1, 1)
+    axis[2].set_xticks(major_ticks)
+    axis[2].set_xticklabels([])
+    axis[2].plot(d['mcsoff'],marker='o')
+    axis[2].set_xlabel('time')
+    axis[2].set_ylabel('mcsoff')
+    axis[2].set_title("mcsoff")
+
+    major_ticks = np.arange(0, len(d['mcs'])+1, 1)
+    axis[3].set_xticks(major_ticks)
+    axis[3].set_xticklabels([])
+    axis[3].plot(d['mcs'],marker='o')
+    axis[3].set_xlabel('time')
+    axis[3].set_ylabel('mcs')
+    axis[3].set_title("mcs")
+
+    plt.tight_layout()
+    # Combine all the operations and display
+    plt.savefig(node_type+'_stats_monitor.png')
+    plt.show()
+
+if __name__ == "__main__":
+
+    node_type = sys.argv[1]#enb or gnb
+
+    d={}
+    d['PHR']=[]
+    d['bler']=[]
+    d['mcsoff']=[]
+    d['mcs']=[]
+
+
+    cmd='ps aux | grep modem | grep -v grep'
+    process=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
+    output = process.stdout.readlines()
+    while len(output)!=0 :
+        collect(d, node_type)
+        process=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
+        output = process.stdout.readlines()
+        time.sleep(1)
+    print('process stopped')
+    with open(node_type+'_stats_monitor.pickle', 'wb') as handle:
+        pickle.dump(d, handle, protocol=pickle.HIGHEST_PROTOCOL)
+    graph(d, node_type)
+
+
diff --git a/ci-scripts/stats_monitor_conf.yaml b/ci-scripts/stats_monitor_conf.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6c0a2b0225f22130043a3344fd8f1ceb3b8e866b
--- /dev/null
+++ b/ci-scripts/stats_monitor_conf.yaml
@@ -0,0 +1,11 @@
+enb :
+  PHR:
+  bler:
+  mcsoff:
+  mcs:  
+
+gnb :
+  dlsch_err:
+  dlsch_err_perc_round_1:
+  ulsch_err:
+  ulsch_err_perc_round_1:
\ No newline at end of file
diff --git a/ci-scripts/stats_monitor_dev.py b/ci-scripts/stats_monitor_dev.py
new file mode 100755
index 0000000000000000000000000000000000000000..14a2ef6a453117500c3782e4943ff2e1a4dc1f99
--- /dev/null
+++ b/ci-scripts/stats_monitor_dev.py
@@ -0,0 +1,103 @@
+import subprocess
+import time
+import shlex
+import re
+import sys
+import matplotlib.pyplot as plt
+import pickle
+import numpy as np
+import os
+import yaml
+
+
+class Stat_Monitor():
+    def __init__(self,):
+        with open('stats_monitor_conf.yaml','r') as f:
+            self.d = yaml.load(f)
+        for node in self.d:
+            for metric in self.d[node]:
+                self.d[node][metric]=[]
+
+
+    def process_gnb (self,node_type,output):
+        for line in output:
+            tmp=line.decode("utf-8")
+            result=re.match(r'^.*\bdlsch_rounds\b ([0-9]+)\/([0-9]+).*\bdlsch_errors\b ([0-9]+)',tmp)
+            if result is not None:
+                self.d[node_type]['dlsch_err'].append(int(result.group(3)))
+                percentage=float(result.group(2))/float(result.group(1))
+                self.d[node_type]['dlsch_err_perc_round_1'].append(percentage)
+            result=re.match(r'^.*\bulsch_rounds\b ([0-9]+)\/([0-9]+).*\bulsch_errors\b ([0-9]+)',tmp)
+            if result is not None:
+                self.d[node_type]['ulsch_err'].append(int(result.group(3)))
+                percentage=float(result.group(2))/float(result.group(1))
+                self.d[node_type]['ulsch_err_perc_round_1'].append(percentage)
+
+
+    def process_enb (self,node_type,output):
+        for line in output:
+            tmp=line.decode("utf-8")
+            result=re.match(r'^.*\bPHR\b ([0-9]+).+\bbler\b ([0-9]+\.[0-9]+).+\bmcsoff\b ([0-9]+).+\bmcs\b ([0-9]+)',tmp)
+            if result is not None:
+                self.d[node_type]['PHR'].append(int(result.group(1)))
+                self.d[node_type]['bler'].append(float(result.group(2)))
+                self.d[node_type]['mcsoff'].append(int(result.group(3)))
+                self.d[node_type]['mcs'].append(int(result.group(4)))
+
+
+
+
+
+    def collect(self,node_type):
+        if node_type=='enb':
+            cmd='cat L1_stats.log MAC_stats.log PDCP_stats.log RRC_stats.log'
+        else: #'gnb'
+            cmd='cat nrL1_stats.log nrMAC_stats.log nrPDCP_stats.log nrRRC_stats.log'
+        process=subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE)
+        output = process.stdout.readlines()
+        if node_type=='enb':
+            self.process_enb(node_type,output)
+        else: #'gnb'
+            self.process_gnb(node_type,output)          
+
+    def graph(self,node_type):
+
+        col = 1
+        figure, axis = plt.subplots(len(self.d[node_type]), col ,figsize=(10, 10)) 
+        i=0
+        for metric in self.d[node_type]:
+            major_ticks = np.arange(0, len(self.d[node_type][metric])+1, 1)
+            axis[i].set_xticks(major_ticks)
+            axis[i].set_xticklabels([])
+            axis[i].plot(self.d[node_type][metric],marker='o')
+            axis[i].set_xlabel('time')
+            axis[i].set_ylabel(metric)
+            axis[i].set_title(metric)
+            i+=1
+  
+        plt.tight_layout()
+        # Combine all the operations and display
+        plt.savefig(node_type+'_stats_monitor.png')
+        plt.show()
+
+
+if __name__ == "__main__":
+
+    node_type = sys.argv[1]#enb or gnb
+    mon=Stat_Monitor()
+
+    #collecting stats when modem process is stopped
+    cmd='ps aux | grep mode | grep -v grep'
+    process=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
+    output = process.stdout.readlines()
+    while len(output)!=0 :
+        mon.collect(node_type)
+        process=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
+        output = process.stdout.readlines()
+        time.sleep(1)
+    print('Process stopped')
+    with open(node_type+'_stats_monitor.pickle', 'wb') as handle:
+        pickle.dump(mon.d, handle, protocol=pickle.HIGHEST_PROTOCOL)
+    mon.graph(node_type)
+
+
diff --git a/ci-scripts/xml_files/fr1_enb_build.xml b/ci-scripts/xml_files/fr1_enb_build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..084f58a59134785c1d1b673c6d0a8c8496b5b1ad
--- /dev/null
+++ b/ci-scripts/xml_files/fr1_enb_build.xml
@@ -0,0 +1,50 @@
+<!--
+
+ 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
+
+-->
+<testCaseList>
+	<htmlTabRef>build-tab</htmlTabRef>
+	<htmlTabName>Build</htmlTabName>
+	<htmlTabIcon>wrench</htmlTabIcon>
+	<TestCaseRequestedList>
+ 000001
+ 000002
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="000001">
+		<class>Build_eNB</class>
+		<desc>Build eNB</desc>
+		<Build_eNB_args>-w USRP -c --eNB --ninja</Build_eNB_args>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+		<backgroundBuild>True</backgroundBuild>
+		<forced_workspace_cleanup>True</forced_workspace_cleanup>
+	</testCase>
+
+	<testCase id="000002">
+		<class>WaitEndBuild_eNB</class>
+		<desc>Wait for end of Build eNB</desc>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/fr1_gnb_build.xml b/ci-scripts/xml_files/fr1_gnb_build.xml
index d0c91f407df41d8d58543ade502653440e31dba1..43cff756209972bbbf605397c37f8c439d472c53 100644
--- a/ci-scripts/xml_files/fr1_gnb_build.xml
+++ b/ci-scripts/xml_files/fr1_gnb_build.xml
@@ -26,7 +26,6 @@
 	<htmlTabIcon>wrench</htmlTabIcon>
 	<TestCaseRequestedList>
  000001
- 000002
 	</TestCaseRequestedList>
 	<TestCaseExclusionList></TestCaseExclusionList>
 
@@ -36,7 +35,6 @@
 		<Build_eNB_args>-w USRP -c --gNB --ninja</Build_eNB_args>
 		<eNB_instance>0</eNB_instance>
 		<eNB_serverId>0</eNB_serverId>
-		<backgroundBuild>True</backgroundBuild>
 		<forced_workspace_cleanup>True</forced_workspace_cleanup>
 	</testCase>
 
diff --git a/ci-scripts/xml_files/fr1_lte_2x2_quectel.xml b/ci-scripts/xml_files/fr1_lte_2x2_quectel.xml
new file mode 100644
index 0000000000000000000000000000000000000000..86d9e5d5f0dbe2b86c9a91a2bbf6b2fc7ba3fc8c
--- /dev/null
+++ b/ci-scripts/xml_files/fr1_lte_2x2_quectel.xml
@@ -0,0 +1,141 @@
+<!--
+
+ 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
+
+-->
+<testCaseList>
+	<htmlTabRef>TEST-LTE-TM2</htmlTabRef>
+	<htmlTabName>LTE 2x2 Ping DL UL with QUECTEL</htmlTabName>
+	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>1</repeatCount>
+	<TestCaseRequestedList>
+ 030000
+ 000002
+ 010000
+ 000001
+ 050000
+ 050001
+ 000002
+ 070000
+ 070001
+ 000001
+ 010002
+ 080000
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="010000">
+		<class>Initialize_UE</class>
+		<desc>Initialize Quectel</desc>
+		<id>nrmodule2_quectel</id>
+		<UE_Trace>yes</UE_Trace>
+	</testCase>
+
+
+	<testCase id="010002">
+		<class>Terminate_UE</class>
+		<desc>Terminate Quectel</desc>
+		<id>nrmodule2_quectel</id>
+	</testCase>
+
+
+	<testCase id="030000">
+		<class>Initialize_eNB</class>
+		<desc>Initialize eNB</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6</Initialize_eNB_args>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+		<air_interface>lte</air_interface>
+		<eNB_Trace>yes</eNB_Trace>
+		<eNB_Stats>yes</eNB_Stats>
+		<USRP_IPAddress>192.168.18.241</USRP_IPAddress>
+	</testCase>
+
+
+	<testCase id="000001">
+		<class>IdleSleep</class>
+		<desc>Sleep</desc>
+		<idle_sleep_time_in_sec>5</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="000002">
+		<class>IdleSleep</class>
+		<desc>Sleep</desc>
+		<idle_sleep_time_in_sec>20</idle_sleep_time_in_sec>
+	</testCase>
+
+
+	<testCase id="050000">
+		<class>Ping</class>
+		<desc>Ping: 20 pings</desc>
+		<id>nrmodule2_quectel</id>
+		<ping_args>-c 20</ping_args>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
+	</testCase>
+	<testCase id="050001">
+		<class>Ping</class>
+		<desc>Ping: 100 pings, size 1024</desc>
+		<id>nrmodule2_quectel</id>
+		<ping_args>-c 100 -s 1024 -i 0,2</ping_args>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
+	</testCase>
+
+
+	<testCase id="070000">
+		<class>Iperf</class>
+		<desc>iperf (DL/26Mbps/UDP)(60 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 26M -t 60</iperf_args>
+		<direction>DL</direction>
+		<id>nrmodule2_quectel</id>
+		<iperf_packetloss_threshold>5</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="070001">
+		<class>Iperf</class>
+		<desc>iperf (UL/7Mbps/UDP)(60 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 7M -t 60</iperf_args>
+		<direction>UL</direction>
+		<id>nrmodule2_quectel</id>
+		<iperf_packetloss_threshold>5</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+
+
+
+	<testCase id="080000">
+		<class>Terminate_eNB</class>
+		<desc>Terminate eNB</desc>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+		<air_interface>lte</air_interface>
+	</testCase>
+
+	<testCase id="080001">
+		<class>Terminate_eNB</class>
+		<desc>Terminate gNB</desc>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+		<air_interface>nr</air_interface>
+	</testCase>
+
+</testCaseList>
+
diff --git a/ci-scripts/xml_files/fr1_multi_node_build.xml b/ci-scripts/xml_files/fr1_multi_node_build.xml
index 57c4685341c9cda60734c02cdbcbd2435f5e5c84..60bc734e65da9db4deb8a535051ce3ef41687430 100644
--- a/ci-scripts/xml_files/fr1_multi_node_build.xml
+++ b/ci-scripts/xml_files/fr1_multi_node_build.xml
@@ -26,7 +26,7 @@
 	<htmlTabIcon>wrench</htmlTabIcon>
 	<TestCaseRequestedList>
  000001 000002
- 000003 000004
+ 000004 000005 000003
 	</TestCaseRequestedList>
 	<TestCaseExclusionList></TestCaseExclusionList>
 
@@ -64,5 +64,10 @@
 		<eNB_serverId>1</eNB_serverId>
 	</testCase>
 
+	<testCase id="000005">
+		<class>IdleSleep</class>
+		<desc>Sleep</desc>
+		<idle_sleep_time_in_sec>120</idle_sleep_time_in_sec>
+	</testCase>
 
 </testCaseList>
diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml
index a8e385b854120a2451253e4fd42c9c4aff314b11..03dea3660719c24f34bf1f3a6ec9af9ee5f41591 100644
--- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml
+++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml
@@ -21,8 +21,8 @@
 
 -->
 <testCaseList>
-	<htmlTabRef>TEST-NSA-FR1-TM1</htmlTabRef>
-	<htmlTabName>NSA Ping DL UL with QUECTEL</htmlTabName>
+	<htmlTabRef>TEST-NSA-FR1-TM2</htmlTabRef>
+	<htmlTabName>NSA 2x2 Ping DL UL with QUECTEL</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
 	<repeatCount>1</repeatCount>
 	<TestCaseRequestedList>
@@ -32,6 +32,9 @@
  010000
  000001
  050000
+ 000002
+ 070000
+ 070001
  000001
  010002
  080001
@@ -57,11 +60,12 @@
 	<testCase id="030000">
 		<class>Initialize_eNB</class>
 		<desc>Initialize eNB</desc>
-		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf</Initialize_eNB_args>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band38.nsa_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6</Initialize_eNB_args>
 		<eNB_instance>0</eNB_instance>
 		<eNB_serverId>0</eNB_serverId>
 		<air_interface>lte</air_interface>
 		<eNB_Trace>yes</eNB_Trace>
+		<eNB_Stats>yes</eNB_Stats>
 		<USRP_IPAddress>192.168.18.241</USRP_IPAddress>
 	</testCase>
 
@@ -69,10 +73,11 @@
 	<testCase id="040000">
 		<class>Initialize_eNB</class>
 		<desc>Initialize gNB</desc>
-		<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf -q</Initialize_eNB_args>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.nsa_2x2.106PRB.usrpn310.conf -q --usrp-tx-thread-config 1 --thread-pool 0,2,4,6</Initialize_eNB_args>
 		<eNB_instance>1</eNB_instance>
 		<eNB_serverId>1</eNB_serverId>
 		<air_interface>nr</air_interface>
+		<eNB_Stats>yes</eNB_Stats>
 		<USRP_IPAddress>192.168.18.240</USRP_IPAddress>
 	</testCase>
 
@@ -111,17 +116,17 @@
 		<iperf_args>-u -b 20M -t 60</iperf_args>
 		<direction>DL</direction>
 		<id>nrmodule2_quectel</id>
-		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_packetloss_threshold>5</iperf_packetloss_threshold>
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
 	<testCase id="070001">
 		<class>Iperf</class>
-		<desc>iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile)</desc>
-		<iperf_args>-u -b 3M -t 60</iperf_args>
+		<desc>iperf (UL/1Mbps/UDP)(20 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 1M -t 20</iperf_args>
 		<direction>UL</direction>
 		<id>nrmodule2_quectel</id>
-		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_packetloss_threshold>5</iperf_packetloss_threshold>
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
diff --git a/ci-scripts/xml_files/fr1_oai_cn_deploy.xml b/ci-scripts/xml_files/fr1_oai_cn_deploy.xml
index 919def7aa39c2ec33891132ffe01d83f493049fc..1ccc952c563ac3823857ab716a66a0976b33918e 100644
--- a/ci-scripts/xml_files/fr1_oai_cn_deploy.xml
+++ b/ci-scripts/xml_files/fr1_oai_cn_deploy.xml
@@ -33,7 +33,7 @@
 	<testCase id="000100">
 		<class>Deploy_EPC</class>
 		<desc>Deploy all EPC containers</desc>
-		<parameters>yaml_files/fr1_epc_tim</parameters>
+		<parameters>yaml_files/fr1_epc_20897</parameters>
 	</testCase>
 
 </testCaseList>
diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml
index 00621245870e2673d1d996e639e503a20f4b5456..469ae8fb1b45714f95a1e028f1cab39d10020d29 100644
--- a/ci-scripts/xml_files/fr1_sa_quectel.xml
+++ b/ci-scripts/xml_files/fr1_sa_quectel.xml
@@ -31,6 +31,9 @@
  010000
  000001
  050000
+ 050001
+ 070000
+ 070001
  000001
  010002
  080000
@@ -82,34 +85,26 @@
 		<desc>Ping: 20pings in 20sec</desc>
 		<id>nrmodule2_quectel</id>
 		<ping_args>-c 20</ping_args>
-		<ping_packetloss_threshold>50</ping_packetloss_threshold>
-	</testCase>
-
-	<testCase id="050001">
-		<class>Ping</class>
-		<desc>Ping: 100pings in 20sec</desc>
-		<id>nrmodule2_quectel</id>
-		<ping_args>-c 100 -i 0.2</ping_args>
-		<ping_packetloss_threshold>50</ping_packetloss_threshold>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
 	</testCase>
 
 	<testCase id="070000">
 		<class>Iperf</class>
-		<desc>iperf (DL/20Mbps/UDP)(60 sec)(single-ue profile)</desc>
-		<iperf_args>-u -b 20M -t 60</iperf_args>
+		<desc>iperf (DL/5Mbps/UDP)(60 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 5M -t 60</iperf_args>
 		<direction>DL</direction>
 		<id>nrmodule2_quectel</id>
-		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_packetloss_threshold>5</iperf_packetloss_threshold>
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
 	<testCase id="070001">
 		<class>Iperf</class>
-		<desc>iperf (UL/3Mbps/UDP)(60 sec)(single-ue profile)</desc>
-		<iperf_args>-u -b 3M -t 60</iperf_args>
+		<desc>iperf (UL/1Mbps/UDP)(60 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 1M -t 60</iperf_args>
 		<direction>UL</direction>
 		<id>nrmodule2_quectel</id>
-		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_packetloss_threshold>5</iperf_packetloss_threshold>
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
diff --git a/ci-scripts/yaml_files/fr1_epc_tim/docker-compose.yml b/ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml
similarity index 95%
rename from ci-scripts/yaml_files/fr1_epc_tim/docker-compose.yml
rename to ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml
index 73a6b3a1fff2b10258d0ed3dbcb21a4878c86681..0005ce8844ad3c5e5aa696aadf63ed4a43b76515 100644
--- a/ci-scripts/yaml_files/fr1_epc_tim/docker-compose.yml
+++ b/ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml
@@ -51,7 +51,7 @@ services:
             LTE_K: FEC86BA6EB707ED08905757B1BB44B8F 
             APN1: oai.ipv4
             APN2: oai2.ipv4
-            FIRST_IMSI: 208990100001127 
+            FIRST_IMSI: 208970100001127 
             NB_USERS: 5
         healthcheck:
             test: /bin/bash -c "pgrep oai_hss"
@@ -78,7 +78,7 @@ services:
             HSS_FQDN: hss.openairinterface.org
             HSS_REALM: openairinterface.org
             MCC: '208'
-            MNC: '99'
+            MNC: '97'
             MME_GID: 32768
             MME_CODE: 3
             TAC_0: 1
@@ -97,15 +97,15 @@ services:
             PEER_MME_IPV4_ADDRESS_FOR_S10_0: 0.0.0.0
             PEER_MME_IPV4_ADDRESS_FOR_S10_1: 0.0.0.0
             MCC_SGW_0: '208'
-            MNC3_SGW_0: '099'
+            MNC3_SGW_0: '097'
             TAC_LB_SGW_0: '01'
             TAC_HB_SGW_0: '00'
             MCC_MME_0: '208'
-            MNC3_MME_0: '099'
+            MNC3_MME_0: '097'
             TAC_LB_MME_0: '02'
             TAC_HB_MME_0: '00'
             MCC_MME_1: '208'
-            MNC3_MME_1: '099'
+            MNC3_MME_1: '097'
             TAC_LB_MME_1: '03'
             TAC_HB_MME_1: '00'
             TAC_LB_SGW_TEST_0: '03'
@@ -138,11 +138,12 @@ services:
             UE_IP_ADDRESS_POOL_1: '12.1.1.2 - 12.1.1.254'
             UE_IP_ADDRESS_POOL_2: '12.0.0.2 - 12.0.0.254'
             MCC: '208'
-            MNC: '99'
-            MNC03: '099'
+            MNC: '97'
+            MNC03: '097'
             TAC: 1
             GW_ID: 1
             REALM: openairinterface.org
+            UE_MTU_IPV4: 1500
         healthcheck:
             test: /bin/bash -c "pgrep oai_spgwc"
             interval: 10s
@@ -168,8 +169,8 @@ services:
             NETWORK_UE_IP: '12.1.1.0/24'
             NETWORK_UE_NAT_OPTION: 'yes'
             MCC: '208'
-            MNC: '99'
-            MNC03: '099'
+            MNC: '97'
+            MNC03: '097'
             TAC: 1
             GW_ID: 1
             REALM: openairinterface.org
diff --git a/ci-scripts/yaml_files/fr1_epc_tim/docker-compose.yml.orig b/ci-scripts/yaml_files/fr1_epc_tim/docker-compose.yml.orig
deleted file mode 100644
index 28ae154838aed5b750eb9954ef7467f05318198d..0000000000000000000000000000000000000000
--- a/ci-scripts/yaml_files/fr1_epc_tim/docker-compose.yml.orig
+++ /dev/null
@@ -1,203 +0,0 @@
-version: '3.8'
-
-services:
-    cassandra:
-        image: cassandra:2.1
-        container_name: prod-cassandra
-        networks:
-            private_net:
-                ipv4_address: 192.168.68.2
-        environment:
-            CASSANDRA_CLUSTER_NAME: "OAI HSS Cluster"
-            CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch
-        healthcheck:
-            test: /bin/bash -c "nodetool status"
-            interval: 10s
-            timeout: 5s
-            retries: 5
-
-    db_init:
-        image: cassandra:2.1
-        container_name: prod-db-init
-        depends_on: [cassandra]
-        deploy:
-            restart_policy:
-                condition: on-failure
-                max_attempts: 10
-        networks:
-            private_net:
-                ipv4_address: 192.168.68.4
-        volumes:
-            - ./oai_db.cql:/home/oai_db.cql
-        entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql 192.168.68.2 && echo 'OK'"
-
-    oai_hss:
-        image: oai-hss:production
-        container_name: prod-oai-hss
-        privileged: true
-        depends_on: [cassandra]
-        networks:
-            private_net:
-                ipv4_address: 192.168.68.3
-            public_net:
-                ipv4_address: 192.168.61.2
-        environment:
-            REALM: openairinterface.org
-            HSS_FQDN: hss.openairinterface.org
-            PREFIX: /openair-hss/etc
-            cassandra_Server_IP: 192.168.68.2
-            OP_KEY: 1006020f0a478bf6b699f15c062e42b3
-            LTE_K: fec86ba6eb707ed08905757b1bb44b8f
-            APN1: oai.ipv4
-            APN2: internet
-            FIRST_IMSI: 222010100001120
-            NB_USERS: 10
-        healthcheck:
-            test: /bin/bash -c "pgrep oai_hss"
-            interval: 10s
-            timeout: 5s
-            retries: 5
-
-    oai_mme:
-        image: oai-mme:production
-        container_name: prod-oai-mme
-        privileged: true
-        depends_on: [oai_hss]
-        networks:
-            public_net:
-                ipv4_address: 192.168.61.3
-        environment:
-            REALM: openairinterface.org
-            PREFIX: /openair-mme/etc
-            INSTANCE: 1
-            PID_DIRECTORY: /var/run
-            HSS_IP_ADDR: 192.168.61.2
-            HSS_HOSTNAME: hss
-            HSS_FQDN: hss.openairinterface.org
-            HSS_REALM: openairinterface.org
-            MCC: '222'
-            MNC: '01'
-            MME_GID: 32768
-            MME_CODE: 3
-            TAC_0: 1
-            TAC_1: 2
-            TAC_2: 3
-            MME_FQDN: mme.openairinterface.org
-            MME_S6A_IP_ADDR: 192.168.61.3
-            MME_INTERFACE_NAME_FOR_S1_MME: eth0
-            MME_IPV4_ADDRESS_FOR_S1_MME: 192.168.61.3
-            MME_INTERFACE_NAME_FOR_S11: eth0
-            MME_IPV4_ADDRESS_FOR_S11: 192.168.61.3
-            MME_INTERFACE_NAME_FOR_S10: lo
-            MME_IPV4_ADDRESS_FOR_S10: 127.0.0.10
-            OUTPUT: CONSOLE
-            SGW_IPV4_ADDRESS_FOR_S11_0: 192.168.61.4
-            PEER_MME_IPV4_ADDRESS_FOR_S10_0: 0.0.0.0
-            PEER_MME_IPV4_ADDRESS_FOR_S10_1: 0.0.0.0
-            MCC_SGW_0: '222'
-            MNC3_SGW_0: '001'
-            TAC_LB_SGW_0: '01'
-            TAC_HB_SGW_0: '00'
-            MCC_MME_0: '222'
-            MNC3_MME_0: '001'
-            TAC_LB_MME_0: '02'
-            TAC_HB_MME_0: '00'
-            MCC_MME_1: '222'
-            MNC3_MME_1: '001'
-            TAC_LB_MME_1: '03'
-            TAC_HB_MME_1: '00'
-            TAC_LB_SGW_TEST_0: '03'
-            TAC_HB_SGW_TEST_0: '00'
-            SGW_IPV4_ADDRESS_FOR_S11_TEST_0: 0.0.0.0
-        healthcheck:
-            test: /bin/bash -c "pgrep oai_mme"
-            interval: 10s
-            timeout: 5s
-            retries: 5
-
-    oai_spgwc:
-        image: oai-spgwc:production
-        privileged: true
-        depends_on: [oai_mme]
-        container_name: prod-oai-spgwc
-        networks:
-            public_net:
-                ipv4_address: 192.168.61.4
-        environment:
-            PID_DIRECTORY: /var/run
-            SGW_INTERFACE_NAME_FOR_S11: eth0
-            SGW_IP_FOR_S5_S8_CP: 127.0.0.11/8
-            PGW_IP_FOR_S5_S8_CP: 127.0.0.12/8
-            PGW_INTERFACE_NAME_FOR_SX: eth0
-            DEFAULT_APN: oai.ipv4
-            DEFAULT_DNS_IPV4_ADDRESS: 192.168.18.129
-            DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4
-            UE_IP_ADDRESS_POOL: '12.1.1.2 - 12.1.1.254'
-            PUSH_PROTOCOL_OPTION: 'yes'
-        healthcheck:
-            test: /bin/bash -c "pgrep oai_spgwc"
-            interval: 10s
-            timeout: 5s
-            retries: 5
-
-    oai_spgwu:
-        image: oai-spgwu-tiny:production
-        privileged: true
-        container_name: prod-oai-spgwu-tiny
-        depends_on: [oai_spgwc]
-        networks:
-            public_net:
-                ipv4_address: 192.168.61.5
-        environment:
-            PID_DIRECTORY: /var/run
-            INSTANCE: 1
-            SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP: eth0
-            PGW_INTERFACE_NAME_FOR_SGI: eth0
-            SGW_INTERFACE_NAME_FOR_SX: eth0
-            SPGWC0_IP_ADDRESS: 192.168.61.4
-            NETWORK_UE_IP: '12.1.1.0/24'
-            NETWORK_UE_NAT_OPTION: 'yes'
-        healthcheck:
-            test: /bin/bash -c "pgrep oai_spgwu"
-            interval: 10s
-            timeout: 5s
-            retries: 5
-
-    flexran_rtc:
-        image: flexran-rtc:production
-        privileged: true
-        container_name: prod-flexran-rtc
-        networks:
-            public_net:
-                ipv4_address: 192.168.61.10
-        healthcheck:
-            test: /bin/bash -c "pgrep rt_controller"
-            interval: 10s
-            timeout: 5s
-            retries: 5
-
-    trf_gen:
-        image: trf-gen:production
-        privileged: true
-        container_name: prod-trf-gen
-        networks:
-            public_net:
-                ipv4_address: 192.168.61.11
-        entrypoint: /bin/bash -c "ip route add 12.1.1.0/24 via 192.168.61.5 dev eth0; sleep infinity"
-        healthcheck:
-            test: /bin/bash -c "ping -c 2 192.168.61.5"
-            interval: 10s
-            timeout: 5s
-            retries: 5
-
-networks:
-    private_net:
-        name: prod-oai-private-net
-        ipam:
-            config:
-                - subnet: 192.168.68.0/26
-    public_net:
-        name: prod-oai-public-net
-        ipam:
-            config:
-                - subnet: 192.168.61.0/26
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index fe91158e69ee9db6b117f97b92f45d7459b954e1..05ccf1655ae2f00eff473342ee03837d360eb171 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -49,6 +49,7 @@
 #include "SCHED_NR/fapi_nr_l1.h"
 #include "PHY/NR_TRANSPORT/nr_transport_proto.h"
 #include "PHY/MODULATION/nr_modulation.h"
+#include "PHY/NR_TRANSPORT/nr_dlsch.h"
 
 #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
 //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
@@ -115,19 +116,36 @@ time_stats_t softmodem_stats_rx_sf; // total rx time
 
 void tx_func(void *param) {
 
-  processingData_L1_t *info = (processingData_L1_t *) param;
+  processingData_L1tx_t *info = (processingData_L1tx_t *) param;
   PHY_VARS_gNB *gNB = info->gNB;
-  int frame_tx = info->frame_tx;
-  int slot_tx = info->slot_tx;
-
-  phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
-
-  // start FH TX processing
-  notifiedFIFO_elt_t *res; 
+  int frame_tx = info->frame;
+  int slot_tx = info->slot;
+
+  phy_procedures_gNB_TX(info,
+                        frame_tx,
+                        slot_tx,
+                        1);
+  info->slot = -1;
+  if ((frame_tx&127) == 0) dump_pdsch_stats(gNB);
+
+  // If the later of the 2 L1 tx thread finishes first,
+  // we wait for the earlier one to finish and start the RU thread
+  // to avoid realtime issues with USRP
+
+  // Start RU TX processing.
+  notifiedFIFO_elt_t *res;
   res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
   processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
+  LOG_D(PHY,"waiting for previous tx to finish, next slot %d,%d\n",syncMsg->next_slot,slot_tx);
+  while (syncMsg->next_slot != slot_tx) {
+    pushNotifiedFIFO(gNB->resp_RU_tx, res);
+    res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
+    syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
+  }
+  LOG_D(PHY,"previous tx finished, next slot %d,%d\n",syncMsg->next_slot,slot_tx);
   syncMsg->frame_tx = frame_tx;
   syncMsg->slot_tx = slot_tx;
+  syncMsg->next_slot = get_next_downlink_slot(gNB, &gNB->gNB_config, frame_tx, slot_tx);
   syncMsg->timestamp_tx = info->timestamp_tx;
   syncMsg->ru = gNB->RU_list[0];
   res->key = slot_tx;
@@ -202,13 +220,6 @@ void rx_func(void *param) {
         }
         up_removed++;
       }
-    for (j = 0; j < NUMBER_OF_NR_DLSCH_MAX; j++)
-      if (gNB->dlsch[j][0]->rnti == rnti_to_remove[i]) {
-        gNB->dlsch[j][0]->rnti = 0;
-        gNB->dlsch[j][0]->harq_mask = 0;
-        //clean_gNB_dlsch(gNB->dlsch[j][0]);
-        down_removed++;
-      }
     for (j = 0; j < NUMBER_OF_NR_PUCCH_MAX; j++)
       if (gNB->pucch[j]->active > 0 &&
           gNB->pucch[j]->pucch_pdu.rnti == rnti_to_remove[i]) {
@@ -256,7 +267,6 @@ void rx_func(void *param) {
   LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
 
   // Call the scheduler
-
   start_meas(&gNB->ul_indication_stats);
   pthread_mutex_lock(&gNB->UL_INFO_mutex);
   gNB->UL_INFO.frame     = frame_rx;
@@ -267,16 +277,17 @@ void rx_func(void *param) {
   pthread_mutex_unlock(&gNB->UL_INFO_mutex);
   stop_meas(&gNB->ul_indication_stats);
   
-  notifiedFIFO_elt_t *res; 
-
   if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
+    notifiedFIFO_elt_t *res;
     res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
-    processingData_L1_t *syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
+    processingData_L1tx_t *syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
+    while (syncMsg->slot != slot_tx) {
+      pushNotifiedFIFO(gNB->resp_L1_tx, res);
+      res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
+      syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
+    }
     syncMsg->gNB = gNB;
-    syncMsg->frame_rx = frame_rx;
-    syncMsg->slot_rx = slot_rx;
-    syncMsg->frame_tx = frame_tx;
-    syncMsg->slot_tx = slot_tx;
+    AssertFatal(syncMsg->slot == slot_tx, "Thread message slot and logical slot number do not match\n");
     syncMsg->timestamp_tx = info->timestamp_tx;
     res->key = slot_tx;
     pushTpool(gNB->threadPool, res);
@@ -326,7 +337,6 @@ static void *process_stats_thread(void *param) {
 
   PHY_VARS_gNB *gNB  = (PHY_VARS_gNB *)param;
 
-  reset_meas(&gNB->phy_proc_tx);
   reset_meas(&gNB->dlsch_encoding_stats);
   reset_meas(&gNB->phy_proc_rx);
   reset_meas(&gNB->ul_indication_stats);
@@ -338,7 +348,8 @@ static void *process_stats_thread(void *param) {
   while(!oai_exit)
   {
     sleep(1);
-    print_meas(&gNB->phy_proc_tx, "L1 Tx processing", NULL, NULL);
+    print_meas(gNB->phy_proc_tx_0, "L1 Tx processing thread 0", NULL, NULL);
+    print_meas(gNB->phy_proc_tx_1, "L1 Tx processing thread 1", NULL, NULL);
     print_meas(&gNB->dlsch_encoding_stats, "DLSCH encoding", NULL, NULL);
     print_meas(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL);
     print_meas(&gNB->ul_indication_stats, "UL Indication", NULL, NULL);
@@ -392,14 +403,38 @@ void init_gNB_Tpool(int inst) {
   // L1 RX result FIFO 
   gNB->resp_L1 = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
   initNotifiedFIFO(gNB->resp_L1);
+  notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func);
+  pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning
 
   // L1 TX result FIFO 
   gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
   initNotifiedFIFO(gNB->resp_L1_tx);
+  // we create 2 threads for L1 tx processing
+  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
+  processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
+  init_DLSCH_struct(gNB, msgDataTx);
+  msgDataTx->slot = -1;
+  memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
+  reset_meas(&msgDataTx->phy_proc_tx);
+  gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx;
+  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
+
+  msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
+  msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
+  init_DLSCH_struct(gNB, msgDataTx);
+  msgDataTx->slot = -1;
+  memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
+  reset_meas(&msgDataTx->phy_proc_tx);
+  gNB->phy_proc_tx_1 = &msgDataTx->phy_proc_tx;
+  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
 
   // RU TX result FIFO 
   gNB->resp_RU_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
   initNotifiedFIFO(gNB->resp_RU_tx);
+  notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_RU_t),0,gNB->resp_RU_tx,ru_tx_func);
+  processingData_RU_t *msgData = (processingData_RU_t*)msgRUTx->msgData;
+  msgData->next_slot = sf_ahead*gNB->frame_parms.slots_per_subframe; // first Tx slot
+  pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning
 
   // Stats measurement thread
   if(opp_enabled == 1) threadCreate(&proc->process_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
diff --git a/executables/nr-ru.c b/executables/nr-ru.c
index 20d4841196f2300c57aa1a77ee78f4037f737d69..e3c6a3d9648d0f5760ec836f2c8ade9903b65217 100644
--- a/executables/nr-ru.c
+++ b/executables/nr-ru.c
@@ -1303,14 +1303,9 @@ void *ru_thread( void *param ) {
   pthread_cond_signal(&RC.ru_cond);
   pthread_mutex_unlock(&RC.ru_mutex);
   wait_sync("ru_thread");
-  notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func);
-  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1_tx,tx_func);
-  notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func);
+
   processingData_L1_t *syncMsg;
   notifiedFIFO_elt_t *res;
-  pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning
-  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
-  pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning
 
   if(!emulate_rf) {
     // Start RF device if any
@@ -1453,9 +1448,15 @@ void *ru_thread( void *param ) {
     else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx);
   }
 
-  delNotifiedFIFO_elt(msg);
-  delNotifiedFIFO_elt(msgL1Tx);
-  delNotifiedFIFO_elt(msgRUTx);
+  res = pullNotifiedFIFO(gNB->resp_L1);
+  delNotifiedFIFO_elt(res);
+  res = pullNotifiedFIFO(gNB->resp_L1_tx);
+  delNotifiedFIFO_elt(res);
+  res = pullNotifiedFIFO(gNB->resp_L1_tx);
+  delNotifiedFIFO_elt(res);
+  res = pullNotifiedFIFO(gNB->resp_RU_tx);
+  delNotifiedFIFO_elt(res);
+
   ru_thread_status = 0;
   return &ru_thread_status;
 }
diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c
index 2b1900200a1c24c46a6178f106b85d8d57fbef64..4edbeee342d9ee69c93b6c3262e9ae52682b4a0c 100644
--- a/nfapi/oai_integration/nfapi_pnf.c
+++ b/nfapi/oai_integration/nfapi_pnf.c
@@ -1104,25 +1104,70 @@ void pnf_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header) {
   free(header);
 }
 
+notifiedFIFO_elt_t *l1tx_message_extract(PHY_VARS_gNB *gNB, int frame, int slot) {
+  notifiedFIFO_elt_t *res;
+  notifiedFIFO_elt_t *freeRes = NULL;
+
+  // check first message
+  res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
+  processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
+  if (msgTx->slot == slot) {
+    return res;
+  }
+  if (msgTx->slot == -1) {
+    freeRes = res;
+  }
+
+  // check second message
+  pushNotifiedFIFO(gNB->resp_L1_tx,res);
+  res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
+  msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
+  if (msgTx->slot == slot) {
+    return res;
+  }
+  if (msgTx->slot == -1) {
+    freeRes = res;
+  }
+
+  if (freeRes) {
+    msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
+    msgTx->num_pdsch_slot=0;
+    msgTx->pdcch_pdu.pdcch_pdu_rel15.numDlDci = 0;
+    msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci = 0;
+    msgTx->slot = slot;
+    msgTx->frame = frame;
+    return freeRes;
+  }
+  pushNotifiedFIFO(gNB->resp_L1_tx,res);
+  AssertFatal(1==0, "It means both L1 Tx messages are still waiting to be processed. This happens when L1 Tx processing is too slow. Message slot %d, scheduled slot %d\n",
+    msgTx->slot, slot);
+}
 
 int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_dci_request_t *req) {
   
   //   LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi);
 
   struct PHY_VARS_gNB_s *gNB = RC.gNB[0];
+
+  // extract the next available thread message (priority to message with current slot, then free message)
+  notifiedFIFO_elt_t *res;
+  res = l1tx_message_extract(gNB, req->SFN, req->Slot);
+  processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
+
   if (proc ==NULL) 
     proc = &gNB->proc.L1_proc;
 
-  for (int i=0; i<req->numPdus; i++) {
-    if (req->ul_dci_pdu_list[i].PDUType == 0) {
-      nfapi_nr_ul_dci_request_pdus_t *ul_dci_req_pdu = &req->ul_dci_pdu_list[i]; 
-      handle_nfapi_nr_ul_dci_pdu(gNB, req->SFN, req->Slot, ul_dci_req_pdu); 
+  if (req->numPdus > 0) {
+    if (req->ul_dci_pdu_list[req->numPdus-1].PDUType == 0) { // copy only the last PDU (PHY can have only one UL PDCCH pdu)
+      msgTx->ul_pdcch_pdu = req->ul_dci_pdu_list[req->numPdus-1]; // copy the last pdu
     } 
     else {
-      LOG_E(PHY,"[PNF] UL_DCI_REQ sfn_slot:%d PDU[%d] - unknown pdu type:%d\n", NFAPI_SFNSLOT2DEC(req->SFN, req->Slot), i, req->ul_dci_pdu_list[i].PDUType);
+      LOG_E(PHY,"[PNF] UL_DCI_REQ sfn_slot:%d PDU[%d] - unknown pdu type:%d\n", NFAPI_SFNSLOT2DEC(req->SFN, req->Slot), req->numPdus-1, req->ul_dci_pdu_list[req->numPdus-1].PDUType);
     }
   }
 
+  pushNotifiedFIFO(gNB->resp_L1_tx,res);
+
   return 0;
 }
 
@@ -1193,14 +1238,17 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7,
 
   for (int i=0; i<req->dl_tti_request_body.nPDUs; i++) {
     // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sfn/sf:%d PDU[%d] size:%d pdcch_vars->num_dci:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size,pdcch_vars->num_dci);
+    notifiedFIFO_elt_t *res;
+    res = l1tx_message_extract(gNB, sfn, slot);
+    processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
 
     if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE) {
-      nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu=&dl_tti_pdu_list[i];
-      handle_nfapi_nr_pdcch_pdu(gNB, sfn, slot, &dl_tti_pdu->pdcch_pdu);
+      // we trust the scheduler sends only one PDCCH PDU per slot
+      msgTx->pdcch_pdu = dl_tti_pdu_list[i].pdcch_pdu; // fills the last received PDCCH PDU
     } 
     else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) {
       //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PDU:%d BCH: pdu_index:%u pdu_length:%d sdu_length:%d BCH_SDU:%x,%x,%x\n", __FUNCTION__, i, pdu_index, bch_pdu->bch_pdu_rel8.length, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length, sdu[0], sdu[1], sdu[2]);
-      handle_nr_nfapi_ssb_pdu(gNB, sfn, slot, &dl_tti_pdu_list[i]);
+      handle_nr_nfapi_ssb_pdu(msgTx, sfn, slot, &dl_tti_pdu_list[i]);
       gNB->pbch_configured=1;
     } 
     else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) {
@@ -1209,21 +1257,11 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7,
       nfapi_nr_pdu_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex];
 
       if (tx_data != NULL) {
-        int UE_id = find_nr_dlsch(rel15_pdu->rnti,gNB,SEARCH_EXIST_OR_FREE);
-        AssertFatal(UE_id!=-1,"no free or exiting dlsch_context\n");
-        AssertFatal(UE_id<NUMBER_OF_UE_MAX,"returned UE_id %d >= %d(NUMBER_OF_UE_MAX)\n",UE_id,NUMBER_OF_UE_MAX);
-        NR_gNB_DLSCH_t *dlsch0 = gNB->dlsch[UE_id][0];
-        int harq_pid = dlsch0->harq_ids[sfn%2][slot];
-
-        if(harq_pid >= dlsch0->Mdlharq) {
-          LOG_E(PHY,"pnf_phy_dl_config_req illegal harq_pid %d\n", harq_pid);
-          return(-1);
-        }
-
-        uint8_t *dlsch_sdu = nr_tx_pdus[UE_id][harq_pid];
-        memcpy(dlsch_sdu, tx_data->TLVs[0].value.direct,tx_data->PDU_length);
+        uint8_t *dlsch_sdu = (uint8_t *)tx_data->TLVs[0].value.direct;
         //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() DLSCH:pdu_index:%d handle_nfapi_dlsch_pdu(eNB, proc_rxtx, dlsch_pdu, transport_blocks:%d sdu:%p) eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols:%d\n", __FUNCTION__, rel8_pdu->pdu_index, rel8_pdu->transport_blocks, dlsch_sdu, eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols);
-        handle_nr_nfapi_pdsch_pdu(gNB, sfn, slot,pdsch_pdu, dlsch_sdu);
+        AssertFatal(msgTx->num_pdsch_slot < gNB->number_of_nr_dlsch_max,"Number of PDSCH PDUs %d exceeded the limit %d\n",
+          msgTx->num_pdsch_slot,gNB->number_of_nr_dlsch_max);
+        handle_nr_nfapi_pdsch_pdu(msgTx, pdsch_pdu, dlsch_sdu);
       } 
       else {
         NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(sfn,slot), rel15_pdu->pduIndex);     
@@ -1231,11 +1269,12 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7,
     }
     else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE) {
       nfapi_nr_dl_tti_csi_rs_pdu *csi_rs_pdu = &dl_tti_pdu_list[i].csi_rs_pdu;
-      handle_nfapi_nr_csirs_pdu(gNB, sfn, slot, csi_rs_pdu);
+      handle_nfapi_nr_csirs_pdu(msgTx, sfn, slot, csi_rs_pdu);
     }
     else {
       NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() UNKNOWN:%d\n", __FUNCTION__, dl_tti_pdu_list[i].PDUType);
     }
+    pushNotifiedFIFO(gNB->resp_L1_tx,res);
   }
 
   if(req->vendor_extension)
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index a2c26e467b29b21ac101cfb62ad25eb982271813..c0236f521feb5f99a0bbe5c5de085ba11b0dd37e 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -519,45 +519,38 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
   LOG_I(PHY,"gNB %d configured\n",Mod_id);
 }
 
+void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) {
+  NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
+  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
+  uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value;
+  msg->num_pdsch_slot = 0;
+
+  for (int i=0; i<gNB->number_of_nr_dlsch_max; i++) {
+    LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d\n",i,gNB->number_of_nr_dlsch_max);
+    for (int j=0; j<2; j++) {
+      msg->dlsch[i][j] = new_gNB_dlsch(fp,1,16,NSOFT,0,grid_size);
+      AssertFatal(msg->dlsch[i][j]!=NULL,"Can't initialize dlsch %d \n", i);
+    }
+  }
+}
 
 void init_nr_transport(PHY_VARS_gNB *gNB) {
-  int i;
-  int j;
   NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
-  nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
   LOG_I(PHY, "Initialise nr transport\n");
-  uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value;
 
   memset(gNB->num_pdsch_rnti, 0, sizeof(uint16_t)*80);
 
-  for (i=0; i <NUMBER_OF_NR_PDCCH_MAX; i++) {
-    LOG_I(PHY,"Initializing PDCCH list for PDCCH %d/%d\n",i,NUMBER_OF_NR_PDCCH_MAX);
-    gNB->pdcch_pdu[i].frame=-1;
-    LOG_I(PHY,"Initializing UL PDCCH list for UL PDCCH %d/%d\n",i,NUMBER_OF_NR_PDCCH_MAX);
-    gNB->ul_pdcch_pdu[i].frame=-1;
-  }
-    
-  for (i=0; i<NUMBER_OF_NR_PUCCH_MAX; i++) {
+  for (int i=0; i<NUMBER_OF_NR_PUCCH_MAX; i++) {
     LOG_I(PHY,"Allocating Transport Channel Buffers for PUCCH %d/%d\n",i,NUMBER_OF_NR_PUCCH_MAX);
     gNB->pucch[i] = new_gNB_pucch();
     AssertFatal(gNB->pucch[i]!=NULL,"Can't initialize pucch %d \n", i);
   }
 
-  for (i=0; i<gNB->number_of_nr_dlsch_max; i++) {
-
-    LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d\n",i,gNB->number_of_nr_dlsch_max);
-
-    for (j=0; j<2; j++) {
-      gNB->dlsch[i][j] = new_gNB_dlsch(fp,1,16,NSOFT,0,grid_size);
-      AssertFatal(gNB->dlsch[i][j]!=NULL,"Can't initialize dlsch %d \n", i);
-    }
-  }
-
-  for (i=0; i<gNB->number_of_nr_ulsch_max; i++) {
+  for (int i=0; i<gNB->number_of_nr_ulsch_max; i++) {
 
     LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH  %d/%d\n",i,gNB->number_of_nr_ulsch_max);
 
-    for (j=0; j<2; j++) {
+    for (int j=0; j<2; j++) {
       // ULSCH for data
       gNB->ulsch[i][j] = new_gNB_ulsch(MAX_LDPC_ITERATIONS, fp->N_RB_UL, 0);
 
diff --git a/openair1/PHY/INIT/phy_init.h b/openair1/PHY/INIT/phy_init.h
index 85101a308052d01115f254a5362124e4a0f75514..dd9232de83ac744a38bf835cea367c8fec8d454b 100644
--- a/openair1/PHY/INIT/phy_init.h
+++ b/openair1/PHY/INIT/phy_init.h
@@ -409,6 +409,7 @@ void init_nr_transport(PHY_VARS_gNB *gNB);
 void init_dfts(void);
 
 void fill_subframe_mask(PHY_VARS_eNB *eNB);
+void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg);
 
 /** @} */
 #endif
diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c
index 020117adba6a495f9941a39eee38f5aee291bb0b..cfb5a2e56ebb799de3d119e54a12714cb51b18bb 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c
@@ -73,8 +73,9 @@ void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB) {
 
     int min_I0=1000,max_I0=0;
     int amin=0,amax=0;
+    fprintf(fd,"Blacklisted PRBs %d/%d\n",gNB->num_ulprbbl,gNB->frame_parms.N_RB_UL);
     for (int i=0; i<gNB->frame_parms.N_RB_UL; i++) {
-      if (i==(gNB->frame_parms.N_RB_UL>>1) - 1) i+=2;
+      if (gNB->ulprbbl[i] > 0) continue;	    
 
       if (gNB->measurements.n0_subband_power_tot_dB[i]<min_I0) {min_I0 = gNB->measurements.n0_subband_power_tot_dB[i]; amin=i;}
 
@@ -82,7 +83,8 @@ void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB) {
     }
 
     for (int i=0; i<gNB->frame_parms.N_RB_UL; i++) {
-     fprintf(fd,"%2d.",gNB->measurements.n0_subband_power_tot_dB[i]-gNB->measurements.n0_subband_power_avg_dB);
+     if (gNB->ulprbbl[i] ==0) fprintf(fd,"%2d.",gNB->measurements.n0_subband_power_tot_dB[i]-gNB->measurements.n0_subband_power_avg_dB);
+     else fprintf(fd," X."); 
      if (i%25 == 24) fprintf(fd,"\n");
     }
     fprintf(fd,"\n");
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c
index faa410b36adf8e7efa1f5e2663cef5014d6272f6..b58efb74f9c334586540ce7b2e2d9fdfa2b3413f 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dci.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c
@@ -134,8 +134,8 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
 						   dci_pdu->AggregationLevel,
 						   0,NULL);
     polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI,1,currentPtr);
-#ifdef DEBUG_CHANNEL_CODING
-    printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]);
+#if DEBUG_CHANNEL_CODING
+    printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,dci_pdu->AggregationLevel);
     printf("DCI PDU: [0]->0x%lx \t [1]->0x%lx\n",
 	   ((uint64_t*)dci_pdu->Payload)[0], ((uint64_t*)dci_pdu->Payload)[1]);
     printf("Encoded Payload (length:%d dwords):\n", encoded_length>>5);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
index c6103fbde11991eb3959ddf150c333840c174404..57fbae4481796a51d512eceafd51842e8ff1dafb 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
@@ -202,107 +202,3 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m,  nfapi_nr_dl_tti_pdcch_pdu_r
     ret |= ((field>>i)&1)<<(size-i-1);
   return ret;
 }*/
-int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) {
-
-  uint16_t i;
-  int16_t first_free_index=-1;
-
-  AssertFatal(gNB!=NULL,"gNB is null\n");
-  for (i=0; i<NUMBER_OF_NR_PDCCH_MAX; i++) {
-    LOG_D(PHY,"searching for frame.slot %d.%d : pdcch_index %d frame.slot %d.%d, first_free_index %d\n", frame,slot,i,gNB->pdcch_pdu[i].frame,gNB->pdcch_pdu[i].slot,first_free_index);
-    if ((gNB->pdcch_pdu[i].frame == frame) &&
-        (gNB->pdcch_pdu[i].slot==slot))       return i;
-    else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i;
-  }
-  if (type == SEARCH_EXIST) return -1;
-
-  return first_free_index;
-}
-
-
-void nr_fill_dci(PHY_VARS_gNB *gNB,
-                 int frame,
-                 int slot,
-		 nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu) {
-
-  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15;
-  NR_gNB_DLSCH_t *dlsch; 
-
-  int pdcch_id = find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST_OR_FREE);
-  AssertFatal(pdcch_id>=0 && pdcch_id<NUMBER_OF_NR_PDCCH_MAX,"Cannot find space for PDCCH, exiting\n");
-  memcpy((void*)&gNB->pdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu));
-  gNB->pdcch_pdu[pdcch_id].frame = frame;
-  gNB->pdcch_pdu[pdcch_id].slot  = slot;
-
-  for (int i=0;i<pdcch_pdu_rel15->numDlDci;i++) {
-
-    //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload;
-
-    int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu[i].RNTI,gNB,SEARCH_EXIST_OR_FREE);
-    if( (dlsch_id<0) || (dlsch_id>=gNB->number_of_nr_dlsch_max) ){
-      LOG_E(PHY,"illegal dlsch_id found!!! rnti %04x dlsch_id %d\n",(unsigned int)pdcch_pdu_rel15->dci_pdu[i].RNTI,dlsch_id);
-      return;
-    }
-    
-    dlsch = gNB->dlsch[dlsch_id][0];
-    int harq_pid = 0;
-
-    dlsch->slot_tx[slot]             = 1;
-    dlsch->harq_ids[frame % 2][slot] = 0;
-    AssertFatal(harq_pid < 8 && harq_pid >= 0,
-		"illegal harq_pid %d\n",harq_pid);
-    
-    dlsch->harq_mask                |= (1<<harq_pid);
-    dlsch->rnti                      = pdcch_pdu_rel15->dci_pdu[i].RNTI;
-    
-    //    nr_fill_cce_list(gNB,0);
-  }
-
-}
-
-
-int16_t find_nr_ul_dci(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) {
-
-  uint16_t i;
-  int16_t first_free_index=-1;
-
-  AssertFatal(gNB!=NULL,"gNB is null\n");
-  for (i=0; i<NUMBER_OF_NR_PDCCH_MAX; i++) {
-    LOG_D(PHY,"searching for frame.slot %d.%d : ul_pdcch_index %d frame.slot %d.%d, first_free_index %d\n", frame,slot,i,gNB->ul_pdcch_pdu[i].frame,gNB->ul_pdcch_pdu[i].slot,first_free_index);
-    if ((gNB->ul_pdcch_pdu[i].frame == frame) &&
-        (gNB->ul_pdcch_pdu[i].slot==slot))       return i;
-    else if (gNB->ul_pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i;
-  }
-  if (type == SEARCH_EXIST) return -1;
-
-  return first_free_index;
-}
-
-
-void nr_fill_ul_dci(PHY_VARS_gNB *gNB,
-		    int frame,
-		    int slot,
-		    nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu) {
-
-  nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
-
-  int pdcch_id = find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST_OR_FREE);
-  AssertFatal(pdcch_id>=0 && pdcch_id<NUMBER_OF_NR_PDCCH_MAX,"Cannot find space for UL PDCCH, exiting\n");
-  memcpy((void*)&gNB->ul_pdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu));
-  gNB->ul_pdcch_pdu[pdcch_id].frame = frame;
-  gNB->ul_pdcch_pdu[pdcch_id].slot  = slot;
-
-  for (int i=0;i<pdcch_pdu_rel15->numDlDci;i++) {
-
-    //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload;
-
-    // if there's no DL DCI then generate CCE list
-    //    nr_fill_cce_list(gNB,0);  
-    /*
-    LOG_D(PHY, "DCI PDU: [0]->0x%lx \t [1]->0x%lx \n",dci_pdu[0], dci_pdu[1]);
-    LOG_D(PHY, "DCI type %d payload (size %d) generated on candidate %d\n", dci_alloc->pdcch_params.dci_format, dci_alloc->size, cand_idx);
-    */
-
-  }
-
-}
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
index 5e00a372666a9701b523ad6356069faeece57969..ecc2cded11c530c980d693ce80be7e003cf0a696 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
@@ -111,10 +111,11 @@ void nr_pdsch_codeword_scrambling_optim(uint8_t *in,
 }
 
 
-uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
+uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
 			  int frame,
 			  int slot) {
 
+  PHY_VARS_gNB *gNB = msgTx->gNB;
   NR_gNB_DLSCH_t *dlsch;
   uint32_t ***pdsch_dmrs = gNB->nr_gold_pdsch_dmrs[slot];
   int32_t** txdataF = gNB->common_vars.txdataF;
@@ -132,9 +133,8 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
   time_stats_t *dlsch_interleaving_stats=&gNB->dlsch_interleaving_stats;
   time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats;
 
-  for (int dlsch_id=0;dlsch_id<gNB->number_of_nr_dlsch_max;dlsch_id++) {
-    dlsch = gNB->dlsch[dlsch_id][0];
-    if (dlsch->slot_tx[slot] == 0) continue;
+  for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
+    dlsch = msgTx->dlsch[dlsch_id][0];
 
     NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
     nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
index ec5bb997a08c2dbe804921ec03f1786e5102a963..4b6ecfe412ce642ba6d4fa86e00cd41fa68df4ad 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
@@ -63,13 +63,11 @@ void nr_pdsch_codeword_scrambling(uint8_t *in,
                                   uint32_t n_RNTI,
                                   uint32_t* out);
 
-void nr_fill_dlsch(PHY_VARS_gNB *gNB,
-                   int frame,
-                   int slot,
+void nr_fill_dlsch(processingData_L1tx_t *msgTx,
                    nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                    unsigned char *sdu); 
 
-uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
+uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
 			  int frame,
 			  int slot);
 void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c
index 543002827d65b9f36e9414c11d36e0705161b5b3..3ba13d2f44d10956512ce5aa9b7df32b1d15b975 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c
@@ -254,48 +254,16 @@ void nr_emulate_dlsch_payload(uint8_t* pdu, uint16_t size) {
     *(pdu+i) = (uint8_t)rand();
 }
 
-int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) {
- 
-   uint16_t i;
-   int16_t first_free_index=-1;
- 
-   AssertFatal(gNB!=NULL,"gNB is null\n");
-   for (i=0; i<gNB->number_of_nr_dlsch_max; i++) {
-     AssertFatal(gNB->dlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i);
-     AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i);
-     LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,
-	   gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index);
-     if ((gNB->dlsch[i][0]->harq_mask >0) &&
-	 (gNB->dlsch[i][0]->rnti==rnti))       return i;
-     else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i;
-   }
-   if (type == SEARCH_EXIST) return -1;
-   if (first_free_index != -1)
-     gNB->dlsch[first_free_index][0]->rnti = 0;
-   return first_free_index;
-   
-}
-
-
-void nr_fill_dlsch(PHY_VARS_gNB *gNB,
-                   int frame,
-                   int slot,
+void nr_fill_dlsch(processingData_L1tx_t *msgTx,
                    nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                    uint8_t *sdu) {
 
-  nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &pdsch_pdu->pdsch_pdu_rel15;
- 
-  int dlsch_id = find_nr_dlsch(rel15->rnti,gNB,SEARCH_EXIST);
-  AssertFatal( (dlsch_id>=0) && (dlsch_id<gNB->number_of_nr_dlsch_max),
-              "illegal or no dlsch_id found!!! rnti %04x dlsch_id %d\n",rel15->rnti,dlsch_id);
-  NR_gNB_DLSCH_t  *dlsch = gNB->dlsch[dlsch_id][0];
+  NR_gNB_DLSCH_t  *dlsch = msgTx->dlsch[msgTx->num_pdsch_slot][0];
   NR_DL_gNB_HARQ_t *harq  = &dlsch->harq_process;
   /// DLSCH struct
   memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu));
-  gNB->num_pdsch_rnti[slot]++;
+  msgTx->num_pdsch_slot++;
   AssertFatal(sdu!=NULL,"sdu is null\n");
   harq->pdu = sdu;
-
-
 }
 
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
index 90f49be16bef4ba361d7f0a18fce71dd441a19f0..8bbf569814795d36cb6ad4d94134264126ad6a4a 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
@@ -306,8 +306,8 @@ void nr_processULSegment(void* arg) {
   int max_ldpc_iterations = p_decoderParms->numMaxIter;
   int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32)));
 
-  int16_t  z [68*384];
-  int8_t   l [68*384];
+  int16_t  z [68*384 + 16] __attribute__ ((aligned(16)));
+  int8_t   l [68*384 + 16] __attribute__ ((aligned(16)));
 
   __m128i *pv = (__m128i*)&z;
   __m128i *pl = (__m128i*)&l;
diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h
index 66cb51adc607dabf4d08e661b582a19cbac042a3..76dd92ef5d03d6af5284991cfb3e966fae915c22 100644
--- a/openair1/PHY/defs_RU.h
+++ b/openair1/PHY/defs_RU.h
@@ -762,6 +762,7 @@ typedef struct RRU_config_s {
 typedef struct processingData_RU {
   int frame_tx;
   int slot_tx;
+  int next_slot;
   openair0_timestamp timestamp_tx;
   RU_t *ru;
 } processingData_RU_t;
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index 855eab216c3d7d0ed0349b5cdd7f8afa3a5c7bbd..11b5112a6cb37e006389c6cc6248a96e5c8e266b 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -122,8 +122,6 @@ typedef struct {
 
 typedef struct {
   uint8_t active;
-  int frame;
-  int slot;
   nfapi_nr_dl_tti_csi_rs_pdu csirs_pdu;
 } NR_gNB_CSIRS_t;
 
@@ -766,7 +764,6 @@ typedef struct PHY_VARS_gNB_s {
   //  nfapi_nr_dl_tti_pdcch_pdu    *pdcch_pdu;
   //  nfapi_nr_ul_dci_request_pdus_t  *ul_dci_pdu;
   uint16_t num_pdsch_rnti[80];
-  NR_gNB_SSB_t       ssb[64];
   NR_gNB_PBCH        pbch;
   nr_cce_t           cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL];
   NR_gNB_COMMON      common_vars;
@@ -774,7 +771,6 @@ typedef struct PHY_VARS_gNB_s {
   NR_gNB_PUSCH       *pusch_vars[NUMBER_OF_NR_ULSCH_MAX];
   NR_gNB_PUCCH_t     *pucch[NUMBER_OF_NR_PUCCH_MAX];
   NR_gNB_PDCCH_t     pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX];
-  NR_gNB_CSIRS_t     csirs_pdu[NUMBER_OF_NR_CSIRS_MAX];
   NR_gNB_UL_PDCCH_t  ul_pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX];
   NR_gNB_DLSCH_t     *dlsch[NUMBER_OF_NR_DLSCH_MAX][2];    // Nusers times two spatial streams
   NR_gNB_ULSCH_t     *ulsch[NUMBER_OF_NR_ULSCH_MAX][2];  // [Nusers times][2 codewords] 
@@ -857,10 +853,13 @@ typedef struct PHY_VARS_gNB_s {
   int pusch_thres;
   int prach_thres;
   uint64_t bad_pucch;
+  int num_ulprbbl;
+  int ulprbbl[275];
   /*
   time_stats_t phy_proc;
   */
-  time_stats_t phy_proc_tx;
+  time_stats_t *phy_proc_tx_0;
+  time_stats_t *phy_proc_tx_1;
   time_stats_t phy_proc_rx;
   time_stats_t rx_prach;
   /*
@@ -952,4 +951,24 @@ typedef struct processingData_L1 {
   PHY_VARS_gNB *gNB;
 } processingData_L1_t;
 
+typedef enum {
+  FILLED,
+  FILLING,
+  NOT_FILLED
+} msgStatus_t;
+
+typedef struct processingData_L1tx {
+  int frame;
+  int slot;
+  openair0_timestamp timestamp_tx;
+  PHY_VARS_gNB *gNB;
+  nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu;
+  nfapi_nr_ul_dci_request_pdus_t ul_pdcch_pdu;
+  NR_gNB_CSIRS_t csirs_pdu[NUMBER_OF_NR_CSIRS_MAX];
+  NR_gNB_DLSCH_t *dlsch[NUMBER_OF_NR_DLSCH_MAX][2];
+  NR_gNB_SSB_t ssb[64];
+  uint16_t num_pdsch_slot;
+  time_stats_t phy_proc_tx;
+} processingData_L1tx_t;
+
 #endif
diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c
index 7d1e7e76843e02f791238f474d8373167e4eca86..4e82c3ecb3e2734b1780eb0dfe7d477cf14c6f64 100644
--- a/openair1/SCHED/nfapi_lte_dummy.c
+++ b/openair1/SCHED/nfapi_lte_dummy.c
@@ -13,11 +13,11 @@ void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
                              nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){}
 
 int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type){return 0;}
-void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
-                            nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
+void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx,
+			       nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                             uint8_t *sdu){
-                            }
-void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB,
+}
+void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx,
 			       int frame, int slot,
 			       nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){
                     }                           
@@ -51,4 +51,5 @@ void  nr_phy_config_request(NR_PHY_Config_t *gNB){}
 
 void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){}
 
-void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){}
\ No newline at end of file
+void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){}
+
diff --git a/openair1/SCHED/nfapi_nr_dummy.c b/openair1/SCHED/nfapi_nr_dummy.c
index 1286a4e48a270c15e13a4c3b6153732bd3fe8b08..511911723ff27005e633305e5744f5b29601324f 100644
--- a/openair1/SCHED/nfapi_nr_dummy.c
+++ b/openair1/SCHED/nfapi_nr_dummy.c
@@ -13,11 +13,11 @@ void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
                              nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){}
 
 int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type){return 0;}
-void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
-                            nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
+void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx,
+			       nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                             uint8_t *sdu){
-                            }
-void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB,
+}
+void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx,
 			       int frame, int slot,
 			       nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){
                     }
@@ -53,4 +53,3 @@ void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){}
 
 //void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){}
 
-                   
\ No newline at end of file
diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c
index b2a802ab0875a71cbf9917bb092b152984d36de8..3a7b630d0965a237b3c3fbed47357d3193bc3a29 100644
--- a/openair1/SCHED_NR/fapi_nr_l1.c
+++ b/openair1/SCHED_NR/fapi_nr_l1.c
@@ -43,7 +43,7 @@ extern int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req);
 
 extern uint8_t nfapi_mode;
 
-void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
+void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot,
                              nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu)
 {
 
@@ -53,11 +53,11 @@ void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
   uint8_t i_ssb = dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex;
 
   LOG_D(PHY,"%d.%d : ssb index %d pbch_pdu: %x\n",frame,slot,i_ssb,dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload);
-  if (gNB->ssb[i_ssb].active)
+  if (msgTx->ssb[i_ssb].active)
     AssertFatal(1==0,"SSB PDU with index %d already active\n",i_ssb);
   else {
-    gNB->ssb[i_ssb].active = true;
-    memcpy((void*)&gNB->ssb[i_ssb].ssb_pdu,&dl_tti_pdu->ssb_pdu,sizeof(dl_tti_pdu->ssb_pdu));
+    msgTx->ssb[i_ssb].active = true;
+    memcpy((void*)&msgTx->ssb[i_ssb].ssb_pdu,&dl_tti_pdu->ssb_pdu,sizeof(dl_tti_pdu->ssb_pdu));
   }
 }
 
@@ -100,46 +100,16 @@ void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
 }*/
 
 
-void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB,
-			       int frame, int slot,
-			       nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu) {
-
-  LOG_D(PHY,"Frame %d, Slot %d: DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci);
-
-  // copy dci configuration into gNB structure
-  //  gNB->pdcch_pdu = pdcch_pdu;
-
-  nr_fill_dci(gNB,frame,slot,pdcch_pdu);
-
-}
-
-
-void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB,
-			       int frame, int slot,
-			       nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu) {
-
-  LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci);
-
-  // copy dci configuration into gNB structure
-  //  gNB->ul_dci_pdu = ul_dci_request_pdu;
-
-  nr_fill_ul_dci(gNB,frame,slot,ul_dci_request_pdu);
-
-}
-
-
-void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB,
-			       int frame, int slot,
+void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx,
+             int frame,int slot,
 			       nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu) {
 
   int found = 0;
 
   for (int id=0; id<NUMBER_OF_NR_CSIRS_MAX; id++) {
-    NR_gNB_CSIRS_t *csirs = &gNB->csirs_pdu[id];
+    NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[id];
     if (csirs->active == 0) {
       LOG_D(PHY,"Frame %d Slot %d CSI_RS with ID %d is now active\n",frame,slot,id);
-      csirs->frame = frame;
-      csirs->slot = slot;
       csirs->active = 1;
       memcpy((void*)&csirs->csirs_pdu, (void*)csirs_pdu, sizeof(nfapi_nr_dl_tti_csi_rs_pdu));
       found = 1;
@@ -151,13 +121,13 @@ void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB,
 }
 
 
-void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
+void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx,
                             nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                             uint8_t *sdu)
 {
 
 
-  nr_fill_dlsch(gNB,frame,slot,pdsch_pdu,sdu);
+  nr_fill_dlsch(msgTx,pdsch_pdu,sdu);
 
 }
 
@@ -178,6 +148,10 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
 
   gNB         = RC.gNB[Mod_id];
 
+  notifiedFIFO_elt_t *res;
+  res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
+  processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
+
   uint8_t number_dl_pdu             = (DL_req==NULL) ? 0 : DL_req->dl_tti_request_body.nPDUs;
   uint8_t number_ul_dci_pdu         = (UL_dci_req==NULL) ? 0 : UL_dci_req->numPdus;
   uint8_t number_ul_tti_pdu         = (UL_tti_req==NULL) ? 0 : UL_tti_req->n_pdus;
@@ -192,33 +166,31 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
       number_ul_dci_pdu,number_ul_tti_pdu);
 
     int pdcch_received=0;
-    gNB->num_pdsch_rnti[slot]=0;
-    for (int i=0; i<gNB->number_of_nr_dlsch_max; i++) {
-      gNB->dlsch[i][0]->rnti=0;
-      gNB->dlsch[i][0]->harq_mask=0;
-    }
+    msgTx->num_pdsch_slot=0;
+    msgTx->pdcch_pdu.pdcch_pdu_rel15.numDlDci = 0;
+    msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci = 0;
+    msgTx->slot = slot;
+    msgTx->frame = frame;
 
     for (int i=0;i<number_dl_pdu;i++) {
       nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i];
       LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType);
       switch (dl_tti_pdu->PDUType) {
         case NFAPI_NR_DL_TTI_SSB_PDU_TYPE:
-          handle_nr_nfapi_ssb_pdu(gNB,frame,slot,
+          handle_nr_nfapi_ssb_pdu(msgTx,frame,slot,
                                   dl_tti_pdu);
           break;
 
         case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE:
           AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n");
-          handle_nfapi_nr_pdcch_pdu(gNB,
-            frame, slot,
-            &dl_tti_pdu->pdcch_pdu);
+          msgTx->pdcch_pdu = dl_tti_pdu->pdcch_pdu;
+
           pdcch_received = 1;
           break;
 
         case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE:
           LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot);
-          handle_nfapi_nr_csirs_pdu(gNB,
-            frame, slot,
+          handle_nfapi_nr_csirs_pdu(msgTx,frame,slot,
             &dl_tti_pdu->csi_rs_pdu);
           break;
 
@@ -229,15 +201,16 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
           AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n",
           pduIndex,TX_req->pdu_list[pduIndex].num_TLV);
           uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct;
-          handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu);
-          break;
+          AssertFatal(msgTx->num_pdsch_slot < gNB->number_of_nr_dlsch_max,"Number of PDSCH PDUs %d exceeded the limit %d\n",
+            msgTx->num_pdsch_slot,gNB->number_of_nr_dlsch_max);
+          handle_nr_nfapi_pdsch_pdu(msgTx,&dl_tti_pdu->pdsch_pdu, sdu);
       }
     }
 
+    if (number_ul_dci_pdu > 0)
+      msgTx->ul_pdcch_pdu = UL_dci_req->ul_dci_pdu_list[number_ul_dci_pdu-1]; // copy the last pdu
 
-    for (int i=0;i<number_ul_dci_pdu;i++) {
-      handle_nfapi_nr_ul_dci_pdu(gNB, frame, slot, &UL_dci_req->ul_dci_pdu_list[i]);
-    }
+    pushNotifiedFIFO(gNB->resp_L1_tx,res);
 
     for (int i = 0; i < number_ul_tti_pdu; i++) {
       switch (UL_tti_req->pdus_list[i].pdu_type) {
diff --git a/openair1/SCHED_NR/fapi_nr_l1.h b/openair1/SCHED_NR/fapi_nr_l1.h
index d9d152a797007d2a86ab9ce359df5db8d321968d..f598b263c336d1918715129eee6e11c1f4d37d26 100644
--- a/openair1/SCHED_NR/fapi_nr_l1.h
+++ b/openair1/SCHED_NR/fapi_nr_l1.h
@@ -37,13 +37,13 @@
 #include "nfapi_nr_interface_scf.h"
 
 // added
-void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,
+void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,
 						int frame,int slot,
 						nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu);
 
 void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO);
 
-void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB,
+void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx,
 			       int frame, int slot,
 			       nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu);
 
@@ -51,7 +51,7 @@ void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB,
 			       int frame, int subframe,
 			       nfapi_nr_dl_tti_pdcch_pdu *dcl_dl_pdu);
 
-void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
+void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx,
 			       nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                             uint8_t *sdu);
 
diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c
index 9be678059710977f460be65f0aa2aa294ccf6ac0..25c39846fe0e57ef492b362fe089906c0eb43ecf 100644
--- a/openair1/SCHED_NR/phy_frame_config_nr.c
+++ b/openair1/SCHED_NR/phy_frame_config_nr.c
@@ -30,6 +30,7 @@
 ************************************************************************/
 
 #include "PHY/defs_nr_common.h"
+#include "PHY/defs_gNB.h"
 #include "PHY/defs_nr_UE.h"
 #include "SCHED_NR/phy_frame_config_nr.h"
 
@@ -308,6 +309,21 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms) {
 *
 *********************************************************************/
 
+int get_next_downlink_slot(PHY_VARS_gNB *gNB, nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) {
+
+  int slot = nr_slot;
+  int frame = nr_frame;
+  int slots_per_frame = gNB->frame_parms.slots_per_frame;
+  while (true) {
+    slot++;
+    if (slot/slots_per_frame) frame++;
+    slot %= slots_per_frame;
+    int slot_type = nr_slot_select(cfg, frame, slot);
+    if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) return slot;
+    AssertFatal(frame < (nr_frame+2), "Something went worng. This shouldn't happen\n");
+  }
+}
+
 int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) {
   /* for FFD all slot can be considered as an uplink */
   int mu = cfg->ssb_config.scs_common.value,check_slot=0;
diff --git a/openair1/SCHED_NR/phy_frame_config_nr.h b/openair1/SCHED_NR/phy_frame_config_nr.h
index 434dc41d1f5901e1986dc6d6074186c4d847e177..aba26283ed0be2f0dc213fe9721c0ca22c00180c 100644
--- a/openair1/SCHED_NR/phy_frame_config_nr.h
+++ b/openair1/SCHED_NR/phy_frame_config_nr.h
@@ -92,5 +92,7 @@ void free_tdd_configuration_nr(NR_DL_FRAME_PARMS *frame_parms);
 
 void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms);
 
+int get_next_downlink_slot(PHY_VARS_gNB *gNB, nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot);
+
 #endif  /* PHY_FRAME_CONFIG_NR_H */
 
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 2e79b9e509a2cd05d44081d1eaf3dbe03b314d42..d6b9e01a96089021bb957cb060883e9745eadccf 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -65,7 +65,7 @@ void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME
 
   fp->ssb_start_subcarrier = (12 * cfg->ssb_table.ssb_offset_point_a.value + sco);
   LOG_D(PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier,cfg->ssb_table.ssb_offset_point_a.value,sco);
-}   
+}
 
 void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_dl_tti_ssb_pdu ssb_pdu) {
 
@@ -124,10 +124,12 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_
 }
 
 
-void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
-                           int frame,int slot,
+void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
+                           int frame,
+                           int slot,
                            int do_meas) {
   int aa;
+  PHY_VARS_gNB *gNB = msgTx->gNB;
   NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
   nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
   int offset = gNB->CC_id;
@@ -138,7 +140,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,1);
 
-  if (do_meas==1) start_meas(&gNB->phy_proc_tx);
+  if (do_meas==1) start_meas(&msgTx->phy_proc_tx);
 
   // clear the transmit data array and beam index for the current slot
   for (aa=0; aa<cfg->carrier_config.num_tx_ant.value; aa++) {
@@ -147,58 +149,44 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
   }
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1);
-
   for (int i=0; i<fp->Lmax; i++) {
-    if (gNB->ssb[i].active) {
-      nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[i].ssb_pdu);
-      gNB->ssb[i].active = false;
+    if (msgTx->ssb[i].active) {
+      nr_common_signal_procedures(gNB,frame,slot,msgTx->ssb[i].ssb_pdu);
+      msgTx->ssb[i].active = false;
     }
   }
   
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0);
 
-  int pdcch_pdu_id=find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST);
-  int ul_pdcch_pdu_id=find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST);
-
-  LOG_D(PHY,"[gNB %d] Frame %d slot %d, pdcch_pdu_id %d, ul_pdcch_pdu_id %d\n",
-	gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id);
+  int num_dl_dci = msgTx->pdcch_pdu.pdcch_pdu_rel15.numDlDci;
+  int num_ul_dci = msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci;
 
-  if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) {
+  if (num_dl_dci > 0 || num_ul_dci > 0) {
     LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n",
-	  gNB->Mod_id, frame, slot,
-	  gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci,
-	  gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu.pdcch_pdu_rel15.numDlDci);
+	  gNB->Mod_id, frame, slot, num_ul_dci, num_dl_dci);
   
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1);
 
     nr_generate_dci_top(gNB,
-			pdcch_pdu_id>=0 ? &gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu : NULL,
-			ul_pdcch_pdu_id>=0 ? &gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu : NULL,
+			num_dl_dci > 0 ? &msgTx->pdcch_pdu : NULL,
+			num_ul_dci > 0 ? &msgTx->ul_pdcch_pdu.pdcch_pdu : NULL,
 			gNB->nr_gold_pdcch_dmrs[slot],
 			&gNB->common_vars.txdataF[0][txdataF_offset],
 			AMP, fp);
 
-    // free up entry in pdcch tables
-    if (pdcch_pdu_id>=0) gNB->pdcch_pdu[pdcch_pdu_id].frame = -1;
-    if (ul_pdcch_pdu_id>=0) gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].frame = -1;
-
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0);
-    if (pdcch_pdu_id >= 0) gNB->pdcch_pdu[pdcch_pdu_id].frame = -1;
-    if (ul_pdcch_pdu_id >= 0) gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].frame = -1;
   }
  
-  for (int i=0; i<gNB->num_pdsch_rnti[slot]; i++) {
+  if (msgTx->num_pdsch_slot > 0) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
-    LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", gNB->num_pdsch_rnti[slot],frame,slot);
-    nr_generate_pdsch(gNB,frame, slot);
+    LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", msgTx->num_pdsch_slot,frame,slot);
+    nr_generate_pdsch(msgTx, frame, slot);
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
   }
 
   for (int i=0;i<NUMBER_OF_NR_CSIRS_MAX;i++){
-    NR_gNB_CSIRS_t *csirs = &gNB->csirs_pdu[i];
-    if ((csirs->active == 1) &&
-	(csirs->frame == frame) &&
-	(csirs->slot == slot) ) {
+    NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[i];
+    if ((csirs->active == 1)) {
       LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot);
       nfapi_nr_dl_tti_csi_rs_pdu_rel15_t csi_params = csirs->csirs_pdu.csi_rs_pdu_rel15;
       nr_generate_csi_rs(gNB, AMP, csi_params, gNB->gNB_config.cell_config.phy_cell_id.value, slot);
@@ -206,7 +194,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
     }
   }
 
-  if (do_meas==1) stop_meas(&gNB->phy_proc_tx);
+  if (do_meas==1) stop_meas(&msgTx->phy_proc_tx);
 
 //  if ((frame&127) == 0) dump_pdsch_stats(gNB);
 
@@ -262,7 +250,7 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) {
   }
 
   //int dumpsig=0;
-  // if all segments are done 
+  // if all segments are done
   if (rdata->nbSegments == ulsch_harq->processedSegments) {
     if (decodeSuccess) {
       LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation (all seg) %d)\n",
@@ -275,9 +263,15 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) {
       nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 0,0);
       //dumpsig=1;
     } else {
-      LOG_D(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, TBS %d) r %d\n",
+      LOG_I(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, TBS %d) r %d\n",
             gNB->Mod_id, ulsch_harq->frame, ulsch_harq->slot,
-            rdata->harq_pid,pusch_pdu->pusch_data.new_data_indicator,ulsch_harq->status, ulsch_harq->round, ulsch_harq->ulsch_pdu.pusch_data.rv_index,ulsch_harq->TBS,r);
+            rdata->harq_pid, pusch_pdu->pusch_data.new_data_indicator, ulsch_harq->status,
+	          ulsch_harq->round,
+            ulsch_harq->ulsch_pdu.pusch_data.rv_index,
+	          ulsch_harq->ulsch_pdu.rb_start,
+	          ulsch_harq->ulsch_pdu.rb_size,
+	          ulsch_harq->TBS,
+	          r);
       ulsch_harq->round++;
       if (ulsch_harq->round >= ulsch->Mlimit) {
         ulsch_harq->status = SCH_IDLE;
@@ -290,7 +284,7 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) {
       LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
       nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 1,0);
     }
-/*    
+/*
     if (ulsch_harq->ulsch_pdu.mcs_index == 9 && dumpsig==1) {
 #ifdef __AVX2__
       int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0;
@@ -492,8 +486,8 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id,
       }
       exit(-1);
 
-    } 
- 
+    }
+
   // crc indication
   uint16_t num_crc = gNB->UL_INFO.crc_ind.number_crcs;
   gNB->UL_INFO.crc_ind.crc_list = &gNB->crc_pdu_list[0];
@@ -538,11 +532,20 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id,
 // Function to fill UL RB mask to be used for N0 measurements
 void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
 
-  int rb = 0;
-  int rb2 = 0;
-
-  for (int symbol=0;symbol<14;symbol++)
-    for (int m=0;m<9;m++) gNB->rb_mask_ul[symbol][m] = 0;
+  int rb2, rb, nb_rb;
+  int prbpos;
+  for (int symbol=0;symbol<14;symbol++) {
+    if (gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol].slot_config.value==1){
+      nb_rb = 0;
+      for (int m=0;m<9;m++) {
+	 gNB->rb_mask_ul[m] = 0;
+	 for (int i=0;i<32;i++) {
+          prbpos = (m*32)+i;
+          if (prbpos>gNB->frame_parms.N_RB_UL) break;
+          gNB->rb_mask_ul[m] |= (gNB->ulprbbl[prbpos]>0 ? 1 : 0)<<i;
+         }
+      }
+      gNB->ulmask_symb = -1;
 
   for (int i=0;i<NUMBER_OF_NR_PUCCH_MAX;i++){
     NR_gNB_PUCCH_t *pucch = gNB->pucch[i];
@@ -679,7 +682,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
           LOG_D(PHY,"frame %d, slot %d: PUCCH signal energy %d\n",frame_rx,slot_rx,power_rxF);
 
           nr_decode_pucch0(gNB,
-	                   frame_rx,
+                           frame_rx,
                            slot_rx,
                            uci_pdu_format0,
                            pucch_pdu);
diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h
index 5e31c08d389bfda7056b4ddc982d27277950b05e..d7e0332b85a5865b87814896ad24fe8deef8a38d 100644
--- a/openair1/SCHED_NR/sched_nr.h
+++ b/openair1/SCHED_NR/sched_nr.h
@@ -36,7 +36,7 @@
 
 void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
 void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME_PARMS *fp);
-void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int frame_tx, int slot_tx, int do_meas);
+void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, int frame_tx, int slot_tx, int do_meas);
 void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
 int  phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
 void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot);
diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c
index 633a214699ae8bd82daff00d7356c0ac239becce..a0e0183fd1f288e2363205254e0ac15a9ad2585a 100644
--- a/openair1/SIMULATION/NR_PHY/dlschsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlschsim.c
@@ -426,7 +426,9 @@ int main(int argc, char **argv)
 	UE->dlsch_SI[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0);
 	UE->dlsch_ra[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0);
 	unsigned char harq_pid = 0; //dlsch->harq_ids[subframe];
-	NR_gNB_DLSCH_t *dlsch = gNB->dlsch[0][0];
+  processingData_L1tx_t msgDataTx;
+  init_DLSCH_struct(gNB, &msgDataTx);
+	NR_gNB_DLSCH_t *dlsch = msgDataTx.dlsch[0][0];
 	nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
 	//time_stats_t *rm_stats, *te_stats, *i_stats;
 	uint8_t is_crnti = 0, llr8_flag = 0;
@@ -634,7 +636,7 @@ int main(int argc, char **argv)
 
 	for (i = 0; i < 2; i++) {
 		printf("gNB %d\n", i);
-		free_gNB_dlsch(&(gNB->dlsch[0][i]),N_RB_DL);
+		free_gNB_dlsch(&(msgDataTx.dlsch[0][i]),N_RB_DL);
 		printf("UE %d\n", i);
 		free_nr_ue_dlsch(&(UE->dlsch[0][0][i]),N_RB_DL);
 	}
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index e80fc7c7e6c4af26a47c593690d40a695dcb8c4a..83d662583017dadc28de44dd900f786c6c54eac6 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -933,8 +933,6 @@ int main(int argc, char **argv)
   // generate signal
   AssertFatal(input_fd==NULL,"Not ready for input signal file\n");
   gNB->pbch_configured = 1;
-  gNB->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234;
-  gNB->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
 
   //Configure UE
   rrc.carrier.MIB = (uint8_t*) malloc(4);
@@ -964,11 +962,25 @@ int main(int argc, char **argv)
   //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
   snrRun = 0;
 
+  gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
+  char tp_param[] = "n";
+  initTpool(tp_param, gNB->threadPool, true);
+  gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
+  initNotifiedFIFO(gNB->resp_L1_tx);
+  // we create 2 threads for L1 tx processing
+  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,processSlotTX);
+  processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
+  init_DLSCH_struct(gNB, msgDataTx);
+  msgDataTx->slot = slot;
+  msgDataTx->frame = frame;
+  memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
+  reset_meas(&msgDataTx->phy_proc_tx);
+  gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx;
+  pushTpool(gNB->threadPool,msgL1Tx);
 
   for (SNR = snr0; SNR < snr1; SNR += .2) {
 
     varArray_t *table_tx=initVarArray(1000,sizeof(double));
-    reset_meas(&gNB->phy_proc_tx); // total gNB tx
     reset_meas(&gNB->dlsch_scrambling_stats);
     reset_meas(&gNB->dlsch_interleaving_stats);
     reset_meas(&gNB->dlsch_rate_matching_stats);
@@ -1009,7 +1021,7 @@ int main(int argc, char **argv)
       int harq_pid = slot;
       NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];
 
-      NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0];
+      NR_gNB_DLSCH_t *gNB_dlsch = msgDataTx->dlsch[0][0];
       nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
       
       UE_harq_process->ack = 0;
@@ -1060,10 +1072,14 @@ int main(int argc, char **argv)
           ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1)/rel15->PTRSFreqDensity);
           printf("[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb );
         }
+
+        msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234;
+        msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
+        msgDataTx->gNB = gNB;
         if (run_initial_sync)
-          nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[0].ssb_pdu);
+          nr_common_signal_procedures(gNB,frame,slot,msgDataTx->ssb[0].ssb_pdu);
         else
-          phy_procedures_gNB_TX(gNB,frame,slot,1);
+          phy_procedures_gNB_TX(msgDataTx,frame,slot,1);
             
         int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP;
         
@@ -1272,10 +1288,10 @@ int main(int argc, char **argv)
     if (print_perf==1) {
       printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n",
 	     1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex,
-	     gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
-	     gNB->dlsch[0][0]->harq_process.K,
-	     gNB->dlsch[0][0]->harq_process.K/((gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
-      printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
+	     msgDataTx->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
+	     msgDataTx->dlsch[0][0]->harq_process.K,
+	     msgDataTx->dlsch[0][0]->harq_process.K/((msgDataTx->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
+      printDistribution(gNB->phy_proc_tx_0,table_tx,"PHY proc tx");
       printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
       printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time");
       printStatIndent3(&gNB->tinput,"DLSCH LDPC input processing time");
diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c
index 46b42666b58746a5b85a2bff4f97d111645adc07..8f4f227f6ca95ef3ce94747d0e501947b4428fd7 100644
--- a/openair1/SIMULATION/NR_PHY/pbchsim.c
+++ b/openair1/SIMULATION/NR_PHY/pbchsim.c
@@ -565,14 +565,15 @@ int main(int argc, char **argv)
 
   nr_gold_pbch(UE);
 
+  processingData_L1tx_t msgDataTx;
   // generate signal
   if (input_fd==NULL) {
 
     for (i=0; i<frame_parms->Lmax; i++) {
       if((SSB_positions >> i) & 0x01) {
 
-        gNB->ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33;
-        gNB->ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i;
+        msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33;
+        msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i;
 
         start_symbol = nr_get_ssb_start_symbol(frame_parms,i);
         int slot = start_symbol/14;
@@ -580,7 +581,7 @@ int main(int argc, char **argv)
         for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++)
           memset(gNB->common_vars.txdataF[aa],0,frame_parms->samples_per_slot_wCP*sizeof(int32_t));
 
-        nr_common_signal_procedures (gNB,frame,slot,gNB->ssb[i].ssb_pdu);
+        nr_common_signal_procedures (gNB,frame,slot,msgDataTx.ssb[i].ssb_pdu);
 
         for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
           if (cyclic_prefix_type == 1) {
@@ -750,7 +751,7 @@ int main(int argc, char **argv)
  
 	  payload_ret = (UE->pbch_vars[0]->xtra_byte == gNB_xtra_byte);
 	  for (i=0;i<3;i++){
-	    payload_ret += (UE->pbch_vars[0]->decoded_output[i] == ((gNB->ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff));
+	    payload_ret += (UE->pbch_vars[0]->decoded_output[i] == ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff));
 	  } 
 	  //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->pbch_vars[0]->xtra_byte);
 	  //printf("ret %d\n", payload_ret);
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index 296555ef475b19f015b895d78424fd3e44954927..69316d6b884c21dab4290b0e505dff962799f462 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -665,6 +665,13 @@ int main(int argc, char **argv)
   char tp_param[] = "n";
   initTpool(tp_param, gNB->threadPool, false);
   initNotifiedFIFO(gNB->respDecode);
+  gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
+  initNotifiedFIFO(gNB->resp_L1_tx);
+  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,NULL);
+  processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
+  msgDataTx->slot = -1;
+  gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx;
+  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
   //gNB_config = &gNB->gNB_config;
 
   //memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 209cdd255dca697aface5b4a6a9bded002e0954a..af21fd8b084b48a30c13152f365660497b4ae093 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -549,6 +549,32 @@ void RCconfig_nr_flexran()
 
 void RCconfig_NR_L1(void) {
   int j;
+  paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
+  ////////// Identification parameters
+  paramdef_t GNBParams[]  = GNBPARAMS_DESC;
+
+  paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
+
+  config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); 
+  int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
+  AssertFatal (num_gnbs > 0,"Failed to parse config file no gnbs %s \n",GNB_CONFIG_STRING_ACTIVE_GNBS);
+
+  config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); 
+  char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr; 
+  if (ulprbbl) LOG_I(NR_PHY,"PRB blacklist %s\n",ulprbbl);
+  char *pt = strtok(ulprbbl,",");
+  int prbbl[275];
+  int num_prbbl=0;
+  memset(prbbl,0,275*sizeof(int));
+
+  while (pt) {
+    prbbl[atoi(pt)] = 1;
+    LOG_I(NR_PHY,"Blacklisting prb %d\n",atoi(pt));
+    pt = strtok(NULL,",");
+    num_prbbl++;
+  }
+
+  
   paramdef_t L1_Params[] = L1PARAMS_DESC;
   paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST,NULL,0};
 
@@ -577,6 +603,9 @@ void RCconfig_NR_L1(void) {
       RC.gNB[j]->pucch0_thres       = *(L1_ParamList.paramarray[j][L1_PUCCH0_DTX_THRESHOLD].uptr);
       RC.gNB[j]->prach_thres        = *(L1_ParamList.paramarray[j][L1_PRACH_DTX_THRESHOLD].uptr);
       RC.gNB[j]->pusch_thres        = *(L1_ParamList.paramarray[j][L1_PUSCH_DTX_THRESHOLD].uptr);
+      RC.gNB[j]->num_ulprbbl        = num_prbbl;
+      LOG_I(NR_PHY,"Copying %d blacklisted PRB to L1 context\n",num_prbbl);
+      memcpy(RC.gNB[j]->ulprbbl,prbbl,275*sizeof(int));
       if(strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
         //sf_ahead = 2; // Need 4 subframe gap between RX and TX
       }else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
@@ -633,6 +662,30 @@ void RCconfig_NR_L1(void) {
 void RCconfig_nr_macrlc() {
   int               j;
 
+  paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
+  ////////// Identification parameters
+  paramdef_t GNBParams[]  = GNBPARAMS_DESC;
+
+  paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
+
+  config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); 
+  int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
+  AssertFatal (num_gnbs > 0,"Failed to parse config file no gnbs %s \n",GNB_CONFIG_STRING_ACTIVE_GNBS);
+  
+  config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); 
+  char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr; 
+  char *pt = strtok(ulprbbl,",");
+  int prbbl[275];
+  int num_prbbl=0;
+  int prb;
+  memset(prbbl,0,275*sizeof(int));
+  while (pt) {
+    prb=atoi(pt); 
+    prbbl[prb] = 1;
+    pt = strtok(NULL,",");
+    num_prbbl++;
+  }
+  
   paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
   paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
 
@@ -702,6 +755,10 @@ void RCconfig_nr_macrlc() {
         AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr));
       } 
       RC.nrmac[j]->ulsch_max_slots_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_SLOTS_INACTIVITY].uptr);
+      RC.nrmac[j]->num_ulprbbl = num_prbbl;
+      LOG_I(NR_MAC,"Blacklisted PRBS %d\n",num_prbbl);
+      memcpy(RC.nrmac[j]->ulprbbl,prbbl,275*sizeof(prbbl[0]));
+
     }//  for (j=0;j<RC.nb_nr_macrlc_inst;j++)
   }else {// MacRLC_ParamList.numelt > 0
     LOG_E(PHY,"No %s configuration found\n", CONFIG_STRING_MACRLC_LIST);
diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h
index 380c6890a559209977cfe07983b82e7b05c5192a..b0d5d2322da4c7b98721771882904658a14b54ad 100644
--- a/openair2/GNB_APP/gnb_paramdef.h
+++ b/openair2/GNB_APP/gnb_paramdef.h
@@ -120,6 +120,8 @@ typedef enum {
 #define GNB_CONFIG_STRING_DOCSIRS                       "do_CSIRS"
 #define GNB_CONFIG_STRING_NRCELLID                      "nr_cellid"
 #define GNB_CONFIG_STRING_MINRXTXTIMEPDSCH              "min_rxtxtime_pdsch"
+#define GNB_CONFIG_STRING_ULPRBBLACKLIST                "ul_prbblacklist"
+
 
 /*-----------------------------------------------------------------------------------------------------------------------------------------*/
 /*                                            cell configuration parameters                                                                */
@@ -147,7 +149,8 @@ typedef enum {
 {GNB_CONFIG_STRING_DOCSIRS,                      NULL,   0,            iptr:NULL,   defintval:0,                 TYPE_INT,       0},  \
 {GNB_CONFIG_STRING_NRCELLID,                     NULL,   0,            u64ptr:NULL, defint64val:1,               TYPE_UINT64,    0},  \
 {GNB_CONFIG_STRING_MINRXTXTIMEPDSCH,             NULL,   0,            iptr:NULL,   defintval:2,                 TYPE_INT,       0}   \
-}															     	
+{GNB_CONFIG_STRING_ULPRBBLACKLIST,               NULL,   0,            strptr:NULL, defstrval:"",                 TYPE_STRING,   0}   \
+}
 
 #define GNB_GNB_ID_IDX                  0
 #define GNB_CELL_TYPE_IDX               1
@@ -170,6 +173,7 @@ typedef enum {
 #define GNB_DO_CSIRS_IDX                18
 #define GNB_NRCELLID_IDX                19
 #define GNB_MINRXTXTIMEPDSCH_IDX        20
+#define GNB_ULPRBBLACKLIST_IDX          21
 
 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
 #define GNBPARAMS_CHECK {                                         \
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index 9202f33375547be359403658327f93942e8a5786..c6752d37c21eaf0adea76ead87a9c0ee16d780fb 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -864,7 +864,7 @@ void nr_get_Msg3alloc(module_id_t module_id,
 
   // msg3 is scheduled in mixed slot in the following TDD period
 
-  uint16_t msg3_nb_rb = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); // sdu has 6 or 8 bytes
+  uint16_t msg3_nb_rb = 8; // sdu has 6 or 8 bytes
 
   int mu = ubwp ?
     ubwp->bwp_Common->genericParameters.subcarrierSpacing :
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index c336de704d2402ecbc1a634bd52563808350c39c..51192b4d632b2236c24684d3a0c1e6a020105596 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -1329,6 +1329,9 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
   const uint16_t symb = ((1 << nrOfSymbols) - 1) << startSymbolIndex;
 
   int st = 0, e = 0, len = 0;
+  for (int i = 0; i < bwpSize; i++) 
+    if (RC.nrmac[module_id]->ulprbbl[i] == 1) vrb_map_UL[i]=symb;
+
   for (int i = 0; i < bwpSize; i++) {
     while ((vrb_map_UL[i] & symb) != 0 && i < bwpSize)
       i++;
@@ -1342,6 +1345,8 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
   }
   st = e - len + 1;
 
+  LOG_D(NR_MAC,"UL %d.%d : start_prb %d, end PRB %d\n",frame,slot,st,e);
+  
   uint8_t rballoc_mask[bwpSize];
 
   /* Calculate mask: if any RB in vrb_map_UL is blocked (1), the current RB will be 0 */
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index c2e2b8d5621b109e0b0565f797ce30e212e0ca74..e57e9540080deefdefb60ef60a9382a84d07e986 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -681,7 +681,8 @@ typedef struct gNB_MAC_INST_s {
   NR_COMMON_channels_t common_channels[NFAPI_CC_MAX];
   /// current PDU index (BCH,DLSCH)
   uint16_t pdu_index[NFAPI_CC_MAX];
-
+  int num_ulprbbl;
+  int ulprbbl[275];
   /// NFAPI Config Request Structure
   nfapi_nr_config_request_scf_t     config[NFAPI_CC_MAX];
   /// NFAPI DL Config Request Structure
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_nsa_n310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_nsa_n310.conf
new file mode 100644
index 0000000000000000000000000000000000000000..59e507ed3e08b9dcda42713fe132efa896b29eea
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_nsa_n310.conf
@@ -0,0 +1,296 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;});	 
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    ssb_SubcarrierOffset                                      = 31; //0;
+    pdsch_AntennaPorts                                        = 1;
+    pusch_AntennaPorts                                        = 1;
+    pusch_TargetSNRx10                                        = 200;
+    pucch_TargetSNRx10                                        = 200;
+
+    servingCellConfigCommon = (
+    {
+ #spCellConfigCommon
+
+      physCellId                                                    = 0;
+
+#  downlinkConfigCommon
+    #frequencyInfoDL
+      # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP)
+      absoluteFrequencySSB                                          = 641272; //641032;      #641968; 641968=start of ssb at 3600MHz + 82 RBs    641032=center of SSB at center of cell
+      dl_frequencyBand                                                 = 78;
+      # this is 3600 MHz
+      dl_absoluteFrequencyPointA                                       = 640000;
+      #scs-SpecificCarrierList
+        dl_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        dl_subcarrierSpacing                                           = 1;
+        dl_carrierBandwidth                                            = 106;
+     #initialDownlinkBWP
+      #genericParameters
+        # this is RBstart=84,L=13 (275*(L-1))+RBstart
+        initialDLBWPlocationAndBandwidth                                        = 6368;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialDLBWPsubcarrierSpacing                                           = 1;
+      #pdcch-ConfigCommon
+        initialDLBWPcontrolResourceSetZero                                      = 0;
+        initialDLBWPsearchSpaceZero                                             = 0;
+      #pdsch-ConfigCommon
+        #pdschTimeDomainAllocationList (up to 16 entries)
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
+  #uplinkConfigCommon 
+     #frequencyInfoUL
+      ul_frequencyBand                                                 = 78;
+      #scs-SpecificCarrierList
+      ul_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      ul_subcarrierSpacing                                           = 1;
+      ul_carrierBandwidth                                            = 106;
+      pMax                                                          = 20;
+     #initialUplinkBWP
+      #genericParameters
+        initialULBWPlocationAndBandwidth                                        = 6368;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialULBWPsubcarrierSpacing                                           = 1;
+      #rach-ConfigCommon
+        #rach-ConfigGeneric
+          prach_ConfigurationIndex                                  = 98;
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+          prach_msg1_FDM                                            = 0;
+          prach_msg1_FrequencyStart                                 = 0;
+          zeroCorrelationZoneConfig                                 = 13;
+          preambleReceivedTargetPower                               = -100;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+          preambleTransMax                                          = 6;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+        powerRampingStep                                            = 1;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+        ra_ResponseWindow                                           = 5;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR                = 4;
+#oneHalf (0..15) 4,8,12,16,...60,64
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB                   = 14; //15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+        ra_ContentionResolutionTimer                                = 7;
+        rsrp_ThresholdSSB                                           = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+        prach_RootSequenceIndex_PR                                  = 2;
+        prach_RootSequenceIndex                                     = 1;
+        # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+        #  
+        msg1_SubcarrierSpacing                                      = 1,
+
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+        restrictedSetConfig                                         = 0,
+      # pusch-ConfigCommon (up to 16 elements)
+        initialULBWPk2_0                      = 2;  # used for UL slot
+        initialULBWPmappingType_0             = 1
+        initialULBWPstartSymbolAndLength_0    = 41; # this is SS=0 L=13
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot
+        initialULBWPmappingType_1             = 1;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
+
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
+        initialULBWPmappingType_2             = 1;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
+
+        msg3_DeltaPreamble                                          = 1;
+        p0_NominalWithGrant                                         =-90;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+        pucchGroupHopping                                           = 0;
+        hoppingId                                                   = 40;
+        p0_nominal                                                  = -90;
+# ssb_PositionsInBurs_BitmapPR
+# 1=short, 2=medium, 3=long
+      ssb_PositionsInBurst_PR                                       = 2;
+      ssb_PositionsInBurst_Bitmap                                   = 1; #0x80;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 
+      ssb_periodicityServingCell                                    = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+      dmrs_TypeA_Position                                           = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      subcarrierSpacing                                             = 1;
+
+
+  #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      referenceSubcarrierSpacing                                    = 1;
+      # pattern1 
+      # dl_UL_TransmissionPeriodicity
+      # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+      dl_UL_TransmissionPeriodicity                                 = 6;
+      nrofDownlinkSlots                                             = 7; //8; //7;
+      nrofDownlinkSymbols                                           = 6; //0; //6;
+      nrofUplinkSlots                                               = 2;
+      nrofUplinkSymbols                                             = 4; //0; //4;
+
+  ssPBCH_BlockPower                                             = -25;
+  }
+
+  );
+
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    amf_ip_address      = ( { ipv4       = "192.168.18.99";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    ///X2
+    enable_x2 = "yes";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
+    target_enb_x2_ip_address      = (
+                                     { ipv4       = "192.168.18.199";
+                                       ipv6       = "192:168:30::17";
+                                       preference = "ipv4";
+                                     }
+                                    );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_NG_AMF            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_NG_AMF              = "192.168.18.198/24";
+        GNB_INTERFACE_NAME_FOR_NGU               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_NGU                 = "192.168.18.198/24";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+        GNB_IPV4_ADDRESS_FOR_X2C                 = "192.168.18.198/24";
+        GNB_PORT_FOR_X2C                         = 36422; # Spec 36422
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+	pusch_proc_threads = 8;
+        }  
+);
+
+RUs = (
+    {		  
+       local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 75;
+         eNB_instances  = [0];
+         sdr_addrs = "mgmt_addr=192.168.18.252,addr=192.168.80.50,clock_source=internal,time_source=    internal"
+         #clock_src = "external";
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    //parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+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";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+