diff --git a/ci-scripts/checkCodingFormattingRules.sh b/ci-scripts/checkCodingFormattingRules.sh
index a805f765dfb9b4ca7c6e3cf481a9f0784c08d722..c29941cade3d2464f591ed3a5873341bacb63a4c 100755
--- a/ci-scripts/checkCodingFormattingRules.sh
+++ b/ci-scripts/checkCodingFormattingRules.sh
@@ -59,7 +59,7 @@ if [ $# -eq 0 ]
 then
     echo " ---- Checking the whole repository ----"
     echo ""
-    NB_FILES_TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt --recursive *.c *.h | grep -c Formatted || true`
+    NB_FILES_TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt --recursive --exclude=ci-scripts --exclude=cmake_targets *.c *.h | grep -c Formatted || true`
     echo "Nb Files that do NOT follow OAI rules: $NB_FILES_TO_FORMAT"
     echo $NB_FILES_TO_FORMAT > ./oai_rules_result.txt
 
@@ -136,7 +136,7 @@ fi
 # Merge request scenario
 
 MERGE_COMMMIT=`git log -n1 --pretty=format:%H`
-TARGET_INIT_COMMIT=`cat .git/refs/remotes/origin/$TARGET_BRANCH`
+TARGET_INIT_COMMIT=`git log -n1 --pretty=format:%H origin/$TARGET_BRANCH`
 
 echo " ---- Checking the modified files by the merge request ----"
 echo ""
diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml
index b888f6bb59fc0257c9d402e18a0e86178d4d2537..51fc4a264eb4794f7e325fa74b257a42c602e75c 100644
--- a/ci-scripts/ci_ueinfra.yaml
+++ b/ci-scripts/ci_ueinfra.yaml
@@ -55,7 +55,7 @@ amarisoft_ue_1:
   Duration : 60
   Ping : /tmp/test_ue1.log
   UELog : /tmp/ue1.log
-  HostIPAddress : 192.168.18.89
+  HostIPAddress : 172.21.16.144
   HostUsername : root
   HostPassword : toor 
   HostSourceCodePath : /tmp
diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py
index d6796ad414e1577e0c9d233e322e46f570f8838f..5b45b48ba67bd0454716428cf89d29cddcf16a97 100644
--- a/ci-scripts/cls_static_code_analysis.py
+++ b/ci-scripts/cls_static_code_analysis.py
@@ -37,6 +37,7 @@ import logging
 import os
 from pathlib import Path
 import time
+from multiprocessing import Process, Lock, SimpleQueue
 
 #-----------------------------------------------------------
 # OAI Testing modules
@@ -237,3 +238,205 @@ class StaticCodeAnalysis():
 
 		return 0
 
+	def LicenceAndFormattingCheck(self, HTML):
+		if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
+			HELP.GenericHelp(CONST.Version)
+			sys.exit('Insufficient Parameter')
+		lIpAddr = self.eNBIPAddress
+		lUserName = self.eNBUserName
+		lPassWord = self.eNBPassword
+		lSourcePath = self.eNBSourceCodePath
+
+		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
+			HELP.GenericHelp(CONST.Version)
+			sys.exit('Insufficient Parameter')
+		logging.debug('Building on server: ' + lIpAddr)
+		mySSH = SSH.SSHConnection()
+		mySSH.open(lIpAddr, lUserName, lPassWord)
+
+		self.testCase_id = HTML.testCase_id
+
+		# on RedHat/CentOS .git extension is mandatory
+		result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
+		if result is not None:
+			full_ran_repo_name = self.ranRepository.replace('git/', 'git')
+		else:
+			full_ran_repo_name = self.ranRepository + '.git'
+		mySSH.command('mkdir -p ' + lSourcePath, '\$', 5)
+		mySSH.command('cd ' + lSourcePath, '\$', 5)
+		mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600)
+		# Raphael: here add a check if git clone or git fetch went smoothly
+		mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5)
+		mySSH.command('git config user.name "OAI Jenkins"', '\$', 5)
+
+		mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30)
+		mySSH.command('mkdir -p cmake_targets/log', '\$', 5)
+		# if the commit ID is provided use it to point to it
+		if self.ranCommitID != '':
+			mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 30)
+		# if the branch is not develop, then it is a merge request and we need to do
+		# the potential merge. Note that merge conflicts should already been checked earlier
+		argToPass = ''
+		if (self.ranAllowMerge):
+			argToPass = '--build-arg MERGE_REQUEST=true --build-arg SRC_BRANCH=' + self.ranBranch
+			if self.ranTargetBranch == '':
+				if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'):
+					mySSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5)
+					argToPass += ' --build-arg TARGET_BRANCH=develop '
+			else:
+				logging.debug('Merging with the target branch: ' + self.ranTargetBranch)
+				mySSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5)
+				argToPass += ' --build-arg TARGET_BRANCH=' + self.ranTargetBranch + ' '
+
+		mySSH.command('docker image rm oai-formatting-check:latest || true', '\$', 60)
+		mySSH.command('docker build --target oai-formatting-check --tag oai-formatting-check:latest ' + argToPass + '--file ci-scripts/docker/Dockerfile.formatting.bionic . > cmake_targets/log/oai-formatting-check.txt 2>&1', '\$', 600)
+
+		mySSH.command('docker image rm oai-formatting-check:latest || true', '\$', 60)
+		mySSH.command('docker image prune --force', '\$', 60)
+		mySSH.command('docker volume prune --force', '\$', 60)
+
+		# Analyzing the logs
+		mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5)
+		mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5)
+		mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5)
+		mySSH.close()
+
+		mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/build_log_' + self.testCase_id + '/*', '.')
+
+		finalStatus = 0
+		if (os.path.isfile('./oai-formatting-check.txt')):
+			analyzed = False
+			nbFilesNotFormatted = 0
+			listFiles = False
+			listFilesNotFormatted = []
+			circularHeaderDependency = False
+			circularHeaderDependencyFiles = []
+			gnuGplLicence = False
+			gnuGplLicenceFiles = []
+			suspectLicence = False
+			suspectLicenceFiles = []
+			with open('./oai-formatting-check.txt', 'r') as logfile:
+				for line in logfile:
+					ret = re.search('./ci-scripts/checkCodingFormattingRules.sh', str(line))
+					if ret is not None:
+						analyzed = True
+					if analyzed:
+						ret = re.search('Nb Files that do NOT follow OAI rules: (?P<nb_errors>[0-9\.]+)', str(line))
+						if ret is not None:
+							nbFilesNotFormatted = int(ret.group('nb_errors'))
+
+						if re.search('=== Files not properly formatted ===', str(line)) is not None:
+							listFiles = True
+						if listFiles:
+							if re.search('Removing intermediate container', str(line)) is not None:
+								listFiles = False
+							elif re.search('Running in|Files not properly formatted', str(line)) is not None:
+								pass
+							else:
+								listFilesNotFormatted.append(str(line).strip())
+
+						if re.search('=== Files with incorrect define protection ===', str(line)) is not None:
+							circularHeaderDependency = True
+						if circularHeaderDependency:
+							if re.search('Removing intermediate container', str(line)) is not None:
+								circularHeaderDependency = False
+							elif re.search('Running in|Files with incorrect define protection', str(line)) is not None:
+								pass
+							else:
+								circularHeaderDependencyFiles.append(str(line).strip())
+
+						if re.search('=== Files with a GNU GPL licence Banner ===', str(line)) is not None:
+							gnuGplLicence = True
+						if gnuGplLicence:
+							if re.search('Removing intermediate container', str(line)) is not None:
+								gnuGplLicence = False
+							elif re.search('Running in|Files with a GNU GPL licence Banner', str(line)) is not None:
+								pass
+							else:
+								gnuGplLicenceFiles.append(str(line).strip())
+
+						if re.search('=== Files with a suspect Banner ===', str(line)) is not None:
+							suspectLicence = True
+						if suspectLicence:
+							if re.search('Removing intermediate container', str(line)) is not None:
+								suspectLicence = False
+							elif re.search('Running in|Files with a suspect Banner', str(line)) is not None:
+								pass
+							else:
+								suspectLicenceFiles.append(str(line).strip())
+
+				logfile.close()
+			if analyzed:
+				logging.debug('files not formatted properly: ' + str(nbFilesNotFormatted))
+				if nbFilesNotFormatted == 0:
+					HTML.CreateHtmlTestRow('File(s) Format', 'OK', CONST.ALL_PROCESSES_OK)
+				else:
+					html_queue = SimpleQueue()
+					html_cell = '<pre style="background-color:white">\n'
+					html_cell += 'Number of files not following OAI Rules: ' + str(nbFilesNotFormatted) + '\n'
+					for nFile in listFilesNotFormatted:
+						html_cell += str(nFile).strip() + '\n'
+					html_cell += '</pre>'
+					html_queue.put(html_cell)
+					HTML.CreateHtmlTestRowQueue('File(s) Format', 'KO', 1, html_queue)
+					del(html_cell)
+					del(html_queue)
+
+				logging.debug('header files not respecting the circular dependency protection: ' + str(len(circularHeaderDependencyFiles)))
+				if len(circularHeaderDependencyFiles) == 0:
+					HTML.CreateHtmlTestRow('Header Circular Dependency', 'OK', CONST.ALL_PROCESSES_OK)
+				else:
+					html_queue = SimpleQueue()
+					html_cell = '<pre style="background-color:white">\n'
+					html_cell += 'Number of files not respecting: ' + str(len(circularHeaderDependencyFiles)) + '\n'
+					for nFile in circularHeaderDependencyFiles:
+						html_cell += str(nFile).strip() + '\n'
+					html_cell += '</pre>'
+					html_queue.put(html_cell)
+					HTML.CreateHtmlTestRowQueue('Header Circular Dependency', 'KO', 1, html_queue)
+					del(html_cell)
+					del(html_queue)
+					finalStatus = -1
+
+				logging.debug('files with a GNU GPL license: ' + str(len(gnuGplLicenceFiles)))
+				if len(gnuGplLicenceFiles) == 0:
+					HTML.CreateHtmlTestRow('Files w/ GNU GPL License', 'OK', CONST.ALL_PROCESSES_OK)
+				else:
+					html_queue = SimpleQueue()
+					html_cell = '<pre style="background-color:white">\n'
+					html_cell += 'Number of files not respecting: ' + str(len(gnuGplLicenceFiles)) + '\n'
+					for nFile in gnuGplLicenceFiles:
+						html_cell += str(nFile).strip() + '\n'
+					html_cell += '</pre>'
+					html_queue.put(html_cell)
+					HTML.CreateHtmlTestRowQueue('Files w/ GNU GPL License', 'KO', 1, html_queue)
+					del(html_cell)
+					del(html_queue)
+					finalStatus = -1
+
+				logging.debug('files with a suspect license: ' + str(len(suspectLicenceFiles)))
+				if len(suspectLicenceFiles) == 0:
+					HTML.CreateHtmlTestRow('Files with suspect license', 'OK', CONST.ALL_PROCESSES_OK)
+				else:
+					html_queue = SimpleQueue()
+					html_cell = '<pre style="background-color:white">\n'
+					html_cell += 'Number of files not respecting: ' + str(len(suspectLicenceFiles)) + '\n'
+					for nFile in suspectLicenceFiles:
+						html_cell += str(nFile).strip() + '\n'
+					html_cell += '</pre>'
+					html_queue.put(html_cell)
+					HTML.CreateHtmlTestRowQueue('Files with suspect license', 'KO', 1, html_queue)
+					del(html_cell)
+					del(html_queue)
+					finalStatus = -1
+
+			else:
+				finalStatus = -1
+				HTML.htmleNBFailureMsg = 'Could not fully analyze oai-formatting-check.txt file'
+				HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
+		else:
+			finalStatus = -1
+			HTML.htmleNBFailureMsg = 'Could not access oai-formatting-check.txt file'
+			HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
+
+		return finalStatus
diff --git a/ci-scripts/docker/Dockerfile.formatting.bionic b/ci-scripts/docker/Dockerfile.formatting.bionic
new file mode 100644
index 0000000000000000000000000000000000000000..01417a3bdb3c68385cac0141a971d7ab90002c21
--- /dev/null
+++ b/ci-scripts/docker/Dockerfile.formatting.bionic
@@ -0,0 +1,31 @@
+FROM ubuntu:bionic AS oai-formatting-check
+
+ARG MERGE_REQUEST
+ARG SRC_BRANCH
+ARG TARGET_BRANCH
+ENV DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update && \
+    DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \
+    DEBIAN_FRONTEND=noninteractive apt-get install --yes \
+       astyle \
+       gawk \
+       git
+
+WORKDIR /oai-ran
+COPY . .
+
+RUN /bin/bash -c "if [[ -v MERGE_REQUEST ]]; then echo 'Source Branch = $SRC_BRANCH'; echo 'Target Branch = $TARGET_BRANCH'; else echo 'Push to develop'; fi"
+RUN /bin/bash -c "if [[ -v MERGE_REQUEST ]]; then ./ci-scripts/checkCodingFormattingRules.sh --src-branch $SRC_BRANCH --target-branch $TARGET_BRANCH; else ./ci-scripts/checkCodingFormattingRules.sh; fi"
+
+RUN echo "=== Files not properly formatted ===" && \
+    /bin/bash -c "if [[ -f oai_rules_result_list.txt ]]; then cat oai_rules_result_list.txt; fi"
+
+RUN echo "=== Files with incorrect define protection ===" && \
+   /bin/bash -c "if [[ -f header-files-w-incorrect-define.txt ]]; then cat header-files-w-incorrect-define.txt; fi"
+
+RUN echo "=== Files with a GNU GPL licence Banner ===" && \
+   /bin/bash -c "if [[ -f files-w-gnu-gpl-license-banner.txt ]]; then cat files-w-gnu-gpl-license-banner.txt; fi"
+
+RUN echo "=== Files with a suspect Banner ===" && \
+  /bin/bash -c "if [[ -f files-w-suspect-banner.txt ]]; then cat files-w-suspect-banner.txt; fi"
diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py
index 0fc37d4ead75759dfacecc3474be9e956afe1dc4..0e0afefaaf7114d421bde4b02f0a2ff31727e1d3 100644
--- a/ci-scripts/epc.py
+++ b/ci-scripts/epc.py
@@ -255,16 +255,19 @@ class EPCManagement():
 			mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts', '\$', 5)
 			mySSH.command('cd /opt/oai-cn5g-fed-v1.3/docker-compose', '\$', 5)
 			mySSH.command('python3 ./core-network.py '+self.cfgDeploy, '\$', 60)
-			time.sleep(2)
-			mySSH.command('docker-compose -p 5gcn ps -a', '\$', 60)
+			if re.search('start-mini-as-ue', self.cfgDeploy):
+				dFile = 'docker-compose-mini-nrf-asue.yaml'
+			else:
+				dFile = 'docker-compose-mini-nrf.yaml'
+			mySSH.command('docker-compose -p 5gcn -f ' + dFile + ' ps -a', '\$', 60)
 			if mySSH.getBefore().count('Up (healthy)') != 6:
 				logging.error('Not all container healthy')
 			else:
-				logging.debug('OK')
-			mySSH.command('docker-compose config | grep --colour=never image', '\$', 10)
+				logging.debug('OK --> all containers are healthy')
+			mySSH.command('docker-compose -p 5gcn -f ' + dFile + ' config | grep --colour=never image', '\$', 10)
 			listOfImages = mySSH.getBefore()
 			for imageLine in listOfImages.split('\\r\\n'):
-				res1 = re.search('image: (?P<name>[a-zA-Z0-9\-]+):(?P<tag>[a-zA-Z0-9\-]+)', str(imageLine))
+				res1 = re.search('image: (?P<name>[a-zA-Z0-9\-/]+):(?P<tag>[a-zA-Z0-9\-]+)', str(imageLine))
 				res2 = re.search('mysql', str(imageLine))
 				if res1 is not None and res2 is None:
 					html_cell += res1.group('name') + ':' + res1.group('tag') + ' '
@@ -536,7 +539,7 @@ class EPCManagement():
 			mySSH.command('python3 ./core-network.py '+self.cfgUnDeploy, '\$', 60)
 			mySSH.command('docker volume prune --force || true', '\$', 60)
 			time.sleep(2)
-			mySSH.command('tshark -r /tmp/oai-cn5g.pcap | egrep --colour=never "Tracking area update" ','\$', 30)
+			mySSH.command('tshark -r /tmp/oai-cn5g-v1.3.pcap | egrep --colour=never "Tracking area update" ','\$', 30)
 			result = re.search('Tracking area update request', mySSH.getBefore())
 			if result is not None:
 				message = 'UE requested ' + str(mySSH.getBefore().count('Tracking area update request')) + 'Tracking area update request(s)'
@@ -830,8 +833,8 @@ class EPCManagement():
 				mySSH.command('zip mme.log.zip mme_check_run.*', '\$', 60)
 		elif re.match('OAICN5G', self.Type, re.IGNORECASE):
 			mySSH.command('cd ' + self.SourceCodePath + '/logs','\$', 5)
-			mySSH.command('cp -f /tmp/oai-cn5g.pcap .','\$', 30)
-			mySSH.command('zip mme.log.zip oai-amf.log oai-nrf.log oai-cn5g.pcap','\$', 30)
+			mySSH.command('cp -f /tmp/oai-cn5g-v1.3.pcap .','\$', 30)
+			mySSH.command('zip mme.log.zip oai-amf.log oai-nrf.log oai-cn5g*.pcap','\$', 30)
 			mySSH.command('mv mme.log.zip ' + self.SourceCodePath + '/scripts','\$', 30)
 		elif re.match('OAI', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE):
 			mySSH.command('zip mme.log.zip mme*.log', '\$', 60)
diff --git a/ci-scripts/main.py b/ci-scripts/main.py
index 03947bdfc968c83f83eed43a6f0ab05212b6c218..adef8859423514c45d7b110b4ea2430376b43e5d 100644
--- a/ci-scripts/main.py
+++ b/ci-scripts/main.py
@@ -799,7 +799,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
 	HTML.startTime=int(round(time.time() * 1000))
 	while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.prematureExit:
 		RAN.prematureExit=False
-		# At every iteratin of the retry loop, a separator will be added
+		# At every iteration of the retry loop, a separator will be added
 		# pass CiTestObj.FailReportCnt as parameter of HTML.CreateHtmlRetrySeparator
 		HTML.CreateHtmlRetrySeparator(CiTestObj.FailReportCnt)
 		for test_case_id in todo_tests:
@@ -923,6 +923,10 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
 					CONTAINERS.UndeployObject(HTML, RAN)
 				elif action == 'Cppcheck_Analysis':
 					SCA.CppCheckAnalysis(HTML)
+				elif action == 'LicenceAndFormattingCheck':
+					ret = SCA.LicenceAndFormattingCheck(HTML)
+					if ret != 0:
+						RAN.prematureExit = True
 				elif action == 'Deploy_Run_PhySim':
 					PHYSIM.Deploy_PhySim(HTML, RAN)
 				elif action == 'DeployGenObject':
diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml
index d6f75191a8da8bc7818d9c7d55adc8b9aad5d21d..b305aff42437b6797f9677155ad4b15adfbb1f9b 100755
--- a/ci-scripts/xml_class_list.yml
+++ b/ci-scripts/xml_class_list.yml
@@ -47,3 +47,4 @@
   - PingFromContainer
   - IperfFromContainer
   - StatsFromGenObject
+  - LicenceAndFormattingCheck
diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml
index 47a939f63c51c18b395017a5ddb0411efff83beb..8d04be3efd22d625fc21a701bb351b480f6dd0f4 100644
--- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml
+++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml
@@ -142,8 +142,8 @@
 		<iperf_args>-u -b 125M -t 60 -i 1 -fm</iperf_args>
 		<direction>DL</direction>
 		<id>idefix</id>
-		<iperf_packetloss_threshold>1</iperf_packetloss_threshold>
-		<iperf_bitrate_threshold>95</iperf_bitrate_threshold>
+		<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
+		<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
diff --git a/ci-scripts/xml_files/formatting_check.xml b/ci-scripts/xml_files/formatting_check.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bdf47af65d2b67fd92f003f8e1108f9b36eb63f3
--- /dev/null
+++ b/ci-scripts/xml_files/formatting_check.xml
@@ -0,0 +1,37 @@
+<!--
+
+ 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>formatting-tab</htmlTabRef>
+	<htmlTabName>License and Formatting Checks</htmlTabName>
+	<htmlTabIcon>wrench</htmlTabIcon>
+	<TestCaseRequestedList>
+ 000002
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="000002">
+		<class>LicenceAndFormattingCheck</class>
+		<desc>License and Formatting Checks</desc>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/fr1_nsa_quectel.xml b/ci-scripts/xml_files/fr1_nsa_quectel.xml
index 0f8c90abdf12b0e97e9c5fc1b343f45dfa311757..a7fd0fc0d7c75a34d1cb05fdfbeac2845483446f 100644
--- a/ci-scripts/xml_files/fr1_nsa_quectel.xml
+++ b/ci-scripts/xml_files/fr1_nsa_quectel.xml
@@ -34,8 +34,8 @@
  050000
  050001
  000001
- 070003
- 070002
+ 070000
+ 070001
  000001
  050000
  050001
@@ -52,14 +52,12 @@
 		<UE_Trace>yes</UE_Trace>
 	</testCase>
 
-
 	<testCase id="010002">
 		<class>Terminate_UE</class>
 		<desc>Terminate Quectel</desc>
 		<id>idefix</id>
 	</testCase>
 
-
 	<testCase id="030000">
 		<class>Initialize_eNB</class>
 		<desc>Initialize eNB</desc>
@@ -70,7 +68,6 @@
 		<eNB_Trace>yes</eNB_Trace>
 	</testCase>
 
-
 	<testCase id="040000">
 		<class>Initialize_eNB</class>
 		<desc>Initialize gNB</desc>
@@ -92,7 +89,6 @@
 		<idle_sleep_time_in_sec>20</idle_sleep_time_in_sec>
 	</testCase>
 
-
 	<testCase id="050000">
 		<class>Ping</class>
 		<desc>Ping: 20pings in 20sec</desc>
@@ -112,39 +108,17 @@
 	</testCase>
 
 	<testCase id="070000">
-		<class>Iperf</class>
-		<desc>iperf (DL/30Mbps/UDP)(30 sec)(single-ue profile)</desc>
-		<iperf_args>-u -b 30M -t 30</iperf_args>
-		<direction>DL</direction>
-		<id>idefix</id>
-		<iperf_packetloss_threshold>1</iperf_packetloss_threshold>
-		<iperf_bitrate_threshold>95</iperf_bitrate_threshold>
-		<iperf_profile>single-ue</iperf_profile>
-	</testCase>
-
-	<testCase id="070001">
-		<class>Iperf</class>
-		<desc>iperf (DL/90Mbps/UDP)(30 sec)(single-ue profile)</desc>
-		<iperf_args>-u -b 90M -t 30</iperf_args>
-		<direction>DL</direction>
-		<id>idefix</id>
-		<iperf_packetloss_threshold>1</iperf_packetloss_threshold>
-		<iperf_bitrate_threshold>95</iperf_bitrate_threshold>
-		<iperf_profile>single-ue</iperf_profile>
-	</testCase>
-
-	<testCase id="070002">
 		<class>Iperf</class>
 		<desc>iperf (DL/125Mbps/UDP)(60 sec)(single-ue profile)</desc>
 		<iperf_args>-u -b 125M -t 60</iperf_args>
 		<direction>DL</direction>
 		<id>idefix</id>
-		<iperf_packetloss_threshold>1</iperf_packetloss_threshold>
-		<iperf_bitrate_threshold>95</iperf_bitrate_threshold>
+		<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
+		<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
-	<testCase id="070003">
+	<testCase id="070001">
 		<class>Iperf</class>
 		<desc>iperf (UL/8Mbps/UDP)(60 sec)(single-ue profile)</desc>
 		<iperf_args>-u -b 8M -t 60</iperf_args>
@@ -155,7 +129,6 @@
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
-
 	<testCase id="080000">
 		<class>Terminate_eNB</class>
 		<desc>Terminate eNB</desc>
diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper
index 554f3ccfe52958d125007b82e8d5c7d4ac9e08b0..179e2de42845ad295300a8d3aad73d7ff398db3c 100755
--- a/cmake_targets/tools/build_helper
+++ b/cmake_targets/tools/build_helper
@@ -381,7 +381,7 @@ check_install_usrp_uhd_driver(){
         $SUDO apt-get remove libuhd3.14.1 -y || true
         $SUDO apt-get remove libuhd3.15.0 -y || true
         local distribution=$(get_distribution_release)
-        if [[ "$distribution" == "ubuntu18.04" ]]; then
+        if [[ "$distribution" == "ubuntu18.04" || "$distribution" == "ubuntu20.04" || "$distribution" == "ubuntu22.04" ]]; then
             $SUDO apt-get remove libuhd4.0.0 -y || true
             $SUDO apt-get remove libuhd4.1.0 -y || true
         fi
@@ -410,13 +410,15 @@ check_install_usrp_uhd_driver(){
             x=$((x + 1))
         done
         $SUDO apt-get update
-        $SUDO apt-get -y install  python python-tk libboost-all-dev libusb-1.0-0-dev
-        if [[ "$distribution" == "ubuntu16.04" ]]; then
+        $SUDO apt-get -y install python-tk libboost-all-dev libusb-1.0-0-dev
+        case "$(get_distribution_release)" in
+          "ubuntu16.04")
             $SUDO apt-get -y install libuhd-dev libuhd3.15.0 uhd-host
-        fi
-        if [[ "$distribution" == "ubuntu18.04" ]]; then
-            $SUDO apt-get -y install libuhd-dev libuhd4.1.0 uhd-host
-        fi
+            ;;
+          "ubuntu18.04" | "ubuntu20.04" | "ubuntu22.04")
+            $SUDO apt-get -y install libuhd-dev libuhd4.2.0 uhd-host
+            ;;
+        esac
     elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
         if [ $IS_CONTAINER -eq 0 ]
         then
diff --git a/doc/BUILD.md b/doc/BUILD.md
index a52ce98cb53f7df132d6b55d64902b32fb7c1036..70d69f5afde23705a7f055e636ef9d61f467d7ba 100644
--- a/doc/BUILD.md
+++ b/doc/BUILD.md
@@ -193,6 +193,7 @@ Using the help option of the build script you can get the list of available opti
 | --UE                                                        | maintained and tested in CI                 | build `lte-uesoftmodem` the LTE UE                           |
 | --gNB                                                       | maintained and tested in CI                 | build `nr-softmodem` the 5G gNodeB                           |
 | --nrUE                                                      | maintained and tested in CI                 | build `nr-uesoftmodem` the 5G UE                             |
+| --arch-native                                               | maintained                                  | build with native architecture optimization                  |
 | --usrp-recplay                                              | deprecated                                  | use the USRP configuration parameters to use the record player. |
 | --build-lib                                                 | maintained                                  | build  optional shared library(ies), which can then be loaded at run time via command line option. Use the --help option to get the list of supported optional libraries. `all` can be used to build all available optional libraries. |
 | --UE-conf-nvram                                             | maintained                                  | Specifies the path to the input file used by the conf2uedata utility. defaults to [openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf](../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf) |
diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md
index 7365bc0f4c7df220fdf4a026b4cb8abecb89946f..547fd5a23bc6fb85849e6db0f0b8e58f38580a7e 100644
--- a/doc/TESTBenches.md
+++ b/doc/TESTBenches.md
@@ -1,45 +1,164 @@
 ## Table of Contents ##
 
-1.   [Legacy 1 Bench](#legacy-1-bench)
-2.   [Legacy 2 Bench](#legacy-2-bench)
-3.   [Next Bench for DEV](#next-bench-for-dev)
-4.   [Next Bench for CI](#next-bench-for-ci)
-5.   [Indoor Live Network Bench](#indoor-live-network-bench)
-6.   [Outdoor Live Network Bench](#outdoor-live-network-bench)
+1.   [Machines](#machines)
+2.   [Networked devices](#networked-devices)
+3.   [Testbenches](#testbenches)
+4.   [Pipelines](#pipelines)
 
+## Machines
 
-## Legacy 1 Bench
-
-**Purpose** : FDD Band 7 and Band 13, LTE-M  
-**Note** : Legacy1 and Legacy2 are duplicated so that they can run in parallel, thus avoiding a CI bottleneck  
-**Note** : Faraday Cages 1 and 2 are physically the same cage  
-
-![image info](./testbenches_doc_resources/legacy1.jpg)
-
-## Legacy 2 Bench
-
-**Purpose** : TDD Band 40, TM2 2xTX 2xRX  
-**Note** : CN can run in a container, could also run on Massive 
-
-![image info](./testbenches_doc_resources/legacy2.jpg)
-
-## Next Bench for DEV
-
-**Note** : Benetel CI can also run on this bench at night 
-
-![image info](./testbenches_doc_resources/next_dev.jpg)
-
-
-## Next Bench for CI
-
-**Note** : The current test running on Caracal could run on this bench with a N300/N300 setup  
-
-![image info](./testbenches_doc_resources/next_ci.jpg)
-
-## Indoor Live Network Bench
-
-![image info](./testbenches_doc_resources/indoor_live.jpg)
-
-## Outdoor Live Network Bench
-
-![image info](./testbenches_doc_resources/outdoor_live.jpg)
+| Machine       | IP address      | Lockable Resource     | Function           | Connected devices                                     |
+| ------------- | --------------- | --------------------- | ------------------ | ----------------------------------------------------- |
+| asterix       | 172.21.16.127   | CI-Asterix-Usage      | gNB                | 173.21.19.14                                          |
+| obelix        | 172.21.16.128   | CI-Obelix-Usage       | eNB, UE (5G)       | 172.21.19.13, X300 (192.168.60.2), B200mini (30C51EB) |
+| porcepix      | 172.21.16.136   | CI-NSA-MiniBench      | Executor, EPC, 5GC | --                                                    |
+| nrmodule2     | 172.21.16.139   | CI-NSA-MiniBench      | Quectel            | Quectel module                                        |
+| nepes         | 172.21.16.137   | CI-NSA-MiniBench      | gNB                | B200mini (30C51D4)                                    |
+| caracal       | 172.21.16.132   | CI-Caracal            | gNB/phytest        | N300 (192.168.10.2)                                   |
+| idefix        | 172.21.16.135   | CI-NSA-MiniBench      | Quectel            | Quectel module                                        |
+| amariue       | 172.21.16.144   | CI-Amarisoft-UE-Usage | TBD                | Amarisoft UE simulator                                |
+| bellatrix     | 192.168.117.115 | CI-RAN-VM-Deployment  | Executor           | --                                                    |
+| nano          | 192.168.12.62   | CI-Bench-1-Phones     | EPC, adb           | 2x COTS (adb)                                         |
+| hutch         | 192.168.12.19   | CI-Bench-1-Phones     | eNB (B7)           | B200mini (30C5239)                                    |
+| starsky       | 192.168.12.18   | CI-Bench-1-Phones     | eNB (B40)          | b200mini (30A3E3C)                                    |
+| carabe        | 192.168.12.211  | CI-Bench-2-OAI-Phone  | UE 4G (B)          | B200mini (30AE8C9)                                    |
+
+Note: The available resources, and their current usage, is indicated here:
+- [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/):
+  "New" Jenkins, i.e., with RAN-Container-Parent
+- [Lockable resources of open5glab jenkins](https://open5glab.eurecom.fr:8083/jenkins/lockable-resources/):
+  "Old" Jenkins, i.e., with RAN-CI-Develop
+
+## Networked devices
+
+| Type          | IP address (mgmt) |
+| ------------- | ----------------- |
+| USRP N310     | 172.21.19.14      |
+| USRP N310     | 172.21.19.13      |
+
+## Testbenches
+
+### OTA Testbench
+
+[Proper image to be followed up. TBD: add antennas/circulators]
+
+Note: obelix and porcepix are both used in the OTA testbench and the 5G
+NSA/Faraday Cage testbench!
+
+![5G OTA Testbench](testbenches_doc_resources/5g-ota-bench.png)
+
+[PDF version](testbenches_doc_resources/5g-ota-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/5g-ota-bench.tex) if you want to modify to reflect your setup
+
+### 5G NSA/Faraday Cage Testbench
+
+**Purpose**: Faraday cage 5G tests
+
+Note: obelix and porcepix are both used in the OTA testbench and the 5G
+NSA/Faraday Cage testbench!
+
+![5G NSA/Faraday Cage Testbench](testbenches_doc_resources/5g-nsa-faraday-bench.png)
+
+[PDF version](testbenches_doc_resources/5g-nsa-faraday-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/5g-nsa-faraday-bench.tex) if you want to modify to reflect your setup
+
+### 4G Testbench(es)
+
+**Purpose**: 4G/LTE testbenches
+
+
+![4G Faraday Cage Testbench](testbenches_doc_resources/4g-faraday-bench.png)
+
+[PDF version](testbenches_doc_resources/4g-faraday-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/4g-faraday-bench.tex) if you want to modify to reflect your setup
+
+## Pipelines
+
+### [RAN-Container-Parent](https://jenkins-oai.eurecom.fr/job/RAN-Container-Parent/)
+
+**Purpose**: automatically triggered tests on MR creation or push, from Gitlab
+Webhook
+
+- [RAN-cppcheck](https://jenkins-oai.eurecom.fr/job/RAN-cppcheck/1664/)
+  - obelix
+  - performs static code analysis, currently not actively enforced
+- [RAN-gNB-nrUE-MONO-TDD-Band78-N300](https://jenkins-oai.eurecom.fr/job/RAN-gNB-nrUE-MONO-TDD-Band78-N300/)
+  - caracal + N310
+  - pure performance test through phy-test scheduler, see command line for more
+    details
+- [RAN-L2-Sim-Test-5G](https://jenkins-oai.eurecom.fr/job/RAN-L2-Sim-Test-5G/)
+  - obelix (gNB, 1x UE, OAI 5GC)
+  - L2simulator: skips physical layer and uses proxy between gNB and UE,
+    currently only ping
+- [RAN-NSA-B200-Module-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-NSA-B200-Module-LTEBOX-Container/)
+  - obelix + B200, nepes + B200, idefix + Quectel, porcepix w/ ltebox
+  - basic NSA test, known to be instable
+- [RAN-PhySim-Cluster](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster/)
+  - asterix (`Asterix-OC-oaicicd-session` resource), tests in OpenShift Cluster
+  - unitary simulators (`nr_dlsim`, etc.)
+- [RAN-RF-Sim-Test-4G](https://jenkins-oai.eurecom.fr/job/RAN-RF-Sim-Test-4G/)
+  - obelix (eNB, 1x UE, OAI EPC)
+  - uses RFsimulator, for FDD 5, 10, 20MHz with core, 5MHz noS1
+- [RAN-RF-Sim-Test-5G](https://jenkins-oai.eurecom.fr/job/RAN-RF-Sim-Test-5G/)
+  - obelix (gNB, 2x UE, OAI 5GC)
+  - uses RFsimulator, TDD 40MHz, FDD 40MHz, F1 split
+- [RAN-RHEL8-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-RHEL8-Image-Builder/)
+  - asterix: RHEL 8 image build using podman
+- [RAN-Ubuntu18-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu18-Image-Builder/)
+  - obelix: Ubuntu 18 image build using docker
+
+### [RAN-CI-NSA-Trigger](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-CI-NSA-Trigger/)
+
+**Purpose**: longer-running over-the-air LTE, NSA, and SA tests, triggered
+through cron job at midnight
+
+- [RAN-LTE-2x2-Module-OAIEPC](https://jenkins-oai.eurecom.fr/job/RAN-LTE-2x2-Module-OAIEPC/)
+  - obelix + N310, nrmodule2 + Quectel, porcepix w/ Magma EPC
+  - LTE 2x2 test with TM1 and TM2
+- [RAN-NSA-B200-Module-LTEBOX](https://jenkins-oai.eurecom.fr/job/RAN-NSA-B200-Module-LTEBOX/)
+  - obelix + B200 (eNB), nepes + B200 (gNB), idefix + Quectel, porcepix w/ ltebox
+  - Note: like [RAN-NSA-B200-Module-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-NSA-B200-Module-LTEBOX-Container/) above, but compiled/run from source
+- [RAN-NSA-2x2-Module-OAIEPC](https://jenkins-oai.eurecom.fr/job/RAN-NSA-2x2-Module-OAIEPC/)
+  - obelix + N310 (eNB), asterix + N310 (gNB), nrmodule2 + Quectel, porcepix w/ Magma EPC
+  - LTE 2x2 and NR 2x2 (non-standalone)
+- [RAN-SA-Module-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-Module-CN5G/)
+  - asterix + N310 (gNB), nrmodule2 + Quectel, porcepix w/ OAI 5GC
+  - NR 2x2 (standalone)
+- [RAN-SA-OAIUE-N310-X300-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-OAIUE-N310-X300-CN5G/)
+  - asterix + N310 (gNB), obelix + N310 or X300 (5G UE), porcepix w/ OAI 5GC
+  - OTA test with OAIUE using both N310 and X300
+- [RAN-SA-AmariS-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-AmariS-CN5G/)
+  - asterix + N310, amariue (1x UE), porcepix w/ OAI 5GC
+  - Amarisoft UE simulator: expected to be increased to more UEs
+
+### [RAN-CI-develop](https://open5glab.eurecom.fr:8083/jenkins/job/RAN-CI-develop/)
+
+**Purpose**: automatically triggered tests, mostly 4G, to be phased out and
+integrated into RAN-Container-Parent
+
+runs tests:
+- bellatrix: runs 4G/5G simulators directly (eNB + 1x UE + (opt.) OAI EPC, gNB + 1x UE in "noS1")
+
+triggers pipelines:
+- [eNB-CI-F1-FDD-Band7-B210](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-CI-F1-FDD-Band7-B210/)
+  - hutch + B210, nano w/ ltebox + 2x UE
+  - tests 4G FDD with F1 split, 5MHz, 10MHz, 20MHz. 5MHz stable, rest known to
+    be unstable
+- [eNB-CI-FDD-Band7-B210](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-CI-FDD-Band7-B210/)
+  - hutch + B210, nano w/ ltebox + 2x UE
+  - tests T tracer, information through FlexRAN, RRC inactivity timers,
+    inactivity timers + FlexRAN, different bandwidths
+- [eNB-CI-IF4p5-FDD-Band7-B210](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-CI-IF4p5-FDD-Band7-B210/)
+  - hutch + B210, nano w/ ltebox + 2x UE
+  - tests IF4.5 split over bandwidths 5, 10, 20 MHz in Band 7
+- [eNB-CI-IF4p5-TDD-Band40-B210](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-CI-IF4p5-TDD-Band40-B210/)
+  - starsky + B210, nano w/ ltebox + 2x UE
+  - tests IF4.5 split over bandwidths 5, 10, 20 MHz in Band 40
+- [eNB-CI-TDD-Band40-B210](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-CI-TDD-Band40-B210/)
+  - starsky + B210, nano w/ ltebox + 2x UE
+  - T tracer, TM1 over bandwidths 5, 10, 20 MHz in Band 40, default scheduler
+    for 20 MHz
+- [eNB-UE-CI-MONO-FDD-Band7-B200](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-UE-CI-MONO-FDD-Band7-B200/)
+  - hutch + B210 (eNB), carabe + B210 (4G UE), nano w/ ltebox
+  - tests OAI 4G for 5 MHz/TM1 with both CN and in noS1 model, MBMS; known to
+    be unstable
+- [UE-CI-FDD-Band20-B200](https://open5glab.eurecom.fr:8083/jenkins/job/UE-CI-FDD-Band20-B200/)
+  - starsky + B210 (sniffer)
+  - Sniff MIB + SIB1 of Orange, SFR
diff --git a/doc/TESTING_5GSA_setup.md b/doc/TESTING_5GSA_setup.md
index 9b27549df438ffda963222e04c23435aecbba53c..357c62c813993ab5adedaf3afb3685687ef45729 100644
--- a/doc/TESTING_5GSA_setup.md
+++ b/doc/TESTING_5GSA_setup.md
@@ -50,7 +50,7 @@ At the moment of writing this document interoperability with the following COTS
 ## 1.1  gNB build and configuration
 To get the code and build the gNB executable:
 
-### Ubuntu 18.04
+### Build gNB
 ```bash
     git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git
     git checkout develop
@@ -61,42 +61,6 @@ To get the code and build the gNB executable:
     ./build_oai --gNB -w USRP
 ```
 
-### Ubuntu 20.04
-```bash
-    # Build UHD from source
-    # https://files.ettus.com/manual/page_build_guide.html
-    sudo apt-get install libboost-all-dev libusb-1.0-0-dev doxygen python3-docutils python3-mako python3-numpy python3-requests python3-ruamel.yaml python3-setuptools cmake build-essential
-    
-    git clone https://github.com/EttusResearch/uhd.git
-    cd uhd/host
-    mkdir build
-    cd build
-    cmake ../
-    make -j 4
-    make test # This step is optional
-    sudo make install
-    sudo ldconfig
-    sudo uhd_images_downloader
-
-
-    git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git
-    git checkout develop
-    
-    # Install dependencies in Ubuntu 20.04
-    cd
-    cd openairinterface5g/
-    source oaienv
-    cd cmake_targets/
-    ./install_external_packages.ubuntu20
-    
-    # Build OAI gNB
-    cd
-    cd openairinterface5g/
-    source oaienv
-    cd cmake_targets/
-    ./build_oai --gNB -w USRP
-```
-
 A reference configuration file for the **monolithic** gNB is provided  [here](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf).     
 
 
diff --git a/doc/testbenches_doc_resources/4g-faraday-bench.pdf b/doc/testbenches_doc_resources/4g-faraday-bench.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..7e31789e9acb9a3cc05719d98304966708925ff9
Binary files /dev/null and b/doc/testbenches_doc_resources/4g-faraday-bench.pdf differ
diff --git a/doc/testbenches_doc_resources/4g-faraday-bench.png b/doc/testbenches_doc_resources/4g-faraday-bench.png
new file mode 100644
index 0000000000000000000000000000000000000000..c69065a369c3f94b3e8a856b892f6b3bed2b42df
Binary files /dev/null and b/doc/testbenches_doc_resources/4g-faraday-bench.png differ
diff --git a/doc/testbenches_doc_resources/4g-faraday-bench.tex b/doc/testbenches_doc_resources/4g-faraday-bench.tex
new file mode 100644
index 0000000000000000000000000000000000000000..6071c89947d5590806f8ac7a31a0fb287058fd9c
--- /dev/null
+++ b/doc/testbenches_doc_resources/4g-faraday-bench.tex
@@ -0,0 +1,59 @@
+\documentclass{standalone}
+
+\usepackage{tikz}
+\usetikzlibrary{backgrounds, positioning, shapes.symbols}
+\usepackage{helvet}
+\renewcommand*{\rmdefault}{\sfdefault}
+
+\begin{document}
+\begin{tikzpicture}
+  [
+    font=\footnotesize,
+    faraday/.style={minimum size=3cm, draw, dashed},
+    duplexer/.style={draw,fill=white},
+  ]
+
+  \node[faraday, label={[anchor=south west]above left:Faraday cage}] (faraday) {};
+
+  \node[above left=0cm and 2.8cm of faraday, label=above:hutch] (hutch)
+    {\includegraphics[width=1.2cm]{server}};
+  \node[right=0.3cm of hutch, label=above:B210] (b210h)
+    {\includegraphics[width=1.2cm]{b210}} edge (hutch);
+  \node[below left=0.35cm of faraday.north east] (anto)
+    {\includegraphics[width=0.3cm]{antenna}};
+  \draw (b210h) -| node [pos=0.25, duplexer] {B7} (anto);
+
+  \node[below left=0cm and 2.8cm of faraday, label=above:starsky] (starsky)
+    {\includegraphics[width=1.2cm]{server}};
+  \node[right=0.3cm of starsky, label=above:B210] (b210s)
+    {\includegraphics[width=1.2cm]{b210}} edge (starsky);
+  \draw (hutch) -- (b210h);
+  \node[above left=0.35cm of faraday.south east] (antn)
+    {\includegraphics[width=0.3cm]{antenna}};
+  \draw (b210s) -| node [pos=0.35, duplexer] {B40} (antn);
+  \node[below right=-0.2cm and 0.8cm of b210s] (antn2)
+    {\includegraphics[width=0.3cm]{antenna}};
+  \draw (b210s) -| (antn2);
+
+  \node[left=5cm of faraday, label=above:nano] (nano)
+    {\includegraphics[width=1.2cm]{server}};
+  \draw (hutch) -- (nano);
+  \draw (starsky) -- (nano);
+  \node[above right=0.0cm and 0.35cm of faraday.west] (phone1)
+    {\includegraphics[height=0.5cm]{phone}};
+  \node[below right=0.0cm and 0.35cm of faraday.west] (phone2)
+    {\includegraphics[height=0.5cm]{phone}};
+  \draw (nano) -- node[above] {USB/adb} +(5cm,0) |- (phone1);
+  \draw (nano) -- +(5cm,0) |- (phone2);
+
+  \node[right=1.5cm of faraday, label=above:B210] (b210c)
+    {\includegraphics[width=1.2cm]{b210}};
+  \node[left=.5cm of faraday.east] (antc)
+    {\includegraphics[width=0.3cm]{antenna}};
+  \draw (b210c) -- node [pos=0.35, duplexer] {B7UE} (antc);
+  \node[right=0.7cm of b210c, label=above:carabe] (carabe)
+    {\includegraphics[width=1.2cm]{server}}
+    edge (b210c);
+
+\end{tikzpicture}
+\end{document}
diff --git a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.pdf b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..f6d960c1a257651b538b404f8f019438d3014f15
Binary files /dev/null and b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.pdf differ
diff --git a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.png b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.png
new file mode 100644
index 0000000000000000000000000000000000000000..c677b598e9894a1bbf0e1e7321497e4c51e6fb17
Binary files /dev/null and b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.png differ
diff --git a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex
new file mode 100644
index 0000000000000000000000000000000000000000..66b52f7f697b76a0922370b87353573f30cbee9b
--- /dev/null
+++ b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex
@@ -0,0 +1,55 @@
+\documentclass{standalone}
+
+\usepackage{tikz}
+\usetikzlibrary{backgrounds, positioning, shapes.symbols}
+\usepackage{helvet}
+\renewcommand*{\rmdefault}{\sfdefault}
+
+\begin{document}
+\begin{tikzpicture}
+  [
+    font=\footnotesize,
+    faraday/.style={minimum size=3cm, draw, dashed},
+    duplexer/.style={draw,fill=white},
+  ]
+
+  \node[faraday, label={[anchor=south east]above right:Faraday cage}] (faraday) {};
+
+  \node[above left=0cm and 2.8cm of faraday, label=above:obelix] (obelix)
+    {\includegraphics[width=1.2cm]{server}};
+  \node[right=0.3cm of obelix, label=above:B200-mini] (b210o)
+    {\includegraphics[width=1.2cm]{b200-mini}} edge (obelix);
+  \node[below right=0.35cm of faraday.north west] (anto)
+    {\includegraphics[width=0.3cm]{antenna}};
+  \draw (b210o) -| node [pos=0.2, duplexer] {B7} (anto);
+
+  \node[below left=0cm and 2.8cm of faraday, label=above:nepes] (nepes)
+    {\includegraphics[width=1.2cm]{server}};
+  \node[right=0.3cm of nepes, label=above:B200-mini] (b210n)
+    {\includegraphics[width=1.2cm]{b200-mini}} edge (nepes);
+  \draw (obelix) -- (b210o);
+  \node[above right=0.35cm of faraday.south west] (antn)
+    {\includegraphics[width=0.3cm]{antenna}};
+  \draw (b210n) -| node [pos=0.2, duplexer] {B78} (antn);
+
+  \node[left=5cm of faraday, label=above:porcepix] (porcepix)
+    {\includegraphics[width=1.2cm]{server}};
+  \draw (obelix) -- (porcepix);
+  \draw (nepes) -- (porcepix);
+
+  \node[right=1.5cm of faraday, label=above:RM500Q-GL] (quectel)
+    {\includegraphics[height=1.2cm]{quectel}};
+  \node[above left=-0.1cm and 0.2cm of faraday.east] (aq2)
+    {\includegraphics[width=0.3cm]{antenna}} edge (quectel);
+  \node[above=-0.2cm of aq2] (aq1)
+    {\includegraphics[width=0.3cm]{antenna}} edge (quectel);
+  \node[below=-0.2cm of aq2] (aq3)
+    {\includegraphics[width=0.3cm]{antenna}} edge (quectel);
+  \node[below=-0.2cm of aq3]
+    {\includegraphics[width=0.3cm]{antenna}} edge (quectel);
+  \node[right=1cm of quectel, label=above:idefix] (idefix)
+    {\includegraphics[width=1.2cm]{server}}
+    edge (quectel);
+
+\end{tikzpicture}
+\end{document}
diff --git a/doc/testbenches_doc_resources/5g-ota-bench.pdf b/doc/testbenches_doc_resources/5g-ota-bench.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..e4d4c15e394ad4664d6eea6580db9952d8d7e341
Binary files /dev/null and b/doc/testbenches_doc_resources/5g-ota-bench.pdf differ
diff --git a/doc/testbenches_doc_resources/5g-ota-bench.png b/doc/testbenches_doc_resources/5g-ota-bench.png
new file mode 100644
index 0000000000000000000000000000000000000000..c93de7ec6fde10508184eff7f68215c72d3924ec
Binary files /dev/null and b/doc/testbenches_doc_resources/5g-ota-bench.png differ
diff --git a/doc/testbenches_doc_resources/5g-ota-bench.tex b/doc/testbenches_doc_resources/5g-ota-bench.tex
new file mode 100644
index 0000000000000000000000000000000000000000..cfd0bda22d60c4b97b6913f5bd8923970f1c4bd2
--- /dev/null
+++ b/doc/testbenches_doc_resources/5g-ota-bench.tex
@@ -0,0 +1,63 @@
+\documentclass{standalone}
+
+\usepackage{tikz}
+\usetikzlibrary{backgrounds, positioning, shapes.symbols}
+\usepackage{helvet}
+\renewcommand*{\rmdefault}{\sfdefault}
+
+\begin{document}
+\begin{tikzpicture}
+  [
+    font=\footnotesize,
+    faraday/.style={minimum size=3cm, draw, dashed},
+    duplexer/.style={draw,fill=white},
+  ]
+
+  \node[label=above:porcepix] (porcepix)
+    {\includegraphics[width=1.2cm]{server}};
+
+  \node[above right=1cm and 2cm of porcepix, label=above:asterix] (asterix)
+    {\includegraphics[width=1.2cm]{server}}
+    edge (porcepix);
+  \node[right=0.3cm of asterix, label=above:N310] (n310a)
+    {\includegraphics[width=1.5cm]{n310}} edge (asterix);
+  \node[right=.2cm of n310a, duplexer] (b78o) {B78} edge (n310a);
+  \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
+    {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
+  \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
+    {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
+
+  \node[right=2cm of porcepix, label=above:obelix] (obelix)
+    {\includegraphics[width=1.2cm]{server}}
+    edge (porcepix);
+  \node[above right=-0.5cm and 0.3cm of obelix, label=above:N310] (n310o)
+    {\includegraphics[width=1.5cm]{n310}} edge (obelix);
+  \node[right=.2cm of n310o, duplexer] (b78o) {B40} edge (n310o);
+  \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
+    {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
+  \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
+    {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
+  \node[below right=-0.5cm and 0.3cm of obelix, label=above:X310] (x310o)
+    {\includegraphics[width=1.5cm]{x310}} edge (obelix);
+  \node[right=.2cm of x310o, duplexer] (b78o) {B78} edge (x310o);
+  \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
+    {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
+  \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
+    {\includegraphics[width=0.3cm]{antenna}} edge (b78o);
+
+  \node[right=5.0cm of n310o, label=above:RM500Q-GL] (quectel)
+    {\includegraphics[height=1.2cm]{quectel}};
+  \node[above left=-0.1cm and 0.8cm of quectel.west] (aq2)
+    {\includegraphics[width=0.3cm]{antenna}} edge (quectel);
+  \node[above=-0.2cm of aq2] (aq1)
+    {\includegraphics[width=0.3cm]{antenna}} edge (quectel);
+  \node[below=-0.2cm of aq2] (aq3)
+    {\includegraphics[width=0.3cm]{antenna}} edge (quectel);
+  \node[below=-0.2cm of aq3]
+    {\includegraphics[width=0.3cm]{antenna}} edge (quectel);
+  \node[right=1cm of quectel, label=above:nrmodule2] (nrmodule2)
+    {\includegraphics[width=1.2cm]{server}}
+    edge (quectel);
+
+\end{tikzpicture}
+\end{document}
diff --git a/doc/testbenches_doc_resources/antenna.pdf b/doc/testbenches_doc_resources/antenna.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..0d48aa8ab9e17defba56fb89e6c7f36c6f3ec548
Binary files /dev/null and b/doc/testbenches_doc_resources/antenna.pdf differ
diff --git a/doc/testbenches_doc_resources/b200-mini.png b/doc/testbenches_doc_resources/b200-mini.png
new file mode 100644
index 0000000000000000000000000000000000000000..0355e45f1837b3ca5129566cb524af070ee06c5d
Binary files /dev/null and b/doc/testbenches_doc_resources/b200-mini.png differ
diff --git a/doc/testbenches_doc_resources/b210.jpg b/doc/testbenches_doc_resources/b210.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..23599b0b1f9cc6d25830ecb3bd12208351dac9da
Binary files /dev/null and b/doc/testbenches_doc_resources/b210.jpg differ
diff --git a/doc/testbenches_doc_resources/indoor_live.jpg b/doc/testbenches_doc_resources/indoor_live.jpg
deleted file mode 100755
index ce8b9cda4817796abf6fb87da43befe6090469be..0000000000000000000000000000000000000000
Binary files a/doc/testbenches_doc_resources/indoor_live.jpg and /dev/null differ
diff --git a/doc/testbenches_doc_resources/legacy1.jpg b/doc/testbenches_doc_resources/legacy1.jpg
deleted file mode 100755
index c3579df3e4a56521eff8f23df1dbca9ba9fd3a59..0000000000000000000000000000000000000000
Binary files a/doc/testbenches_doc_resources/legacy1.jpg and /dev/null differ
diff --git a/doc/testbenches_doc_resources/legacy2.jpg b/doc/testbenches_doc_resources/legacy2.jpg
deleted file mode 100755
index f40d167a2db2626f4be2a47fb82528cc9df5abae..0000000000000000000000000000000000000000
Binary files a/doc/testbenches_doc_resources/legacy2.jpg and /dev/null differ
diff --git a/doc/testbenches_doc_resources/n310.png b/doc/testbenches_doc_resources/n310.png
new file mode 100644
index 0000000000000000000000000000000000000000..7d6ead5718497c72f4fd972f3da5fd9fe95744d1
Binary files /dev/null and b/doc/testbenches_doc_resources/n310.png differ
diff --git a/doc/testbenches_doc_resources/next_ci.jpg b/doc/testbenches_doc_resources/next_ci.jpg
deleted file mode 100755
index 2d4111510c061b5d18ed1ae3097e3c6cc0040437..0000000000000000000000000000000000000000
Binary files a/doc/testbenches_doc_resources/next_ci.jpg and /dev/null differ
diff --git a/doc/testbenches_doc_resources/next_dev.jpg b/doc/testbenches_doc_resources/next_dev.jpg
deleted file mode 100755
index 72e9f63bf91cdb7fd47a44780126b7269bf0475f..0000000000000000000000000000000000000000
Binary files a/doc/testbenches_doc_resources/next_dev.jpg and /dev/null differ
diff --git a/doc/testbenches_doc_resources/outdoor_live.jpg b/doc/testbenches_doc_resources/outdoor_live.jpg
deleted file mode 100755
index eba44a3c00e7456c7d2d0cc12ea1e77db31ae10a..0000000000000000000000000000000000000000
Binary files a/doc/testbenches_doc_resources/outdoor_live.jpg and /dev/null differ
diff --git a/doc/testbenches_doc_resources/phone.pdf b/doc/testbenches_doc_resources/phone.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..4451c7af1ac6af3251edb72fada64e08384d23a6
Binary files /dev/null and b/doc/testbenches_doc_resources/phone.pdf differ
diff --git a/doc/testbenches_doc_resources/quectel.png b/doc/testbenches_doc_resources/quectel.png
new file mode 100644
index 0000000000000000000000000000000000000000..443e62dcb569996103380797afafbe382835298e
Binary files /dev/null and b/doc/testbenches_doc_resources/quectel.png differ
diff --git a/doc/testbenches_doc_resources/server.pdf b/doc/testbenches_doc_resources/server.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..6034fcf667018a2709804dc9bfa136a56aec281f
Binary files /dev/null and b/doc/testbenches_doc_resources/server.pdf differ
diff --git a/doc/testbenches_doc_resources/x310.jpg b/doc/testbenches_doc_resources/x310.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..3e14d30a15849d57cc30fb384024e825217fb50e
Binary files /dev/null and b/doc/testbenches_doc_resources/x310.jpg differ
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
index e67897b44d3b93ba0c08599c7fd35da0c14fa11c..f5404ecfdb80d9804e5d3bcc519d6aecc07508dc 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
@@ -467,6 +467,7 @@ typedef struct {
   uint8_t nEpreRatioOfPDSCHToPTRS;
   /// MCS table for this DLSCH
   uint8_t mcs_table;
+  uint32_t tbslbrm;
   uint8_t nscid;
   uint16_t dlDmrsScramblingId;
   uint16_t pduBitmap;
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
index f84ae5a37e5ea2a9773474e009951aa3d59b4193..8b564a5e3743be1a3ccf14ff2c53581eb7ceb11d 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
@@ -776,6 +776,10 @@ typedef struct {
   nfapi_nr_dl_dci_pdu_t dci_pdu[MAX_DCI_CORESET];
 }  nfapi_nr_dl_tti_pdcch_pdu_rel15_t;
 
+typedef struct {
+  uint32_t tbSizeLbrmBytes;
+}nfapi_v3_pdsch_maintenance_parameters_t;
+
 typedef struct {
   uint16_t pduBitmap;
   uint16_t rnti;
@@ -854,6 +858,7 @@ typedef struct {
   uint8_t nEpreRatioOfPDSCHToPTRS;
   // Beamforming
   nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming;
+  nfapi_v3_pdsch_maintenance_parameters_t maintenance_parms_v3;
 }nfapi_nr_dl_tti_pdsch_pdu_rel15_t;
 
 
@@ -1187,6 +1192,10 @@ typedef struct
 #define PUSCH_PDU_BITMAP_PUSCH_PTRS 0x4
 #define PUSCH_PDU_BITMAP_DFTS_OFDM  0x8
 
+typedef struct {
+  uint32_t tbSizeLbrmBytes;
+}nfapi_v3_pusch_maintenance_parameters_t;
+
 typedef struct
 {
   uint16_t pdu_bit_map;//Bitmap indicating presence of optional PDUs (see above)
@@ -1232,7 +1241,7 @@ typedef struct
   nfapi_nr_dfts_ofdm_t dfts_ofdm;
   //beamforming
   nfapi_nr_ul_beamforming_t beamforming;
-
+  nfapi_v3_pdsch_maintenance_parameters_t maintenance_parms_v3;
 } nfapi_nr_pusch_pdu_t;
 
 //for pucch_pdu:
diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h
index 8fe31f208ea4c76db380866faa87aa2d0277add2..51cae1bd8cab1e5b4e2884ba8e39d0dd0346401b 100644
--- a/openair1/PHY/CODING/coding_defs.h
+++ b/openair1/PHY/CODING/coding_defs.h
@@ -481,16 +481,11 @@ uint32_t nr_compute_tbs(uint16_t Qm,
                         uint8_t tb_scaling,
 			uint8_t Nl);
 
-uint32_t nr_compute_tbslbrm(uint16_t table,
-			    uint16_t nb_rb,
-		            uint8_t Nl);
-
 void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f);
 
 void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f);
 
-int nr_rate_matching_ldpc(uint8_t Ilbrm,
-                          uint32_t Tbslbrm,
+int nr_rate_matching_ldpc(uint32_t Tbslbrm,
                           uint8_t BG,
                           uint16_t Z,
                           uint8_t *w,
@@ -501,8 +496,7 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm,
                           uint8_t rvidx,
                           uint32_t E);
 
-int nr_rate_matching_ldpc_rx(uint8_t Ilbrm,
-                             uint32_t Tbslbrm,
+int nr_rate_matching_ldpc_rx(uint32_t Tbslbrm,
                              uint8_t BG,
                              uint16_t Z,
                              int16_t *w,
diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c
index 782bb390243c65b73569d0b732773c18a4884a82..06dfcaa4a943e35d9c121490a30c0a7fd69510f8 100644
--- a/openair1/PHY/CODING/nr_rate_matching.c
+++ b/openair1/PHY/CODING/nr_rate_matching.c
@@ -387,8 +387,7 @@ void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f)
 }
 
 
-int nr_rate_matching_ldpc(uint8_t Ilbrm,
-                          uint32_t Tbslbrm,
+int nr_rate_matching_ldpc(uint32_t Tbslbrm,
                           uint8_t BG,
                           uint16_t Z,
                           uint8_t *w,
@@ -409,7 +408,7 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm,
   //Bit selection
   N = (BG==1)?(66*Z):(50*Z);
 
-  if (Ilbrm == 0)
+  if (Tbslbrm == 0)
       Ncb = N;
   else {
       Nref = 3*Tbslbrm/(2*C); //R_LBRM = 2/3
@@ -419,11 +418,11 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm,
   ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z;
 
 #ifdef RM_DEBUG
-  printf("nr_rate_matching_ldpc: E %d, F %d, Foffset %d, k0 %d, Ncb %d, rvidx %d, Ilbrm %d\n", E, F, Foffset,ind, Ncb, rvidx, Ilbrm);
+  printf("nr_rate_matching_ldpc: E %d, F %d, Foffset %d, k0 %d, Ncb %d, rvidx %d, Tbslbrm %d\n", E, F, Foffset,ind, Ncb, rvidx, Tbslbrm);
 #endif
 
   if (Foffset > E) {
-    LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > E %d) F %d, k0 %d, Ncb %d, rvidx %d, Ilbrm %d\n",Foffset,E,F, ind, Ncb, rvidx, Ilbrm);
+    LOG_E(PHY,"nr_rate_matching: invalid parameters (Foffset %d > E %d) F %d, k0 %d, Ncb %d, rvidx %d, Tbslbrm %d\n",Foffset,E,F, ind, Ncb, rvidx, Tbslbrm);
     return -1;
   }
   if (Foffset > Ncb) {
@@ -471,8 +470,7 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm,
   return 0;
 }
 
-int nr_rate_matching_ldpc_rx(uint8_t Ilbrm,
-                             uint32_t Tbslbrm,
+int nr_rate_matching_ldpc_rx(uint32_t Tbslbrm,
                              uint8_t BG,
                              uint16_t Z,
                              int16_t *w,
@@ -498,7 +496,7 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm,
   //Bit selection
   N = (BG==1)?(66*Z):(50*Z);
 
-  if (Ilbrm == 0)
+  if (Tbslbrm == 0)
       Ncb = N;
   else {
       Nref = (3*Tbslbrm/(2*C)); //R_LBRM = 2/3
@@ -516,7 +514,7 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm,
   }
 
 #ifdef RM_DEBUG
-  printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, k0 %d, Ncb %d, rvidx %d, Ilbrm %d\n", clear, E, ind, Ncb, rvidx, Ilbrm);
+  printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, k0 %d, Ncb %d, rvidx %d, Tbslbrm %d\n", clear, E, ind, Ncb, rvidx, Tbslbrm);
 #endif
 
   if (clear==1) memset(w,0,Ncb*sizeof(int16_t));
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
index f7abc2a513cf6d587f11afb912a5ad77cbdc010a..84ea27fb9c982027350217eb428bbb255bae29fd 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
@@ -240,19 +240,12 @@ void ldpc8blocks( void *p) {
           impp->F,
           Kr-impp->F-2*(*impp->Zc),
           mod_order,nb_rb,rel15->nrOfLayers);
-    // for tbslbrm calculation according to 5.4.2.1 of 38.212
-    uint8_t Nl = 4;
 
-    if (rel15->nrOfLayers < Nl)
-      Nl = rel15->nrOfLayers;
-
-    uint32_t Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl);
-    uint8_t Ilbrm = 1;
+    uint32_t Tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes;
 
     uint8_t e[E];
     bzero (e, E);
-    nr_rate_matching_ldpc(Ilbrm,
-                          Tbslbrm,
+    nr_rate_matching_ldpc(Tbslbrm,
                           impp->BG,
                           *impp->Zc,
                           impp->d[rr],
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
index 39f14b05f89912e3a927e5bee68a87019967ec54..b4e1034fb66ade3fc91434ca4d44b282ba7e8578 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
@@ -234,7 +234,6 @@ void nr_processULSegment(void* arg) {
   int rv_index = rdata->rv_index;
   int r_offset = rdata->r_offset;
   uint8_t kc = rdata->Kc;
-  uint32_t Tbslbrm = rdata->Tbslbrm;
   short* ulsch_llr = rdata->ulsch_llr;
   int max_ldpc_iterations = p_decoderParms->numMaxIter;
   int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32)));
@@ -244,8 +243,6 @@ void nr_processULSegment(void* arg) {
 
   __m128i *pv = (__m128i*)&z;
   __m128i *pl = (__m128i*)&l;
-  
-  uint8_t  Ilbrm    = 0;
 
   Kr = ulsch_harq->K;
   Kr_bytes = Kr>>3;
@@ -293,8 +290,7 @@ void nr_processULSegment(void* arg) {
 
   //start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
 
-  if (nr_rate_matching_ldpc_rx(Ilbrm,
-                               Tbslbrm,
+  if (nr_rate_matching_ldpc_rx(rdata->tbslbrm,
                                p_decoderParms->BG,
                                p_decoderParms->Z,
                                ulsch_harq->d[r],
@@ -394,7 +390,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
   uint32_t r_offset;
   uint32_t offset;
   int kc;
-  int Tbslbrm;
   int E;
 
 #ifdef PRINT_CRC_CHECK
@@ -539,7 +534,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
   if (!frame%100)
     printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z);
 #endif
-  Tbslbrm = nr_compute_tbslbrm(0,nb_rb,n_layers);
 
   p_decParams->Z = harq_process->Z;
 
@@ -590,10 +584,10 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
     rdata->r_offset = r_offset;
     rdata->Kr_bytes = Kr_bytes;
     rdata->rv_index = pusch_pdu->pusch_data.rv_index;
-    rdata->Tbslbrm = Tbslbrm;
     rdata->offset = offset;
     rdata->ulsch = ulsch;
     rdata->ulsch_id = ULSCH_id;
+    rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
     pushTpool(phy_vars_gNB->threadPool,req);
     phy_vars_gNB->nbDecode++;
     LOG_D(PHY,"Added a block to decode, in pipe: %d\n",phy_vars_gNB->nbDecode);
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
index 95d2cd95779347f81396d59b61b3c0e87b14ff84..a832e8f29c9f1aebd2b9bc1d9f79df8829d00534 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
@@ -289,8 +289,6 @@ void nr_processDLSegment(void* arg) {
   __m128i *pv = (__m128i*)&z;
   __m128i *pl = (__m128i*)&l;
 
-  uint8_t Ilbrm = 1;
-
   Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb"
   Kr_bytes = Kr>>3;
   K_bits_F = Kr-harq_process->F;
@@ -323,8 +321,7 @@ void nr_processDLSegment(void* arg) {
         harq_process->round); */
   //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_IN);
 
-  if (nr_rate_matching_ldpc_rx(Ilbrm,
-                               Tbslbrm,
+  if (nr_rate_matching_ldpc_rx(Tbslbrm,
                                p_decoderParms->BG,
                                p_decoderParms->Z,
                                harq_process->d[r],
@@ -451,7 +448,6 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
   phy_vars_ue->dl_stats[harq_process->DLround]++;
   LOG_D(PHY,"Round %d RV idx %d\n",harq_process->DLround,harq_process->rvidx);
   uint8_t kc;
-  uint32_t Tbslbrm;// = 950984;
   uint16_t nb_rb;// = 30;
   double Coderate;// = 0.0;
   uint8_t dmrs_Type = harq_process->dmrsConfigType;
@@ -567,10 +563,6 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
     if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!frame%100))
       LOG_I(PHY,"K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl);
   }
-  if ((harq_process->Nl)<4)
-    Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl);
-  else
-    Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4);
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT);
   p_decParams->Z = harq_process->Z;
@@ -621,7 +613,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
     rdata->r_offset = r_offset;
     rdata->Kr_bytes = Kr_bytes;
     rdata->rv_index = harq_process->rvidx;
-    rdata->Tbslbrm = Tbslbrm;
+    rdata->Tbslbrm = harq_process->tbslbrm;
     rdata->offset = offset;
     rdata->dlsch = dlsch;
     rdata->dlsch_id = 0;
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
index 4086f60f02e956f5f2fe4c10bea0f5f9a7cbbf8b..08e99434dd782a2864021abad753265a76ac6370 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
@@ -260,6 +260,7 @@ typedef struct {
   uint16_t ptrs_symbols;
   // PTRS symbol index, to be updated every PTRS symbol within a slot.
   uint8_t ptrs_symbol_index;
+  uint32_t tbslbrm;
   uint8_t nscid;
   uint16_t dlDmrsScramblingId;
   /// PDU BITMAP 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
index 87ba2090e7c1997209b2008939595a615ef1b158..5de615a0ccfc0412a4da8b132328b8db8e719ab5 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
@@ -171,8 +171,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
                       NR_UE_ULSCH_t *ulsch,
                       NR_DL_FRAME_PARMS* frame_parms,
                       uint8_t harq_pid,
-                      unsigned int G)
-{
+                      unsigned int G) {
+
   start_meas(&ue->ulsch_encoding_stats);
 
 /////////////////////////parameters and variables initialization/////////////////////////
@@ -188,9 +188,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
   uint16_t Kr=0;
   uint32_t r_offset=0;
   uint32_t F=0;
-  uint8_t Ilbrm = 0;
-  uint32_t Tbslbrm = 950984; //max tbs
   float Coderate = 0.0;
+
 ///////////
 /////////////////////////////////////////////////////////////////////////////////////////  
 
@@ -376,12 +375,9 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
 
     uint32_t E = nr_get_E(G, harq_process->C, mod_order, harq_process->pusch_pdu.nrOfLayers, r);
 
-    Tbslbrm = nr_compute_tbslbrm(0,nb_rb,harq_process->pusch_pdu.nrOfLayers);
-
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN);
     start_meas(&ue->ulsch_rate_matching_stats);
-    if (nr_rate_matching_ldpc(Ilbrm,
-                              Tbslbrm,
+    if (nr_rate_matching_ldpc(0,
                               harq_process->BG,
                               *pz,
                               harq_process->d[r],
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index 3c16da129afe6787c4d12950c88bd058aea42752..9b9c59f8b78da1e01eb9df3b1d0091c9d86db2d2 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -934,8 +934,8 @@ typedef struct LDPCDecode_s {
   int segment_r;
   int r_offset;
   int offset;
-  int Tbslbrm;
   int decodeIterations;
+  uint32_t tbslbrm;
 } ldpcDecode_t;
 
 struct ldpcReqId {
diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
index e81a3990285ffbbe5a968e1d0d702121423c8b1d..8427b28178b5ff615547e077b7787589acc71e4b 100644
--- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
+++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
@@ -315,6 +315,7 @@ void configure_dlsch(NR_UE_DLSCH_t *dlsch0,
   dlsch0_harq->mcs = dlsch_config_pdu->mcs;
   dlsch0_harq->rvidx = dlsch_config_pdu->rv;
   dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH;
+  dlsch0_harq->tbslbrm = dlsch_config_pdu->tbslbrm;
   dlsch0_harq->nscid = dlsch_config_pdu->nscid;
   dlsch0_harq->dlDmrsScramblingId = dlsch_config_pdu->dlDmrsScramblingId;
   //get nrOfLayers from DCI info
@@ -341,6 +342,7 @@ void configure_dlsch(NR_UE_DLSCH_t *dlsch0,
   LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\n", dlsch0->g_pucch, dlsch0_harq->mcs);
 }
 
+
 int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
 
   bool found = false;
diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c
index 6f747b36a63e59715d927a9398fadae8fc2b15cc..a14a1ff3c6f3acd5e89ca032409d9493c8210e66 100644
--- a/openair1/SIMULATION/NR_PHY/dlschsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlschsim.c
@@ -119,6 +119,7 @@ int main(int argc, char **argv)
         double DS_TDL = .03;
 	cpuf = get_cpu_freq_GHz();
 	char gNBthreads[128]="n";
+        int Tbslbrm = 950984;
 
 	if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == 0) {
 		exit_fun("[NR_DLSCHSIM] Error, configuration module init failed\n");
@@ -457,6 +458,7 @@ int main(int argc, char **argv)
 	rel15->dlDmrsSymbPos = 4;
 	rel15->mcsIndex[0] = Imcs;
         rel15->numDmrsCdmGrpsNoData = 1;
+        rel15->maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm;
 	double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc
 	short channel_output_fixed[16 * 68 * 384];
 	//unsigned char *estimated_output;
@@ -476,6 +478,7 @@ int main(int argc, char **argv)
 	harq_process->dmrsConfigType = NFAPI_NR_DMRS_TYPE1;
 	harq_process->dlDmrsSymbPos = 4;
 	harq_process->n_dmrs_cdm_groups = 1;
+        harq_process->tbslbrm = Tbslbrm;
 	printf("harq process ue mcs = %d Qm = %d, symb %d\n", harq_process->mcs, harq_process->Qm, nb_symb_sch);
 
 	unsigned char *test_input=dlsch->harq_process.pdu;
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c
index c33946fa5ac781a95c795e122cb498d765de373b..855b6e98224e6710776538e8d8bab850e3206acb 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c
@@ -92,12 +92,10 @@ uint32_t nr_compute_tbs(uint16_t Qm,
 
 }
 
-
 //tbslbrm calculation according to 5.4.2.1 of 38.212
 uint32_t nr_compute_tbslbrm(uint16_t table,
 			    uint16_t nb_rb,
-		            uint8_t Nl)
-{
+		            uint8_t Nl) {
 
   uint16_t R, nb_re;
   uint16_t nb_rb_lbrm=0;
@@ -122,34 +120,31 @@ uint32_t nr_compute_tbslbrm(uint16_t table,
   Ninfo = (nb_re * R * Qm * Nl)>>10;
 
   if (Ninfo <=3824) {
-    	n = max(3, floor(log2(Ninfo)) - 6);
-        Np_info = max(24, (Ninfo>>n)<<n);
-        for (int i=0; i<INDEX_MAX_TBS_TABLE; i++) {
-        	if (Tbstable_nr[i] >= Np_info){
-        		nr_tbs = Tbstable_nr[i];
-        		break;
-        	}
-        }
+    n = max(3, floor(log2(Ninfo)) - 6);
+    Np_info = max(24, (Ninfo>>n)<<n);
+    for (int i=0; i<INDEX_MAX_TBS_TABLE; i++) {
+      if (Tbstable_nr[i] >= Np_info){
+        nr_tbs = Tbstable_nr[i];
+        break;
+      }
+    }
   }
   else {
-    	n = log2(Ninfo-24)-5;
-        Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n);
-
-        if (R <= 256) { 
-            C = CEILIDIV((Np_info+24),3816);
-            nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
-        }
-        else {
-            if (Np_info > 8424){
-                C = CEILIDIV((Np_info+24),8424);
-                nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
-            }
-            else {
-            	nr_tbs = ((CEILIDIV((Np_info+24),8))<<3) - 24;
-            }
-
-        }
+    n = log2(Ninfo-24)-5;
+    Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n);
 
+    if (R <= 256) {
+      C = CEILIDIV((Np_info+24),3816);
+      nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
+    }
+    else {
+      if (Np_info > 8424){
+        C = CEILIDIV((Np_info+24),8424);
+        nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
+      }
+      else
+        nr_tbs = ((CEILIDIV((Np_info+24),8))<<3) - 24;
+    }
   }
   return nr_tbs;
 }
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index cc5d38f9d5eeb6976ead7105307701662cef70be..4d41432f443b892f8937c1e224456bbb212a9868 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -4087,6 +4087,25 @@ uint16_t compute_pucch_prb_size(uint8_t format,
   }
 }
 
+int get_bw_tbslbrm(NR_BWP_t *genericParameters,
+                   NR_CellGroupConfig_t *cg) {
+
+  int bw = 0;
+  if (cg && cg->spCellConfig && cg->spCellConfig->spCellConfigDedicated &&
+      cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList) {
+    struct NR_ServingCellConfig__downlinkBWP_ToAddModList *BWP_list = cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
+    for (int i=0; i<BWP_list->list.count; i++) {
+      genericParameters = &BWP_list->list.array[i]->bwp_Common->genericParameters;
+      int curr_bw = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
+      if (curr_bw > bw)
+        bw = curr_bw;
+    }
+  }
+  else
+    bw = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
+  return bw;
+}
+
 /* extract UL PTRS values from RRC and validate it based upon 38.214 6.2.3 */
 bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config,
                         uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable,
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
index 80b69d2e5f1ff792a09a2f20e8ff5f0f28da57ff..442ddd7f2af2781d1d6b9609608d8b7f5472c616 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
@@ -122,6 +122,13 @@ uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB);
 
 uint16_t get_nr_srs_offset(NR_SRS_PeriodicityAndOffset_t periodicityAndOffset);
 
+int get_bw_tbslbrm(NR_BWP_t *genericParameters,
+                   NR_CellGroupConfig_t *cg);
+
+uint32_t nr_compute_tbslbrm(uint16_t table,
+			    uint16_t nb_rb,
+		            uint8_t Nl);
+
 void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
                                            frame_t frameP,
                                            NR_MIB_t *mib,
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 362d979026de92bbfdae27e4ae1115b4828c2155..44d054202236dfc4cb11edd172d4f8da099cc1f4 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -919,6 +919,19 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
       LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_0->mcs);
       return -1;
     }
+
+    int bw_tbslbrm;
+    if (mac->scc || mac->scc_SIB || mac->cg) {
+      NR_BWP_t genericParameters = mac->scc ? mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters :
+                                              mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters;
+      bw_tbslbrm = get_bw_tbslbrm(&genericParameters, mac->cg);
+    }
+    else
+      bw_tbslbrm = dlsch_config_pdu_1_0->BWPSize;
+    dlsch_config_pdu_1_0->tbslbrm = nr_compute_tbslbrm(dlsch_config_pdu_1_0->mcs_table,
+			                               bw_tbslbrm,
+		                                       1);
+
     /* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
     dlsch_config_pdu_1_0->ndi = dci->ndi;
     /* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
@@ -1324,6 +1337,17 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     dl_config->number_pdus = dl_config->number_pdus + 1;
     /* TODO same calculation for MCS table as done in UL */
     dlsch_config_pdu_1_1->mcs_table = (pdsch_Config->mcs_Table) ? (*pdsch_Config->mcs_Table + 1) : 0;
+
+    // TBS_LBRM according to section 5.4.2.1 of 38.212
+    long *maxMIMO_Layers = mac->cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers;
+    AssertFatal (maxMIMO_Layers != NULL,"Option with max MIMO layers not configured is not supported\n");
+    int nl_tbslbrm = *maxMIMO_Layers < 4 ? *maxMIMO_Layers : 4;
+    NR_BWP_t genericParameters = mac->scc ? mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters :
+                                            mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters;
+    int bw_tbslbrm = get_bw_tbslbrm(&genericParameters, mac->cg);
+    dlsch_config_pdu_1_1->tbslbrm = nr_compute_tbslbrm(dlsch_config_pdu_1_1->mcs_table,
+			                               bw_tbslbrm,
+		                                       nl_tbslbrm);
     /*PTRS configuration */
     dlsch_config_pdu_1_1->pduBitmap = 0;
     if(pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) {
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index c797b6b0d788509ba6157af7b58c242a4416754f..b895543518812cd0e45cfb0f9a2b906109584f2c 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -1425,6 +1425,11 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
       pdsch_pdu_rel15->TBSize[0] = TBS;
     }
 
+    int bw_tbslbrm = get_bw_tbslbrm(genericParameters, ra->CellGroup);
+    pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx,
+                                                                               bw_tbslbrm,
+                                                                               1);
+
     // Fill PDCCH DL DCI PDU
     nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
     pdcch_pdu_rel15->numDlDci++;
@@ -1802,6 +1807,11 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra
     int x_Overhead = 0;
     nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, tb_scaling);
 
+    int bw_tbslbrm = get_bw_tbslbrm(genericParameters, ra->CellGroup);
+    pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx,
+                                                                               bw_tbslbrm,
+                                                                               1);
+
     pdsch_pdu_rel15->precodingAndBeamforming.num_prgs=1;
     pdsch_pdu_rel15->precodingAndBeamforming.prg_size=275;
     pdsch_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces=1;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
index 9229cfbdbd292f5926f4522ea710f93976ae7da7..b4ba1063f1877e96df852b5b1b4416d7af265860 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
@@ -504,6 +504,10 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
   LOG_D(NR_MAC,"sib1:rbStart %d, rbSize %d\n",pdsch_pdu_rel15->rbStart,pdsch_pdu_rel15->rbSize);
   LOG_D(NR_MAC,"sib1:dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->dlDmrsSymbPos);
 
+  pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(0,
+                                                                             pdsch_pdu_rel15->BWPSize,
+                                                                             1);
+
   /* Fill PDCCH DL DCI PDU */
   nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
   pdcch_pdu_rel15->numDlDci++;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index 5229ea06db727f5e738a769aa29685b8dd1ff319..3dba8ff928d176b76a198c691f8f25d3fc8d5ca2 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -1257,6 +1257,17 @@ void nr_schedule_ue_spec(module_id_t module_id,
     // Resource Allocation in time domain
     pdsch_pdu->StartSymbolIndex = ps->startSymbolIndex;
     pdsch_pdu->NrOfSymbols = ps->nrOfSymbols;
+
+    // TBS_LBRM according to section 5.4.2.1 of 38.212
+    long *maxMIMO_Layers = cg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers;
+    AssertFatal (maxMIMO_Layers != NULL,"Option with max MIMO layers not configured is not supported\n");
+    int nl_tbslbrm = *maxMIMO_Layers < 4 ? *maxMIMO_Layers : 4;
+    // Maximum number of PRBs across all configured DL BWPs
+    int bw_tbslbrm = get_bw_tbslbrm(genericParameters, cg);
+    pdsch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(ps->mcsTableIdx,
+                                                                         bw_tbslbrm,
+                                                                         nl_tbslbrm);
+
     NR_PDSCH_Config_t *pdsch_Config=NULL;
 
     if (bwp &&
@@ -1310,7 +1321,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
     dci_pdu_rel15_t dci_payload;
     memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t));
     // bwp indicator
-    const int n_dl_bwp = bwp ? UE_info->CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count : 0;
+    const int n_dl_bwp = bwp ? cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count : 0;
     AssertFatal(n_dl_bwp <= 1, "downlinkBWP_ToAddModList has %d BWP!\n", n_dl_bwp);
     // as per table 7.3.1.1.2-1 in 38.212
     dci_payload.bwp_indicator.val = bwp ? (n_dl_bwp < 4 ? bwp->bwp_Id : bwp->bwp_Id - 1) : 0;
@@ -1357,7 +1368,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
 
     const int rnti_type = NR_RNTI_C;
     fill_dci_pdu_rel15(scc,
-                       UE_info->CellGroup[UE_id],
+                       cg,
                        dci_pdu,
                        &dci_payload,
                        dci_format,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 5c4fb3ca4c9fb4c530d4185fcd49941f72410dff..e72687f3ad2f9339ef081725faedba3d1c8661bf 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -1835,6 +1835,8 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
     pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size;
     pusch_pdu->pusch_data.num_cb = 0; //CBG not supported
 
+    pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = 0;
+
     LOG_D(NR_MAC,"PUSCH PDU : data_scrambling_identity %x, dmrs_scrambling_id %x\n",pusch_pdu->data_scrambling_id,pusch_pdu->ul_dmrs_scrambling_id);
     /* TRANSFORM PRECODING --------------------------------------------------------*/
 
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c
index c9b8d9cd3eb1f4701f3d788f838035f098571b91..2b64202408b4a3a2c1525cea744f8c3d4a7215f6 100755
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c
@@ -1022,38 +1022,8 @@ void fill_default_csi_MeasConfig(int uid,
   NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1,sizeof(*csi_MeasConfig));
   setupRelease_csi_MeasConfig->choice.setup = csi_MeasConfig;
 
-  if (dl_antenna_ports > 1) {
-    csi_MeasConfig->csi_IM_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceToAddModList));
-    NR_CSI_IM_Resource_t *imres0 = calloc(1,sizeof(*imres0));
-    imres0->csi_IM_ResourceId = 0;
-    imres0->csi_IM_ResourceElementPattern = calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern));
-    imres0->csi_IM_ResourceElementPattern->present = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern1;
-    imres0->csi_IM_ResourceElementPattern->choice.pattern1 = calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern->choice.pattern1));
-    imres0->csi_IM_ResourceElementPattern->choice.pattern1->subcarrierLocation_p1 = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern__pattern1__subcarrierLocation_p1_s4;
-    imres0->csi_IM_ResourceElementPattern->choice.pattern1->symbolLocation_p1 = 6;
-    imres0->freqBand = calloc(1,sizeof(*imres0->freqBand));
-    imres0->freqBand->startingRB = 0;
-    imres0->freqBand->nrofRBs = ((curr_bwp>>2)+(curr_bwp%4>0))<<2;
-    imres0->periodicityAndOffset = calloc(1,sizeof(*imres0->periodicityAndOffset));
-    imres0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320;
-    imres0->periodicityAndOffset->choice.slots320 = 0;
-    ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceToAddModList->list,imres0);
-    csi_MeasConfig->csi_IM_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceSetToAddModList));
-    NR_CSI_IM_ResourceSet_t *imset0 = calloc(1,sizeof(*imset0));
-    imset0->csi_IM_ResourceSetId = 0;
-    NR_CSI_IM_ResourceId_t *res0 = calloc(1,sizeof(*res0));
-    *res0 = 0;
-    ASN_SEQUENCE_ADD(&imset0->csi_IM_Resources,res0);
-    ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceSetToAddModList->list,imset0);
-  }
-  else {
-    csi_MeasConfig->csi_IM_ResourceToAddModList = NULL;
-    csi_MeasConfig->csi_IM_ResourceSetToAddModList = NULL;
-  }
-
-  csi_MeasConfig->nzp_CSI_RS_ResourceSetToReleaseList = NULL;
-
   config_csirs(scc, csi_MeasConfig, uid, dl_antenna_ports, curr_bwp, configuration->do_CSIRS);
+  config_csiim(configuration->do_CSIRS, dl_antenna_ports, curr_bwp, csi_MeasConfig);
 
   csi_MeasConfig->csi_SSB_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_SSB_ResourceSetToAddModList));
   csi_MeasConfig->csi_SSB_ResourceSetToReleaseList = NULL;
@@ -1155,7 +1125,7 @@ void fill_default_csi_MeasConfig(int uid,
     csirep1->reportFreqConfiguration->pmi_FormatIndicator = calloc(1,sizeof(*csirep1->reportFreqConfiguration->pmi_FormatIndicator));
     *csirep1->reportFreqConfiguration->pmi_FormatIndicator=NR_CSI_ReportConfig__reportFreqConfiguration__pmi_FormatIndicator_widebandPMI;
     csirep1->reportFreqConfiguration->csi_ReportingBand = NULL;
-/*calloc(1,sizeof(*csirep1->reportFreqConfiguration->csi_ReportingBand));
+    /*calloc(1,sizeof(*csirep1->reportFreqConfiguration->csi_ReportingBand));
      csirep1->reportFreqConfiguration->csi_ReportingBand->present = NR_CSI_ReportConfig__reportFreqConfiguration__csi_ReportingBand_PR_subbands7;
      csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.size=1;
      csirep1->reportFreqConfiguration->csi_ReportingBand->choice.subbands7.bits_unused=1;
@@ -1310,7 +1280,7 @@ void fill_initial_SpCellConfig(int uid,
   pucchfmt2->pi2BPSK=NULL;
   pucchfmt2->simultaneousHARQ_ACK_CSI=calloc(1,sizeof(*pucchfmt2->simultaneousHARQ_ACK_CSI));
   *pucchfmt2->simultaneousHARQ_ACK_CSI=NR_PUCCH_FormatConfig__simultaneousHARQ_ACK_CSI_true;
-
+  
   pucch_Config->spatialRelationInfoToAddModList = calloc(1,sizeof(*pucch_Config->spatialRelationInfoToAddModList));
   NR_PUCCH_SpatialRelationInfo_t *pucchspatial = calloc(1,sizeof(*pucchspatial));
   pucchspatial->pucch_SpatialRelationInfoId = 1;
diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c
index 32b10bfaf770094c16db09e099acbb3b031fc418..ede39d0325155aea05a962506e56d9ce0de75b0d 100644
--- a/openair2/RRC/NR/nr_rrc_config.c
+++ b/openair2/RRC/NR/nr_rrc_config.c
@@ -171,6 +171,103 @@ void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
   csi_MeasConfig->nzp_CSI_RS_ResourceToReleaseList = NULL;
 }
 
+void set_csiim_offset(struct NR_CSI_ResourcePeriodicityAndOffset *periodicityAndOffset,
+                      struct NR_CSI_ResourcePeriodicityAndOffset *target_periodicityAndOffset) {
+
+  switch(periodicityAndOffset->present) {
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots4:
+      periodicityAndOffset->choice.slots4 = target_periodicityAndOffset->choice.slots4;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots5:
+      periodicityAndOffset->choice.slots5 = target_periodicityAndOffset->choice.slots5;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots8:
+      periodicityAndOffset->choice.slots8 = target_periodicityAndOffset->choice.slots8;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots10:
+      periodicityAndOffset->choice.slots10 = target_periodicityAndOffset->choice.slots10;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots16:
+      periodicityAndOffset->choice.slots16 = target_periodicityAndOffset->choice.slots16;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots20:
+      periodicityAndOffset->choice.slots20 = target_periodicityAndOffset->choice.slots20;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots32:
+      periodicityAndOffset->choice.slots32 = target_periodicityAndOffset->choice.slots32;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots40:
+      periodicityAndOffset->choice.slots40 = target_periodicityAndOffset->choice.slots40;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots64:
+      periodicityAndOffset->choice.slots64 = target_periodicityAndOffset->choice.slots64;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots80:
+      periodicityAndOffset->choice.slots80 = target_periodicityAndOffset->choice.slots80;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots160:
+      periodicityAndOffset->choice.slots160 = target_periodicityAndOffset->choice.slots160;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots320:
+      periodicityAndOffset->choice.slots320 = target_periodicityAndOffset->choice.slots320;
+      break;
+    case NR_CSI_ResourcePeriodicityAndOffset_PR_slots640:
+      periodicityAndOffset->choice.slots640 = target_periodicityAndOffset->choice.slots640;
+      break;
+    default:
+      AssertFatal(1==0,"CSI periodicity not among allowed values\n");
+  }
+
+}
+
+void config_csiim(int do_csirs, int dl_antenna_ports, int curr_bwp,
+                  NR_CSI_MeasConfig_t *csi_MeasConfig) {
+
+ if (do_csirs && dl_antenna_ports > 1) {
+   csi_MeasConfig->csi_IM_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceToAddModList));
+   NR_CSI_IM_Resource_t *imres = calloc(1,sizeof(*imres));
+   imres->csi_IM_ResourceId = 0;
+   NR_NZP_CSI_RS_Resource_t *nzpcsi = NULL;
+   for (int i=0; i<csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list.count; i++){
+     nzpcsi = csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list.array[i];
+     if (nzpcsi->nzp_CSI_RS_ResourceId == imres->csi_IM_ResourceId)
+       break;
+   }
+   AssertFatal(nzpcsi->nzp_CSI_RS_ResourceId == imres->csi_IM_ResourceId, "Couldn't find NZP CSI-RS corresponding to CSI-IM\n");
+   imres->csi_IM_ResourceElementPattern = calloc(1,sizeof(*imres->csi_IM_ResourceElementPattern));
+   imres->csi_IM_ResourceElementPattern->present = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern1;
+   imres->csi_IM_ResourceElementPattern->choice.pattern1 = calloc(1,sizeof(*imres->csi_IM_ResourceElementPattern->choice.pattern1));
+   // starting subcarrier is 4 in the following configuration
+   // this is ok for current possible CSI-RS configurations (using only the first 4 symbols)
+   // TODO needs a more dynamic setting if CSI-RS is changed
+   imres->csi_IM_ResourceElementPattern->choice.pattern1->subcarrierLocation_p1 = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern__pattern1__subcarrierLocation_p1_s4;
+   imres->csi_IM_ResourceElementPattern->choice.pattern1->symbolLocation_p1 = nzpcsi->resourceMapping.firstOFDMSymbolInTimeDomain; // same symbol as CSI-RS
+   imres->freqBand = calloc(1,sizeof(*imres->freqBand));
+   imres->freqBand->startingRB = 0;
+   imres->freqBand->nrofRBs = ((curr_bwp>>2)+(curr_bwp%4>0))<<2;
+   imres->periodicityAndOffset = calloc(1,sizeof(*imres->periodicityAndOffset));
+   // same period and offset of the associated CSI-RS
+   imres->periodicityAndOffset->present = nzpcsi->periodicityAndOffset->present;
+   set_csiim_offset(imres->periodicityAndOffset, nzpcsi->periodicityAndOffset);
+   ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceToAddModList->list,imres);
+   csi_MeasConfig->csi_IM_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceSetToAddModList));
+   NR_CSI_IM_ResourceSet_t *imset = calloc(1,sizeof(*imset));
+   imset->csi_IM_ResourceSetId = 0;
+   NR_CSI_IM_ResourceId_t *res = calloc(1,sizeof(*res));
+   *res = imres->csi_IM_ResourceId;
+   ASN_SEQUENCE_ADD(&imset->csi_IM_Resources,res);
+   ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceSetToAddModList->list,imset);
+ }
+ else {
+   csi_MeasConfig->csi_IM_ResourceToAddModList = NULL;
+   csi_MeasConfig->csi_IM_ResourceSetToAddModList = NULL;
+ }
+
+ csi_MeasConfig->csi_IM_ResourceToReleaseList = NULL;
+ csi_MeasConfig->csi_IM_ResourceSetToReleaseList = NULL;
+}
+
+
 void prepare_sim_uecap(NR_UE_NR_Capability_t *cap,
                        NR_ServingCellConfigCommon_t *scc,
                        int numerology,
diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h
index cce03ed02a201e8639f7b19675edc6f20a9d4a24..5e5aea1a80418e1ffa3480f4cdce7b459da90102 100644
--- a/openair2/RRC/NR/nr_rrc_config.h
+++ b/openair2/RRC/NR/nr_rrc_config.h
@@ -119,6 +119,8 @@ void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
                   int num_dl_antenna_ports,
                   int curr_bwp,
                   int do_csirs);
+void config_csiim(int do_csirs, int dl_antenna_ports, int curr_bwp,
+                  NR_CSI_MeasConfig_t *csi_MeasConfig);
 void set_dl_mcs_table(int scs,
                       NR_UE_NR_Capability_t *cap,
                       NR_SpCellConfig_t *SpCellConfig,
diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c
index c09ee39ca446dc70e734bb4bacf1df92fbbcd635..4ba4e4b2533c6d491765a01edfa2935243aecd2a 100644
--- a/openair2/RRC/NR/rrc_gNB_reconfig.c
+++ b/openair2/RRC/NR/rrc_gNB_reconfig.c
@@ -1033,39 +1033,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  NR_CSI_MeasConfig_t *csi_MeasConfig = calloc(1,sizeof(*csi_MeasConfig));
  secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup = csi_MeasConfig;
 
- if (do_csirs && dl_antenna_ports > 1) {
-   csi_MeasConfig->csi_IM_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceToAddModList));
-   NR_CSI_IM_Resource_t *imres0 = calloc(1,sizeof(*imres0));
-   imres0->csi_IM_ResourceId = 0;
-   imres0->csi_IM_ResourceElementPattern = calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern));
-   imres0->csi_IM_ResourceElementPattern->present = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern1;
-   imres0->csi_IM_ResourceElementPattern->choice.pattern1 = calloc(1,sizeof(*imres0->csi_IM_ResourceElementPattern->choice.pattern1));
-   imres0->csi_IM_ResourceElementPattern->choice.pattern1->subcarrierLocation_p1 = NR_CSI_IM_Resource__csi_IM_ResourceElementPattern__pattern1__subcarrierLocation_p1_s4;
-   imres0->csi_IM_ResourceElementPattern->choice.pattern1->symbolLocation_p1 = 6;
-   imres0->freqBand = calloc(1,sizeof(*imres0->freqBand));
-   imres0->freqBand->startingRB = 0;
-   imres0->freqBand->nrofRBs = ((curr_bwp>>2)+(curr_bwp%4>0))<<2;
-   imres0->periodicityAndOffset = calloc(1,sizeof(*imres0->periodicityAndOffset));
-   imres0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320;
-   imres0->periodicityAndOffset->choice.slots320 = 0;
-   ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceToAddModList->list,imres0);
-   csi_MeasConfig->csi_IM_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_IM_ResourceSetToAddModList));
-   NR_CSI_IM_ResourceSet_t *imset0 = calloc(1,sizeof(*imset0));
-   imset0->csi_IM_ResourceSetId = 0;
-   NR_CSI_IM_ResourceId_t *res0 = calloc(1,sizeof(*res0));
-   *res0 = 0;
-   ASN_SEQUENCE_ADD(&imset0->csi_IM_Resources,res0);
-   ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_IM_ResourceSetToAddModList->list,imset0);
- }
- else {
-   csi_MeasConfig->csi_IM_ResourceToAddModList = NULL;
-   csi_MeasConfig->csi_IM_ResourceSetToAddModList = NULL;
- }
-
- csi_MeasConfig->csi_IM_ResourceToReleaseList = NULL;
- csi_MeasConfig->csi_IM_ResourceSetToReleaseList = NULL;
-
  config_csirs(servingcellconfigcommon, csi_MeasConfig, uid, dl_antenna_ports, curr_bwp, do_csirs);
+ config_csiim(do_csirs, dl_antenna_ports, curr_bwp, csi_MeasConfig);
 
  csi_MeasConfig->csi_SSB_ResourceSetToAddModList = calloc(1,sizeof(*csi_MeasConfig->csi_SSB_ResourceSetToAddModList));
  csi_MeasConfig->csi_SSB_ResourceSetToReleaseList = NULL;
diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md
index 4a8d5ff79acb1092a590d0b0ca2bc49af105e3f2..feb7f015b96683857b4245a9ea2029ff5557a636 100644
--- a/targets/ARCH/rfsimulator/README.md
+++ b/targets/ARCH/rfsimulator/README.md
@@ -61,6 +61,8 @@ Setting the env variable RFSIMULATOR can be used instead of using the serveraddr
 
 ## How to use the RF simulator options
 
+To define and use a channel model, the configuration file needs to include a channel configuration file. To do this, add `@include "channelmod_rfsimu.conf"` to the end of the configuration file, and place the channel configuration file in the same directory. An example channel configuration file `channelmod_rfsimu.conf` is in `ci-scripts/conf_files`.
+
 Add the following options to the command line to enable the channel model and the IQ samples saving for future replay:
 ```bash
 --rfsimulator.options chanmod,saviq
@@ -82,6 +84,8 @@ Example run:
 sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --rfsimulator.options chanmod --rfsimulator.modelname AWGN 
 ```
 
+where `@include "channelmod_rfsimu.conf"` has been added at the end of the file, and `ci-scripts/conf_files/channelmod_rfsimu.conf` copied to `targets/PROJECTS/GENERIC-LTE-EPC/CONF/`.
+
 ## 4G case
 
 For the UE, it should be set to the IP address of the eNB. For example:
@@ -102,9 +106,7 @@ $OPENAIR_DIR/targets/bin/conf2uedata -c $OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurec
 
 ## 5G case
 
-The 5G RF simulator will be aligned with the 4G as the efforts for merging the 5G specific branches into the develop make progresses.
-
-After regular build, add the simulation driver (do not use ./build_oai -w SIMU until 4G and 5G branches are merged).
+If `build_oai` has not been run with `-w SIMU`, you need to build the `rfsimulator` manually. To do so:
 ```bash
 cd ran_build/build
 make rfsimulator
@@ -113,7 +115,7 @@ make rfsimulator
 ### Launch gNB in one window
 
 ```bash
-sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test
+sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD --rfsim --phy-test --nokrnmod 1
 ```
 
 ### Launch UE in another window
@@ -124,15 +126,17 @@ sudo RFSIMULATOR=<TARGET_GNB_INTERFACE_ADDRESS> ./nr-uesoftmodem --rfsim --phy-t
 
 Notes:
 
-1. <TARGET_GNB_INTERFACE_ADDRESS> can be 127.0.0.1 if both gNB and nrUE executables run on the same host, OR the IP interface address of the remote host running the gNB executable, if the gNB and nrUE run on separate hosts
-2. the --rrc_config_path parameter SHALL specify where the 2 RAW files are located (`rbconfig.raw` and `reconfig.raw`).
+1. This starts the gNB and UE in the `phy-test` UP-only mode where the gNB is started as if a UE had already connected, and a configurable scheduler is used instead of the default one. The options `-m`, `-l`, `-t`, `-M`, `-T`, `-D`, and `-U` can be used to configure this scheduler.
+2. <TARGET_GNB_INTERFACE_ADDRESS> can be 127.0.0.1 if both gNB and nrUE executables run on the same host, OR the IP interface address of the remote host running the gNB executable, if the gNB and nrUE run on separate hosts.
+3. The --rrc_config_path parameter SHALL specify where the 2 RAW files are located (`rbconfig.raw` and `reconfig.raw`).
    - If you are running on the same machine and launched the 2 executables (`nr-softmodem` and `nr-uesoftmodem`) from the same directory, nothing has to be done.
    - If you launched the 2 executables from 2 different folders, just point to the location where you launched the `nr-softmodem`:
      * `sudo RFSIMULATOR=<TARGET_GNB_INTERFACE_ADDRESS> ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path /the/path/where/you/launched/nr-softmodem`
    - If you are not running on the same machine or launched the 2 executables from 2 different folders, you need to **COPY** the 2 raw files
      * `scp usera@machineA:/the/path/where/you/launched/nr-softmodem/r*config.raw userb@machineB:/the/path/where/you/will/launch/nr-uesoftmodem/`
      * Obviously this operation SHALL be done before launching the `nr-uesoftmodem` executable.
-3. to enable the noS1 mode --noS1 and --nokrnmod 1 options should be added to the command line
+4. To enable the noS1 mode, `--noS1` option should be added to the command line.
+5. To operate the gNB/UE with a 5GC, start them using the `--sa` option. More information can be found [here](../../../doc/TESTING_5GSA_setup.md#2-sa-setup-with-oai-nr-ue-softmodem).
 
 
 In the UE, you can add `-d` option to get the softscope.