diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container
new file mode 100644
index 0000000000000000000000000000000000000000..fbf9ba8f4b551070ff35bdc6ffbce1f9b0d17d69
--- /dev/null
+++ b/ci-scripts/Jenkinsfile-GitLab-Container
@@ -0,0 +1,261 @@
+#!/bin/groovy
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+// Location of the executor node
+def nodeExecutor = params.nodeExecutor
+
+// Tags to shorten pipeline duration
+def doMandatoryTests = false
+def doFullTestsuite = false
+
+pipeline {
+  agent {
+    label nodeExecutor
+  }
+  options {
+    disableConcurrentBuilds()
+    timestamps()
+    gitLabConnection('OAI GitLab')
+    ansiColor('xterm')
+  }
+
+  stages {
+    stage ("Verify Parameters") {
+      steps {
+        script {
+          JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
+          JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
+
+          echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
+          def allParametersPresent = true
+
+          echo '\u2705 \u001B[32mVerify Labels\u001B[0m'
+          if ("MERGE".equals(env.gitlabActionType)) {
+            LABEL_CHECK = sh returnStdout: true, script: 'ci-scripts/checkGitLabMergeRequestLabels.sh --mr-id ' + env.gitlabMergeRequestIid
+            LABEL_CHECK = LABEL_CHECK.trim()
+            if (LABEL_CHECK == 'NONE') {
+              def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Your merge request has none of the mandatory labels:\n\n"
+              message += " - BUILD-ONLY\n"
+              message += " - 4G-LTE\n"
+              message += " - 5G-NR\n"
+              message += " - CI\n\n"
+              message += "Not performing CI due to lack of labels"
+              addGitLabMRComment comment: message
+              error('Not performing CI due to lack of labels')
+            } else if (LABEL_CHECK == 'FULL') {
+              doMandatoryTests = true
+              doFullTestsuite = true
+            } else if (LABEL_CHECK == 'SHORTEN-5G') {
+              doMandatoryTests = true
+            } else {
+              def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): We will perform only build stages on your Merge Request"
+              addGitLabMRComment comment: message
+            }
+          } else {
+            doMandatoryTests = true
+            doFullTestsuite = true
+          }
+        }
+      }
+    }
+    stage ("Verify Guidelines") {
+      steps {
+        echo "Git URL     is ${GIT_URL}"
+        echo "GitLab Act    is ${env.gitlabActionType}"
+        script {
+          if ("MERGE".equals(env.gitlabActionType)) {
+            // since a bit, in push events, gitlabUserEmail is not populated
+            gitCommitAuthorEmailAddr = env.gitlabUserEmail
+            echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
+            // GitLab-Jenkins plugin integration is lacking to perform the merge by itself
+            // Doing it manually --> it may have merge conflicts
+            sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}"
+          } else {
+            echo "Git Branch    is ${GIT_BRANCH}"
+            echo "Git Commit    is ${GIT_COMMIT}"
+            // since a bit, in push events, gitlabUserEmail is not populated
+            gitCommitAuthorEmailAddr = sh returnStdout: true, script: 'git log -n1 --pretty=format:%ae ${GIT_COMMIT}'
+            gitCommitAuthorEmailAddr = gitCommitAuthorEmailAddr.trim()
+            echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
+            sh "git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG"
+          }
+        }
+      }
+      post {
+        failure {
+          script {
+            def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI"
+            addGitLabMRComment comment: message
+            currentBuild.result = 'FAILURE'
+          }
+        }
+      }
+    }
+    // Build Stages are Mandatory
+    // Later we will add a Ubuntu20 build
+    stage ("Image Building Processes") {
+      parallel {
+        stage ("Ubuntu18 Build") {
+          steps {
+            script {
+              triggerSlaveJob ('RAN-Ubuntu18-Image-Builder', 'Ubuntu18-Images-Build')
+            }
+          }
+          post {
+            always {
+              script {
+                finalizeSlaveJob('RAN-Ubuntu18-Image-Builder')
+              }
+            }
+            failure {
+              script {
+                currentBuild.result = 'FAILURE'
+              }
+            }
+          }
+        }
+        stage ("RHEL8 Build") {
+          steps {
+            script {
+              triggerSlaveJob ('RAN-RHEL8-Image-Builder', 'RHEL8-Images-Build')
+            }
+          }
+          post {
+            always {
+              script {
+                finalizeSlaveJob('RAN-RHEL8-Image-Builder')
+              }
+            }
+            failure {
+              script {
+                currentBuild.result = 'FAILURE'
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  post {
+    always {
+      script {
+        emailext attachmentsPattern: '*results*.html',
+           body: '''Hi,
+
+Here are attached HTML report files for $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!
+
+Regards,
+OAI CI Team''',
+           replyTo: 'no-reply@openairinterface.org',
+           subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!',
+           to: gitCommitAuthorEmailAddr
+
+        if (fileExists('.git/CI_COMMIT_MSG')) {
+          sh "rm -f .git/CI_COMMIT_MSG"
+        }
+      }
+    }
+    success {
+      script {
+        def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")"
+        if ("MERGE".equals(env.gitlabActionType)) {
+          echo "This is a MERGE event"
+          addGitLabMRComment comment: message
+        }
+      }
+    }
+    failure {
+      script {
+        def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")"
+        if ("MERGE".equals(env.gitlabActionType)) {
+          echo "This is a MERGE event"
+          addGitLabMRComment comment: message
+        }
+      }
+    }
+  }
+}
+
+// ----  Slave Job functions
+
+def triggerSlaveJob (jobName, gitlabStatusName) {
+  // Workaround for the "cancelled" GitLab pipeline notification
+  // The slave job is triggered with the propagate false so the following commands are executed
+  // Its status is now PASS/SUCCESS from a stage pipeline point of view
+  // localStatus variable MUST be analyzed to properly assess the status
+  localStatus = build job: jobName,
+    parameters: [
+      string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)),
+      string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)),
+      string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)),
+      booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)),
+      string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch))
+    ], propagate: false
+  localResult = localStatus.getResult()
+  echo "${jobName} Slave Job status is ${localResult}"
+  gitlabCommitStatus(name: gitlabStatusName) {
+    if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
+       echo "${jobName} Slave Job is OK"
+    } else {
+       echo "${jobName} Slave Job is KO"
+       sh "ci-scripts/fail.sh"
+    }
+  }
+}
+
+def triggerSlaveJobNoGitLab (jobName) {
+  // Workaround for the "cancelled" GitLab pipeline notification
+  // The slave job is triggered with the propagate false so the following commands are executed
+  // Its status is now PASS/SUCCESS from a stage pipeline point of view
+  // localStatus variable MUST be analyzed to properly assess the status
+  localStatus = build job: jobName,
+    parameters: [
+      string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)),
+      string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)),
+      string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)),
+      booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)),
+      string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch))
+    ], propagate: false
+  localResult = localStatus.getResult()
+  echo "${jobName} Slave Job status is ${localResult}"
+  if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
+     echo "${jobName} Slave Job is OK"
+  } else {
+     echo "${jobName} Slave Job is KO"
+     sh "ci-scripts/fail.sh"
+  }
+}
+
+def finalizeSlaveJob(jobName) {
+  // In case of any non-success, we are retrieving the HTML report of the last completed
+  // slave job. The only drop-back is that we may retrieve the HTML report of a previous build
+  fileName = "test_results-${jobName}.html"
+  if (!fileExists(fileName)) {
+    copyArtifacts(projectName: jobName,
+      filter: 'test_results*.html',
+      selector: lastCompleted())
+    if (fileExists(fileName)) {
+      sh "sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' ${fileName}"
+      archiveArtifacts artifacts: fileName
+    }
+  }
+}
diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab
index ff661543c0001279b5f81203ed82383fd5ed0241..de49275b7ead1652a3b11e716e981359faa0df78 100644
--- a/ci-scripts/Jenkinsfile-gitlab
+++ b/ci-scripts/Jenkinsfile-gitlab
@@ -196,16 +196,6 @@ pipeline {
             }
         }
 
-        stage ("Start VM -- enb-usrp") {
-            steps {
-              lock (vmResource) {
-                timeout (time: 5, unit: 'MINUTES') {
-                    sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon"
-                }
-              }
-            }
-        }
-
         stage ("Start VM -- phy-sim") {
             steps {
               lock (vmResource) {
@@ -251,7 +241,7 @@ pipeline {
                 stage ("Analysis with cppcheck") {
                     steps {
                         gitlabCommitStatus(name: "Analysis with cppcheck") {
-                            timeout (time: 20, unit: 'MINUTES') {
+                            timeout (time: 30, unit: 'MINUTES') {
                                 sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID}"
                             }
                         }
@@ -260,7 +250,7 @@ pipeline {
                 stage ("Build basic simulator") {
                     steps {
                         gitlabCommitStatus(name: "Build basic-sim") {
-                            timeout (time: 20, unit: 'MINUTES') {
+                            timeout (time: 30, unit: 'MINUTES') {
                                 sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant basic-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
                             }
                         }
@@ -269,7 +259,7 @@ pipeline {
                 stage ("Build 5G gNB-USRP") {
                     steps {
                         gitlabCommitStatus(name: "Build gNB-USRP") {
-                            timeout (time: 20, unit: 'MINUTES') {
+                            timeout (time: 30, unit: 'MINUTES') {
                                 sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant gnb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
                             }
                         }
@@ -278,25 +268,16 @@ pipeline {
                 stage ("Build 5G NR-UE-USRP") {
                     steps {
                         gitlabCommitStatus(name: "Build nr-UE-USRP") {
-                            timeout (time: 20, unit: 'MINUTES') {
+                            timeout (time: 30, unit: 'MINUTES') {
                                 sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant nr-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
                             }
                         }
                     }
                 }
-                stage ("Build eNB-USRP") {
-                    steps {
-                        gitlabCommitStatus(name: "Build eNB-USRP") {
-                            timeout (time: 20, unit: 'MINUTES') {
-                                sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID}"
-                            }
-                        }
-                    }
-                }
                 stage ("Build physical simulators") {
                     steps {
                         gitlabCommitStatus(name: "Build phy-sim") {
-                            timeout (time: 20, unit: 'MINUTES') {
+                            timeout (time: 30, unit: 'MINUTES') {
                                sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant phy-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
                             }
                         }
@@ -305,7 +286,7 @@ pipeline {
                 stage ("Build eNB-ethernet") {
                     steps {
                         gitlabCommitStatus(name: "Build eNB-ethernet") {
-                            timeout (time: 20, unit: 'MINUTES') {
+                            timeout (time: 30, unit: 'MINUTES') {
                                 sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
                             }
                         }
@@ -316,7 +297,7 @@ pipeline {
                       // This is typically the last one to finish.
                       lock (vmResource) {
                         gitlabCommitStatus(name: "Build UE-ethernet") {
-                            timeout (time: 20, unit: 'MINUTES') {
+                            timeout (time: 30, unit: 'MINUTES') {
                                 sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant ue-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive"
                             }
                         }
diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel
new file mode 100644
index 0000000000000000000000000000000000000000..8ac2e6adffa3a5d5d3f434e8f936b6de33da667f
--- /dev/null
+++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel
@@ -0,0 +1,293 @@
+#!/bin/groovy
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
+
+// Location of the python executor node shall be in the same subnet as the others servers
+def pythonExecutor = params.pythonExecutor
+
+// Location of the test XML file to be run
+def testXMLFile = params.pythonTestXmlFile
+def mainPythonAllXmlFiles = ""
+def buildStageStatus = true
+
+// Name of the test stage
+def testStageName = params.pipelineTestStageName
+
+// Name of the phone resource
+def ciSmartPhonesResource1 = params.SmartPhonesResource1
+def ciSmartPhonesResource2 = params.SmartPhonesResource2
+
+// Global Parameters. Normally they should be populated when the master job
+// triggers the slave job with parameters
+def eNB_Repository
+def eNB_Branch
+def eNB_CommitID
+def eNB_AllowMergeRequestProcess
+def eNB_TargetBranch
+
+pipeline {
+    agent {
+        label pythonExecutor
+    }
+    options {
+        disableConcurrentBuilds()
+        ansiColor('xterm')
+        lock(extra: [[resource: ciSmartPhonesResource2]], resource: ciSmartPhonesResource1)
+    }
+    stages {
+        stage("Build Init") {
+            steps {
+                // update the build name and description
+                buildName "${params.eNB_MR}"
+                buildDescription "Branch : ${params.eNB_Branch}"
+            }
+        }
+        stage ("Verify Parameters") {
+            steps {
+                script {
+                    echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
+                    def allParametersPresent = true
+
+                    // It is already to late to check it
+                    if (params.pythonExecutor != null) {
+                        echo "eNB CI executor node  :   ${pythonExecutor}"
+                    }
+                    // If not present picking a default Stage Name
+                    if (params.pipelineTestStageName == null) {
+                        // picking default
+                        testStageName = 'Template Test Stage'
+                    }
+
+                    if (params.SmartPhonesResource1 == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.SmartPhonesResource2 == null) {
+                        allParametersPresent = false
+                    }
+                    // 1st eNB parameters
+                    if (params.eNB_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB_SourceCodePath == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB_Credentials == null) {
+                        allParametersPresent = false
+                    }
+                    // 2nd eNB parameters
+                    if (params.eNB1_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB1_SourceCodePath == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB1_Credentials == null) {
+                        allParametersPresent = false
+                    }
+                    // 3rd eNB parameters
+                    if (params.eNB2_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB2_SourceCodePath == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB2_Credentials == null) {
+                        allParametersPresent = false
+                    }
+                    // the following 4 parameters should be pushed by the master trigger
+                    // if not present, take the job GIT variables (used for developing)
+                    if (params.eNB_Repository == null) {
+                        eNB_Repository = env.GIT_URL
+                    } else {
+                        eNB_Repository = params.eNB_Repository
+                    }
+                    echo "eNB_Repository        :   ${eNB_Repository}"
+                    if (params.eNB_Branch == null) {
+                        eNB_Branch = env.GIT_BRANCH
+                    } else {
+                        eNB_Branch = params.eNB_Branch
+                    }
+                    echo "eNB_Branch            :   ${eNB_Branch}"
+                    if (params.eNB_CommitID == null) {
+                        eNB_CommitID = env.GIT_COMMIT
+                    } else {
+                        eNB_CommitID = params.eNB_CommitID
+                    }
+                    echo "eNB_CommitID          :   ${eNB_CommitID}"
+                    if (params.eNB_AllowMergeRequestProcess!= null) {
+                        eNB_AllowMergeRequestProcess = params.eNB_AllowMergeRequestProcess
+                        if (eNB_AllowMergeRequestProcess) {
+                            if (params.eNB_TargetBranch != null) {
+                                eNB_TargetBranch = params.eNB_TargetBranch
+                            } else {
+                                eNB_TargetBranch = 'develop'
+                            }
+                            echo "eNB_TargetBranch      :   ${eNB_TargetBranch}"
+                        }
+                    }
+
+                    if (params.EPC_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.EPC_Type == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.EPC_SourceCodePath == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.EPC_Credentials == null) {
+                        allParametersPresent = false
+                    }
+
+                    if (params.ADB_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.ADB_Credentials == null) {
+                        allParametersPresent = false
+                    }
+
+                    if (allParametersPresent) {
+                        echo "All parameters are present"
+                        if (eNB_AllowMergeRequestProcess) {
+                            sh "git fetch"
+                            sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
+                        } else {
+                            sh "git fetch"
+                            sh "git checkout -f ${eNB_CommitID}"
+                        }
+                    } else {
+                        echo "Some parameters are missing"
+                        sh "./ci-scripts/fail.sh"
+                    }
+                }
+            }
+        }
+        stage ("Build and Test") {
+            steps {
+                script {
+                    dir ('ci-scripts') {
+                        echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
+                        // If not present picking a default XML file
+                        if (params.pythonTestXmlFile == null) {
+                            // picking default
+                            testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
+                            echo "Test XML file(default):   ${testXMLFile}"
+                            mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
+                        } else {
+                            String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
+                            for (xmlFile in myXmlTestSuite) {
+                                if (fileExists(xmlFile)) {
+                                    mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
+                                    echo "Test XML file         :   ${xmlFile}"
+                                }
+                            }
+                        }
+                        withCredentials([
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'],
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'],
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'],
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'],
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password']
+                        ]) {
+                            sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}"
+                            String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
+                            for (xmlFile in myXmlTestSuite) {
+                                if (fileExists(xmlFile)) {
+                                    try {
+                                        sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${xmlFile}"
+                                    } catch (Exception e) {
+                                        currentBuild.result = 'FAILURE'
+                                        buildStageStatus = false
+                                    }
+                                }
+                            }
+                            sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}"
+                        }
+                    }
+                }
+            }
+        }
+        stage('Log Collection') {
+            parallel {
+                stage('Log Collection (eNB - Build)') {
+                    steps {
+                        withCredentials([
+                             [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
+                        ]) {
+                            echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m'
+                            sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}"
+
+                            echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m'
+                            sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true"
+                        }
+                        script {
+                            if(fileExists("build.log.${env.BUILD_ID}.zip")) {
+                                archiveArtifacts "build.log.${env.BUILD_ID}.zip"
+                            }
+                        }
+                    }
+                }
+                stage('Log Collection (eNB - Run)') {
+                    steps {
+                        withCredentials([
+                             [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
+                        ]) {
+                            echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
+                            sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}"
+
+                            echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m'
+                            sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true"
+                        }
+                        script {
+                            if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
+                                archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
+                            }
+                            if(fileExists("ci-scripts/test_results.html")) {
+                                sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
+                                sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
+                                archiveArtifacts "test_results-${JOB_NAME}.html"
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    post {
+        always {
+            script {
+                if (params.pipelineZipsConsoleLog != null) {
+                    if (params.pipelineZipsConsoleLog) {
+                        echo "Archiving Jenkins console log"
+                        sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
+                        sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
+                        if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
+                            archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa
new file mode 100644
index 0000000000000000000000000000000000000000..66d12eed33a7c5172649aff6cde5a95bd449fda6
--- /dev/null
+++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa
@@ -0,0 +1,297 @@
+#!/bin/groovy
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
+
+// Location of the python executor node shall be in the same subnet as the others servers
+def pythonExecutor = params.pythonExecutor
+
+// Location of the test XML file to be run
+def testXMLFile = params.pythonTestXmlFile
+def mainPythonAllXmlFiles = ""
+def buildStageStatus = true
+
+// Name of the test stage
+def testStageName = params.pipelineTestStageName
+
+// Name of the phone resource
+def ciSmartPhonesResource1 = params.SmartPhonesResource1
+def ciSmartPhonesResource2 = params.SmartPhonesResource2
+def ciSmartPhonesResource3 = params.SmartPhonesResource3
+
+// Global Parameters. Normally they should be populated when the master job
+// triggers the slave job with parameters
+def eNB_Repository
+def eNB_Branch
+def eNB_CommitID
+def eNB_AllowMergeRequestProcess
+def eNB_TargetBranch
+
+pipeline {
+    agent {
+        label pythonExecutor
+    }
+    options {
+        disableConcurrentBuilds()
+        ansiColor('xterm')
+        lock(extra: [[resource: ciSmartPhonesResource2],[resource: ciSmartPhonesResource3]], resource: ciSmartPhonesResource1)
+    }
+    stages {
+        stage("Build Init") {
+            steps {
+                // update the build name and description
+                buildName "${params.eNB_MR}"
+                buildDescription "Branch : ${params.eNB_Branch}"
+            }
+        }
+        stage ("Verify Parameters") {
+            steps {
+                script {
+                    echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
+                    def allParametersPresent = true
+
+                    // It is already to late to check it
+                    if (params.pythonExecutor != null) {
+                        echo "eNB CI executor node  :   ${pythonExecutor}"
+                    }
+                    // If not present picking a default Stage Name
+                    if (params.pipelineTestStageName == null) {
+                        // picking default
+                        testStageName = 'Template Test Stage'
+                    }
+
+                    if (params.SmartPhonesResource1 == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.SmartPhonesResource2 == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.SmartPhonesResource3== null) {
+                        allParametersPresent = false
+                    }
+                    // 1st eNB parameters
+                    if (params.eNB_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB_SourceCodePath == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB_Credentials == null) {
+                        allParametersPresent = false
+                    }
+                    // 2nd eNB parameters
+                    if (params.eNB1_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB1_SourceCodePath == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB1_Credentials == null) {
+                        allParametersPresent = false
+                    }
+                    // 3rd eNB parameters
+                    if (params.eNB2_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB2_SourceCodePath == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB2_Credentials == null) {
+                        allParametersPresent = false
+                    }
+                    // the following 4 parameters should be pushed by the master trigger
+                    // if not present, take the job GIT variables (used for developing)
+                    if (params.eNB_Repository == null) {
+                        eNB_Repository = env.GIT_URL
+                    } else {
+                        eNB_Repository = params.eNB_Repository
+                    }
+                    echo "eNB_Repository        :   ${eNB_Repository}"
+                    if (params.eNB_Branch == null) {
+                        eNB_Branch = env.GIT_BRANCH
+                    } else {
+                        eNB_Branch = params.eNB_Branch
+                    }
+                    echo "eNB_Branch            :   ${eNB_Branch}"
+                    if (params.eNB_CommitID == null) {
+                        eNB_CommitID = env.GIT_COMMIT
+                    } else {
+                        eNB_CommitID = params.eNB_CommitID
+                    }
+                    echo "eNB_CommitID          :   ${eNB_CommitID}"
+                    if (params.eNB_AllowMergeRequestProcess!= null) {
+                        eNB_AllowMergeRequestProcess = params.eNB_AllowMergeRequestProcess
+                        if (eNB_AllowMergeRequestProcess) {
+                            if (params.eNB_TargetBranch != null) {
+                                eNB_TargetBranch = params.eNB_TargetBranch
+                            } else {
+                                eNB_TargetBranch = 'develop'
+                            }
+                            echo "eNB_TargetBranch      :   ${eNB_TargetBranch}"
+                        }
+                    }
+
+                    if (params.EPC_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.EPC_Type == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.EPC_SourceCodePath == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.EPC_Credentials == null) {
+                        allParametersPresent = false
+                    }
+
+                    if (params.ADB_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.ADB_Credentials == null) {
+                        allParametersPresent = false
+                    }
+
+                    if (allParametersPresent) {
+                        echo "All parameters are present"
+                        if (eNB_AllowMergeRequestProcess) {
+                            sh "git fetch"
+                            sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
+                        } else {
+                            sh "git fetch"
+                            sh "git checkout -f ${eNB_CommitID}"
+                        }
+                    } else {
+                        echo "Some parameters are missing"
+                        sh "./ci-scripts/fail.sh"
+                    }
+                }
+            }
+        }
+        stage ("Build and Test") {
+            steps {
+                script {
+                    dir ('ci-scripts') {
+                        echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
+                        // If not present picking a default XML file
+                        if (params.pythonTestXmlFile == null) {
+                            // picking default
+                            testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
+                            echo "Test XML file(default):   ${testXMLFile}"
+                            mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
+                        } else {
+                            String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
+                            for (xmlFile in myXmlTestSuite) {
+                                if (fileExists(xmlFile)) {
+                                    mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
+                                    echo "Test XML file         :   ${xmlFile}"
+                                }
+                            }
+                        }
+                        withCredentials([
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'],
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'],
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'],
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'],
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password']
+                        ]) {
+                            sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}"
+                            String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
+                            for (xmlFile in myXmlTestSuite) {
+                                if (fileExists(xmlFile)) {
+                                    try {
+                                        sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${xmlFile}"
+                                    } catch (Exception e) {
+                                        currentBuild.result = 'FAILURE'
+                                        buildStageStatus = false
+                                    }
+                                }
+                            }
+                            sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}"
+                        }
+                    }
+                }
+            }
+        }
+        stage('Log Collection') {
+            parallel {
+                stage('Log Collection (eNB - Build)') {
+                    steps {
+                        withCredentials([
+                             [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
+                        ]) {
+                            echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m'
+                            sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}"
+
+                            echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m'
+                            sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true"
+                        }
+                        script {
+                            if(fileExists("build.log.${env.BUILD_ID}.zip")) {
+                                archiveArtifacts "build.log.${env.BUILD_ID}.zip"
+                            }
+                        }
+                    }
+                }
+                stage('Log Collection (eNB - Run)') {
+                    steps {
+                        withCredentials([
+                             [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
+                        ]) {
+                            echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
+                            sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}"
+
+                            echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m'
+                            sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true"
+                        }
+                        script {
+                            if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
+                                archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
+                            }
+                            if(fileExists("ci-scripts/test_results.html")) {
+                                sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
+                                sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
+                                archiveArtifacts "test_results-${JOB_NAME}.html"
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    post {
+        always {
+            script {
+                if (params.pipelineZipsConsoleLog != null) {
+                    if (params.pipelineZipsConsoleLog) {
+                        echo "Archiving Jenkins console log"
+                        sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
+                        sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
+                        if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
+                            archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/ci-scripts/Jenkinsfile-tmp-ran b/ci-scripts/Jenkinsfile-tmp-ran
index ab1573de7fc374d040e22e353e1641cca4b70edf..7d5307620f0ad4b8034cc174a86b5fff2544db89 100644
--- a/ci-scripts/Jenkinsfile-tmp-ran
+++ b/ci-scripts/Jenkinsfile-tmp-ran
@@ -241,6 +241,10 @@ pipeline {
         stage ("Terminate") {
             parallel {
                 stage('Terminate UE') {
+                    // Bypassing this stage if there are no abd server defined
+                    when {
+                      expression { params.ADB_IPAddress != "none" }
+                    }
                     steps {
                         echo '\u2705 \u001B[32mTerminate UE\u001B[0m'
                         withCredentials([
@@ -275,6 +279,10 @@ pipeline {
                     }
                 }
                 stage('Terminate SPGW') {
+                    // Bypassing this stage if EPC server is not defined
+                    when {
+                      expression { params.EPC_IPAddress != "none" }
+                    }
                     steps {
                         echo '\u2705 \u001B[32mTerminate SPGW\u001B[0m'
                         withCredentials([
@@ -292,6 +300,10 @@ pipeline {
                     }
                 }
                 stage('Terminate MME') {
+                    // Bypassing this stage if EPC server is not defined
+                    when {
+                      expression { params.EPC_IPAddress != "none" }
+                    }
                     steps {
                         echo '\u2705 \u001B[32mTerminate MME\u001B[0m'
                         withCredentials([
@@ -309,6 +321,10 @@ pipeline {
                     }
                 }
                 stage('Terminate HSS') {
+                    // Bypassing this stage if EPC server is not defined
+                    when {
+                      expression { params.EPC_IPAddress != "none" }
+                    }
                     steps {
                         echo '\u2705 \u001B[32mTerminate HSS\u001B[0m'
                         withCredentials([
@@ -371,6 +387,10 @@ pipeline {
                     }
                 }
                 stage('Log Collection (SPGW)') {
+                    // Bypassing this stage if EPC server is not defined
+                    when {
+                      expression { params.EPC_IPAddress != "none" }
+                    }
                     steps {
                         withCredentials([
                              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
@@ -389,6 +409,10 @@ pipeline {
                     }
                 }
                 stage('Log Collection (MME)') {
+                    // Bypassing this stage if EPC server is not defined
+                    when {
+                      expression { params.EPC_IPAddress != "none" }
+                    }
                     steps {
                         withCredentials([
                              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
@@ -407,6 +431,10 @@ pipeline {
                     }
                 }
                 stage('Log Collection (HSS)') {
+                    // Bypassing this stage if EPC server is not defined
+                    when {
+                      expression { params.EPC_IPAddress != "none" }
+                    }
                     steps {
                         withCredentials([
                              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
@@ -425,6 +453,10 @@ pipeline {
                     }
                 }
                 stage('Log Collection (Ping)') {
+                    // Bypassing this stage if EPC server is not defined
+                    when {
+                      expression { params.EPC_IPAddress != "none" }
+                    }
                     steps {
                         withCredentials([
                              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
@@ -443,6 +475,10 @@ pipeline {
                     }
                 }
                 stage('Log Collection (Iperf)') {
+                    // Bypassing this stage if EPC server is not defined
+                    when {
+                      expression { params.EPC_IPAddress != "none" }
+                    }
                     steps {
                         withCredentials([
                              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
@@ -482,7 +518,7 @@ pipeline {
         // Making sure that we really shutdown every thing before leaving
         failure {
             script {
-                if (!termStatusArray[termUE]) {
+                if ((!termStatusArray[termUE]) && (params.ADB_IPAddress != "none")) {
                     withCredentials([
                         [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password']
                     ]) {
@@ -496,21 +532,21 @@ pipeline {
                         sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}"
                     }
                 }
-                if (!termStatusArray[termSPGW]) {
+                if ((!termStatusArray[termSPGW]) && (params.EPC_IPAddress != "none")) {
                     withCredentials([
                         [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
                     ]) {
                         sh "python3 ci-scripts/main.py --mode=TerminateSPGW --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCType=${params.EPC_Type} --EPCSourceCodePath=${params.EPC_SourceCodePath}"
                     }
                 }
-                if (!termStatusArray[termMME]) {
+                if ((!termStatusArray[termMME]) && (params.EPC_IPAddress != "none")) {
                     withCredentials([
                         [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
                     ]) {
                         sh "python3 ci-scripts/main.py --mode=TerminateMME --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCType=${params.EPC_Type} --EPCSourceCodePath=${params.EPC_SourceCodePath}"
                     }
                 }
-                if (!termStatusArray[termHSS]) {
+                if ((!termStatusArray[termHSS]) && (params.EPC_IPAddress != "none")) {
                     withCredentials([
                         [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
                     ]) {
diff --git a/ci-scripts/Jenkinsfile-trig-nsa b/ci-scripts/Jenkinsfile-trig-nsa
new file mode 100644
index 0000000000000000000000000000000000000000..3dd5ce3b50ccd74719a9e8ab4c968b53263360e3
--- /dev/null
+++ b/ci-scripts/Jenkinsfile-trig-nsa
@@ -0,0 +1,73 @@
+#!/bin/groovy
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
+
+// Location of the python executor node shall be in the same subnet as the others servers
+def pythonExecutor = params.pythonExecutor
+
+def TARGET_BRANCH = "develop"
+def ALLOW_MERGE = true
+
+pipeline {
+    agent {
+        label pythonExecutor
+    }
+    stages {
+        stage ("Launcher") {
+            steps {
+                script {     
+                    //retrieve MR that are opened nd with tag READY_TO_BE_MERGED             
+                    MR_LIST= sh returnStdout: true, script: 'curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests?state=opened&per_page=100&labels=READY_TO_BE_MERGED" | jq ".[].iid" || true '
+                    echo "List of selected MR:\n${MR_LIST}" 
+                    def MR_ARRAY = MR_LIST.split('\n') 
+                    //for every selected MR, retrieve the branch name and the latest commit              
+                    for (MR in MR_ARRAY) {
+                        SRC_BRANCH=sh returnStdout: true, script: """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".source_branch" || true """
+                        SRC_BRANCH=SRC_BRANCH.trim()
+                        COMMIT_ID=sh returnStdout: true, script:  """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".sha" || true """
+                        COMMIT_ID=COMMIT_ID.trim()
+                        echo "Testing NSA on : ${MR} ${SRC_BRANCH} ${COMMIT_ID}"
+                        //calling NSA sub job
+                        build job: "RAN-CI-NSA-B210", wait : false, propagate : false, parameters: [
+                            string(name: 'eNB_MR', value: String.valueOf(MR)),                          
+                            string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
+                            string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
+                            string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
+                            booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE))
+                        ]
+                        //calling Benetel sub job
+                        build job: "RAN-CI-BENETEL", wait : false, propagate : false, parameters: [
+                            string(name: 'eNB_MR', value: String.valueOf(MR)),                          
+                            string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)),
+                            string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)),
+                            string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)),
+                            booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE))
+                        ]
+                    }
+                }                                  
+            }   
+        }
+    }
+}
+
+
diff --git a/ci-scripts/buildOnVM.sh b/ci-scripts/buildOnVM.sh
index 861cab0782d1ebb5f189f5fea225df243da9cc27..2b1a5e0c71526534c7173111a2909a31c150e5cd 100755
--- a/ci-scripts/buildOnVM.sh
+++ b/ci-scripts/buildOnVM.sh
@@ -62,6 +62,12 @@ function build_on_vm {
     echo "ARCHIVES_LOC        = $ARCHIVES_LOC"
     echo "BUILD_OPTIONS       = $BUILD_OPTIONS"
 
+    if [[ "$VM_NAME" == *"-enb-usrp"* ]]
+    then
+        echo "This VM type is no longer supported in the pipeline framework"
+        return
+    fi
+
     IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME`
 
     if [ $IS_VM_ALIVE -eq 0 ]
@@ -158,6 +164,9 @@ function build_on_vm {
     echo "cd tmp" >> $VM_CMDS
     echo "echo \"unzip -qq -DD ../localZip.zip\"" >> $VM_CMDS
     echo "unzip -qq -DD ../localZip.zip" >> $VM_CMDS
+    # Trying to make some room on filesystem before building
+    echo "rm ../localZip.zip" >> $VM_CMDS
+    echo "export CI_ENV=True" >> $VM_CMDS
     if [[ "$VM_NAME" == *"-cppcheck"* ]]
     then
         echo "mkdir cmake_targets/log" >> $VM_CMDS
@@ -208,7 +217,15 @@ function build_on_vm {
             echo "echo \"./build_oai -I $BUILD_OPTIONS \"" >> $VM_CMDS
             echo "./build_oai -I $BUILD_OPTIONS > log/install-build.txt 2>&1" >> $VM_CMDS
         else
-            echo "echo \"./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS
+            if [[ "$VM_NAME" == *"-enb-ethernet"* ]]
+            then
+                echo "echo \"sleep 170 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS
+            elif [[ "$VM_NAME" == *"-ue-ethernet"* ]]
+            then
+                echo "echo \"sleep 60 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS
+            else
+                echo "echo \"./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS
+            fi
             echo "chmod 775 ./my-vm-build.sh " >> $VM_CMDS
             echo "echo \"sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh\"" >> $VM_CMDS
             echo "sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh" >> $VM_CMDS
diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py
index 0c07dfe91fe24f044f5b52915ea12ad57944aa90..0debe424684b8c9396cb85058df8bae4db280d50 100644
--- a/ci-scripts/cls_containerize.py
+++ b/ci-scripts/cls_containerize.py
@@ -35,6 +35,7 @@ import sys              # arg
 import re               # reg
 import logging
 import os
+import shutil
 import time
 from multiprocessing import Process, Lock, SimpleQueue
 from zipfile import ZipFile
@@ -124,7 +125,7 @@ class Containerize():
 			self.cli = 'docker'
 			self.dockerfileprefix = '.ubuntu18'
 		elif self.host == 'Red Hat':
-			self.cli = 'podman'
+			self.cli = 'sudo podman'
 			self.dockerfileprefix = '.rhel8.2'
 
 		imageNames = []
@@ -173,6 +174,7 @@ class Containerize():
 		# 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
 		imageTag = 'develop'
+		sharedTag = 'develop'
 		if (self.ranAllowMerge):
 			imageTag = 'ci-temp'
 			if self.ranTargetBranch == '':
@@ -188,38 +190,23 @@ class Containerize():
 			mySSH.command('mkdir -p tmp/entitlement/', '\$', 5) 
 			mySSH.command('sudo cp /etc/rhsm/ca/redhat-uep.pem tmp/ca/', '\$', 5)
 			mySSH.command('sudo cp /etc/pki/entitlement/*.pem tmp/entitlement/', '\$', 5)
-			
-		#mySSH.close()
-		#return 0
+
 		sharedimage = 'ran-build'
 		# Let's remove any previous run artifacts if still there
-		mySSH.command(self.cli + ' image prune --force', '\$', 5)
-		mySSH.command(self.cli + ' image rm ' + sharedimage + ':' + imageTag, '\$', 5)
-		for image,pattern in imageNames:
-			mySSH.command(self.cli + ' image rm ' + image + ':' + imageTag, '\$', 5)
-		# Build the shared image
-		mySSH.command(self.cli + ' build --target ' + sharedimage + ' --tag ' + sharedimage + ':' + imageTag + ' --file docker/Dockerfile.ran' + self.dockerfileprefix + ' --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 1600)
-		# Build the target image(s)
-		previousImage = sharedimage + ':' + imageTag
-		danglingShaOnes=[]
+		mySSH.command(self.cli + ' image prune --force', '\$', 30)
+		if (not self.ranAllowMerge):
+			mySSH.command(self.cli + ' image rm ' + sharedimage + ':' + sharedTag, '\$', 30)
 		for image,pattern in imageNames:
-			# the archived Dockerfiles have "ran-build:latest" as base image
-			# we need to update them with proper tag
-			mySSH.command('sed -i -e "s#' + sharedimage + ':latest#' + sharedimage + ':' + imageTag + '#" docker/Dockerfile.' + pattern + self.dockerfileprefix, '\$', 5)
-			mySSH.command(self.cli + ' build --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + self.dockerfileprefix + ' . > cmake_targets/log/' + image + '.log 2>&1', '\$', 1200)
-			# Retrieving the dangling image(s) for the log collection
-			mySSH.command(self.cli + ' images --filter "dangling=true" --filter "since=' + previousImage + '" -q | sed -e "s#^#sha=#"', '\$', 5)
-			result = re.search('sha=(?P<imageShaOne>[a-zA-Z0-9\-\_]+)', mySSH.getBefore())
-			if result is not None:
-				danglingShaOnes.append((image, result.group('imageShaOne')))
-			previousImage = image + ':' + imageTag
+			mySSH.command(self.cli + ' image rm ' + image + ':' + imageTag, '\$', 30)
 
-		imageTag = 'ci-temp'
-		# First verify if images were properly created.
+		# Build the shared image only on Push Events (not on Merge Requests)
+		if (not self.ranAllowMerge):
+			mySSH.command(self.cli + ' build --target ' + sharedimage + ' --tag ' + sharedimage + ':' + sharedTag + ' --file docker/Dockerfile.ran' + self.dockerfileprefix + ' --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 1600)
+		# First verify if the shared image was properly created.
 		status = True
-		mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + sharedimage + ':' + imageTag, '\$', 5)
-		if mySSH.getBefore().count('No such object') != 0:
-			logging.error('Could not build properly ran-build')
+		mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + sharedimage + ':' + sharedTag, '\$', 5)
+		if mySSH.getBefore().count('o such image') != 0:
+			logging.error('\u001B[1m Could not build properly ran-build\u001B[0m')
 			status = False
 		else:
 			result = re.search('Size *= *(?P<size>[0-9\-]+) *bytes', mySSH.getBefore())
@@ -240,11 +227,40 @@ class Containerize():
 						self.allImagesSize['ran-build'] = str(round(imageSize,1)) + ' Gbytes'
 			else:
 				logging.debug('ran-build size is unknown')
+		# If the shared image failed, no need to continue
+		if not status:
+			# Recover the name of the failed container?
+			mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5)
+			mySSH.command(self.cli + ' image prune --force', '\$', 30)
+			mySSH.close()
+			logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
+			HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK)
+			HTML.CreateHtmlTabFooter(False)
+			sys.exit(1)
+		else:
+			# Recover build logs, for the moment only possible when build is successful
+			mySSH.command(self.cli + ' create --name test ' + sharedimage + ':' + sharedTag, '\$', 5)
+			mySSH.command('mkdir -p cmake_targets/log/ran-build', '\$', 5)
+			mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-build', '\$', 5)
+			mySSH.command(self.cli + ' rm -f test', '\$', 5)
+
+		# Build the target image(s)
 		for image,pattern in imageNames:
+			# the archived Dockerfiles have "ran-build:latest" as base image
+			# we need to update them with proper tag
+			mySSH.command('sed -i -e "s#' + sharedimage + ':latest#' + sharedimage + ':' + sharedTag + '#" docker/Dockerfile.' + pattern + self.dockerfileprefix, '\$', 5)
+			mySSH.command(self.cli + ' build --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + self.dockerfileprefix + ' . > cmake_targets/log/' + image + '.log 2>&1', '\$', 1200)
+			# split the log
+			mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5)
+			mySSH.command('python3 ci-scripts/docker_log_split.py --logfilename=cmake_targets/log/' + image + '.log', '\$', 5)
+			# checking the status of the build
 			mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + image + ':' + imageTag, '\$', 5)
-			if mySSH.getBefore().count('No such object') != 0:
-				logging.error('Could not build properly ' + image)
+			if mySSH.getBefore().count('o such image') != 0:
+				logging.error('\u001B[1m Could not build properly ' + image + '\u001B[0m')
 				status = False
+				# Here we should check if the last container corresponds to a failed command and destroy it
+				mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5)
+				self.allImagesSize[image] = 'N/A -- Build Failed'
 			else:
 				result = re.search('Size *= *(?P<size>[0-9\-]+) *bytes', mySSH.getBefore())
 				if result is not None:
@@ -264,39 +280,27 @@ class Containerize():
 							self.allImagesSize[image] = str(round(imageSize,1)) + ' Gbytes'
 				else:
 					logging.debug('ran-build size is unknown')
-		if not status:
-			mySSH.close()
-			logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
-			HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK)
-			#HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize)
-			HTML.CreateHtmlTabFooter(False)
-			sys.exit(1)
+					self.allImagesSize[image] = 'unknown'
+			# Now pruning dangling images in between target builds
+			mySSH.command(self.cli + ' image prune --force', '\$', 30)
 
-		# Recover build logs, for the moment only possible when build is successful
-		mySSH.command(self.cli + ' create --name test ' + sharedimage + ':' + imageTag, '\$', 5)
-		mySSH.command('mkdir -p cmake_targets/log/ran-build', '\$', 5)
-		mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-build', '\$', 5)
-		mySSH.command(self.cli + ' rm -f test', '\$', 5)
-		for image,shaone in danglingShaOnes:
-			mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5)
-			mySSH.command(self.cli + ' create --name test ' + shaone, '\$', 5)
-			mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/' + image, '\$', 5)
-			mySSH.command(self.cli + ' rm -f test', '\$', 5)
-		mySSH.command(self.cli + ' image prune --force', '\$', 5)
-		mySSH.command('cd cmake_targets', '\$', 5)
+		# 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.command('cd /tmp/CI-eNB/cmake_targets', '\$', 5)
+
+		mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5)
+		mySSH.command('rm -f build_log_' + self.testCase_id + '.zip || true', '\$', 5)
 		if (os.path.isfile('./build_log_' + self.testCase_id + '.zip')):
 			os.remove('./build_log_' + self.testCase_id + '.zip')
+		if (os.path.isdir('./build_log_' + self.testCase_id)):
+			shutil.rmtree('./build_log_' + self.testCase_id)
 		mySSH.command('zip -r -qq build_log_' + self.testCase_id + '.zip build_log_' + self.testCase_id, '\$', 5)
 		mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/build_log_' + self.testCase_id + '.zip', '.')
-		#mySSH.command('rm -f build_log_' + self.testCase_id + '.zip','\$', 5)
+		mySSH.command('rm -f build_log_' + self.testCase_id + '.zip','\$', 5)
 		mySSH.close()
 		ZipFile('build_log_' + self.testCase_id + '.zip').extractall('.')
-	
+
 		#Trying to identify the errors and warnings for each built images
 		imageNames1 = imageNames
 		shared = ('ran-build','ran')
@@ -328,9 +332,16 @@ class Containerize():
 				files[fil] = errorandwarnings
 			self.collectInfo[image] = files
 		
-		logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m')
-		HTML.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK)
-		HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize)
+		if status:
+			logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m')
+			HTML.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK)
+			HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize)
+		else:
+			logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
+			HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK)
+			HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize)
+			HTML.CreateHtmlTabFooter(False)
+			sys.exit(1)
 
 	def DeployObject(self, HTML, EPC):
 		if self.eNB_serverId[self.eNB_instance] == '0':
diff --git a/ci-scripts/conf_files/benetel-4g.conf b/ci-scripts/conf_files/benetel-4g.conf
new file mode 100644
index 0000000000000000000000000000000000000000..9423ebe56ecb84c5b2559abf057ce8f1fde8bad3
--- /dev/null
+++ b/ci-scripts/conf_files/benetel-4g.conf
@@ -0,0 +1,285 @@
+Active_eNBs = ( "eNB-Eurecom-LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    # real_time choice in {hard, rt-preempt, no}
+    real_time       =  "no";
+
+    ////////// Identification parameters:
+    eNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_ENB";
+
+    eNB_name  =  "eNB-Eurecom-LTEBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code = 1;
+    plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } );
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "NGFI_RCC_IF4p5";
+      node_timing               = "synch_to_ext_device";
+      node_synch_ref            = 0;
+      frame_type					      = "FDD";
+      tdd_config 					      = 3;
+      tdd_config_s            			      = 0;
+      prefix_type             			      = "NORMAL";
+      eutra_band              			      = 7;
+      downlink_frequency      			      = 2655000000L;
+      uplink_frequency_offset 			      = -120000000;
+      Nid_cell					      = 0;
+      N_RB_DL                 			      = 100;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 1;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 125;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 90;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 0;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 0;
+      pdsch_referenceSignalPower 			      = -10;
+      pdsch_p_b                  			      = 0;
+      pusch_n_SB                 			      = 1;
+      pusch_enable64QAM          			      = "DISABLE";
+      pusch_hoppingMode                                  = "interSubFrame";
+      pusch_hoppingOffset                                = 0;
+      pusch_groupHoppingEnabled  			      = "ENABLE";
+      pusch_groupAssignment      			      = 0;
+      pusch_sequenceHoppingEnabled		   	      = "DISABLE";
+      pusch_nDMRS1                                       = 1;
+      phich_duration                                     = "NORMAL";
+      phich_resource                                     = "ONESIXTH";
+      srs_enable                                         = "DISABLE";
+      /*  srs_BandwidthConfig                                =;
+      srs_SubframeConfig                                 =;
+      srs_ackNackST                                      =;
+      srs_MaxUpPts                                       =;*/
+
+      pusch_p0_Nominal                                   = -96;
+      pusch_alpha                                        = "AL1";
+      pucch_p0_Nominal                                   = -104;
+      msg3_delta_Preamble                                = 6;
+      pucch_deltaF_Format1                               = "deltaF2";
+      pucch_deltaF_Format1b                              = "deltaF3";
+      pucch_deltaF_Format2                               = "deltaF0";
+      pucch_deltaF_Format2a                              = "deltaF0";
+      pucch_deltaF_Format2b		    	      = "deltaF0";
+
+      rach_numberOfRA_Preambles                          = 64;
+      rach_preamblesGroupAConfig                         = "DISABLE";
+      /*
+      rach_sizeOfRA_PreamblesGroupA                      = ;
+      rach_messageSizeGroupA                             = ;
+      rach_messagePowerOffsetGroupB                      = ;
+      */
+      rach_powerRampingStep                              = 4;
+      rach_preambleInitialReceivedTargetPower            = -108;
+      rach_preambleTransMax                              = 10;
+      rach_raResponseWindowSize                          = 10;
+      rach_macContentionResolutionTimer                  = 48;
+      rach_maxHARQ_Msg3Tx                                = 4;
+
+      pcch_default_PagingCycle                           = 128;
+      pcch_nB                                            = "oneT";
+      bcch_modificationPeriodCoeff			      = 2;
+      ue_TimersAndConstants_t300			      = 1000;
+      ue_TimersAndConstants_t301			      = 1000;
+      ue_TimersAndConstants_t310			      = 1000;
+      ue_TimersAndConstants_t311			      = 10000;
+      ue_TimersAndConstants_n310			      = 20;
+      ue_TimersAndConstants_n311			      = 1;
+      ue_TransmissionMode                                    = 1;
+
+      //Parameters for SIB18
+      rxPool_sc_CP_Len                                       = "normal";
+      rxPool_sc_Period                                       = "sf40";
+      rxPool_data_CP_Len                                     = "normal";
+      rxPool_ResourceConfig_prb_Num                          = 20;
+      rxPool_ResourceConfig_prb_Start                        = 5;
+      rxPool_ResourceConfig_prb_End                          = 44;
+      rxPool_ResourceConfig_offsetIndicator_present          = "prSmall";
+      rxPool_ResourceConfig_offsetIndicator_choice           = 0;
+      rxPool_ResourceConfig_subframeBitmap_present           = "prBs40";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_buf              = "00000000000000000000";
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_size             = 5;
+      rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused      = 0;
+/*    rxPool_dataHoppingConfig_hoppingParameter                       = 0;
+      rxPool_dataHoppingConfig_numSubbands                            = "ns1";
+      rxPool_dataHoppingConfig_rbOffset                               = 0;
+      rxPool_commTxResourceUC-ReqAllowed                              = "TRUE";
+*/
+      // Parameters for SIB19
+      discRxPool_cp_Len                                               = "normal"
+      discRxPool_discPeriod                                           = "rf32"
+      discRxPool_numRetx                                              = 1;
+      discRxPool_numRepetition                                        = 2;
+      discRxPool_ResourceConfig_prb_Num                               = 5;
+      discRxPool_ResourceConfig_prb_Start                             = 3;
+      discRxPool_ResourceConfig_prb_End                               = 21;
+      discRxPool_ResourceConfig_offsetIndicator_present               = "prSmall";
+      discRxPool_ResourceConfig_offsetIndicator_choice                = 0;
+      discRxPool_ResourceConfig_subframeBitmap_present                = "prBs40";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf          = "f0ffffffff";
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_size         = 5;
+      discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused  = 0;
+
+      //SSB central frequency of NR secondary cell group (for ENDC NSA) 
+      nr_scg_ssb_freq	      	    	      	   	      	      = 640000;	
+      }
+    );
+
+
+    srb1_parameters :
+    {
+        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
+        timer_poll_retransmit    = 80;
+
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = 35;
+
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = 0;
+
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  4;
+
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  99999;
+
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+    }
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "CI_MME_IP_ADDR";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    enable_measurement_reports = "yes";
+
+    ///X2
+    enable_x2 = "yes";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "CI_ENB_IP_ADDR";
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "CI_ENB_IP_ADDR";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+        ENB_IPV4_ADDRESS_FOR_X2C                 = "127.0.0.1";
+        ENB_PORT_FOR_X2C                         = 36422; # Spec 36422
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+	phy_test_mode = 0;
+        puSch10xSnr     =  160;
+        puCch10xSnr     =  160;
+        }
+);
+
+L1s = (
+      {
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        prach_dtx_threshold = 150;
+      }
+);
+
+RUs = (
+    {
+        //local_if_name  = "enp129s0f0";
+        local_if_name  = "dpdk";
+        sdr_addrs      = "softmodem -m 2048 -l 35 -n 2 -b 0000:81:00.3 --proc-type auto --file-prefix ggg -- -p 0x1";
+        #sdr_addrs      = "softmodem -l 8 -n 2 -- -p 0x2";
+        #remote_address = "127.0.0.2";
+        #local_address  = "127.0.0.1";
+        #local_portc    = 50000;
+        #remote_portc   = 50000;
+        #local_portd    = 50001;
+        #remote_portd   = 50001;
+        local_rf       = "no"
+        tr_preference  = "raw_if4p5"
+        nb_tx          = 1
+        nb_rx          = 1
+        att_tx         = 0
+        att_rx         = 0;
+        eNB_instances  = [0];
+    }
+);
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    #parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+NETWORK_CONTROLLER :
+{
+    FLEXRAN_ENABLED        = "no";
+    FLEXRAN_INTERFACE_NAME = "lo";
+    FLEXRAN_IPV4_ADDRESS   = "127.0.0.1";
+    FLEXRAN_PORT           = 2210;
+    FLEXRAN_CACHE          = "/mnt/oai_agent_cache";
+    FLEXRAN_AWAIT_RECONF   = "no";
+};
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
diff --git a/ci-scripts/conf_files/benetel-5g.conf b/ci-scripts/conf_files/benetel-5g.conf
new file mode 100644
index 0000000000000000000000000000000000000000..0dfe7854ee893c034ca5f4b7a51506835f746b48
--- /dev/null
+++ b/ci-scripts/conf_files/benetel-5g.conf
@@ -0,0 +1,317 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;});	 
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    ssb_SubcarrierOffset                                      = 31; //0;
+    pdsch_AntennaPorts                                        = 1;
+    #pusch_TargetSNRx10                                        = 200;
+    #pucch_TargetSNRx10                                        = 200;
+    pusch_TargetSNRx10                                        = 200;
+    pucch_TargetSNRx10                                        = 200;
+	
+    servingCellConfigCommon = (
+    {
+ #spCellConfigCommon
+
+      physCellId                                                    = 0;
+
+#  downlinkConfigCommon
+    #frequencyInfoDL
+      # this is is the central frequency of SSB 
+      absoluteFrequencySSB                                          = 640000; //641272
+      dl_frequencyBand                                                 = 78;
+      # the carrier frequency is assumed to be in the middle of the carrier, i.e. dl_absoluteFrequencyPointA_kHz + dl_carrierBandwidth*12*SCS_kHz/2
+      dl_absoluteFrequencyPointA                                       = 638728; //640000;
+      #scs-SpecificCarrierList
+        dl_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        dl_subcarrierSpacing                                           = 1;
+        dl_carrierBandwidth                                            = 106;
+     #initialDownlinkBWP
+      #genericParameters
+        # this is RBstart=84,L=13 (275*(L-1))+RBstart
+        initialDLBWPlocationAndBandwidth                                        = 6366; //28875; //6366; #6407; #3384;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialDLBWPsubcarrierSpacing                                           = 1;
+      #pdcch-ConfigCommon
+        initialDLBWPcontrolResourceSetZero                                      = 0;
+        initialDLBWPsearchSpaceZero                                             = 0;
+      #pdsch-ConfigCommon
+        #pdschTimeDomainAllocationList (up to 16 entries)
+             initialDLBWPk0_0                    = 0;
+             #initialULBWPmappingType
+	     #0=typeA,1=typeB
+             initialDLBWPmappingType_0           = 0;
+             #this is SS=1,L=13
+             initialDLBWPstartSymbolAndLength_0  = 40;
+
+             initialDLBWPk0_1                    = 0;
+             initialDLBWPmappingType_1           = 0;
+             #this is SS=2,L=12 
+             initialDLBWPstartSymbolAndLength_1  = 53;
+
+             initialDLBWPk0_2                    = 0;
+             initialDLBWPmappingType_2           = 0;
+             #this is SS=1,L=12 
+             initialDLBWPstartSymbolAndLength_2  = 54;
+
+             initialDLBWPk0_3                    = 0;
+             initialDLBWPmappingType_3           = 0;
+             #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57)
+             initialDLBWPstartSymbolAndLength_3  = 57; //43; //57;
+  #uplinkConfigCommon 
+     #frequencyInfoUL
+      ul_frequencyBand                                                 = 78;
+      #scs-SpecificCarrierList
+      ul_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      ul_subcarrierSpacing                                           = 1;
+      ul_carrierBandwidth                                            = 106;
+      pMax                                                          = 20;
+     #initialUplinkBWP
+      #genericParameters
+        initialULBWPlocationAndBandwidth                                        = 6366; //28875; //6366; #6407; #3384;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialULBWPsubcarrierSpacing                                           = 1;
+      #rach-ConfigCommon
+        #rach-ConfigGeneric
+          prach_ConfigurationIndex                                  = 4;
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+          prach_msg1_FDM                                            = 0;
+          prach_msg1_FrequencyStart                                 = 74;
+          zeroCorrelationZoneConfig                                 = 13;
+          preambleReceivedTargetPower                               = -118;
+          #preambleReceivedTargetPower                               = -104;
+          #preambleReceivedTargetPower                               = -108;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+          preambleTransMax                                          = 6;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+        powerRampingStep                                            = 2;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+        ra_ResponseWindow                                           = 5;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR                = 4;
+#oneHalf (0..15) 4,8,12,16,...60,64
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB                   = 14; //15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+        ra_ContentionResolutionTimer                                = 7;
+        rsrp_ThresholdSSB                                           = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+        prach_RootSequenceIndex_PR                                  = 1;
+        prach_RootSequenceIndex                                     = 1;
+        # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+        #  
+        #msg1_SubcarrierSpacing                                      = 1,
+
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+        restrictedSetConfig                                         = 0,
+      # pusch-ConfigCommon (up to 16 elements)
+        initialULBWPk2_0                      = 2;
+        initialULBWPmappingType_0             = 1
+        # this is SS=0 L=11
+        initialULBWPstartSymbolAndLength_0    = 55;
+ 	
+	initialULBWPk2_1                      = 2;
+        initialULBWPmappingType_1             = 1;
+        # this is SS=0 L=12
+        initialULBWPstartSymbolAndLength_1    = 69;
+
+        initialULBWPk2_2                      = 7;
+        initialULBWPmappingType_2             = 1;
+        # this is SS=10 L=4
+        initialULBWPstartSymbolAndLength_2    = 52;
+
+        msg3_DeltaPreamble                                          = 1;
+        #p0_NominalWithGrant                                         =-90;
+        p0_NominalWithGrant                                         =-118;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+        pucchGroupHopping                                           = 0;
+        hoppingId                                                   = 40;
+        #p0_nominal                                                  = -90;
+        p0_nominal                                                  = -118;
+# ssb_PositionsInBurs_BitmapPR
+# 1=short, 2=medium, 3=long
+      ssb_PositionsInBurst_PR                                       = 2;
+      ssb_PositionsInBurst_Bitmap                                   = 1; #0x80;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 
+      ssb_periodicityServingCell                                    = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+      dmrs_TypeA_Position                                           = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      subcarrierSpacing                                             = 1;
+
+
+  #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      referenceSubcarrierSpacing                                    = 1;
+      # pattern1 
+      # dl_UL_TransmissionPeriodicity
+      # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+      dl_UL_TransmissionPeriodicity                                 = 6;
+      nrofDownlinkSlots                                             = 7; //8; //7;
+      nrofDownlinkSymbols                                           = 6; //0; //6;
+      nrofUplinkSlots                                               = 2;
+      nrofUplinkSymbols                                             = 4; //0; //4;
+
+  #ssPBCH_BlockPower                                             = 10;
+  ssPBCH_BlockPower                                             = -35;
+  }
+
+  );
+
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "CI_MME_IP_ADDR";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    ///X2
+    enable_x2 = "yes";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
+    target_enb_x2_ip_address      = (
+                                     { ipv4       = "127.0.0.1";
+                                       ipv6       = "192:168:30::17";
+                                       preference = "ipv4";
+                                     }
+                                    );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "CI_GNB_IP_ADDR";
+        GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "CI_GNB_IP_ADDR";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+        GNB_IPV4_ADDRESS_FOR_X2C                 = "127.0.0.2/24";
+        GNB_PORT_FOR_X2C                         = 36422; # Spec 36422
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+	pusch_proc_threads = 8;
+        }  
+);
+
+RUs = (
+    {		  
+       local_rf       = "no"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 114;
+         eNB_instances  = [0];
+         //clock_src = "internal";
+         clock_src = "external";
+
+        local_if_name  = "dpdk";
+        sdr_addrs      = "softmodem -m 2048 -l 34  -n 3 -b 0000:81:00.2 --proc-type auto --file-prefix hhh -- -p 0x1";
+        remote_address = "127.0.0.2";
+        local_address  = "127.0.0.1";
+        local_portc    = 50000;
+        remote_portc   = 50000;
+        local_portd    = 50001;
+        remote_portd   = 50001;
+        tr_preference  = "raw_if4p5"
+
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    //parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_DISABLE";
+  }
+);
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf
new file mode 100644
index 0000000000000000000000000000000000000000..32de0aa4f57d6ea6d05d8625fc93b547056db0dc
--- /dev/null
+++ b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf
@@ -0,0 +1,292 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    ssb_SubcarrierOffset                                      = 0;
+    pdsch_AntennaPorts                                        = 1;
+
+    servingCellConfigCommon = (
+    {
+ #spCellConfigCommon
+
+      physCellId                                                    = 0;
+
+#  downlinkConfigCommon
+    #frequencyInfoDL
+      # this is 2150 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
+      absoluteFrequencySSB                                          = 433096;
+      dl_frequencyBand                                                 = 66;
+      # this is 2150 MHz
+      dl_absoluteFrequencyPointA                                       = 430000;
+      #scs-SpecificCarrierList
+        dl_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+        dl_subcarrierSpacing                                           = 1;
+        dl_carrierBandwidth                                            = 106;
+     #initialDownlinkBWP
+      #genericParameters
+        # this is RBstart=0,L=50 (275*(L-1))+RBstart
+        initialDLBWPlocationAndBandwidth                                        = 13475;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+        initialDLBWPsubcarrierSpacing                                           = 1;
+      #pdcch-ConfigCommon
+        initialDLBWPcontrolResourceSetZero                                      = 12;
+        initialDLBWPsearchSpaceZero                                             = 0;
+      #pdsch-ConfigCommon
+        #pdschTimeDomainAllocationList (up to 16 entries)
+             initialDLBWPk0_0                    = 0;
+             #initialULBWPmappingType
+       #0=typeA,1=typeB
+             initialDLBWPmappingType_0           = 0;
+             #this is SS=1,L=13
+             initialDLBWPstartSymbolAndLength_0  = 40;
+
+             initialDLBWPk0_1                    = 0;
+             initialDLBWPmappingType_1           = 0;
+             #this is SS=2,L=12
+             initialDLBWPstartSymbolAndLength_1  = 53;
+
+             initialDLBWPk0_2                    = 0;
+             initialDLBWPmappingType_2           = 0;
+             #this is SS=1,L=12
+             initialDLBWPstartSymbolAndLength_2  = 54;
+
+             initialDLBWPk0_3                    = 0;
+             initialDLBWPmappingType_3           = 0;
+             #this is SS=1,L=4
+             initialDLBWPstartSymbolAndLength_3  = 57;
+  #uplinkConfigCommon
+     #frequencyInfoUL
+      ul_frequencyBand                                                 = 66;
+      ul_absoluteFrequencyPointA                                       = 350000;
+      #scs-SpecificCarrierList
+      ul_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+      ul_subcarrierSpacing                                           = 1;
+      ul_carrierBandwidth                                            = 106;
+      pMax                                                          = 20;
+     #initialUplinkBWP
+      #genericParameters
+        initialULBWPlocationAndBandwidth                                        = 13475;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+        initialULBWPsubcarrierSpacing                                           = 1;
+      #rach-ConfigCommon
+        #rach-ConfigGeneric
+          prach_ConfigurationIndex                                  = 98;
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+          prach_msg1_FDM                                            = 0;
+          prach_msg1_FrequencyStart                                 = 0;
+          zeroCorrelationZoneConfig                                 = 13;
+          preambleReceivedTargetPower                               = -118;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+          preambleTransMax                                          = 6;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+        powerRampingStep                                            = 1;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+        ra_ResponseWindow                                           = 4;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR                = 4;
+#oneHalf (0..15) 4,8,12,16,...60,64
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB                   = 15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+        ra_ContentionResolutionTimer                                = 7;
+        rsrp_ThresholdSSB                                           = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+        prach_RootSequenceIndex_PR                                  = 2;
+        prach_RootSequenceIndex                                     = 1;
+        # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+        #
+        msg1_SubcarrierSpacing                                      = 1,
+
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+        restrictedSetConfig                                         = 0,
+      # pusch-ConfigCommon (up to 16 elements)
+        initialULBWPk2_0                      = 6;
+        initialULBWPmappingType_0             = 1
+        # this is SS=0 L=11
+        initialULBWPstartSymbolAndLength_0    = 55;
+
+  initialULBWPk2_1                      = 6;
+        initialULBWPmappingType_1             = 1;
+        # this is SS=0 L=12
+        initialULBWPstartSymbolAndLength_1    = 69;
+
+        initialULBWPk2_2                      = 7;
+        initialULBWPmappingType_2             = 1;
+        # this is SS=10 L=4
+        initialULBWPstartSymbolAndLength_2    = 52;
+        msg3_DeltaPreamble                                          = 1;
+        p0_NominalWithGrant                                         =-90;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+        pucchGroupHopping                                           = 0;
+        hoppingId                                                   = 40;
+        p0_nominal                                                  = -90;
+# ssb_PositionsInBurs_BitmapPR
+# 1=short, 2=medium, 3=long
+      ssb_PositionsInBurst_PR                                       = 2;
+      ssb_PositionsInBurst_Bitmap                                   = 1;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
+      ssb_periodicityServingCell                                    = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+      dmrs_TypeA_Position                                           = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+      subcarrierSpacing                                             = 1;
+
+
+  #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+      referenceSubcarrierSpacing                                    = 1;
+      # pattern1
+      # dl_UL_TransmissionPeriodicity
+      # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+      dl_UL_TransmissionPeriodicity                                 = 6;
+      nrofDownlinkSlots                                             = 7;
+      nrofDownlinkSymbols                                           = 6;
+      nrofUplinkSlots                                               = 2;
+      nrofUplinkSymbols                                             = 4;
+
+  ssPBCH_BlockPower                                             = 10;
+  }
+
+  );
+
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.12.26";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
+        GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+  }
+);
+
+MACRLCs = (
+  {
+  num_cc = 1;
+  tr_s_preference = "local_L1";
+  tr_n_preference = "local_RRC";
+  }
+);
+
+L1s = (
+  {
+  num_cc = 1;
+  tr_n_preference = "local_mac";
+  pusch_proc_threads = 8;
+  }
+);
+
+RUs = (
+    {
+       local_rf       = "yes"
+         nb_tx          = 1;
+         nb_rx          = 1;
+         att_tx         = 0;
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 75;
+         eNB_instances  = [0];
+         ##beamforming 1x2 matrix: 1 layer x 2 antennas
+         bf_weights = [0x00007fff, 0x0000];
+         ##beamforming 1x4 matrix: 1 layer x 4 antennas
+         #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
+         ## beamforming 2x2 matrix:
+         # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+         ## beamforming 4x4 matrix:
+         #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
+
+         sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2";
+         clock_src = "external";
+         # if_freq = 3700000000L;
+         # if_offset = 1000000;
+    }
+);
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
index aeba400cad73ace17cb920bb5a2802b74dfa37af..decaa392d752cacfd789a23b9054e3c226431781 100644
--- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -23,7 +23,7 @@ gNBs =
 
     ssb_SubcarrierOffset                                      = 0;
     pdsch_AntennaPorts                                        = 1;
-	
+
     servingCellConfigCommon = (
     {
  #spCellConfigCommon
@@ -227,14 +227,15 @@ MACRLCs = (
 	num_cc = 1;
 	tr_s_preference = "local_L1";
 	tr_n_preference = "local_RRC";
-        }  
+	}
 );
 
 L1s = (
-    	{
+	{
 	num_cc = 1;
 	tr_n_preference = "local_mac";
-        }  
+	pusch_proc_threads = 8;
+	}
 );
 
 RUs = (
@@ -248,8 +249,15 @@ RUs = (
          max_pdschReferenceSignalPower = -27;
          max_rxgain                    = 75;
          eNB_instances  = [0];
-         #beamforming 1x4 matrix:
-         bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
+         ##beamforming 1x2 matrix: 1 layer x 2 antennas
+         bf_weights = [0x00007fff, 0x0000];
+         ##beamforming 1x4 matrix: 1 layer x 4 antennas
+         #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
+         ## beamforming 2x2 matrix:
+         # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+         ## beamforming 4x4 matrix:
+         #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
+
          sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2";
          clock_src = "external";
     }
diff --git a/ci-scripts/createVM.sh b/ci-scripts/createVM.sh
index 237a1a5d5e4521197c51a2f69433a38340f1c6e3..b67668f0bcc4036736b381d9caf84ab6e8567c19 100755
--- a/ci-scripts/createVM.sh
+++ b/ci-scripts/createVM.sh
@@ -87,6 +87,12 @@ function create_vm {
     echo "VM_CPU              = $VM_CPU"
     echo "VM_DISK             = $VM_DISK GBytes"
 
+    if [[ "$VM_NAME" == *"-enb-usrp"* ]]
+    then
+        echo "This VM type is no longer supported in the pipeline framework"
+        return
+    fi
+
     echo "############################################################"
     echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base"
     echo "############################################################"
diff --git a/ci-scripts/docker_log_split.py b/ci-scripts/docker_log_split.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c3c9e41dcac79f2b527fc980da803b7b33465fc
--- /dev/null
+++ b/ci-scripts/docker_log_split.py
@@ -0,0 +1,92 @@
+#/*
+# * 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
+# */
+#---------------------------------------------------------------------
+# Python for CI of OAI-eNB + COTS-UE
+#
+#   Required Python Version
+#     Python 3.x
+#
+#   Required Python Package
+#     pexpect
+#---------------------------------------------------------------------
+
+
+#-----------------------------------------------------------
+# Import Libs
+#-----------------------------------------------------------
+import sys		# arg
+import re		# reg
+import os
+import subprocess
+
+
+class SplitReport():
+	def __init__(self):
+		self.logfilename = ''
+		self.destinationFolder = ''
+
+	def split(self):
+		self.destinationFolder = self.logfilename.replace(".log","")
+		if os.path.isfile(self.logfilename):
+			newImageLog = open(self.logfilename + '.new', 'w')
+			copyFlag = True
+			with open(self.logfilename, 'r') as imageLog:
+				for line in imageLog:
+					header = False
+					ret = re.search('====== Start of log for ([0-9\.A-Za-z\-\_]+) ======', line)
+					if ret is not None:
+						copyFlag = False
+						header = True
+						detailedLogFile = open(self.destinationFolder + '/' + ret.group(1), 'w')
+					if copyFlag:
+						newImageLog.write(line)
+					ret = re.search('====== End of log for ([0-9\.A-Za-z\-\_]+) ======', line)
+					if ret is not None:
+						copyFlag = True
+						detailedLogFile.close()
+					elif not copyFlag and not header:
+						detailedLogFile.write(line)
+			imageLog.close()
+			newImageLog.close()
+			os.rename(self.logfilename + '.new', self.logfilename)
+		else:
+			print('Cannot split unfound file')
+
+#--------------------------------------------------------------------------------------------------------
+#
+# Start of main
+#
+#--------------------------------------------------------------------------------------------------------
+
+argvs = sys.argv
+argc = len(argvs)
+
+SP = SplitReport()
+
+while len(argvs) > 1:
+	myArgv = argvs.pop(1)
+	if re.match('^\-\-logfilename=(.+)$', myArgv, re.IGNORECASE):
+		matchReg = re.match('^\-\-logfilename=(.+)$', myArgv, re.IGNORECASE)
+		SP.logfilename = matchReg.group(1)
+
+SP.split()
+
+sys.exit(0)
diff --git a/ci-scripts/oai-ci-vm-tool b/ci-scripts/oai-ci-vm-tool
index 9b9fe462f15d07200b316cedb3b8273451b91807..d8f088b707e608f33cc1f25c727708dfd60f131b 100755
--- a/ci-scripts/oai-ci-vm-tool
+++ b/ci-scripts/oai-ci-vm-tool
@@ -172,6 +172,7 @@ function setvar_usage {
 function variant__v1__enb_usrp {
     NB_PATTERN_FILES=9
     BUILD_OPTIONS="--eNB -w USRP --mu"
+    VM_MEMORY=3072
 }
     
 function variant__v2__basic_sim {
@@ -213,15 +214,15 @@ function variant__v6__nr_ue_usrp {
 function variant__v7__enb_ethernet {
     VM_MEMORY=4096
     ARCHIVES_LOC=enb_eth
-    NB_PATTERN_FILES=8
-    BUILD_OPTIONS="--eNB"
+    NB_PATTERN_FILES=9
+    BUILD_OPTIONS="--eNB -w USRP"
 }
 
 function variant__v8__ue_ethernet {
     VM_MEMORY=4096
     ARCHIVES_LOC=ue_eth
-    NB_PATTERN_FILES=12
-    BUILD_OPTIONS="--UE"
+    NB_PATTERN_FILES=13
+    BUILD_OPTIONS="--UE -w USRP"
 }
 
 function variant__v10__flexran_rtc {
diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py
index 774d7f19c6a4f240ca36409aa2418a8b0005c57f..783adb98e68e584e211094622aee0f7d02a1d2fe 100644
--- a/ci-scripts/ran.py
+++ b/ci-scripts/ran.py
@@ -239,6 +239,7 @@ class RANManagement():
 		while (count > 0) and buildOAIprocess:
 			mySSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 6)
 			result = re.search('build_oai', mySSH.getBefore())
+			print(result)
 			if result is None:
 				buildOAIprocess = False
 			else:
@@ -464,7 +465,7 @@ class RANManagement():
 				self.prematureExit = True
 				return
 			else:
-				mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4)
+				mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting|Started"', '\$', 4)
 				if rruCheck:
 					result = re.search('wait RUs', mySSH.getBefore())
 				else:
diff --git a/ci-scripts/reportBuildLocally.sh b/ci-scripts/reportBuildLocally.sh
index 44d200c3b6419b1c0fe354fdb33db882c9bcb1f2..19a486303f10e5355d49c8b1e425b9c42314e6dc 100755
--- a/ci-scripts/reportBuildLocally.sh
+++ b/ci-scripts/reportBuildLocally.sh
@@ -580,16 +580,42 @@ function report_build {
     sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Expression depends on order of evaluation of side effects" unknownEvaluationOrder
     sca_summary_table_footer ./archives/cppcheck/cppcheck.xml
 
-    summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_usrp
-    summary_table_row "LTE SoftModem - Release 15" ./archives/enb_usrp/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_usrp_row1.html
-    summary_table_row "Coding - Release 15" ./archives/enb_usrp/coding.Rel15.txt "Built target coding" ./enb_usrp_row2.html
-    summary_table_row "OAI USRP device if - Release 15" ./archives/enb_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_usrp_row3.html
-    summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_usrp_row4.html
-    summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_usrp_row5.html
-    summary_table_row "NASMESH - Release 15" ./archives/enb_usrp/nasmesh.Rel15.txt "Built target nasmesh" ./enb_usrp_row6.html
-    summary_table_row "RB Tool - Release 15" ./archives/enb_usrp/rb_tool.Rel15.txt "Built target rb_tool" ./enb_usrp_row7.html
-    summary_table_row "RF Simulator - Release 15" ./archives/enb_usrp/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_usrp_row8.html
-    summary_table_row "TCP Bridge - Release 15" ./archives/enb_usrp/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_usrp_row9.html
+#    summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_usrp
+#    summary_table_row "LTE SoftModem - Release 15" ./archives/enb_usrp/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_usrp_row1.html
+#    summary_table_row "Coding - Release 15" ./archives/enb_usrp/coding.Rel15.txt "Built target coding" ./enb_usrp_row2.html
+#    summary_table_row "OAI USRP device if - Release 15" ./archives/enb_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_usrp_row3.html
+#    summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_usrp_row4.html
+#    summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_usrp_row5.html
+#    summary_table_row "NASMESH - Release 15" ./archives/enb_usrp/nasmesh.Rel15.txt "Built target nasmesh" ./enb_usrp_row6.html
+#    summary_table_row "RB Tool - Release 15" ./archives/enb_usrp/rb_tool.Rel15.txt "Built target rb_tool" ./enb_usrp_row7.html
+#    summary_table_row "RF Simulator - Release 15" ./archives/enb_usrp/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_usrp_row8.html
+#    summary_table_row "TCP Bridge - Release 15" ./archives/enb_usrp/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_usrp_row9.html
+#    summary_table_footer
+#
+    summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_eth
+    summary_table_row "LTE SoftModem - Release 15" ./archives/enb_eth/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_eth_row1.html
+    summary_table_row "Coding - Release 15" ./archives/enb_eth/coding.Rel15.txt "Built target coding" ./enb_eth_row2.html
+    summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_eth_row3.html
+    summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_eth_row4.html
+    summary_table_row "RF Simulator - Release 15" ./archives/enb_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_eth_row5.html
+    summary_table_row "TCP OAI Bridge - Release 15" ./archives/enb_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_eth_row6.html
+    summary_table_row "OAI USRP device if - Release 15" ./archives/enb_eth/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_eth_row7.html
+    summary_table_row "NASMESH - Release 15" ./archives/enb_eth/nasmesh.Rel15.txt "Built target nasmesh" ./enb_eth_row8.html
+    summary_table_row "RB Tool - Release 15" ./archives/enb_eth/rb_tool.Rel15.txt "Built target rb_tool" ./enb_eth_row9.html
+    summary_table_footer
+
+    summary_table_header "OAI Build: 4G LTE UE -- USRP option" ./archives/ue_eth
+    summary_table_row "LTE UE SoftModem - Release 15" ./archives/ue_eth/lte-uesoftmodem.Rel15.txt "Built target lte-uesoftmodem" ./ue_eth_row1.html
+    summary_table_row "Coding - Release 15" ./archives/ue_eth/coding.Rel15.txt "Built target coding" ./ue_eth_row2.html
+    summary_table_row "OAI ETHERNET transport - Release 15" ./archives/ue_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./ue_eth_row3.html
+    summary_table_row "Parameters Lib Config - Release 15" ./archives/ue_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./ue_eth_row4.html
+    summary_table_row "RF Simulator - Release 15" ./archives/ue_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./ue_eth_row5.html
+    summary_table_row "TCP OAI Bridge - Release 15" ./archives/ue_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./ue_eth_row6.html
+    summary_table_row "Conf 2 UE Data - Release 15" ./archives/ue_eth/conf2uedata.Rel15.txt "Built target conf2uedata" ./ue_eth_row7.html
+    summary_table_row "NVRAM - Release 15" ./archives/ue_eth/nvram.Rel15.txt "Built target nvram" ./ue_eth_row8.html
+    summary_table_row "UE IP - Release 15" ./archives/ue_eth/ue_ip.Rel15.txt "Built target ue_ip" ./ue_eth_row9.html
+    summary_table_row "USIM - Release 15" ./archives/ue_eth/usim.Rel15.txt "Built target usim" ./ue_eth_row9a.html
+    summary_table_row "OAI USRP device if - Release 15" ./archives/ue_eth/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./ue_eth_row9b.html
     summary_table_footer
 
     summary_table_header "OAI Build: 4G LTE basic simulator option" ./archives/basic_sim
@@ -676,28 +702,6 @@ function report_build {
         summary_table_footer
     fi
 
-    summary_table_header "OAI Build: 4G LTE eNB -- ETHERNET transport option" ./archives/enb_eth
-    summary_table_row "LTE SoftModem - Release 15" ./archives/enb_eth/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_eth_row1.html
-    summary_table_row "Coding - Release 15" ./archives/enb_eth/coding.Rel15.txt "Built target coding" ./enb_eth_row2.html
-    summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_eth_row3.html
-    summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_eth_row4.html
-    summary_table_row "RF Simulator - Release 15" ./archives/enb_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_eth_row5.html
-    summary_table_row "TCP OAI Bridge - Release 15" ./archives/enb_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_eth_row6.html
-    summary_table_footer
-
-    summary_table_header "OAI Build: 4G LTE UE -- ETHERNET transport option" ./archives/ue_eth
-    summary_table_row "LTE UE SoftModem - Release 15" ./archives/ue_eth/lte-uesoftmodem.Rel15.txt "Built target lte-uesoftmodem" ./ue_eth_row1.html
-    summary_table_row "Coding - Release 15" ./archives/ue_eth/coding.Rel15.txt "Built target coding" ./ue_eth_row2.html
-    summary_table_row "OAI ETHERNET transport - Release 15" ./archives/ue_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./ue_eth_row3.html
-    summary_table_row "Parameters Lib Config - Release 15" ./archives/ue_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./ue_eth_row4.html
-    summary_table_row "RF Simulator - Release 15" ./archives/ue_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./ue_eth_row5.html
-    summary_table_row "TCP OAI Bridge - Release 15" ./archives/ue_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./ue_eth_row6.html
-    summary_table_row "Conf 2 UE Data - Release 15" ./archives/ue_eth/conf2uedata.Rel15.txt "Built target conf2uedata" ./ue_eth_row7.html
-    summary_table_row "NVRAM - Release 15" ./archives/ue_eth/nvram.Rel15.txt "Built target nvram" ./ue_eth_row8.html
-    summary_table_row "UE IP - Release 15" ./archives/ue_eth/ue_ip.Rel15.txt "Built target ue_ip" ./ue_eth_row9.html
-    summary_table_row "USIM - Release 15" ./archives/ue_eth/usim.Rel15.txt "Built target usim" ./ue_eth_row9a.html
-    summary_table_footer
-
     if [ -e ./archives/red_hat ]
     then
         echo "   <h2>Red Hat Enterprise Linux Server release 7.6) -- Summary</h2>" >> ./build_results.html
@@ -714,9 +718,23 @@ function report_build {
     echo "   <button data-toggle=\"collapse\" data-target=\"#oai-compilation-details\">Details for Compilation Errors and Warnings </button>" >> ./build_results.html
     echo "   <div id=\"oai-compilation-details\" class=\"collapse\">" >> ./build_results.html
 
-    if [ -f ./enb_usrp_row1.html ] || [ -f ./enb_usrp_row2.html ] || [ -f ./enb_usrp_row3.html ] || [ -f ./enb_usrp_row4.html ]
+#    if [ -f ./enb_usrp_row1.html ] || [ -f ./enb_usrp_row2.html ] || [ -f ./enb_usrp_row3.html ] || [ -f ./enb_usrp_row4.html ]
+#    then
+#        for DETAILS_TABLE in `ls ./enb_usrp_row*.html`
+#        do
+#            cat $DETAILS_TABLE >> ./build_results.html
+#        done
+#    fi
+    if [ -f ./enb_eth_row1.html ] || [ -f ./enb_eth_row2.html ] || [ -f ./enb_eth_row3.html ] || [ -f ./enb_eth_row4.html ] || [ -f ./enb_eth_row5.html ] || [ -f ./enb_eth_row6.html ] || [ -f ./enb_eth_row7.html ] || [ -f ./enb_eth_row8.html ] || [ -f ./enb_eth_row9.html ]
+    then
+        for DETAILS_TABLE in `ls ./enb_eth_row*.html`
+        do
+            cat $DETAILS_TABLE >> ./build_results.html
+        done
+    fi
+    if [ -f ./ue_eth_row1.html ] || [ -f ./ue_eth_row2.html ] || [ -f ./ue_eth_row3.html ] || [ -f ./ue_eth_row4.html ] || [ -f ./ue_eth_row5.html ] || [ -f ./ue_eth_row6.html ] || [ -f ./ue_eth_row7.html ] || [ -f ./ue_eth_row8.html ] || [ -f ./ue_eth_row9.html ] || [ -f ./ue_eth_row9a.html ] || [ -f ./ue_eth_row9b.html ]
     then
-        for DETAILS_TABLE in `ls ./enb_usrp_row*.html`
+        for DETAILS_TABLE in `ls ./ue_eth_row*.html`
         do
             cat $DETAILS_TABLE >> ./build_results.html
         done
@@ -749,20 +767,6 @@ function report_build {
             cat $DETAILS_TABLE >> ./build_results.html
         done
     fi
-    if [ -f ./enb_eth_row1.html ] || [ -f ./enb_eth_row2.html ] || [ -f ./enb_eth_row3.html ] || [ -f ./enb_eth_row4.html ] || [ -f ./enb_eth_row5.html ] || [ -f ./enb_eth_row6.html ]
-    then
-        for DETAILS_TABLE in `ls ./enb_eth_row*.html`
-        do
-            cat $DETAILS_TABLE >> ./build_results.html
-        done
-    fi
-    if [ -f ./ue_eth_row1.html ] || [ -f ./ue_eth_row2.html ] || [ -f ./ue_eth_row3.html ] || [ -f ./ue_eth_row4.html ] || [ -f ./ue_eth_row5.html ] || [ -f ./ue_eth_row6.html ]
-    then
-        for DETAILS_TABLE in `ls ./ue_eth_row*.html`
-        do
-            cat $DETAILS_TABLE >> ./build_results.html
-        done
-    fi
     if [ -f ./enb_usrp_rh_row1.html ] || [ -f ./enb_usrp_rh_row2.html ] || [ -f ./enb_usrp_rh_row3.html ] || [ -f ./enb_usrp_rh_row4.html ]
     then
         for DETAILS_TABLE in `ls ./enb_usrp_rh_row*.html`
diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh
index 8562f4b2de49411b922b4f8f39fda765ecebe3c9..415ded57a415c667c4f84c0d77bf8b67568380e9 100755
--- a/ci-scripts/reportTestLocally.sh
+++ b/ci-scripts/reportTestLocally.sh
@@ -749,7 +749,7 @@ function report_test {
         echo "      </tr>" >> ./test_simulator_results.html
 
         EPC_CONFIGS=("noS1")
-        TRANS_MODES=("tdd")
+        TRANS_MODES=("fdd" "tdd")
         BW_CASES=(106)
         for CN_CONFIG in ${EPC_CONFIGS[@]}
         do
diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh
index 70eabb7b695ecc4218c2d80143e47f3ff8124b0b..f81868504945af2c1b5d4eeb8fb69c90da1aa800 100755
--- a/ci-scripts/runTestOnVM.sh
+++ b/ci-scripts/runTestOnVM.sh
@@ -379,7 +379,7 @@ function check_iperf {
     local LOC_IS_DL=`echo $LOC_BASE_LOG | grep -c _dl`
     local LOC_IS_BASIC_SIM=`echo $LOC_BASE_LOG | grep -c basic_sim`
     local LOC_IS_RF_SIM=`echo $LOC_BASE_LOG | grep -c rf_sim`
-    local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c tdd_106prb`
+    local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c _106prb`
     if [ -f ${LOC_BASE_LOG}_client.txt ]
     then
         local FILE_COMPLETE=`egrep -c "Server Report" ${LOC_BASE_LOG}_client.txt`
@@ -2189,39 +2189,50 @@ function run_test_on_vm {
 
     if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf-sim.* ]]
     then
-        CN_CONFIG="noS1"
-        CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf
-        S1_NOS1_CFG=0
-        PRB=106
-        FREQUENCY=3510
-
         if [ ! -d $ARCHIVES_LOC ]
         then
             mkdir --parents $ARCHIVES_LOC
         fi
 
-        local try_cnt=0
-        NR_STATUS=0
+        CN_CONFIG="noS1"
+        S1_NOS1_CFG=0
 
         ######### start of RA TEST loop
-        while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI
+        # for the moment only TDD
+        TRANS_MODES=("tdd")
+        for TMODE in ${TRANS_MODES[@]}
         do
+          if [[ $TMODE =~ .*fdd.* ]]
+          then
+            CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf
+            PRB=106
+            FREQUENCY=37000
+          else
+            CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf
+            PRB=106
+            FREQUENCY=3510
+          fi
 
+          local try_cnt=0
+          NR_STATUS=0
+          while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI
+
+          do
             SYNC_STATUS=0
             RA_STATUS=0
-            rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}*ra_test.log
+            rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}*ra_test.log
 
             echo "############################################################"
-            echo "${CN_CONFIG} : Starting the gNB"
+            echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (RA TEST)"
             echo "############################################################"
-            CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb_ra_test.log
+            CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb_ra_test.log
             #last argument = 1 is to enable --do-ra for RA test
             start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1
 
             echo "############################################################"
-            echo "${CN_CONFIG} : Starting the NR-UE"
+            echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (RA TEST)"
             echo "############################################################"
-            CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue_ra_test.log
+            CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue_ra_test.log
             #last argument = 1 is to enable --do-ra for RA test
             start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1
             if [ $NR_UE_SYNC -eq 0 ]
@@ -2260,35 +2271,47 @@ function run_test_on_vm {
             else
                 try_cnt=$((try_cnt+10))
             fi
+          done
         done
         ########### end RA test
         
         sleep 30
 
-
         ######### start of PHY TEST loop
-        try_cnt=0
-        while [ $try_cnt -lt 4 ]
+        SYNC_STATUS=0
+        PING_STATUS=0
+        IPERF_STATUS=0
+        TRANS_MODES=("fdd tdd")
+        for TMODE in ${TRANS_MODES[@]}
         do
+          if [[ $TMODE =~ .*fdd.* ]]
+          then
+            CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf
+            PRB=106
+            FREQUENCY=37000
+          else
+            CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf
+            PRB=106
+            FREQUENCY=3510
+          fi
 
-
-            SYNC_STATUS=0
-            PING_STATUS=0
-            IPERF_STATUS=0
-            rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_gnb.log $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ue.log 
-            rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log
-            rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_iperf_dl*txt $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_iperf_ul*txt
+          try_cnt=0
+          while [ $try_cnt -lt 4 ]
+          do
+            rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log
+            rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log
+            rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl*txt $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul*txt
 
             echo "############################################################"
-            echo "${CN_CONFIG} : Starting the gNB"
+            echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (PHY TEST)"
             echo "############################################################"
-            CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log
+            CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log
             start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 0
 
             echo "############################################################"
-            echo "${CN_CONFIG} : Starting the NR-UE"
+            echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (PHY TEST)"
             echo "############################################################"
-            CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log
+            CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log
             start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 0
             if [ $NR_UE_SYNC -eq 0 ]
             then
@@ -2306,7 +2329,7 @@ function run_test_on_vm {
             echo "${CN_CONFIG} : Pinging the gNB from NR-UE"
             echo "############################################################"
             get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR
-            PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log
+            PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log
             ping_epc_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $ENB_IP_ADDR $PING_LOG_FILE 1 0
             scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC
             check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20
@@ -2315,7 +2338,7 @@ function run_test_on_vm {
             echo "${CN_CONFIG} : Pinging the NR-UE from gNB"
             echo "############################################################"
             get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1
-            PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log
+            PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log
             ping_enb_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR $UE_IP_ADDR $PING_LOG_FILE 0
             scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC
             check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20
@@ -2324,7 +2347,7 @@ function run_test_on_vm {
             echo "${CN_CONFIG} : iperf DL -- NR-UE is server and gNB is client"
             echo "############################################################"
             THROUGHPUT="30K"
-            CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_dl
+            CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl
             get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR
             get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1
             generic_iperf $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 
@@ -2346,7 +2369,7 @@ function run_test_on_vm {
             echo "${CN_CONFIG} : iperf UL -- gNB is server and NR-UE is client"
             echo "############################################################"
             THROUGHPUT="30K"
-            CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_ul
+            CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul
             get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR
             get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1
             generic_iperf $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0
@@ -2368,6 +2391,7 @@ function run_test_on_vm {
             else
                 try_cnt=$((try_cnt+10))
             fi
+          done
         done
         ######### end of loop
         full_l2_sim_destroy
diff --git a/ci-scripts/waitBuildOnVM.sh b/ci-scripts/waitBuildOnVM.sh
index f066dacd8123abb5ccff3c1eff3a0f6ed5df5663..ff2129a187d4a0216d75c73a05889418650e9f44 100755
--- a/ci-scripts/waitBuildOnVM.sh
+++ b/ci-scripts/waitBuildOnVM.sh
@@ -47,6 +47,12 @@ function wait_on_vm_build {
     echo "ARCHIVES_LOC        = $ARCHIVES_LOC"
     echo "BUILD_OPTIONS       = $BUILD_OPTIONS"
 
+    if [[ "$VM_NAME" == *"-enb-usrp"* ]]
+    then
+        echo "This VM type is no longer supported in the pipeline framework"
+        return
+    fi
+
     IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME`
 
     if [ $IS_VM_ALIVE -eq 0 ]
@@ -84,6 +90,12 @@ function wait_on_vm_build {
 }
 
 function check_on_vm_build {
+    if [[ "$VM_NAME" == *"-enb-usrp"* ]]
+    then
+        echo "This VM type is no longer supported in the pipeline framework"
+        return
+    fi
+
     echo "############################################################"
     echo "Creating a tmp folder to store results and artifacts"
     echo "############################################################"
diff --git a/ci-scripts/xml_files/fr1_multi_node_test.xml b/ci-scripts/xml_files/benetel_multi_node_build.xml
similarity index 50%
rename from ci-scripts/xml_files/fr1_multi_node_test.xml
rename to ci-scripts/xml_files/benetel_multi_node_build.xml
index 8c56f0bcec9354394dc622d86675e30ff1281dff..5ac28951b4ad308f078402f0cebd117ba01e4112 100644
--- a/ci-scripts/xml_files/fr1_multi_node_test.xml
+++ b/ci-scripts/xml_files/benetel_multi_node_build.xml
@@ -21,57 +21,34 @@
 
 -->
 <testCaseList>
-	<htmlTabRef>test-fr1-tm1</htmlTabRef>
-	<htmlTabName>Test-FR1-TM1</htmlTabName>
-	<htmlTabIcon>tasks</htmlTabIcon>
-	<repeatCount>1</repeatCount>
+	<htmlTabRef>build-tab</htmlTabRef>
+	<htmlTabName>Build</htmlTabName>
+	<htmlTabIcon>wrench</htmlTabIcon>
 	<TestCaseRequestedList>
- 030000
- 040000
- 000001
- 070001
- 070000
+ 000001 000002
 	</TestCaseRequestedList>
-	<TestCaseExclusionList>
-	</TestCaseExclusionList>
+	<TestCaseExclusionList></TestCaseExclusionList>
 
-	<testCase id="030000">
-		<class>Initialize_eNB</class>
-		<desc>Initialize eNB</desc>
-		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf</Initialize_eNB_args>
+	<testCase id="000001">
+		<class>Build_eNB</class>
+		<desc>Build eNB</desc>
+		<Build_eNB_args>--eNB -t benetel4g -w None</Build_eNB_args>
+		<forced_workspace_cleanup>True</forced_workspace_cleanup>
 		<eNB_instance>0</eNB_instance>
 		<eNB_serverId>0</eNB_serverId>
-		<air_interface>lte</air_interface>
 	</testCase>
 
-	<testCase id="040000">
-		<class>Initialize_eNB</class>
-		<desc>Initialize gNB (3/4 sampling rate)</desc>
-		<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E</Initialize_eNB_args>
+
+	<testCase id="000002">
+		<class>Build_eNB</class>
+		<desc>Build gNB</desc>
+		<Build_eNB_args>--gNB -t benetel5g -w None</Build_eNB_args>
+		<forced_workspace_cleanup>True</forced_workspace_cleanup>
 		<eNB_instance>1</eNB_instance>
 		<eNB_serverId>1</eNB_serverId>
-		<air_interface>nr</air_interface>
 	</testCase>
 
-	<testCase id="000001">
-		<class>IdleSleep</class>
-		<desc>Sleep</desc>
-		<idle_sleep_time_in_sec>30</idle_sleep_time_in_sec>
-	</testCase>
 
-	<testCase id="070000">
-		<class>Terminate_eNB</class>
-		<desc>Terminate eNB</desc>
-		<eNB_instance>0</eNB_instance>
-		<eNB_serverId>0</eNB_serverId>
-	</testCase>
 
-	<testCase id="070001">
-		<class>Terminate_eNB</class>
-		<desc>Terminate gNB</desc>
-		<eNB_instance>1</eNB_instance>
-		<eNB_serverId>1</eNB_serverId>
-	</testCase>
 
 </testCaseList>
-
diff --git a/ci-scripts/xml_files/benetel_nsa_base.xml b/ci-scripts/xml_files/benetel_nsa_base.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0aed28dffa8e92de6377fdf51bdeac58215f9529
--- /dev/null
+++ b/ci-scripts/xml_files/benetel_nsa_base.xml
@@ -0,0 +1,162 @@
+<!--
+
+ Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The OpenAirInterface Software Alliance licenses this file to You under
+ the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.openairinterface.org/?page_id=698
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ For more information about the OpenAirInterface (OAI) Software Alliance:
+      contact@openairinterface.org
+
+-->
+<testCaseList>
+	<htmlTabRef>TEST-FR1-TM1</htmlTabRef>
+	<htmlTabName>FR1</htmlTabName>
+	<htmlTabIcon>tasks</htmlTabIcon>
+	<TestCaseRequestedList>
+ 010000
+ 030000
+ 040000
+ 010001
+ 000001
+ 050000
+ 050001
+ 000001
+ 060000
+ 060001
+ 000001
+ 070000
+ 070001
+ 010002
+ 000001
+ 080001
+ 080000
+ 010003
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="010000">
+		<class>Initialize_UE</class>
+		<desc>Initialize UE</desc>
+	</testCase>
+
+	<testCase id="010003">
+		<class>Terminate_UE</class>
+		<desc>Terminate UE</desc>
+	</testCase>
+
+	<testCase id="010001">
+		<class>Attach_UE</class>
+		<desc>Attach UE</desc>
+	</testCase>
+
+	<testCase id="010002">
+		<class>Detach_UE</class>
+		<desc>Detach UE</desc>
+	</testCase>
+
+
+	<testCase id="030000">
+		<class>Initialize_eNB</class>
+		<desc>Initialize eNB</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/benetel-4g.conf</Initialize_eNB_args>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+		<air_interface>lte</air_interface>
+   </testCase>
+
+
+	<testCase id="040000">
+		<class>Initialize_eNB</class>
+		<desc>Initialize gNB</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/benetel-5g.conf</Initialize_eNB_args>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+		<air_interface>nr</air_interface>
+	</testCase>
+
+	<testCase id="000001">
+		<class>IdleSleep</class>
+		<desc>Sleep</desc>
+		<idle_sleep_time_in_sec>20</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="050000">
+		<class>Ping</class>
+		<desc>Ping: 20pings in 20sec</desc>
+		<ping_args>-c 20</ping_args>
+		<ping_packetloss_threshold>50</ping_packetloss_threshold>
+	</testCase>
+
+	<testCase id="050001">
+		<class>Ping</class>
+		<desc>Ping: 100pings in 20sec</desc>
+		<ping_args>-c 100 -i 0.2</ping_args>
+		<ping_packetloss_threshold>50</ping_packetloss_threshold>
+	</testCase>
+
+
+	<testCase id="060000">
+		<class>Iperf</class>
+		<desc>iperf (DL/2.5Mbps/UDP)(60 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 2.5M -t 60 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="060001">
+		<class>Iperf</class>
+		<desc>iperf (UL/1.5Mbps/UDP)(60 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 1.5M -t 60 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+
+	<testCase id="070000">
+		<class>Iperf</class>
+		<desc>iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 20M -t 20 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="070001">
+		<class>Iperf</class>
+		<desc>iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 3M -t 20 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+
+
+	<testCase id="080000">
+		<class>Terminate_eNB</class>
+		<desc>Terminate eNB</desc>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+		<air_interface>lte</air_interface>
+	</testCase>
+
+	<testCase id="080001">
+		<class>Terminate_eNB</class>
+		<desc>Terminate gNB</desc>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+		<air_interface>nr</air_interface>
+	</testCase>
+
+</testCaseList>
+
diff --git a/ci-scripts/xml_files/fr1_image_build.xml b/ci-scripts/xml_files/container_image_build.xml
similarity index 93%
rename from ci-scripts/xml_files/fr1_image_build.xml
rename to ci-scripts/xml_files/container_image_build.xml
index 9dd386b646cd6e1975882e62f49852700efd5cf8..430729c49c79b8b09cca0cf109c1495ac44c12aa 100644
--- a/ci-scripts/xml_files/fr1_image_build.xml
+++ b/ci-scripts/xml_files/container_image_build.xml
@@ -22,7 +22,7 @@
 -->
 <testCaseList>
 	<htmlTabRef>build-tab</htmlTabRef>
-	<htmlTabName>Build</htmlTabName>
+	<htmlTabName>Build Container Images</htmlTabName>
 	<htmlTabIcon>wrench</htmlTabIcon>
 	<TestCaseRequestedList>
  000001
@@ -31,7 +31,7 @@
 
 	<testCase id="000001">
 		<class>Build_Image</class>
-		<desc>Build eNB Image</desc>
+		<desc>Build all Images</desc>
 		<kind>all</kind>
 		<eNB_instance>0</eNB_instance>
 		<eNB_serverId>0</eNB_serverId>
diff --git a/ci-scripts/xml_files/fr1_multi_node_build.xml b/ci-scripts/xml_files/fr1_multi_node_build.xml
index 7b4eacef3a3d091e7397bfc89a7f8422c459998c..57c4685341c9cda60734c02cdbcbd2435f5e5c84 100644
--- a/ci-scripts/xml_files/fr1_multi_node_build.xml
+++ b/ci-scripts/xml_files/fr1_multi_node_build.xml
@@ -37,6 +37,7 @@
 		<eNB_instance>0</eNB_instance>
 		<eNB_serverId>0</eNB_serverId>
 		<backgroundBuild>True</backgroundBuild>
+		<forced_workspace_cleanup>True</forced_workspace_cleanup>
 	</testCase>
 
 	<testCase id="000004">
@@ -53,6 +54,7 @@
 		<eNB_instance>1</eNB_instance>
 		<eNB_serverId>1</eNB_serverId>
 		<backgroundBuild>True</backgroundBuild>
+		<forced_workspace_cleanup>True</forced_workspace_cleanup>
 	</testCase>
 
 	<testCase id="000003">
diff --git a/ci-scripts/xml_files/fr1_ran_ue_iperf.xml b/ci-scripts/xml_files/fr1_nsa_base.xml
similarity index 80%
rename from ci-scripts/xml_files/fr1_ran_ue_iperf.xml
rename to ci-scripts/xml_files/fr1_nsa_base.xml
index 8ead3afc62ee152e39cc03bc389c53b4409b3be9..96bdc79f0f9138e2d43597237575014f28700c04 100644
--- a/ci-scripts/xml_files/fr1_ran_ue_iperf.xml
+++ b/ci-scripts/xml_files/fr1_nsa_base.xml
@@ -21,8 +21,8 @@
 
 -->
 <testCaseList>
-	<htmlTabRef>TEST-FR1-TM1</htmlTabRef>
-	<htmlTabName>FR1</htmlTabName>
+	<htmlTabRef>TEST-NSA-FR1-TM1</htmlTabRef>
+	<htmlTabName>NSA FULL</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
 	<TestCaseRequestedList>
  010000
@@ -31,14 +31,17 @@
  010001
  000001
  050000
+ 050001
  000001
  060000
  060001
  000001
+ 070000
+ 070001
  010002
  000001
- 070001
- 070000
+ 080001
+ 080000
  010003
 	</TestCaseRequestedList>
 	<TestCaseExclusionList></TestCaseExclusionList>
@@ -96,6 +99,13 @@
 		<ping_packetloss_threshold>50</ping_packetloss_threshold>
 	</testCase>
 
+	<testCase id="050001">
+		<class>Ping</class>
+		<desc>Ping: 100pings in 20sec</desc>
+		<ping_args>-c 100 -i 0.2</ping_args>
+		<ping_packetloss_threshold>50</ping_packetloss_threshold>
+	</testCase>
+
 
 	<testCase id="060000">
 		<class>Iperf</class>
@@ -113,7 +123,26 @@
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
+
 	<testCase id="070000">
+		<class>Iperf</class>
+		<desc>iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 20M -t 20 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="070001">
+		<class>Iperf</class>
+		<desc>iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 3M -t 20 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+
+
+	<testCase id="080000">
 		<class>Terminate_eNB</class>
 		<desc>Terminate eNB</desc>
 		<eNB_instance>0</eNB_instance>
@@ -121,7 +150,7 @@
 		<air_interface>lte</air_interface>
 	</testCase>
 
-	<testCase id="070001">
+	<testCase id="080001">
 		<class>Terminate_eNB</class>
 		<desc>Terminate gNB</desc>
 		<eNB_instance>1</eNB_instance>
diff --git a/ci-scripts/xml_files/fr1_ran_ue_base.xml b/ci-scripts/xml_files/fr1_nsa_base_ref.xml
similarity index 80%
rename from ci-scripts/xml_files/fr1_ran_ue_base.xml
rename to ci-scripts/xml_files/fr1_nsa_base_ref.xml
index 847967f81e9f9808d982f89615eed1c1be9a079d..fd47db10b2b1ecdc8fb084c4656451c35e54ca91 100644
--- a/ci-scripts/xml_files/fr1_ran_ue_base.xml
+++ b/ci-scripts/xml_files/fr1_nsa_base_ref.xml
@@ -21,8 +21,8 @@
 
 -->
 <testCaseList>
-	<htmlTabRef>TEST-FR1-TM1</htmlTabRef>
-	<htmlTabName>FR1</htmlTabName>
+	<htmlTabRef>TEST-NSA-FR1-TM1</htmlTabRef>
+	<htmlTabName>NSA FULL</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
 	<TestCaseRequestedList>
  010000
@@ -32,16 +32,15 @@
  000001
  050000
  050001
- 050002
- 050002
  000001
  060000
  060001
  000001
+ 070000
  010002
  000001
- 070001
- 070000
+ 080001
+ 080000
  010003
 	</TestCaseRequestedList>
 	<TestCaseExclusionList></TestCaseExclusionList>
@@ -100,13 +99,6 @@
 	</testCase>
 
 	<testCase id="050001">
-		<class>Ping</class>
-		<desc>Ping: 5pings in 1sec</desc>
-		<ping_args>-c 5 -i 0.2</ping_args>
-		<ping_packetloss_threshold>50</ping_packetloss_threshold>
-	</testCase>
-
-	<testCase id="050002">
 		<class>Ping</class>
 		<desc>Ping: 100pings in 20sec</desc>
 		<ping_args>-c 100 -i 0.2</ping_args>
@@ -116,21 +108,40 @@
 
 	<testCase id="060000">
 		<class>Iperf</class>
-		<desc>iperf (DL/1Mbps/UDP)(30 sec)(single-ue profile)</desc>
-		<iperf_args>-u -b 1M -t 30 -i 1</iperf_args>
+		<desc>iperf (DL/3Mbps/UDP)(20 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 3M -t 20 -i 1</iperf_args>
 		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
 	<testCase id="060001">
 		<class>Iperf</class>
-		<desc>iperf (UL/1Mbps/UDP)(30 sec)(single-ue profile)</desc>
-		<iperf_args>-u -b 1M -t 30 -i 1 -R</iperf_args>
+		<desc>iperf (UL/1Mbps/UDP)(20 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 1M -t 20 -i 1 -R</iperf_args>
 		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
 		<iperf_profile>single-ue</iperf_profile>
 	</testCase>
 
+
 	<testCase id="070000">
+		<class>Iperf</class>
+		<desc>iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 20M -t 20 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="070001">
+		<class>Iperf</class>
+		<desc>iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile)</desc>
+		<iperf_args>-u -b 3M -t 20 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+
+
+	<testCase id="080000">
 		<class>Terminate_eNB</class>
 		<desc>Terminate eNB</desc>
 		<eNB_instance>0</eNB_instance>
@@ -138,7 +149,7 @@
 		<air_interface>lte</air_interface>
 	</testCase>
 
-	<testCase id="070001">
+	<testCase id="080001">
 		<class>Terminate_eNB</class>
 		<desc>Terminate gNB</desc>
 		<eNB_instance>1</eNB_instance>
diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index e11c850b8e732a85c262062b531160a2ffc3b5b8..626d93862536854c5555e96cd75daeabd9285221 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -926,6 +926,9 @@ set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidd
 # Benetel 4G library
 ######################################################################
 
+
+include_directories ("/usr/include/dpdk")
+
 set(HWLIB_BENETEL_4G_SOURCE
   ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/benetel.c
   ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/shared_buffers.c
@@ -1967,7 +1970,8 @@ set(NR_PDCP_SRC
   ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
   ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c
   ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c
-  ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
+  ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_sdu.c
+  ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c
   ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c
   ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
   )
@@ -3141,7 +3145,7 @@ target_link_libraries (nr-uesoftmodem
   RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB
   PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB
   NFAPI_USER_LIB MISC_NFAPI_NR_LIB S1AP_LIB S1AP_ENB
-  ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} 
+  ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
   NFAPI_USER_LIB S1AP_LIB S1AP_ENB
   ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB
   -Wl,--end-group z dl)
diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml
index 089d0503fdf02a7b0726223adec38c78e343a7c5..016c76dc06632e5b10a3021c0628a844eed4e50f 100644
--- a/cmake_targets/autotests/test_case_list.xml
+++ b/cmake_targets/autotests/test_case_list.xml
@@ -1294,7 +1294,8 @@
                                  (Test10: SC-FDMA, 75 PRBs),
                                  (Test11: SC-FDMA, 216 PRBs),
                                  (Test12: SC-FDMA, 273 PRBs),
-                                 (Test13: SC-FDMA, 3 DMRS)</desc>
+                                 (Test13: SC-FDMA, 3 DMRS),
+                                 (Test14: MCS 16 50 PRBs 2 RX_Antenna)</desc>
       <pre_compile_prog></pre_compile_prog>
       <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog>
       <compile_prog_args> --phy_simulators  -c </compile_prog_args>
@@ -1313,9 +1314,10 @@
                       -n100 -s2 -Z -r75
                       -n100 -s2 -Z -r216 -R217
                       -n100 -s2 -Z -r270 -R273
-                      -n100 -s2 -Z -U 2 0 2</main_exec_args>
+                      -n100 -s2 -Z -U 2 0 2
+                      -n100 -m16 -s10 -z2</main_exec_args>
 
-      <tags>nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13</tags>
+      <tags>nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13 nr_ulsim.test14</tags>
       <search_expr_true>PUSCH test OK</search_expr_true>
       <search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
       <nruns>3</nruns>
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index 960b24104773b4ce6816c6c90920389eb4b98b5c..dba6d7da6de129cbc89ef6ba4ebadf14d99e0f8b 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -48,8 +48,9 @@ DEADLINE_SCHEDULER_FLAG_USER=""
 CPU_AFFINITY_FLAG_USER="False" #Only valid when low-latency flag is set to False
 REL="Rel15"
 HW="None"
-TP="None"
+TP="Ethernet"
 EPC=0
+VERBOSE_CI=0
 VERBOSE_COMPILE=0
 CFLAGS_PROCESSOR_USER=""
 RUN_GROUP=0
@@ -289,6 +290,9 @@ function main() {
             esac
 			echo_info "Setting hardware to: $HW"
             shift 2;;
+       -t | --transport)
+	    TP=$2
+            shift 2;;
        -P | --phy_simulators)
             SIMUS_PHY=1
             echo_info "Will compile dlsim, ulsim, ..."
@@ -324,6 +328,10 @@ function main() {
             HWLAT_TEST=1
             echo_info "Will compile hw latency test program"
             shift;;
+       --verbose-ci)
+	        VERBOSE_CI=1
+            echo_info "Will compile with verbose instructions in CI Docker env"
+            shift;;
        --verbose-compile)
 	        VERBOSE_COMPILE=1
             echo_info "Will compile with verbose instructions"
@@ -936,12 +944,30 @@ function main() {
           echo_info "Building transport protocol libraries"
           rm -f liboai_transpro.so
           rm -f $dbin/liboai_transpro.so
-          compilations \
-              $build_dir oai_eth_transpro \
-              liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL
-          ln -sf liboai_eth_transpro.so liboai_transpro.so
-          ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so
-          echo_info "liboai_transpro.so is linked to ETHERNET transport"
+	  if [ "$TP" == "Ethernet" ]; then
+              compilations \
+		  $build_dir oai_eth_transpro \
+		  liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL
+              ln -sf liboai_eth_transpro.so liboai_transpro.so
+              ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so
+              echo_info "liboai_transpro.so is linked to ETHERNET transport"
+	  fi
+	  if [ "$TP" == "benetel4g" ]; then
+              compilations \
+		  $build_dir benetel_4g \
+		  libbenetel_4g.so $dbin/libbenetel_4g.$REL
+              ln -sf libbenetel_4g.so liboai_transpro.so
+              ln -sf $dbin/libbenetel_4g.so.$REL $dbin/liboai_transpro.so
+              echo_info "liboai_transpro.so is linked to BENETEL4G transport"
+	  fi
+	  if [ "$TP" == "benetel5g" ]; then
+              compilations \
+		  $build_dir benetel_5g \
+		  libbenetel_5g.so $dbin/libbenetel_5g.$REL
+              ln -sf libbenetel_5g.so liboai_transpro.so
+              ln -sf $dbin/libbenetel_5g.so.$REL $dbin/liboai_transpro.so
+              echo_info "liboai_transpro.so is linked to BENETEL4G transport"
+	  fi
       fi
   fi
 
diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper
index 674d4a0cacf5312336a5df55376ba7e2af3aec30..9b8363fc2b96f6e966418847029ba7926572ae4c 100755
--- a/cmake_targets/tools/build_helper
+++ b/cmake_targets/tools/build_helper
@@ -41,7 +41,7 @@ KERNEL_VERSION=$(uname -r | cut -d '.' -f1)
 KERNEL_MAJOR=$(uname -r | cut -d '.' -f2)
 
 #check if we run inside a container
-IS_CONTAINER=`egrep -c "docker|podman|kubepods" /proc/self/cgroup || true`
+IS_CONTAINER=`egrep -c "docker|podman|kubepods|libpod|buildah" /proc/self/cgroup || true`
 #sudo is not needed when we are root
 if [ "$UID" = 0 ]
 then
@@ -221,6 +221,11 @@ compilations() {
     ret=$?
   } > $dlog/$2.$REL.txt 2>&1
   set -e
+  if [ "$VERBOSE_CI" == "1" ]; then
+     echo_info "====== Start of log for $2.$REL.txt ======"
+     cat $dlog/$2.$REL.txt
+     echo_info "====== End of log for $2.$REL.txt ======"
+  fi
   if [[ $ret -ne 0 ]]; then
      check_warnings "$dlog/$2.$REL.txt"
      check_errors "$dlog/$2.$REL.txt"
@@ -273,6 +278,10 @@ install_protobuf_from_source(){
     make -j`nproc`
     $SUDO make install
     $SUDO ldconfig
+    if [[ -v CI_ENV ]]; then
+        cd /tmp
+        $SUDO rm -rf protobuf*
+    fi
     ) >& $protobuf_install_log
 }
 
@@ -295,6 +304,10 @@ install_protobuf_c_from_source(){
     make -j`nproc`
     $SUDO make install
     $SUDO ldconfig
+    if [[ -v CI_ENV ]]; then
+        cd /tmp
+        $SUDO rm -rf protobuf*
+    fi
     ) >& $protobuf_c_install_log
 }
 
@@ -351,10 +364,10 @@ check_install_usrp_uhd_driver(){
     elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
         if [ $IS_CONTAINER -eq 0 ]
         then
-            $SUDO $INSTALLER -y install python boost libusb-devel libusbx-devel boost-devel python-mako python-docutils cmake
+            $SUDO $INSTALLER -y install python boost libusb-devel libusbx-devel boost-devel python-mako python-docutils $CMAKE
             $SUDO -H pip install requests
         else
-            $SUDO $INSTALLER -y install boost boost-devel cmake3
+            $SUDO $INSTALLER -y install boost boost-devel $CMAKE
             $SUDO pip3 install mako requests
         fi
         if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "centos" ]]; then
@@ -480,7 +493,7 @@ install_soapy_from_source(){
     #git checkout tags/release_003_010_001_001
     mkdir -p build
     cd build
-    cmake ../
+    $CMAKE ../
     echo "Compiling SoapyRemote"
     make -j`nproc`
     $SUDO make install
@@ -499,7 +512,7 @@ install_soapy_iris_from_source(){
     cd sklk-soapyiris
     mkdir -p build
     cd build
-    cmake ../
+    $CMAKE ../
     echo "Compiling SoapyIris"
     make -j`nproc`
     $SUDO make install
@@ -676,7 +689,7 @@ check_install_oai_software() {
 	automake  \
 	bison  \
 	build-essential \
-	cmake \
+	$CMAKE \
 	cmake-curses-gui  \
         ninja-build \
 	doxygen \
@@ -831,6 +844,9 @@ install_asn1c_from_source(){
     $SUDO make install
     cd -
     $SUDO ldconfig
+    if [[ -v CI_ENV ]]; then
+        $SUDO rm -rf /tmp/asn1c
+    fi
     ) > $asn1_install_log 2>&1
 }
 
diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c
index 9fd67a6dbb9cf6a0f3f385b4df81788c465601b9..4e6ec9d3db11ad76cd1ebe2f514b59f69454f545 100644
--- a/common/utils/LOG/log.c
+++ b/common/utils/LOG/log.c
@@ -88,7 +88,8 @@ int write_file_matlab(const char *fname,
 					  void *data,
 					  int length,
 					  int dec,
-					  unsigned int format)
+					  unsigned int format,
+            int multiVec)
 {
   FILE *fp=NULL;
   int i;
@@ -100,8 +101,7 @@ int write_file_matlab(const char *fname,
 
   //printf("Writing %d elements of type %d to %s\n",length,format,fname);
 
-
-  if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) {
+  if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14 || multiVec) {
     fp = fopen(fname,"a+");
   } else if (format != 10 && format !=11  && format != 12 && format != 13 && format != 14) {
     fp = fopen(fname,"w+");
@@ -137,8 +137,7 @@ int write_file_matlab(const char *fname,
     return(0);	
   }
 
-
-  if (format != 10 && format !=11  && format != 12 && format != 13 && format != 14)
+  if ((format != 10 && format !=11  && format != 12 && format != 13 && format != 14) || multiVec)
     fprintf(fp,"%s = [",vname);
 
   switch (format) {
@@ -247,7 +246,7 @@ int write_file_matlab(const char *fname,
     AssertFatal(false, "unknown dump format: %d\n", format);
   }
 
-  if (format != 10 && format !=11 && format !=12 && format != 13 && format != 15) {
+  if ((format != 10 && format !=11 && format !=12 && format != 13 && format != 15) || multiVec) {
     fprintf(fp,"];\n");
     fclose(fp);
     return(0);
diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h
index 49c6bdfd4c32bf696995dd66192fef781125b7f2..0cbae7ae2c79fa784ed078601fc71de313fad6b8 100644
--- a/common/utils/LOG/log.h
+++ b/common/utils/LOG/log.h
@@ -335,6 +335,7 @@ typedef struct {
 @param length length of data vector to output
 @param dec    decimation level
 @param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit)
+@param multiVec create new file or append to existing (useful for writing multiple vectors to same file. Just call the function multiple times with same file name and with this parameter set to 1)
 */
 #define MATLAB_RAW (1<<31)
 #define MATLAB_SHORT 0
@@ -354,7 +355,7 @@ typedef struct {
 #define MATLAB_CSHORT_BRACKET2 14
 #define MATLAB_CSHORT_BRACKET3 15
   
-int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format);
+int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format, int multiVec);
 
 /*----------------macro definitions for reading log configuration from the config module */
 #define CONFIG_STRING_LOG_PREFIX                           "log_config"
@@ -414,7 +415,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
 
 /* bitmask dependent macros, to generate debug file such as matlab file or message dump */
 #    define LOG_DUMPFLAG(D) (g_log->dump_mask & D)
-#    define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)/* */
+#    define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0)/* */
 /* define variable only used in LOG macro's */
 #    define LOG_VAR(A,B) A B
 #  else /* T_TRACER: remove all debugging and tracing messages, except errors */
@@ -431,7 +432,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
 #    define LOG_DUMPFLAG(D) (g_log->debug_mask & D)
 #    define LOG_DUMPMSG(c, f, b, s, x...) do {  if(g_log->dump_mask & f) log_dump(c, b, s, LOG_DUMP_CHAR, x)  ;}   while (0)  /* */
 
-#    define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)
+#    define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0)
 #    define LOG_VAR(A,B) A B
 #  endif /* T_TRACER */
 /* avoid warnings for variables only used in LOG macro's but set outside debug section */
@@ -439,9 +440,10 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
 #define LOG_USEDINLOG_VAR(A,B) GCC_NOTUSED A B
 
 /* unfiltered macros, useful for simulators or messages at init time, before log is configured */
-#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)
+#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0)
 #define LOG_UI(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ; } while(0)
 #define LOG_UDUMPMSG(c, b, s, f, x...) do { log_dump(c, b, s, f, x)  ;}   while (0)  /* */
+#    define LOG_MM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 1);} while(0)
 /* @}*/
 
 
diff --git a/common/utils/T/.gitignore b/common/utils/T/.gitignore
index d754ff7c38730801afa6f6629ef45b9c9d4dcc03..6a6e5817c5d20da48e684ae4401878124d30b812 100644
--- a/common/utils/T/.gitignore
+++ b/common/utils/T/.gitignore
@@ -4,6 +4,7 @@ T_IDs.h
 T_messages.txt.h
 genids
 tracer/enb
+tracer/gnb
 tracer/extract_config
 tracer/record
 tracer/replay
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index bad6444e1303d385c9808608a599cf6e43330bab..fedc50cf5da319b31392cc801cea4d39cd9967fa 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -1,7 +1,3 @@
-ID = BENETEL
-  GROUP = ALL
-  FORMAT = int,frame : int,slot : buffer,rxdataF
-
 #general logs
 ID = ENB_MASTER_TICK
     DESC = eNodeB master tick - one tick per ms, to be used as "reference clock", mostly for ticktime view
@@ -93,6 +89,10 @@ ID = GNB_PHY_MIB
     DESC = NR MIB data
     GROUP = ALL:PHY:GNB:WIRESHARK
     FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data
+ID = GNB_PHY_PUCCH_PUSCH_IQ
+    DESC = gNodeB input data in the frequency domain for a slot where some PUCCH or PUSCH detection was done
+    GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
+    FORMAT = int,frame : int,slot : buffer,rxdataF
 
 #MAC logs
 ID = ENB_MAC_UE_DL_SDU
diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile
index 792c2a407c1ce1233ad8930396a86996020c2001..0713d9a3df9f0233baee15abbe92aad211654b24 100644
--- a/common/utils/T/tracer/Makefile
+++ b/common/utils/T/tracer/Makefile
@@ -7,7 +7,8 @@ LIBS=-lm
 XLIBS=-lX11 -lpng -lXft
 
 all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
-     extract_input_subframe extract_output_subframe to_vcd extract multi
+     extract_input_subframe extract_output_subframe to_vcd extract multi \
+     gnb
 
 record: utils.o record.o database.o config.o
 	$(CC) $(CFLAGS) -o record $^ $(LIBS)
@@ -60,6 +61,11 @@ macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \
 multi: multi.o utils.o database.o config.o
 	$(CC) $(CFLAGS) -o multi $^ $(LIBS)
 
+gnb: utils.o gnb.o database.o event.o handler.o config.o \
+         view/view.a gui/gui.a logger/logger.a \
+         filter/filter.a
+	$(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS)
+
 multi.o: ../T_IDs.h
 
 ../T_IDs.h:
@@ -85,7 +91,7 @@ filter/filter.a:
 clean:
 	rm -f *.o core tracer_remote textlog enb ue vcd record replay
 	rm -f extract_config macpdu2wireshark extract_input_subframe
-	rm -f extract_output_subframe to_vcd extract multi
+	rm -f extract_output_subframe to_vcd extract multi gnb
 	cd gui && $(MAKE) clean
 	cd view && $(MAKE) clean
 	cd logger && $(MAKE) clean
diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c
new file mode 100644
index 0000000000000000000000000000000000000000..4aaa4898a1fcc7902c189d8732f3a481c9562634
--- /dev/null
+++ b/common/utils/T/tracer/gnb.c
@@ -0,0 +1,172 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include "database.h"
+#include "handler.h"
+#include "config.h"
+#include "logger/logger.h"
+#include "view/view.h"
+#include "gui/gui.h"
+
+typedef struct {
+  widget *pucch_pusch_iq_plot;
+  logger *pucch_pusch_iq_logger;
+} gnb_gui;
+
+typedef struct {
+  int socket;
+  int *is_on;
+  int nevents;
+  pthread_mutex_t lock;
+  gnb_gui *e;
+  void *database;
+} gnb_data;
+
+void is_on_changed(void *_d)
+{
+  gnb_data *d = _d;
+  char t;
+
+  if (pthread_mutex_lock(&d->lock)) abort();
+
+  if (d->socket == -1) goto no_connection;
+
+  t = 1;
+  if (socket_send(d->socket, &t, 1) == -1 ||
+      socket_send(d->socket, &d->nevents, sizeof(int)) == -1 ||
+      socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1)
+    goto connection_dies;
+
+no_connection:
+  if (pthread_mutex_unlock(&d->lock)) abort();
+  return;
+
+connection_dies:
+  close(d->socket);
+  d->socket = -1;
+  if (pthread_mutex_unlock(&d->lock)) abort();
+}
+
+void usage(void)
+{
+  printf(
+"options:\n"
+"    -d   <database file>      this option is mandatory\n"
+"    -ip <host>                connect to given IP address (default %s)\n"
+"    -p  <port>                connect to given port (default %d)\n",
+  DEFAULT_REMOTE_IP,
+  DEFAULT_REMOTE_PORT
+  );
+  exit(1);
+}
+
+static void *gui_thread(void *_g)
+{
+  gui *g = _g;
+  gui_loop(g);
+  return NULL;
+}
+
+static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database,
+    gnb_data *ed)
+{
+  widget *main_window;
+  widget *top_container;
+  widget *line;
+  widget *w;
+  logger *l;
+  view *v;
+
+  main_window = new_toplevel_window(g, 500, 300, "gNB tracer");
+
+  top_container = new_container(g, VERTICAL);
+  widget_add_child(g, main_window, top_container, -1);
+
+  line = new_container(g, HORIZONTAL);
+  widget_add_child(g, top_container, line, -1);
+
+  /* PUCCH/PUSCH IQ data */
+  w = new_xy_plot(g, 55, 55, "", 50);
+  e->pucch_pusch_iq_plot = w;
+  widget_add_child(g, line, w, -1);
+  xy_plot_set_range(g, w, -1000, 1000, -1000, 1000);
+  xy_plot_set_title(g, w, "rxdataF");
+  l = new_iqlog_full(h, database, "GNB_PHY_PUCCH_PUSCH_IQ", "rxdataF");
+  v = new_view_xy(300*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
+  logger_add_view(l, v);
+  e->pucch_pusch_iq_logger = l;
+}
+
+int main(int n, char **v)
+{
+  char *database_filename = NULL;
+  void *database;
+  char *ip = DEFAULT_REMOTE_IP;
+  int port = DEFAULT_REMOTE_PORT;
+  int *is_on;
+  int number_of_events;
+  int i;
+  event_handler *h;
+  gnb_data gnb_data;
+  gui *g;
+  gnb_gui eg;
+
+  for (i = 1; i < n; i++) {
+    if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
+    if (!strcmp(v[i], "-d"))
+      { if (i > n-2) usage(); database_filename = v[++i]; continue; }
+    usage();
+  }
+
+  if (database_filename == NULL) {
+    printf("ERROR: provide a database file (-d)\n");
+    exit(1);
+  }
+
+  database = parse_database(database_filename);
+
+  load_config_file(database_filename);
+
+  number_of_events = number_of_ids(database);
+  is_on = calloc(number_of_events, sizeof(int));
+  if (is_on == NULL) abort();
+
+  h = new_handler(database);
+
+  on_off(database, "GNB_PHY_PUCCH_PUSCH_IQ", is_on, 1);
+
+  gnb_data.database = database;
+  gnb_data.socket = -1;
+  gnb_data.is_on = is_on;
+  gnb_data.nevents = number_of_events;
+  if (pthread_mutex_init(&gnb_data.lock, NULL)) abort();
+
+  g = gui_init();
+  new_thread(gui_thread, g);
+
+  gnb_main_gui(&eg, g, h, database, &gnb_data);
+
+  OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
+
+restart:
+  clear_remote_config();
+  if (gnb_data.socket != -1) close(gnb_data.socket);
+  gnb_data.socket = connect_to(ip, port);
+
+  /* send the first message - activate selected traces */
+  is_on_changed(&gnb_data);
+
+  /* read messages */
+  while (1) {
+    event e;
+    e = get_event(gnb_data.socket, &ebuf, database);
+    if (e.type == -1) goto restart;
+    if (pthread_mutex_lock(&gnb_data.lock)) abort();
+    handle_event(h, e);
+    if (pthread_mutex_unlock(&gnb_data.lock)) abort();
+  }
+
+  return 0;
+}
diff --git a/common/utils/T/tracer/logger/iqlog.c b/common/utils/T/tracer/logger/iqlog.c
index 168c50e39b0978be0409769acf42fcfd9bbbcb33..1947de2bca4c3bfee863ffe73023b8f12bba160d 100644
--- a/common/utils/T/tracer/logger/iqlog.c
+++ b/common/utils/T/tracer/logger/iqlog.c
@@ -74,6 +74,44 @@ static void _event(void *p, event e)
     l->common.v[i]->append(l->common.v[i], l->i, l->q, count);
 }
 
+static void _event_full(void *p, event e)
+{
+  struct iqlog *l = p;
+  int i;
+  void *buffer;
+  int bsize;
+  int nsamples;
+  float *idst, *qdst;
+
+  if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
+    return;
+
+  buffer = e.e[l->buffer_arg].b;
+  bsize = e.e[l->buffer_arg].bsize;
+
+  nsamples = bsize / 4;
+
+  if (nsamples > l->max_length) {
+    l->i = realloc(l->i, nsamples * sizeof(float));
+    if (l->i == NULL) abort();
+    l->q = realloc(l->q, nsamples * sizeof(float));
+    if (l->q == NULL) abort();
+    l->max_length = nsamples;
+  }
+
+  idst = l->i;
+  qdst = l->q;
+  for (i = 0; i < nsamples; i++) {
+    *idst = ((int16_t *)buffer)[i * 2];
+    *qdst = ((int16_t *)buffer)[i * 2 + 1];
+    idst++;
+    qdst++;
+  }
+
+  for (i = 0; i < l->common.vsize; i++)
+    l->common.v[i]->append(l->common.v[i], l->i, l->q, nsamples);
+}
+
 logger *new_iqlog(event_handler *h, void *database,
     char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti,
     char *buffer_varname)
@@ -149,3 +187,43 @@ logger *new_iqlog(event_handler *h, void *database,
 
   return ret;
 }
+
+logger *new_iqlog_full(event_handler *h, void *database, char *event_name,
+    char *buffer_varname)
+{
+  struct iqlog *ret;
+  int event_id;
+  database_event_format f;
+  int i;
+
+  ret = calloc(1, sizeof(struct iqlog)); if (ret == NULL) abort();
+
+  ret->common.event_name = strdup(event_name);
+  if (ret->common.event_name == NULL) abort();
+  ret->database = database;
+
+  event_id = event_id_from_name(database, event_name);
+
+  ret->common.handler_id = register_handler_function(h, event_id, _event_full,
+                                                     ret);
+
+  f = get_format(database, event_id);
+
+  /* look for args */
+  ret->buffer_arg = -1;
+  for (i = 0; i < f.count; i++) {
+    if (!strcmp(f.name[i], buffer_varname)) ret->buffer_arg = i;
+  }
+  if (ret->buffer_arg == -1) {
+    printf("%s:%d: buffer argument '%s' not found in event '%s'\n",
+        __FILE__, __LINE__, buffer_varname, event_name);
+    abort();
+  }
+  if (strcmp(f.type[ret->buffer_arg], "buffer") != 0) {
+    printf("%s:%d: argument '%s' has wrong type (should be 'buffer')\n",
+        __FILE__, __LINE__, buffer_varname);
+    abort();
+  }
+
+  return ret;
+}
diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h
index 7c019b4797244b5edc4a8120cc551392f52b09fb..d746161e7061907ae5783acf170c64716f98b039 100644
--- a/common/utils/T/tracer/logger/logger.h
+++ b/common/utils/T/tracer/logger/logger.h
@@ -23,6 +23,8 @@ logger *new_ticklog(void *event_handler, void *database,
 logger *new_iqlog(void *event_handler, void *database,
     char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti,
     char *buffer_varname);
+logger *new_iqlog_full(void *event_handler, void *database, char *event_name,
+    char *buffer_varname);
 logger *new_iqdotlog(void *event_handler, void *database,
     char *event_name, char *I, char *Q);
 
diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c
index 5f07fc00aa7ca7905552d5881b92a0ff39e1669b..0671aed813d6b4f6c81265fdba82e08dcae53e8a 100644
--- a/common/utils/nr/nr_common.c
+++ b/common/utils/nr/nr_common.c
@@ -32,6 +32,81 @@
 
 #include <stdint.h>
 #include "assertions.h"
+#include "nr_common.h"
+
+// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101)
+// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101)
+// Notes:
+// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL
+// - Frequencies are expressed in KHz
+// - col: NR_band ul_min  ul_max  dl_min  dl_max  step  N_OFFs_DL  deltaf_raster
+nr_bandentry_t nr_bandtable[] = {
+  {1,   1920000, 1980000, 2110000, 2170000, 20, 422000, 100},
+  {2,   1850000, 1910000, 1930000, 1990000, 20, 386000, 100},
+  {3,   1710000, 1785000, 1805000, 1880000, 20, 361000, 100},
+  {5,    824000,  849000,  869000,  894000, 20, 173800, 100},
+  {7,   2500000, 2570000, 2620000, 2690000, 20, 524000, 100},
+  {8,    880000,  915000,  925000,  960000, 20, 185000, 100},
+  {12,   698000,  716000,  729000,  746000, 20, 145800, 100},
+  {14,   788000,  798000,  758000,  768000, 20, 151600, 100},
+  {18,   815000,  830000,  860000,  875000, 20, 172000, 100},
+  {20,   832000,  862000,  791000,  821000, 20, 158200, 100},
+  {25,  1850000, 1915000, 1930000, 1995000, 20, 386000, 100},
+  {26,   814000,  849000,  859000,  894000, 20, 171800, 100},
+  {28,   703000,  758000,  758000,  813000, 20, 151600, 100},
+  {29,      000,     000,  717000,  728000, 20, 143400, 100},
+  {30,  2305000, 2315000, 2350000, 2360000, 20, 470000, 100},
+  {34,  2010000, 2025000, 2010000, 2025000, 20, 402000, 100},
+  {38,  2570000, 2620000, 2570000, 2630000, 20, 514000, 100},
+  {39,  1880000, 1920000, 1880000, 1920000, 20, 376000, 100},
+  {40,  2300000, 2400000, 2300000, 2400000, 20, 460000, 100},
+  {41,  2496000, 2690000, 2496000, 2690000,  3, 499200,  15},
+  {41,  2496000, 2690000, 2496000, 2690000,  6, 499200,  30},
+  {47,  5855000, 5925000, 5855000, 5925000,  1, 790334,  15},
+  //{48,  3550000, 3700000, 3550000, 3700000,  1, 636667,  15},
+  //{48,  3550000, 3700000, 3550000, 3700000,  2, 636668,  30},
+  {50,  1432000, 1517000, 1432000, 1517000, 20, 286400, 100},
+  {51,  1427000, 1432000, 1427000, 1432000, 20, 285400, 100},
+  {53,  2483500, 2495000, 2483500, 2495000, 20, 496700, 100},
+  {65,  1920000, 2010000, 2110000, 2200000, 20, 422000, 100},
+  {66,  1710000, 1780000, 2110000, 2200000, 20, 422000, 100},
+  {70,  1695000, 1710000, 1995000, 2020000, 20, 399000, 100},
+  {71,   663000,  698000,  617000,  652000, 20, 123400, 100},
+  {74,  1427000, 1470000, 1475000, 1518000, 20, 295000, 100},
+  {75,      000,     000, 1432000, 1517000, 20, 286400, 100},
+  {76,      000,     000, 1427000, 1432000, 20, 285400, 100},
+  {77,  3300000, 4200000, 3300000, 4200000,  1, 620000,  15},
+  {77,  3300000, 4200000, 3300000, 4200000,  2, 620000,  30},
+  {78,  3300000, 3800000, 3300000, 3800000,  1, 620000,  15},
+  {78,  3300000, 3800000, 3300000, 3800000,  2, 620000,  30},
+  {79,  4400010, 5000000, 4400010, 5000000,  1, 693334,  15},
+  {79,  4400010, 5000000, 4400010, 5000000,  2, 693334,  30},
+  {80,  1710000, 1785000,     000,     000, 20, 342000, 100},
+  {81,   880000,  915000,     000,     000, 20, 176000, 100},
+  {82,   832000,  862000,     000,     000, 20, 166400, 100},
+  {83,   703000,  748000,     000,     000, 20, 140600, 100},
+  {84,  1920000, 1980000,     000,     000, 20, 384000, 100},
+  {86,  1710000, 1785000,     000,     000, 20, 342000, 100},
+  {89,   824000,  849000,     000,     000, 20, 342000, 100},
+  {90,  2496000, 2690000, 2496000, 2690000, 3,  499200,  15},
+  {90,  2496000, 2690000, 2496000, 2690000, 6,  499200,  30},
+  {90,  2496000, 2690000, 2496000, 2690000, 20, 499200, 100},
+  {91,   832000,  862000, 1427000, 1432000, 20, 285400, 100},
+  {92,   832000,  862000, 1432000, 1517000, 20, 286400, 100},
+  {93,   880000,  915000, 1427000, 1432000, 20, 285400, 100},
+  {94,   880000,  915000, 1432000, 1517000, 20, 286400, 100},
+  {95,  2010000, 2025000,     000,     000, 20, 402000, 100},
+  {257,26500020,29500000,26500020,29500000,  1,2054166,  60},
+  {257,26500080,29500000,26500080,29500000,  2,2054167, 120},
+  {258,24250080,27500000,24250080,27500000,  1,2016667,  60},
+  {258,24250080,27500000,24250080,27500000,  2,2016667, 120},
+  {260,37000020,40000000,37000020,40000000,  1,2229166,  60},
+  {260,37000080,40000000,37000080,40000000,  2,2229167, 120},
+  {261,27500040,28350000,27500040,28350000,  1,2070833,  60},
+  {261,27500040,28350000,27500040,28350000,  2,2070833, 120}
+};
+
+const size_t nr_bandtable_size = sizeof(nr_bandtable) / sizeof(nr_bandentry_t);
 
 int NRRIV2BW(int locationAndBandwidth,int N_RB) {
   int tmp = locationAndBandwidth/N_RB;
diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h
index 5601c0fcbf8f5755b42fc484db8bbbd8ccdf6aa9..6389c2c09431071b43608e2229b0268773173ed3 100644
--- a/common/utils/nr/nr_common.h
+++ b/common/utils/nr/nr_common.h
@@ -36,6 +36,20 @@
 #include <stdint.h>
 #include "assertions.h"
 
+typedef struct nr_bandentry_s {
+  int16_t band;
+  uint64_t ul_min;
+  uint64_t ul_max;
+  uint64_t dl_min;
+  uint64_t dl_max;
+  uint64_t step_size;
+  uint64_t N_OFFs_DL;
+  uint8_t deltaf_raster;
+} nr_bandentry_t;
+
+extern const size_t nr_bandtable_size;
+extern nr_bandentry_t nr_bandtable[];
+
 int NRRIV2BW(int locationAndBandwidth,int N_RB);
 int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB);
 int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize);
diff --git a/doc/NFAPI_archi.md b/doc/NFAPI_archi.md
new file mode 100644
index 0000000000000000000000000000000000000000..61c66bd0435953a5e4e0431a23808fbed6135243
--- /dev/null
+++ b/doc/NFAPI_archi.md
@@ -0,0 +1,132 @@
+# global
+
+xnf is pnf or vnf
+
+The xnf starting functions are configure_nfapi_xnf()
+
+The OAI code that read the configuration parameters call these functions that will create autonomous thread for xnf control part
+
+These control threads create a SCTP socket by Linux API call (no use of OpenAir internal architecture with SCTP itti thread).
+
+The main() function of softmodem has to create and start the other threads+loop on event for appropriate work: RF Rx in pnf, NGAP, GTP-U, X2, RLC, PDCP for vnf
+
+NFAPI has it's own code directly on Linux+Posix, it doesn't reuse any piece of the OpenAir framework: SCTP thread, thread creation and management, ... 
+
+## signaling (P5) xnf main loop
+
+nfapi_vnf_start() create the SCTP socket, then do event waiting in a infinite loop while(vnf->terminate == 0). It accepts the pnf connections, then process the messages on reception
+
+nfapi_pnf_start() initiate connection to vnf until it has a link. Then it enter a similar infinite loop in pnf_message_pump()
+
+After some checks, when a message is obtained, it calls pnf_handle_p5_message() or vnf_handle_p4_p5_message() that have a switch on each p5 message types: the enum nfapi_message_id_e
+
+Each message type has it's own processing function in the switch, like 
+```
+case NFAPI_START_RESPONSE:
+        vnf_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx);
+        break;
+```
+
+These loops are autonomous in their thread waiting incoming message.
+
+## P7 xnf main loop
+
+When the p5 interface receives appropriate message, it starts the p7 interface by launching a thread (see the calls to pthread_create() in nfapi/oai_integration/nfapi_xnf.c)
+
+The p7 main loops starting is a bit simpler, thanks to UDP non connected protocol. The xnf_dispatch_p7_message() do p7 fragments re-assembly, then 
+calls xnf_dispatch_p7_message() that have the big switch on message type (as in p5 above description)
+
+So, we have the logic for UL reception in vnf, and DL reception in pnf
+
+## P7 UL transmission by PNF
+
+RF samples are received, and decoding is done by the PNF using control data transmitted by the VNF to the PNF through downlink p7 messages (UL_TTI_req and UL_DCI_req). 
+
+After decoding, results are accumulated into the xNB->UL_INFO structure at the PNF. 
+
+The data in the UL_INFO struct is transmitted through a socket in the form of 'uplink indication functions' from the PNF to the VNF. Each uplink indication message is transmitted from their respective handle functions in NR_UL_indication(). For example,
+
+```
+
+void handle_nr_rach(NR_UL_IND_t *UL_info) {
+  if(NFAPI_MODE == NFAPI_MODE_PNF) {
+    if (UL_info->rach_ind.number_of_pdus>0) {
+      oai_nfapi_nr_rach_indication(&UL_info->rach_ind); //This function calls the routines required for packing + transmission through socket
+      UL_info->rach_ind.number_of_pdus = 0;
+    }
+  }
+
+```
+
+## P7 UL reception at VNF
+
+Through the infinite loop [while(vnf_p7->terminate == 0)] running in nfapi_nr_vnf_p7_start(), the VNF receives and unpacks the uplink indication message received on its socket. Based on the unpacked message, UL_INFO struct on the VNF side gets populated. The NR_UL_indication() function is then called at the VNF, which uses UL_INFO. 
+
+```
+
+// have a p7 message
+			if(FD_ISSET(vnf_p7->socket, &rfds))
+			{
+				vnf_nr_p7_read_dispatch_message(vnf_p7); 
+
+				// Call the scheduler
+				struct PHY_VARS_gNB_s *gNB = RC.gNB[0];
+				pthread_mutex_lock(&gNB->UL_INFO_mutex);
+				gNB->UL_INFO.frame     = vnf_frame;
+				gNB->UL_INFO.slot      = vnf_slot;
+
+				gNB->UL_INFO.module_id = gNB->Mod_id;
+				gNB->UL_INFO.CC_id     = gNB->CC_id;
+				gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
+				pthread_mutex_unlock(&gNB->UL_INFO_mutex);
+			}
+
+```
+
+vnf_nr_dispatch_p7_message() is the function that contains the switch on various message headers so that the appropriate unpack function is called. 
+
+## P7 DL Transmission by VNF 
+
+DL messages are scheduled at the VNF, through NR_UL_indication() after processing of UL_INFO. The function performing the scheduling of channels (and consequently p7 messages in nFAPI) is gNB_dlsch_ulsch_scheduler(). 
+
+The function NR_schedule_response calls oai_nfapi_[DL P7 msg]_req(), which contains the routines for packing + transmission of scheduled messages through the socket to the PNF. For example, to send the 'TX_data_req' p7 message 
+
+```
+
+if (Sched_INFO->TX_req->Number_of_PDUs > 0)
+{
+  oai_nfapi_tx_data_req(Sched_INFO->TX_req);
+}
+
+```
+
+## P7 DL Reception at PNF 
+
+Through the infinite loop [while(pnf_p7->terminate == 0)] running in pnf_nr_p7_message_pump(), the PNF receives and unpacks the downlink P7 message received on its socket. Based on the unpacked message, the appropriate message structures are filled in the PNF, and these are used further down the pipeline for processing. 
+
+While receiving the DL P7 message, we check whether the message was received within a timing window from which it was sent. The duration of the window can be set by the user (set as a parameter for xnf in the p5 messages). A point to note is that the DL information must be received by the PNF within a timing window at least lesser than the duration of slot_ahead variable (timing_window <= slot_ahead * slot_duration). Ideally, it should be received within a duration significantly lesser than slot_ahead so that there is adequate time for PHY processing. 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md
index d13b193ff96fb7afc62a9ce7df8f7a9a26e9c9e0..8d84646e071ea2bba568b05dcc3c81177bfcf3f4 100644
--- a/doc/RUNMODEM.md
+++ b/doc/RUNMODEM.md
@@ -132,9 +132,9 @@ With the RF simulator (on the same machine):
 
 `sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD`
 
-## sa setup with OAI
+## SA setup with OAI
 
-The sa flag is used to run gNB in standalone mode. Currently OAI in NR standalone mode transmits and receives SIB1.
+The sa flag is used to run gNB in standalone mode. Currently OAI in NR standalone mode transmits and receives SIB1 and triggers the RA procedure for initial access.
 
 In order to run gNB in standalone mode, the following flag is needed at gNB:
 
@@ -147,8 +147,9 @@ At the gNB the --sa flag does the following
 - it encodes the RRCConfiguration and the RBconfig message and stores them in the binary files rbconfig.raw and reconfig.raw
 - the RRC encodes SIB1 according the configuration file and transmits it through PDSCH
 
-At the UE the --sa flag will
-- read the binary files rbconfig.raw and reconfig.raw from the current directory (a different directory can be specified with the flag --rrc_config_path) and process them.
+At the UE the --sa flag will:
+- Read the binary files rbconfig.raw and reconfig.raw from the current directory (a different directory can be specified with the flag --rrc_config_path) and process them
+- After the successful decoding of a SIB1 at RRC, the UE will start the 5G NR Initial Access Procedure by triggering the RA procedure.
 
 From the `cmake_targets/ran_build/build` folder:
 
@@ -168,7 +169,7 @@ With the RF simulator (on the same machine):
 
 ## IF setup with OAI
 
-The -C and -CO flags can be used together at UE side to set custom downlink and uplink FR1 intermediate frequencies for the IF equipment.
+The -C and --CO flags can be used together at UE side to set custom downlink and uplink FR1 arbitrary frequencies for the IF equipment.
 
 In order to run this setup, the following flags are needed at the UE side:
 
@@ -182,9 +183,11 @@ and the following parameters must be configured in the RUs section of the gNB co
 
 `if_offset`
 
-### Run OAI with custom DL/UL intermediate frequencies
+The values must be given in Hz.
 
-The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 at gNB side.
+### Run OAI with custom DL/UL arbitrary frequencies
+
+The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 (FDD) at gNB side.
 
 From the `cmake_targets/ran_build/build` folder:
 
diff --git a/docker/Dockerfile.eNB.rhel8.2 b/docker/Dockerfile.eNB.rhel8.2
index 5fcd5a7b9f07d041f66d3aa92dca8a3c72c57c83..aa8b9aa228962ed012e39d2bb21a02e0a62d2b8f 100644
--- a/docker/Dockerfile.eNB.rhel8.2
+++ b/docker/Dockerfile.eNB.rhel8.2
@@ -27,14 +27,15 @@
 
 FROM localhost/ran-build:latest AS enb-build 
 
+RUN rm -Rf /oai-ran
 WORKDIR /oai-ran
+COPY . .
 
 #run build_oai to build the target image
 RUN /bin/sh oaienv && \ 
     cd cmake_targets && \
-    rm -Rf log && \
     mkdir -p log && \
-    ./build_oai --eNB --ninja -w USRP
+    ./build_oai --eNB --ninja -w USRP --verbose-ci
 
 # debug
 #RUN ldconfig -v && ldd /oai-ran/targets/bin/lte-softmodem.Rel15
diff --git a/docker/Dockerfile.eNB.ubuntu18 b/docker/Dockerfile.eNB.ubuntu18
index cdfb37ebfc343637e2bfbdce2ff3d2f0f147a09c..95d7194c317e6c38fceefbfebfd93fc64e649ca0 100644
--- a/docker/Dockerfile.eNB.ubuntu18
+++ b/docker/Dockerfile.eNB.ubuntu18
@@ -27,14 +27,15 @@
 
 FROM ran-build:latest AS enb-build 
 
+RUN rm -Rf /oai-ran
 WORKDIR /oai-ran
+COPY . .
 
 #run build_oai to build the target image
 RUN /bin/sh oaienv && \ 
     cd cmake_targets && \
-    rm -Rf log && \
     mkdir -p log && \
-    ./build_oai --eNB --ninja -w USRP
+    ./build_oai --eNB --ninja -w USRP --verbose-ci
 
 RUN apt-get install -y python3-pip && \
     pip3 install --ignore-installed pyyaml && \
diff --git a/docker/Dockerfile.gNB.rhel8.2 b/docker/Dockerfile.gNB.rhel8.2
index fb9ade927f8db1a1c7d559b3ddb26db4cb6af8df..6969c691fdf6197dccb14cf8925bbda766f3581d 100644
--- a/docker/Dockerfile.gNB.rhel8.2
+++ b/docker/Dockerfile.gNB.rhel8.2
@@ -27,14 +27,15 @@
 
 FROM localhost/ran-build:latest AS gnb-build 
 
+RUN rm -Rf /oai-ran
 WORKDIR /oai-ran
+COPY . .
 
 #run build_oai to build the target image
 RUN /bin/sh oaienv && \ 
     cd cmake_targets && \
-    rm -Rf log && \
     mkdir -p log && \
-    ./build_oai --gNB --ninja -w USRP
+    ./build_oai --gNB --ninja -w USRP --verbose-ci
 
 #debug
 #RUN ldconfig -v
diff --git a/docker/Dockerfile.gNB.ubuntu18 b/docker/Dockerfile.gNB.ubuntu18
index d43ad4709dbedcef7c76861cc2677a38c95dc8d4..276d6989c4e9bf61d87cb4c86a32ff8c55ff7d4b 100644
--- a/docker/Dockerfile.gNB.ubuntu18
+++ b/docker/Dockerfile.gNB.ubuntu18
@@ -27,14 +27,15 @@
 
 FROM ran-build:latest AS gnb-build 
 
+RUN rm -Rf /oai-ran
 WORKDIR /oai-ran
+COPY . .
 
 #run build_oai to build the target image
 RUN /bin/sh oaienv && \ 
     cd cmake_targets && \
-    rm -Rf log && \
     mkdir -p log && \
-    ./build_oai --gNB --ninja -w USRP
+    ./build_oai --gNB --ninja -w USRP --verbose-ci
 
 #debug
 RUN ldconfig -v
diff --git a/docker/Dockerfile.lteUE.rhel8.2 b/docker/Dockerfile.lteUE.rhel8.2
index 0a853dcd6b5dc211a730cf0a82f074e9118eea61..e22343d63cec65d90e23051c44abb3da778094b3 100644
--- a/docker/Dockerfile.lteUE.rhel8.2
+++ b/docker/Dockerfile.lteUE.rhel8.2
@@ -27,15 +27,15 @@
 
 FROM localhost/ran-build:latest AS lte-ue-build 
 
-
+RUN rm -Rf /oai-ran
 WORKDIR /oai-ran
+COPY . .
 
 #run build_oai to build the target image
 RUN /bin/sh oaienv && \ 
     cd cmake_targets && \
-    rm -Rf log && \
     mkdir -p log && \
-    ./build_oai --UE --ninja -w USRP
+    ./build_oai --UE --ninja -w USRP --verbose-ci
 
 # debug
 #RUN ldconfig -v && ldd /oai-ran/targets/bin/lte-uesoftmodem.Rel15
diff --git a/docker/Dockerfile.lteUE.ubuntu18 b/docker/Dockerfile.lteUE.ubuntu18
index 8793cc54f79d87e470a46a4520b7f2ee519d1865..6af2e619918e776d0b46ec4b466d4677dacd627a 100644
--- a/docker/Dockerfile.lteUE.ubuntu18
+++ b/docker/Dockerfile.lteUE.ubuntu18
@@ -27,14 +27,15 @@
 
 FROM ran-build:latest AS lte-ue-build 
 
+RUN rm -Rf /oai-ran
 WORKDIR /oai-ran
+COPY . .
 
 #run build_oai to build the target image
 RUN /bin/sh oaienv && \ 
     cd cmake_targets && \
-    rm -Rf log && \
     mkdir -p log && \
-    ./build_oai --UE --ninja -w USRP
+    ./build_oai --UE --ninja -w USRP --verbose-ci
 
 # debug
 #RUN ldconfig -v
diff --git a/docker/Dockerfile.nrUE.rhel8.2 b/docker/Dockerfile.nrUE.rhel8.2
index f9f3f8e4bfcdfd4e95d3d8ae10ed206788f7af53..01988fd6ff6608d8f132eefbce4524c16149a305 100644
--- a/docker/Dockerfile.nrUE.rhel8.2
+++ b/docker/Dockerfile.nrUE.rhel8.2
@@ -27,14 +27,15 @@
 
 FROM localhost/ran-build:latest AS nr-ue-build 
 
+RUN rm -Rf /oai-ran
 WORKDIR /oai-ran
+COPY . .
 
 #run build_oai to build the target image
 RUN /bin/sh oaienv && \ 
     cd cmake_targets && \
-    rm -Rf log && \
     mkdir -p log && \
-    ./build_oai --nrUE --ninja -w USRP
+    ./build_oai --nrUE --ninja -w USRP --verbose-ci
 
 # debug
 #RUN ldconfig -v
diff --git a/docker/Dockerfile.nrUE.ubuntu18 b/docker/Dockerfile.nrUE.ubuntu18
index 5450194f3539ad83663017e31e53e10185dc9a37..c96bcf80ef106613c06080574455f09f724cb42a 100644
--- a/docker/Dockerfile.nrUE.ubuntu18
+++ b/docker/Dockerfile.nrUE.ubuntu18
@@ -27,14 +27,15 @@
 
 FROM ran-build:latest AS nr-ue-build 
 
+RUN rm -Rf /oai-ran
 WORKDIR /oai-ran
+COPY . .
 
 #run build_oai to build the target image
 RUN /bin/sh oaienv && \ 
     cd cmake_targets && \
-    rm -Rf log && \
     mkdir -p log && \
-    ./build_oai --nrUE --ninja -w USRP
+    ./build_oai --nrUE --ninja -w USRP --verbose-ci
 
 # debug
 #RUN ldconfig -v
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index 2f7944e313a07376d2c78f25d9928aa596960371..410c41d9b13c117e16f848e1f023cb30e06d3af4 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -81,10 +81,11 @@
 
 #include "s1ap_eNB.h"
 #include "SIMULATION/ETH_TRANSPORT/proto.h"
-
+#include <executables/softmodem-common.h>
 
 #include "T.h"
 #include "nfapi/oai_integration/vendor_ext.h"
+#include <nfapi/oai_integration/nfapi_pnf.h>
 //#define DEBUG_THREADS 1
 
 //#define USRP_DEBUG 1
@@ -92,17 +93,6 @@
 // extern openair0_device openair0;
 
 
-extern volatile int start_gNB;
-extern volatile int start_UE;
-extern volatile int oai_exit;
-
-extern openair0_config_t openair0_cfg[MAX_CARDS];
-
-extern int transmission_mode;
-
-extern uint16_t sf_ahead;
-extern uint16_t sl_ahead;
-
 //pthread_t                       main_gNB_thread;
 
 time_stats_t softmodem_stats_mt; // main thread
@@ -111,40 +101,43 @@ time_stats_t softmodem_stats_rxtx_sf; // total tx time
 time_stats_t nfapi_meas; // total tx time
 time_stats_t softmodem_stats_rx_sf; // total rx time
 
-/* mutex, cond and variable to serialize phy proc TX calls
- * (this mechanism may be relaxed in the future for better
- * performances)
- */
-static struct {
-  pthread_mutex_t  mutex_phy_proc_tx;
-  pthread_cond_t   cond_phy_proc_tx;
-  volatile uint8_t phy_proc_CC_id;
-} sync_phy_proc;
 
-extern double cpuf;
+#include "executables/thread-common.h"
 
-void init_gNB(int,int);
-void stop_gNB(int nb_inst);
 
-int wakeup_txfh(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, int frame_tx, int slot_tx, uint64_t timestamp_tx);
-int wakeup_tx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, uint64_t timestamp_tx);
-#include "executables/thread-common.h"
-//extern PARALLEL_CONF_t get_thread_parallel_conf(void);
-//extern WORKER_CONF_t   get_thread_worker_conf(void);
+//#define TICK_TO_US(ts) (ts.diff)
+#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
 
 
-void wakeup_prach_gNB(PHY_VARS_gNB *gNB, RU_t *ru, int frame, int subframe);
+void tx_func(void *param) {
 
-extern uint8_t nfapi_mode;
-extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
-extern void oai_slot_ind(uint16_t sfn, uint16_t slot);
-extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
+  processingData_L1_t *info = (processingData_L1_t *) param;
+  PHY_VARS_gNB *gNB = info->gNB;
+  int frame_tx = info->frame_tx;
+  int slot_tx = info->slot_tx;
 
-//#define TICK_TO_US(ts) (ts.diff)
-#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
+  phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
 
-static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, char *thread_name) {
+  // start FH TX processing
+  notifiedFIFO_elt_t *res; 
+  res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
+  processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
+  syncMsg->frame_tx = frame_tx;
+  syncMsg->slot_tx = slot_tx;
+  syncMsg->timestamp_tx = info->timestamp_tx;
+  syncMsg->ru = gNB->RU_list[0];
+  res->key = slot_tx;
+  pushTpool(gNB->threadPool, res);
+}
 
+void rx_func(void *param) {
+  //printf("inside rx func. \n");
+  processingData_L1_t *info = (processingData_L1_t *) param;
+  PHY_VARS_gNB *gNB = info->gNB;
+  int frame_rx = info->frame_rx;
+  int slot_rx = info->slot_rx;
+  int frame_tx = info->frame_tx;
+  int slot_tx = info->slot_tx;
   sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe;
   nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
 
@@ -235,22 +228,18 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
   rnti_to_remove_count = 0;
   if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1);
 
-  /*
-  // if this is IF5 or 3GPP_gNB
-  if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) {
-    wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx);
-  }
-  */
   // Call the scheduler
 
-  pthread_mutex_lock(&gNB->UL_INFO_mutex);
-  gNB->UL_INFO.frame     = frame_rx;
-  gNB->UL_INFO.slot      = slot_rx;
-  gNB->UL_INFO.module_id = gNB->Mod_id;
-  gNB->UL_INFO.CC_id     = gNB->CC_id;
-  gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
-  pthread_mutex_unlock(&gNB->UL_INFO_mutex);
-  
+  if(NFAPI_MODE == NFAPI_MONOLITHIC) 
+  {
+    pthread_mutex_lock(&gNB->UL_INFO_mutex);
+    gNB->UL_INFO.frame     = frame_rx;
+    gNB->UL_INFO.slot      = slot_rx;
+    gNB->UL_INFO.module_id = gNB->Mod_id;
+    gNB->UL_INFO.CC_id     = gNB->CC_id;
+    gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
+    pthread_mutex_unlock(&gNB->UL_INFO_mutex);
+  }
   // RX processing
   int tx_slot_type; int rx_slot_type;
   if(NFAPI_MODE != NFAPI_MONOLITHIC) { //slot selection routines not working properly in nfapi, so temporarily hardcoding
@@ -298,23 +287,24 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
     phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
   }
 
-  if (oai_exit) return(-1);
+  stop_meas( &softmodem_stats_rxtx_sf );
+  LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
 
-  // *****************************************
-  // TX processing for subframe n+sf_ahead
-  // run PHY TX procedures the one after the other for all CCs to avoid race conditions
-  // (may be relaxed in the future for performance reasons)
-  // *****************************************
+  notifiedFIFO_elt_t *res; 
 
   if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
-
-    if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) {
-      phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
-    }
+    res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
+    processingData_L1_t *syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
+    syncMsg->gNB = gNB;
+    syncMsg->frame_rx = frame_rx;
+    syncMsg->slot_rx = slot_rx;
+    syncMsg->frame_tx = frame_tx;
+    syncMsg->slot_tx = slot_tx;
+    syncMsg->timestamp_tx = info->timestamp_tx;
+    res->key = slot_tx;
+    pushTpool(gNB->threadPool, res);
   }
-
-  stop_meas( &softmodem_stats_rxtx_sf );
-  LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
+    
 #if 0
   LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
         softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now,
@@ -354,477 +344,7 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
         TICK_TO_US(gNB->ulsch_tc_intl2_stats)
        );
 #endif
-  return(0);
-}
-
-static void *gNB_L1_thread_tx(void *param) {
-  PHY_VARS_gNB *gNB        = (PHY_VARS_gNB *)param;
-  gNB_L1_proc_t *gNB_proc  = &gNB->proc;
-  gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB_proc->L1_proc_tx;
-  //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
-  char thread_name[100];
-
-  sprintf(thread_name,"gNB_L1_thread_tx\n");
-
-  while (!oai_exit) {
-    if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break;
-
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 );
-
-    if (oai_exit) break;
-
-    // *****************************************
-    // TX processing for subframe n+4
-    // run PHY TX procedures the one after the other for all CCs to avoid race conditions
-    // (may be relaxed in the future for performance reasons)
-    // *****************************************
-    int      frame_tx = L1_proc_tx->frame_tx;
-    int      slot_tx = L1_proc_tx->slot_tx;
-    uint64_t timestamp_tx = L1_proc_tx->timestamp_tx;
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,slot_tx);
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,frame_tx);
-    phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
-
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 1 );
-    pthread_mutex_lock( &L1_proc_tx->mutex );
-    L1_proc_tx->instance_cnt = -1;
-
-    // the thread can now be woken up
-    if (pthread_cond_signal(&L1_proc_tx->cond) != 0) {
-      LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
-      exit_fun( "ERROR pthread_cond_signal" );
-    }
-    pthread_mutex_unlock(&L1_proc_tx->mutex);
-
-    wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx);
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 0 );
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
-  }
-
-  return 0;
-}
-
-/*!
- * \brief The RX UE-specific and TX thread of gNB.
- * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
- * \returns a pointer to an int. The storage is not on the heap and must not be freed.
- */
-
-static void *gNB_L1_thread( void *param ) {
-  static int gNB_thread_rxtx_status;
-  PHY_VARS_gNB *gNB        = (PHY_VARS_gNB *)param;
-  gNB_L1_proc_t *gNB_proc  = &gNB->proc;
-  gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc;
-  //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
-  char thread_name[100];
-  // set default return value
-  // set default return value
-  gNB_thread_rxtx_status = 0;
-
-  sprintf(thread_name,"gNB_L1_thread");
-
-
-  while (!oai_exit) {
-
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 );
-    int frame_rx          = L1_proc->frame_rx;
-    int slot_rx;
-    if (NFAPI_MODE == NFAPI_MODE_PNF)
-      slot_rx = (L1_proc->slot_rx) + 1;
-    else 
-      slot_rx = L1_proc->slot_rx;
-    int frame_tx          = L1_proc->frame_tx;
-    int slot_tx           = L1_proc->slot_tx;
-    uint64_t timestamp_tx = L1_proc->timestamp_tx;
-    if(NFAPI_MODE==NFAPI_MODE_VNF)
-      if (gNB->CC_id==0) {
-        int next_slot;
-        next_slot = (slot_rx + 1) % 20;
-        if (rxtx(gNB,frame_rx,next_slot,frame_tx,next_slot,thread_name) < 0) break;
-      }
-    if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break;
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 );
-
-
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx);
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,slot_rx);
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,frame_tx);
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_GNB,frame_rx);
-
-    if (oai_exit) break;
-
-    if (gNB->CC_id==0) {
-      if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break;
-    }
-
-   
-    if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break;
-   
-    if (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)  wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx);
-    else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(gNB,L1_proc,frame_tx,slot_tx,timestamp_tx);
-  } // while !oai_exit
-
-  LOG_D(PHY, " *** Exiting gNB thread RXn_TXnp4\n");
-  gNB_thread_rxtx_status = 0;
-  return &gNB_thread_rxtx_status;
-}
-
-
-#if 0 
-// Wait for gNB application initialization to be complete (gNB registration to MME)
-static void wait_system_ready (char *message, volatile int *start_flag) {
-  static char *indicator[] = {".    ", "..   ", "...  ", ".... ", ".....",
-                              " ....", "  ...", "   ..", "    .", "     "
-                             };
-  int i = 0;
-
-  while ((!oai_exit) && (*start_flag == 0)) {
-    LOG_N(EMU, message, indicator[i]);
-    fflush(stdout);
-    i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0]));
-    usleep(200000);
-  }
-
-  LOG_D(EMU,"\n");
-}
-#endif
-
-
-
-
-
-void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru) {
-  gNB_L1_proc_t *proc           = &gNB->proc;
-  gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
-  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
-  RU_proc_t *ru_proc=&ru->proc;
-  proc->frame_rx    = frame_rx;
-  proc->slot_rx = slot_rx;
-  sl_ahead = sf_ahead*fp->slots_per_subframe;
-
-  if (!oai_exit) {
-    T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->slot_rx));
-    L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
-    L1_proc->frame_rx     = ru_proc->frame_rx;
-    L1_proc->slot_rx      = ru_proc->tti_rx;
-    L1_proc->frame_tx     = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
-    L1_proc->slot_tx      = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
-
-    if (rxtx(gNB,L1_proc->frame_rx,L1_proc->slot_rx,L1_proc->frame_tx,L1_proc->slot_tx,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id);
-
-    ru_proc->timestamp_tx = L1_proc->timestamp_tx;
-    ru_proc->tti_tx       = L1_proc->slot_tx;
-    ru_proc->frame_tx     = L1_proc->frame_tx;
-  }
-}
-
-int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx) {
-
-  RU_t *ru;
-  RU_proc_t *ru_proc;
-
-  int waitret = 0, ret = 0, time_ns = 1000*1000;
-  struct timespec now, abstime;
-  // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time
-  // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1);
-  time_ns = time_ns/gNB->frame_parms.slots_per_subframe;
-  AssertFatal((ret = pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
-  while (proc->instance_cnt_RUs < 0) {
-    clock_gettime(CLOCK_REALTIME, &now);
-    abstime.tv_sec = now.tv_sec;
-    abstime.tv_nsec = now.tv_nsec + time_ns;
-
-    if (abstime.tv_nsec >= 1000*1000*1000) {
-      abstime.tv_nsec -= 1000*1000*1000;
-      abstime.tv_sec  += 1;
-    }
-    if((waitret = pthread_cond_timedwait(&proc->cond_RUs,&proc->mutex_RUs_tx,&abstime)) == 0) break; // this unlocks mutex_rxtx while waiting and then locks it again
-  }
-  proc->instance_cnt_RUs = -1;
-  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
-  AssertFatal((ret = pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0);
-
-  if (waitret == ETIMEDOUT) {
-    LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx);
-
-    AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
-    gNB->proc.RU_mask_tx = 0;
-    AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
-    AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
-    proc->instance_cnt_RUs = 0;
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
-    AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
-
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1);
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0);
-
-    return(-1);
-  }
-
-  for(int i=0; i<gNB->num_RU; i++)
-  {
-    ru      = gNB->RU_list[i];
-    ru_proc = &ru->proc;
-
-
-    if (ru_proc->instance_cnt_gNBs == 0) {
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1);
-      LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->tti_tx, proc->frame_rx, proc->slot_rx);
-      AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
-      gNB->proc.RU_mask_tx = 0;
-      AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
-
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0);
-      return(-1);
-    }
-    AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret);
-
-    ru_proc->instance_cnt_gNBs = 0;
-    ru_proc->timestamp_tx = timestamp_tx;
-    ru_proc->tti_tx       = slot_tx;
-    ru_proc->frame_tx     = frame_tx;
-
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs);
-
-    LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx);
-    // the thread can now be woken up
-    AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0,
-                "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
-    AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret);
-
-  }
-  return(0);
-}
-
-int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx) {
-
-
-  gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB->proc.L1_proc_tx;
-
-  int ret;
- 
-  
-  AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret);
-
-
-  while(L1_proc_tx->instance_cnt == 0) {
-    pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex);
-  }
-
-  L1_proc_tx->instance_cnt = 0;
-
-  
-  L1_proc_tx->slot_rx       = slot_rx;
-  L1_proc_tx->frame_rx      = frame_rx;
-  L1_proc_tx->slot_tx       = slot_tx;
-  L1_proc_tx->frame_tx      = frame_tx;
-  L1_proc_tx->timestamp_tx  = timestamp_tx;
-
- 
-  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1);
-  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0);
-  // the thread can now be woken up
-  // the thread can now be woken up
-  AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n");
-  
-  AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret);
-
-  return(0);
-}
-
-int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
-  gNB_L1_proc_t *proc=&gNB->proc;
-  gNB_L1_rxtx_proc_t *L1_proc=&proc->L1_proc;
-  NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
-  RU_proc_t *ru_proc=&ru->proc;
-  int ret;
-  int i;
-  struct timespec abstime;
-  int time_ns = 50000;
-  int wait_timer = 0;
-  bool do_last_check = 1;
-  
-  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret);
-  for (i=0; i<gNB->num_RU; i++) {
-    if (ru == gNB->RU_list[i]) {
-      if ((proc->RU_mask&(1<<i)) > 0)
-        LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
-              gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask);
-      proc->RU_mask |= (1<<i);
-    }
-  }
-  if (proc->RU_mask != (1<<gNB->num_RU)-1) {  // not all RUs have provided their information so return
-    LOG_E(PHY,"Not all RUs have provided their info\n");
-    AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret);
-    return(0);
-  }
-  else { // all RUs have provided their information so continue on and wakeup gNB processing
-    proc->RU_mask = 0;
-    AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret);
-  }
-
-  // wake up TX for subframe n+sf_ahead
-  // lock the TX mutex and make sure the thread is ready
-  while (wait_timer < 200) {
-    clock_gettime(CLOCK_REALTIME, &abstime);
-    abstime.tv_nsec = abstime.tv_nsec + time_ns;
-
-    if (abstime.tv_nsec >= 1000*1000*1000) {
-      abstime.tv_nsec -= 1000*1000*1000;
-      abstime.tv_sec  += 1;
-    }
-
-    AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
-
-    if (L1_proc->instance_cnt == 0) { // L1_thread is busy so wait for a bit
-      AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
-      wait_timer += 50;
-      usleep(50);
-    }
-    else {
-      do_last_check = 0;
-      break;
-    }
-  }
-  if (do_last_check) {
-    AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
-    if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
-      AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
-      LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx);
-      return (-1);
-    }
-  }
-
-  ++L1_proc->instance_cnt;
-  // We have just received and processed the common part of a subframe, say n.
-  // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
-  // transmitted timestamp of the next TX slot (first).
-
-  // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, 
-  // we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
-  // and proc->slot_tx = proc->slot_rx+sf_ahead
-  L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
-  L1_proc->frame_rx     = ru_proc->frame_rx;
-  L1_proc->slot_rx  = ru_proc->tti_rx;
-  L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
-  L1_proc->slot_tx  = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
-
-  LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sf_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sf_ahead);
-
-  pthread_mutex_unlock( &L1_proc->mutex );
-
-  // the thread can now be woken up
-  if (pthread_cond_signal(&L1_proc->cond) != 0) {
-    LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n");
-    exit_fun( "ERROR pthread_cond_signal" );
-    return(-1);
-  }
-
-  return(0);
 }
-/*
-void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) {
-
-  gNB_L1_proc_t *proc = &gNB->proc;
-  LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms;
-  int i;
-
-  if (ru!=NULL) {
-    pthread_mutex_lock(&proc->mutex_RU_PRACH);
-    for (i=0;i<gNB->num_RU;i++) {
-      if (ru == gNB->RU_list[i]) {
-  LOG_D(PHY,"frame %d, subframe %d: RU %d for gNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,gNB->Mod_id,proc->RU_mask_prach,gNB->num_RU);
-  if ((proc->RU_mask_prach&(1<<i)) > 0)
-    LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information (PRACH) from RU %d (num_RU %d, mask %x) has not been served yet!\n",
-    gNB->Mod_id,frame,subframe,ru->idx,gNB->num_RU,proc->RU_mask_prach);
-  proc->RU_mask_prach |= (1<<i);
-      }
-    }
-    if (proc->RU_mask_prach != (1<<gNB->num_RU)-1) {  // not all RUs have provided their information so return
-      pthread_mutex_unlock(&proc->mutex_RU_PRACH);
-      return;
-    }
-    else { // all RUs have provided their information so continue on and wakeup gNB processing
-      proc->RU_mask_prach = 0;
-      pthread_mutex_unlock(&proc->mutex_RU_PRACH);
-    }
-  }
-
-  // check if we have to detect PRACH first
-  if (is_prach_subframe(fp,frame,subframe)>0) {
-    LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe);
-    if (proc->instance_cnt_prach == 0) {
-      LOG_W(PHY,"[gNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe);
-      return;
-    }
-
-    // wake up thread for PRACH RX
-    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
-      LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
-      exit_fun( "error locking mutex_prach" );
-      return;
-    }
-
-    ++proc->instance_cnt_prach;
-    // set timing for prach thread
-    proc->frame_prach = frame;
-    proc->subframe_prach = subframe;
-
-    // the thread can now be woken up
-    if (pthread_cond_signal(&proc->cond_prach) != 0) {
-      LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB PRACH thread %d\n", proc->thread_index);
-      exit_fun( "ERROR pthread_cond_signal" );
-      return;
-    }
-
-    pthread_mutex_unlock( &proc->mutex_prach );
-  }
-
-}*/
-
-/*!
- * \brief The prach receive thread of gNB.
- * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
- * \returns a pointer to an int. The storage is not on the heap and must not be freed.
- */
-/*
-static void* gNB_thread_prach( void* param ) {
- static int gNB_thread_prach_status;
-
-
- PHY_VARS_gNB *gNB= (PHY_VARS_gNB *)param;
- gNB_L1_proc_t *proc = &gNB->proc;
-
- // set default return value
- gNB_thread_prach_status = 0;
-
-
-
- while (!oai_exit) {
-
-   if (oai_exit) break;
-
-
-   if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break;
-
-   LOG_D(PHY,"Running gNB prach procedures\n");
-   prach_procedures(gNB ,0);
-
-   if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break;
- }
-
- LOG_I(PHY, "Exiting gNB thread PRACH\n");
-
- gNB_thread_prach_status = 0;
- return &gNB_thread_prach_status;
-}
-*/
-
-extern void init_td_thread(PHY_VARS_gNB *);
-extern void init_te_thread(PHY_VARS_gNB *);
-
 static void *process_stats_thread(void *param) {
 
   PHY_VARS_gNB *gNB  = (PHY_VARS_gNB *)param;
@@ -845,71 +365,13 @@ static void *process_stats_thread(void *param) {
   return(NULL);
 }
 
-
-void init_gNB_proc(int inst) {
-  int i=0;
-  int CC_id = 0;
+void init_gNB_Tpool(int inst) {
   PHY_VARS_gNB *gNB;
-  gNB_L1_proc_t *proc;
-  gNB_L1_rxtx_proc_t *L1_proc,*L1_proc_tx;
-//  LOG_I(PHY,"%s(inst:%d) RC.nb_nr_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_nr_CC[inst]);
   gNB = RC.gNB[inst];
-  LOG_I(PHY,"Initializing gNB processes instance:%d CC_id %d \n",inst,CC_id);
-  
-  proc = &gNB->proc;
-  L1_proc                        = &proc->L1_proc;
-  L1_proc_tx                     = &proc->L1_proc_tx;
-  L1_proc->instance_cnt          = -1;
-  L1_proc_tx->instance_cnt       = -1;
-  L1_proc->instance_cnt_RUs      = 0;
-  L1_proc_tx->instance_cnt_RUs   = 0;
-  proc->instance_cnt_prach       = -1;
-  proc->instance_cnt_asynch_rxtx = -1;
-  proc->CC_id                    = CC_id;
-  proc->first_rx                 =1;
-  proc->first_tx                 =1;
-  proc->RU_mask                  =0;
-  proc->RU_mask_tx               = (1<<gNB->num_RU)-1;
-  proc->RU_mask_prach            =0;
-  pthread_mutex_init( &gNB->UL_INFO_mutex, NULL);
-  pthread_mutex_init( &L1_proc->mutex, NULL);
-  pthread_mutex_init( &L1_proc_tx->mutex, NULL);
-  pthread_cond_init( &L1_proc->cond, NULL);
-  pthread_cond_init( &L1_proc_tx->cond, NULL);
-  pthread_mutex_init( &proc->mutex_prach, NULL);
-  pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
-  pthread_mutex_init( &proc->mutex_RU,NULL);
-  pthread_mutex_init( &proc->mutex_RU_tx,NULL);
-  pthread_mutex_init( &proc->mutex_RU_PRACH,NULL);
-  pthread_cond_init( &proc->cond_prach, NULL);
-  pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
-  LOG_I(PHY,"gNB->single_thread_flag:%d\n", gNB->single_thread_flag);
-  
-  if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
-    threadCreate( &L1_proc->pthread, gNB_L1_thread, gNB, "L1_proc", -1, OAI_PRIORITY_RT );
-    threadCreate( &L1_proc_tx->pthread, gNB_L1_thread_tx, gNB,"L1_proc_tx", -1, OAI_PRIORITY_RT);
-  }
-  
-  if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
-  //pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB );
-  char name[16];
-  
-  if (gNB->single_thread_flag==0) {
-    snprintf( name, sizeof(name), "L1 %d", i );
-    pthread_setname_np( L1_proc->pthread, name );
-    snprintf( name, sizeof(name), "L1TX %d", i );
-    pthread_setname_np( L1_proc_tx->pthread, name );
-  }
-  
-  AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach);
-
-  /* setup PHY proc TX sync mechanism */
-  pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL);
-  pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL);
-  sync_phy_proc.phy_proc_CC_id = 0;
+  gNB_L1_proc_t *proc = &gNB->proc;
 
+  // ULSCH decoding threadpool
   gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
-  gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
   int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
   int threadCnt = min(numCPU, gNB->pusch_proc_threads);
   char ul_pool[80];
@@ -920,70 +382,40 @@ void init_gNB_proc(int inst) {
     s_offset += 3;
   }
   initTpool(ul_pool, gNB->threadPool, false);
+  // ULSCH decoder result FIFO
+  gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
   initNotifiedFIFO(gNB->respDecode);
-}
 
+  // L1 RX result FIFO 
+  gNB->resp_L1 = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
+  initNotifiedFIFO(gNB->resp_L1);
+
+  // L1 TX result FIFO 
+  gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
+  initNotifiedFIFO(gNB->resp_L1_tx);
+
+  // RU TX result FIFO 
+  gNB->resp_RU_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
+  initNotifiedFIFO(gNB->resp_RU_tx);
+
+  // Stats measurement thread
+  if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW);
+}
 
 
 /*!
  * \brief Terminate gNB TX and RX threads.
  */
 void kill_gNB_proc(int inst) {
-  int *status;
   PHY_VARS_gNB *gNB;
-  gNB_L1_proc_t *proc;
-  gNB_L1_rxtx_proc_t *L1_proc, *L1_proc_tx;
 
   gNB=RC.gNB[inst];
-  proc = &gNB->proc;
-  L1_proc     = &proc->L1_proc;
-  L1_proc_tx  = &proc->L1_proc_tx;
-  LOG_I(PHY, "Killing TX inst %d\n",inst );
-  
-  if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
-    pthread_mutex_lock(&L1_proc->mutex);
-    L1_proc->instance_cnt = 0;
-    pthread_cond_signal(&L1_proc->cond);
-    pthread_mutex_unlock(&L1_proc->mutex);
-    pthread_mutex_lock(&L1_proc_tx->mutex);
-    L1_proc_tx->instance_cnt = 0;
-    pthread_cond_signal(&L1_proc_tx->cond);
-    pthread_mutex_unlock(&L1_proc_tx->mutex);
-  }
   
-  proc->instance_cnt_prach = 0;
-  pthread_cond_signal( &proc->cond_prach );
-  pthread_cond_signal( &proc->cond_asynch_rxtx );
-  pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
-  //    LOG_D(PHY, "joining pthread_prach\n");
-  //    pthread_join( proc->pthread_prach, (void**)&status );
-  LOG_I(PHY, "Destroying prach mutex/cond\n");
-  pthread_mutex_destroy( &proc->mutex_prach );
-  pthread_cond_destroy( &proc->cond_prach );
   LOG_I(PHY, "Destroying UL_INFO mutex\n");
   pthread_mutex_destroy(&gNB->UL_INFO_mutex);
   
-  if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) {
-    LOG_I(PHY, "Joining L1_proc mutex/cond\n");
-    pthread_join( L1_proc->pthread, (void **)&status );
-    LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n");
-    pthread_join( L1_proc_tx->pthread, (void **)&status );
-  }
-  
-  LOG_I(PHY, "Destroying L1_proc mutex/cond\n");
-  pthread_mutex_destroy( &L1_proc->mutex );
-  pthread_cond_destroy( &L1_proc->cond );
-  LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n");
-  pthread_mutex_destroy( &L1_proc_tx->mutex );
-  pthread_cond_destroy( &L1_proc_tx->cond );
-  pthread_mutex_destroy( &proc->mutex_RU );
-  pthread_mutex_destroy( &proc->mutex_RU_tx );
-  
 }
 
-
-
-
 void reset_opp_meas(void) {
   int sfn;
   reset_meas(&softmodem_stats_mt);
@@ -1051,15 +483,9 @@ printf("after %p\n", gNB->common_vars.rxdataF[aa]);
      * (not tested in other modes).
      */
     //init_precoding_weights(RC.gNB[inst]);
-    init_gNB_proc(inst);
+    init_gNB_Tpool(inst);
   }
 
-  for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
-    AssertFatal(RC.ru[ru_id]!=NULL,"ru_id %d is null\n",ru_id);
-    RC.ru[ru_id]->nr_wakeup_rxtx         = wakeup_rxtx;
-    //    RC.ru[ru_id]->wakeup_prach_eNB    = wakeup_prach_gNB;
-    RC.ru[ru_id]->gNB_top             = gNB_top;
-  }
 }
 
 void init_gNB(int single_thread_flag,int wait_for_sync) {
diff --git a/executables/nr-ru.c b/executables/nr-ru.c
index d0bc1a3e0ed61810f99ceba490fb6d6908871205..1e8cae3adce181938321ec94ac820ae1a39e3c4f 100644
--- a/executables/nr-ru.c
+++ b/executables/nr-ru.c
@@ -790,259 +790,6 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
   }
 }
 
-
-
-/*!
- * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU.
- * This handles the RX FH for an asynchronous RRU/UE
- * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process.
- * \returns a pointer to an int. The storage is not on the heap and must not be freed.
- */
-void *ru_thread_asynch_rxtx( void *param ) {
-  static int ru_thread_asynch_rxtx_status;
-  RU_t *ru         = (RU_t *)param;
-  RU_proc_t *proc  = &ru->proc;
-  nfapi_nr_config_request_scf_t *cfg = &ru->config;
-  int slot=0, frame=0;
-  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
-  wait_sync("ru_thread_asynch_rxtx");
-  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
-  printf( "waiting for devices (ru_thread_asynch_rx)\n");
-  wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch");
-  printf( "devices ok (ru_thread_asynch_rx)\n");
-
-  while (!oai_exit) {
-
-    if (slot==ru->nr_frame_parms->slots_per_frame) {
-      slot=0;
-      frame++;
-      frame&=1023;
-    } else {
-      slot++;
-    }
-
-    LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n");
-
-    // asynchronous receive from north (RRU IF4/IF5)
-    if (ru->fh_north_asynch_in) {
-      if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0)
-        ru->fh_north_asynch_in(ru,&frame,&slot);
-    } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n");
-  }
-
-  ru_thread_asynch_rxtx_status=0;
-  return(&ru_thread_asynch_rxtx_status);
-}
-
-
-
-
-/*!
- * \brief The prach receive thread of RU.
- * \param param is a \ref RU_proc_t structure which contains the info what to process.
- * \returns a pointer to an int. The storage is not on the heap and must not be freed.
- */
-void *ru_thread_prach( void *param ) {
-  static int ru_thread_prach_status;
-  RU_t *ru        = (RU_t *)param;
-  RU_proc_t *proc = (RU_proc_t *)&ru->proc;
-  // set default return value
-  ru_thread_prach_status = 0;
-
-  while (RC.ru_mask>0) {
-    usleep(1e6);
-    LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__);
-  }
-
-  LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__);
-
-  while (!oai_exit) {
-    
-
-    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
-
-    /*VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );
-
-    if (ru->gNB_list[0]){
-      prach_procedures(
-        ru->gNB_list[0],0
-        );
-    }
-    else {
-       rx_prach(NULL,
-            ru,
-          NULL,
-                NULL,
-                NULL,
-                proc->frame_prach,
-                0,0
-          );
-    }
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/
-    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
-  }
-
-  LOG_I(PHY, "Exiting RU thread PRACH\n");
-  ru_thread_prach_status = 0;
-  return &ru_thread_prach_status;
-}
-
-
-int wakeup_synch(RU_t *ru) {
-  struct timespec wait;
-  wait.tv_sec=0;
-  wait.tv_nsec=5000000L;
-
-  // wake up synch thread
-  // lock the synch mutex and make sure the thread is ready
-  if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) {
-    LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch );
-    exit_fun( "error locking mutex_synch" );
-    return(-1);
-  }
-
-  ++ru->proc.instance_cnt_synch;
-
-  // the thread can now be woken up
-  if (pthread_cond_signal(&ru->proc.cond_synch) != 0) {
-    LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n");
-    exit_fun( "ERROR pthread_cond_signal" );
-    return(-1);
-  }
-
-  pthread_mutex_unlock( &ru->proc.mutex_synch );
-  return(0);
-}
-
-void do_ru_synch(RU_t *ru) {
-  NR_DL_FRAME_PARMS *fp  = ru->nr_frame_parms;
-  RU_proc_t *proc         = &ru->proc;
-  int i;
-  void *rxp[2],*rxp2[2];
-  int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32)));
-  int rxs;
-  int ic;
-
-  // initialize the synchronization buffer to the common_vars.rxdata
-  for (int i=0; i<ru->nb_rx; i++)
-    rxp[i] = &ru->common.rxdata[i][0];
-
-  double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0];
-  double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0];
-
-  for (i=0; i<4; i++) {
-    ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i];
-    ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1;
-  }
-
-  ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
-
-  while ((ru->in_synch ==0)&&(!oai_exit)) {
-    // read in frame
-    rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
-                                     &(proc->timestamp_rx),
-                                     rxp,
-                                     fp->samples_per_subframe*10,
-                                     ru->nb_rx);
-
-    if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs);
-
-    // wakeup synchronization processing thread
-    wakeup_synch(ru);
-    ic=0;
-
-    while ((ic>=0)&&(!oai_exit)) {
-      // continuously read in frames, 1ms at a time,
-      // until we are done with the synchronization procedure
-      for (i=0; i<ru->nb_rx; i++)
-        rxp2[i] = (void *)&dummy_rx[i][0];
-
-      for (i=0; i<10; i++)
-        rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
-                                         &(proc->timestamp_rx),
-                                         rxp2,
-                                         fp->samples_per_subframe,
-                                         ru->nb_rx);
-
-      pthread_mutex_lock(&ru->proc.mutex_synch);
-      ic = ru->proc.instance_cnt_synch;
-      pthread_mutex_unlock(&ru->proc.mutex_synch);
-    } // ic>=0
-  } // in_synch==0
-
-  // read in rx_offset samples
-  LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset);
-  rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
-                                   &(proc->timestamp_rx),
-                                   rxp,
-                                   ru->rx_offset,
-                                   ru->nb_rx);
-
-  for (i=0; i<4; i++) {
-    ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1;
-    ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2;
-  }
-
-  ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
-}
-
-
-
-void wakeup_gNB_L1s(RU_t *ru) {
-  int i;
-  PHY_VARS_gNB **gNB_list = ru->gNB_list;
-  LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top);
-
-  if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) {
-    // call gNB function directly
-    char string[20];
-    sprintf(string,"Incoming RU %u",ru->idx);
-    LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx);
-    ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru);
-  } else {
-    LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB);
-
-    for (i=0; i<ru->num_gNB; i++) {
-      LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx);
-
-      if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) {
-        LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx);
-      }
-    }
-  }
-}
-
-int wakeup_prach_ru(RU_t *ru) {
-  struct timespec wait;
-  wait.tv_sec=0;
-  wait.tv_nsec=5000000L;
-
-  if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) {
-    LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach);
-    exit_fun( "error locking mutex_rxtx" );
-    return(-1);
-  }
-
-  if (ru->proc.instance_cnt_prach==-1) {
-    ++ru->proc.instance_cnt_prach;
-    ru->proc.frame_prach    = ru->proc.frame_rx;
-    ru->proc.subframe_prach = ru->proc.tti_rx;
-
-    // DJP - think prach_procedures() is looking at gNB frame_prach
-    if (ru->gNB_list[0]) {
-      ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx;
-      ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx;
-    }
-
-    LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx);
-    // the thread can now be woken up
-    AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n");
-  } else LOG_W(PHY,"RU prach thread busy, skipping\n");
-
-  pthread_mutex_unlock( &ru->proc.mutex_prach );
-  return(0);
-}
-
 // this is for RU with local RF unit
 void fill_rf_config(RU_t *ru, char *rf_config_file) {
   int i;
@@ -1052,46 +799,94 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
   int mu = config->ssb_config.scs_common.value;
   int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value;
 
-  if (mu == NR_MU_0) { //or if LTE
-    if(N_RB == 100) {
+  if (mu == NR_MU_0) {
+    switch(N_RB) {
+    case 270:
+      if (fp->threequarter_fs) {
+        cfg->sample_rate=92.16e6;
+        cfg->samples_per_frame = 921600;
+        cfg->tx_bw = 50e6;
+        cfg->rx_bw = 50e6;
+      } else {
+        cfg->sample_rate=61.44e6;
+        cfg->samples_per_frame = 614400;
+        cfg->tx_bw = 50e6;
+        cfg->rx_bw = 50e6;
+      }
+    case 216:
+      if (fp->threequarter_fs) {
+        cfg->sample_rate=46.08e6;
+        cfg->samples_per_frame = 460800;
+        cfg->tx_bw = 40e6;
+        cfg->rx_bw = 40e6;
+      }
+      else {
+        cfg->sample_rate=61.44e6;
+        cfg->samples_per_frame = 614400;
+        cfg->tx_bw = 40e6;
+        cfg->rx_bw = 40e6;
+      }
+      break;
+    case 106:
       if (fp->threequarter_fs) {
         cfg->sample_rate=23.04e6;
         cfg->samples_per_frame = 230400;
-        cfg->tx_bw = 10e6;
-        cfg->rx_bw = 10e6;
-      } else {
+        cfg->tx_bw = 20e6;
+        cfg->rx_bw = 20e6;
+      }
+      else {
         cfg->sample_rate=30.72e6;
         cfg->samples_per_frame = 307200;
+        cfg->tx_bw = 20e6;
+        cfg->rx_bw = 20e6;
+      }
+      break;
+    case 52:
+      if (fp->threequarter_fs) {
+        cfg->sample_rate=11.52e6;
+        cfg->samples_per_frame = 115200;
         cfg->tx_bw = 10e6;
         cfg->rx_bw = 10e6;
       }
-    } else if(N_RB == 50) {
-      cfg->sample_rate=15.36e6;
-      cfg->samples_per_frame = 153600;
-      cfg->tx_bw = 5e6;
-      cfg->rx_bw = 5e6;
-    } else if (N_RB == 25) {
-      cfg->sample_rate=7.68e6;
-      cfg->samples_per_frame = 76800;
-      cfg->tx_bw = 2.5e6;
-      cfg->rx_bw = 2.5e6;
-    } else if (N_RB == 6) {
-      cfg->sample_rate=1.92e6;
-      cfg->samples_per_frame = 19200;
-      cfg->tx_bw = 1.5e6;
-      cfg->rx_bw = 1.5e6;
-    } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB);
+      else {
+        cfg->sample_rate=15.36e6;
+        cfg->samples_per_frame = 153600;
+        cfg->tx_bw = 10e6;
+        cfg->rx_bw = 10e6;
+      }
+    case 25:
+      if (fp->threequarter_fs) {
+        cfg->sample_rate=5.76e6;
+        cfg->samples_per_frame = 57600;
+        cfg->tx_bw = 5e6;
+        cfg->rx_bw = 5e6;
+      }
+      else {
+        cfg->sample_rate=7.68e6;
+        cfg->samples_per_frame = 76800;
+        cfg->tx_bw = 5e6;
+        cfg->rx_bw = 5e6;
+      }
+      break;
+    default:
+      AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
+    }
   } else if (mu == NR_MU_1) {
-    if(N_RB == 273) {
+    switch(N_RB) {
+    case 273:
       if (fp->threequarter_fs) {
-        AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n");
+        cfg->sample_rate=184.32e6;
+        cfg->samples_per_frame = 1843200;
+        cfg->tx_bw = 100e6;
+        cfg->rx_bw = 100e6;
       } else {
         cfg->sample_rate=122.88e6;
         cfg->samples_per_frame = 1228800;
         cfg->tx_bw = 100e6;
         cfg->rx_bw = 100e6;
       }
-    } else if(N_RB == 217) {
+      break;
+    case 217:
       if (fp->threequarter_fs) {
         cfg->sample_rate=92.16e6;
         cfg->samples_per_frame = 921600;
@@ -1103,7 +898,8 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
         cfg->tx_bw = 80e6;
         cfg->rx_bw = 80e6;
       }
-    } else if(N_RB == 106) {
+      break;
+    case 106:
       if (fp->threequarter_fs) {
         cfg->sample_rate=46.08e6;
         cfg->samples_per_frame = 460800;
@@ -1116,20 +912,68 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
         cfg->tx_bw = 40e6;
         cfg->rx_bw = 40e6;
       }
-    } else {
+      break;
+    case 51:
+      if (fp->threequarter_fs) {
+        cfg->sample_rate=23.04e6;
+        cfg->samples_per_frame = 230400;
+        cfg->tx_bw = 20e6;
+        cfg->rx_bw = 20e6;
+      }
+      else {
+        cfg->sample_rate=30.72e6;
+        cfg->samples_per_frame = 307200;
+        cfg->tx_bw = 20e6;
+        cfg->rx_bw = 20e6;
+      }
+      break;
+    case 24:
+      if (fp->threequarter_fs) {
+        cfg->sample_rate=11.52e6;
+        cfg->samples_per_frame = 115200;
+        cfg->tx_bw = 10e6;
+        cfg->rx_bw = 10e6;
+      }
+      else {
+        cfg->sample_rate=15.36e6;
+        cfg->samples_per_frame = 153600;
+        cfg->tx_bw = 10e6;
+        cfg->rx_bw = 10e6;
+      }
+      break;
+    default:
       AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
     }
   } else if (mu == NR_MU_3) {
-    if (N_RB == 66) {
-      cfg->sample_rate = 122.88e6;
-      cfg->samples_per_frame = 1228800;
-      cfg->tx_bw = 100e6;
-      cfg->rx_bw = 100e6;
-    } else if(N_RB == 32) {
-      cfg->sample_rate=61.44e6;
-      cfg->samples_per_frame = 614400;
-      cfg->tx_bw = 50e6;
-      cfg->rx_bw = 50e6;
+    switch(N_RB) {
+    case 66:
+      if (fp->threequarter_fs) {
+        cfg->sample_rate=184.32e6;
+        cfg->samples_per_frame = 1843200;
+        cfg->tx_bw = 100e6;
+        cfg->rx_bw = 100e6;
+      } else {
+        cfg->sample_rate = 122.88e6;
+        cfg->samples_per_frame = 1228800;
+        cfg->tx_bw = 100e6;
+        cfg->rx_bw = 100e6;
+      }
+      break;
+    case 32:
+      if (fp->threequarter_fs) {
+        cfg->sample_rate=92.16e6;
+        cfg->samples_per_frame = 921600;
+        cfg->tx_bw = 50e6;
+        cfg->rx_bw = 50e6;
+      } else {
+        cfg->sample_rate=61.44e6;
+        cfg->samples_per_frame = 614400;
+        cfg->tx_bw = 50e6;
+        cfg->rx_bw = 50e6;
+      }
+      break;
+    default:
+      AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
     }
   } else {
     AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu);
@@ -1176,60 +1020,52 @@ int setup_RU_buffers(RU_t *ru) {
   int i,j;
   int card,ant;
   //uint16_t N_TA_offset = 0;
-  NR_DL_FRAME_PARMS *frame_parms;
+  NR_DL_FRAME_PARMS *fp;
   nfapi_nr_config_request_scf_t *config = &ru->config;
 
   if (ru) {
-    frame_parms = ru->nr_frame_parms;
-    printf("setup_RU_buffers: frame_parms = %p\n",frame_parms);
+    fp = ru->nr_frame_parms;
+    printf("setup_RU_buffers: frame_parms = %p\n",fp);
   } else {
     printf("ru pointer is NULL\n");
     return(-1);
   }
+
   int mu = config->ssb_config.scs_common.value;
   int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value;
 
-
   if (config->cell_config.frame_duplex_type.value == TDD) {
     int N_TA_offset =  config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples  for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2
 
     double factor=1;
-
     switch (mu) {
-    case 0: //15 kHz scs
-      AssertFatal(N_TA_offset == 400,"scs_common 15kHz only for FR1\n");
-      if (N_RB <= 25) factor = .25;      // 7.68 Ms/s
-      else if (N_RB <=50) factor = .5;   // 15.36 Ms/s
-      else if (N_RB <=75) factor = 1.0;  // 30.72 Ms/s
-      else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s
-      else AssertFatal(1==0,"Too many PRBS for mu=0\n");
-      break;
-    case 1: //30 kHz sc
-      AssertFatal(N_TA_offset == 400,"scs_common 30kHz only for FR1\n");
-      if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s
-      else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s
-      break;
-    case 2: //60 kHz scs
-      AssertFatal(1==0,"scs_common should not be 60 kHz\n");
-      break;
-    case 3: //120 kHz scs
-      AssertFatal(N_TA_offset == 431,"scs_common 120kHz only for FR2\n");
-      break;
-    case 4: //240 kHz scs
-      AssertFatal(1==0,"scs_common should not be 60 kHz\n");
-      if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s
-      else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s
-      else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB);
-      break;
-
-      if      (N_RB == 100) ru->N_TA_offset = 624;
-      else if (N_RB == 50)  ru->N_TA_offset = 624/2;
-      else if (N_RB == 25)  ru->N_TA_offset = 624/4;
+      case 0: //15 kHz scs
+        AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n");
+        factor = fp->samples_per_subframe / 30720.0;
+        break;
+      case 1: //30 kHz sc
+        AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n");
+        factor = fp->samples_per_subframe / 30720.0;
+        break;
+      case 2: //60 kHz scs
+        AssertFatal(1==0, "scs_common should not be 60 kHz\n");
+        break;
+      case 3: //120 kHz scs
+        AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n");
+        factor = fp->samples_per_subframe / 61440.0;
+        break;
+      case 4: //240 kHz scs
+        AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n");
+        factor = fp->samples_per_subframe / 61440.0;
+        break;
+      default:
+        AssertFatal(1==0, "Invalid scs_common!\n");
     }
-    if (frame_parms->threequarter_fs == 1) factor = factor*.75;
+
     ru->N_TA_offset = (int)(N_TA_offset * factor);
-    LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d)\n",ru->idx,ru->N_TA_offset,factor,
-	  config->carrier_config.uplink_frequency.value, N_RB);
+
+    LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d, mu %d)\n",ru->idx,ru->N_TA_offset,factor,
+	  config->carrier_config.uplink_frequency.value, N_RB, mu);
   }
   else ru->N_TA_offset = 0;
 
@@ -1301,136 +1137,61 @@ void *ru_stats_thread(void *param) {
   return(NULL);
 }
 
-void *ru_thread_tx( void *param ) {
-  RU_t               *ru      = (RU_t *)param;
-  RU_proc_t          *proc    = &ru->proc;
-  NR_DL_FRAME_PARMS  *fp      = ru->nr_frame_parms;
-  PHY_VARS_gNB       *gNB;
-  gNB_L1_proc_t      *gNB_proc;
-  gNB_L1_rxtx_proc_t *L1_proc;
-  char               filename[40];
-  int                print_frame = 8;
-  int                i = 0;
-  int                ret;
-  
-
-  wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
-  printf( "ru_thread_tx ready\n");
-
-  while (!oai_exit) {
+void ru_tx_func(void *param) {
 
-    LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n");
-    // wait until eNBs are finished subframe RX n and TX n+4
-
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 );
-    wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 );
-
-    ret = pthread_mutex_lock(&proc->mutex_gNBs);
-    AssertFatal(ret == 0,"mutex_lock return %d\n",ret);
-    int frame_tx=proc->frame_tx;
-    int tti_tx  =proc->tti_tx;
-    uint64_t timestamp_tx = proc->timestamp_tx;
-
-    ret = pthread_mutex_unlock(&proc->mutex_gNBs);
-    AssertFatal(ret == 0,"mutex_lock returns %d\n",ret);
-
-    if (oai_exit) break;
-
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx );
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx );
-
-    // do TX front-end processing if needed (precoding and/or IDFTs)
-    if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx);
+  processingData_RU_t *info = (processingData_RU_t *) param;
+  RU_t *ru = info->ru;
+  NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
+  int frame_tx = info->frame_tx;
+  int slot_tx = info->slot_tx;
+  int print_frame = 8;
+  char filename[40];
 
-    // do OFDM with/without TX front-end processing  if needed
-    if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx);
+  // do TX front-end processing if needed (precoding and/or IDFTs)
+  if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,slot_tx);
 
-    if(!emulate_rf) {
-      // do outgoing fronthaul (south) if needed
-      if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx);
+  // do OFDM with/without TX front-end processing  if needed
+  if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,slot_tx);
 
-      if (ru->fh_north_out) ru->fh_north_out(ru);
-    } else {
-      if(proc->frame_tx == print_frame) {
-        for (i=0; i<ru->nb_tx; i++) {
+  if(!emulate_rf) {
+    // do outgoing fronthaul (south) if needed
+    if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,slot_tx,info->timestamp_tx);
 
-          if(proc->tti_tx == 0) {
-            sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_tx);
-            LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
+    if (ru->fh_north_out) ru->fh_north_out(ru);
+  } else {
+    if(frame_tx == print_frame) {
+      for (int i=0; i<ru->nb_tx; i++) {
 
-            sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
-            LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
+        if(slot_tx == 0) {
+          sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, slot_tx);
+          LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
 
-            sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
-            LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
-          }
+          sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, slot_tx);
+          LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
 
-          if(proc->tti_tx == 9) {
-            sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
-            LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1);
-            sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame);
-            FILE *output_fd = fopen(filename,"w");
-
-            if (output_fd) {
-              fwrite(&ru->common.txdata[i][0],
-                     sizeof(int32_t),
-                     fp->samples_per_frame,
-                     output_fd);
-              fclose(output_fd);
-            } else {
-              LOG_E(PHY,"Cannot write to file %s\n",filename);
-            }
-          }//if(proc->tti_tx == 9)
-        }//for (i=0; i<ru->nb_tx; i++)
-      }//if(proc->frame_tx == print_frame)
-    }//else  emulate_rf
-
-    release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs);
-
-    for(i = 0; i<ru->num_gNB; i++) {
-      gNB       = ru->gNB_list[i];
-      gNB_proc  = &gNB->proc;
-      L1_proc   = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc;
-      ret = pthread_mutex_lock(&gNB_proc->mutex_RU_tx);
-      AssertFatal(ret == 0,"mutex_lock returns %d\n",ret);
-
-      for (int j=0; j<gNB->num_RU; j++) {
-        if (ru == gNB->RU_list[j]) {
-          if ((gNB_proc->RU_mask_tx&(1<<j)) > 0)
-            LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n",
-                  gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx);
-
-          gNB_proc->RU_mask_tx |= (1<<j);
+          sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, slot_tx);
+          LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
         }
-      }
-
-      if (gNB_proc->RU_mask_tx != (1<<gNB->num_RU)-1) {  // not all RUs have provided their information so return
-        ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx);
-        AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
-      } else { // all RUs TX are finished so send the ready signal to gNB processing
-        gNB_proc->RU_mask_tx = 0;
-        ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx);
-        AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
-
-        ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx);
-        AssertFatal(ret == 0,"mutex_lock returns %d\n",ret);
-        // the thread can now be woken up
-        if (L1_proc->instance_cnt_RUs == -1) {
-          L1_proc->instance_cnt_RUs = 0;
-          VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
-          AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
-                      "ERROR pthread_cond_signal for gNB_L1_thread\n");
-        } //else AssertFatal(1==0,"gNB TX thread is not ready\n");
-        ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx);
-        AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
-      }
-    }
-  }
 
-  release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx");
-  return 0;
+        if(slot_tx == 9) {
+          sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
+          LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1);
+          sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame);
+          FILE *output_fd = fopen(filename,"w");
+
+          if (output_fd) {
+            fwrite(&ru->common.txdata[i][0],
+                   sizeof(int32_t),
+                   fp->samples_per_frame,
+                   output_fd);
+            fclose(output_fd);
+          } else {
+            LOG_E(PHY,"Cannot write to file %s\n",filename);
+          }
+        }//if(slot_tx == 9)
+      }//for (i=0; i<ru->nb_tx; i++)
+    }//if(frame_tx == print_frame)
+  }//else  emulate_rf
 }
 
 void *ru_thread( void *param ) {
@@ -1438,12 +1199,11 @@ void *ru_thread( void *param ) {
   RU_t               *ru      = (RU_t *)param;
   RU_proc_t          *proc    = &ru->proc;
   NR_DL_FRAME_PARMS  *fp      = ru->nr_frame_parms;
+  PHY_VARS_gNB       *gNB     = RC.gNB[0];
   int                ret;
   int                slot     = fp->slots_per_frame-1;
   int                frame    = 1023;
-  char               filename[40], threadname[40];
-  int                print_frame = 8;
-  int                i = 0;
+  char               threadname[40];
   int                aa;
 
   nfapi_nr_config_request_scf_t *cfg = &ru->config;
@@ -1503,6 +1263,15 @@ void *ru_thread( void *param ) {
   pthread_mutex_unlock(&RC.ru_mutex);
   wait_sync("ru_thread");
 
+  notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func);
+  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1_tx,tx_func);
+  notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func);
+  processingData_L1_t *syncMsg;
+  notifiedFIFO_elt_t *res; 
+  pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning
+  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
+  pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning
+
   if(!emulate_rf) {
     // Start RF device if any
     if (ru->start_rf) {
@@ -1511,19 +1280,6 @@ void *ru_thread( void *param ) {
       else LOG_I(PHY,"RU %d rf device ready\n",ru->idx);
     } else LOG_I(PHY,"RU %d no rf device\n",ru->idx);
 
-    // if an asnych_rxtx thread exists
-    // wakeup the thread because the devices are ready at this point
-
-    if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) {
-      pthread_mutex_lock(&proc->mutex_asynch_rxtx);
-      proc->instance_cnt_asynch_rxtx=0;
-      pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
-      pthread_cond_signal(&proc->cond_asynch_rxtx);
-    } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx);
-
-    // if this is a slave RRU, try to synchronize on the DL frequency
-    if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru);
-
     // start trx write thread
     if(usrp_tx_thread == 1){
       if (ru->start_write_thread){
@@ -1537,11 +1293,6 @@ void *ru_thread( void *param ) {
     }
   }
 
-  pthread_mutex_lock(&proc->mutex_FH1);
-  proc->instance_cnt_FH1 = 0;
-  pthread_mutex_unlock(&proc->mutex_FH1);
-  pthread_cond_signal(&proc->cond_FH1);
-
   // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
   struct timespec slot_start;
 	clock_gettime(CLOCK_MONOTONIC, &slot_start);
@@ -1585,24 +1336,17 @@ void *ru_thread( void *param ) {
     if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot);
     else AssertFatal(1==0, "No fronthaul interface at south port");
 
+    proc->timestamp_tx = proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe);
+    proc->frame_tx     = (proc->tti_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
+    proc->tti_tx      = (proc->tti_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame;
+
     LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n",
           frame,slot,
           proc->frame_rx,proc->tti_rx,
           proc->frame_tx,proc->tti_tx,
           RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx,
-	        RC.gNB[0]->proc.frame_tx);
-    /*
-          LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n",
-              ru->do_prach,
-              is_prach_subframe(fp, proc->frame_rx, proc->tti_rx),
-              proc->frame_rx,proc->tti_rx);
-
-        if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) {
-          wakeup_prach_ru(ru);
-        }*/
+	  RC.gNB[0]->proc.frame_tx);
 
-    // adjust for timing offset between RU
-    //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx);
     if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023;
 
     // do RX front-end processing (frequency-shift, dft) if needed
@@ -1615,7 +1359,6 @@ void *ru_thread( void *param ) {
     if (slot == 8)
       slot_type = NR_UPLINK_SLOT;
     if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
-    //if (proc->tti_rx==8) {
 
       if (ru->feprx) {
       ru->feprx(ru,proc->tti_rx);
@@ -1665,50 +1408,17 @@ void *ru_thread( void *param ) {
     }
 
     // At this point, all information for subframe has been received on FH interface
+    res = pullTpool(gNB->resp_L1, gNB->threadPool);
+    syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
+    syncMsg->gNB = gNB;
+    syncMsg->frame_rx = proc->frame_rx;
+    syncMsg->slot_rx = proc->tti_rx;
+    syncMsg->frame_tx = proc->frame_tx;
+    syncMsg->slot_tx = proc->tti_tx;
+    syncMsg->timestamp_tx = proc->timestamp_tx;
+    res->key = proc->tti_rx;
+    pushTpool(gNB->threadPool, res);
 
-    // wakeup all gNB processes waiting for this RU
-    if (ru->num_gNB>0) wakeup_gNB_L1s(ru);
-
-    if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) {
-      // do TX front-end processing if needed (precoding and/or IDFTs)
-      if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx);
-
-      // do OFDM with/without TX front-end processing  if needed
-      if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx);
-
-      if(!emulate_rf) {
-        // do outgoing fronthaul (south) if needed
-        if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx);
-
-        if (ru->fh_north_out) ru->fh_north_out(ru);
-      } else {
-        if(proc->frame_tx == print_frame) {
-          for (i=0; i<ru->nb_tx; i++) {
-            sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
-            LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1);
-
-            if(proc->tti_tx == 9) {
-              sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
-              LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1);
-              sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame);
-              FILE *output_fd = fopen(filename,"w");
-
-              if (output_fd) {
-                fwrite(&ru->common.txdata[i][0],
-                       sizeof(int32_t),
-                       fp->samples_per_frame,
-                       output_fd);
-                fclose(output_fd);
-              } else {
-                LOG_E(PHY,"Cannot write to file %s\n",filename);
-              }
-            }//if(proc->tti_tx == 9)
-          }//for (i=0; i<ru->nb_tx; i++)
-        }//if(proc->frame_tx == print_frame)
-      }//else  emulate_rf
-
-      proc->emulate_rf_busy = 0;
-    }//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD)
   }
 
   printf( "Exiting ru_thread \n");
@@ -1719,85 +1429,13 @@ void *ru_thread( void *param ) {
     else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx);
   }
 
+  delNotifiedFIFO_elt(msg);
+  delNotifiedFIFO_elt(msgL1Tx);
+  delNotifiedFIFO_elt(msgRUTx);
+
   ru_thread_status = 0;
   return &ru_thread_status;
 }
-/*
-// This thread run the initial synchronization like a UE
-void *ru_thread_synch(void *arg) {
-
-  RU_t *ru = (RU_t*)arg;
-  NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms;
-  int32_t sync_pos,sync_pos2;
-  uint32_t peak_val;
-  uint32_t sync_corr[307200] __attribute__((aligned(32)));
-  static int ru_thread_synch_status;
-
-
-
-  wait_sync("ru_thread_synch");
-
-  // initialize variables for PSS detection
-  lte_sync_time_init(ru->nr_frame_parms);
-
-  while (!oai_exit) {
-
-    // wait to be woken up
-    if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break;
-
-    // if we're not in synch, then run initial synch
-    if (ru->in_synch == 0) {
-      // run intial synch like UE
-      LOG_I(PHY,"Running initial synchronization\n");
-
-      sync_pos = lte_sync_time_gNB(ru->common.rxdata,
-           fp,
-           fp->samples_per_subframe*5,
-           &peak_val,
-           sync_corr);
-      LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val);
-
-      if (sync_pos >= 0) {
-  if (sync_pos >= fp->nb_prefix_samples)
-    sync_pos2 = sync_pos - fp->nb_prefix_samples;
-  else
-    sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples;
-
-  if (fp->frame_type == FDD) {
-
-    // PSS is hypothesized in last symbol of first slot in Frame
-    int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples;
-
-    if (sync_pos2 >= sync_pos_slot)
-      ru->rx_offset = sync_pos2 - sync_pos_slot;
-    else
-      ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot;
-  }
-  else {
-
-  }
-
-  LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset);
-
-  if ((peak_val > 300000) && (sync_pos > 0)) {
-  //      if (sync_pos++ > 3) {
-  write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2);
-  write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1);
-  exit(-1);
-  }
-
-  ru->in_synch=1;
-      }
-    }
-
-    if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break;
-  } // oai_exit
-
-  ru_thread_synch_status = 0;
-  return &ru_thread_synch_status;
-
-}
-*/
 
 int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) {
   return(ru->ifdevice.trx_start_func(&ru->ifdevice));
@@ -1819,17 +1457,10 @@ int start_write_thread(RU_t *ru) {
 void init_RU_proc(RU_t *ru) {
   int i=0;
   RU_proc_t *proc;
-  char name[100];
   LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
   proc = &ru->proc;
   memset((void *)proc,0,sizeof(RU_proc_t));
   proc->ru = ru;
-  proc->instance_cnt_prach       = -1;
-  proc->instance_cnt_synch       = -1;
-  proc->instance_cnt_FH          = -1;
-  proc->instance_cnt_FH1         = -1;
-  proc->instance_cnt_gNBs        = -1;
-  proc->instance_cnt_asynch_rxtx = -1;
   proc->instance_cnt_emulateRF   = -1;
   proc->first_rx                 = 1;
   proc->first_tx                 = 1;
@@ -1840,44 +1471,13 @@ void init_RU_proc(RU_t *ru) {
 
   for (i=0; i<10; i++) proc->symbol_mask[i]=0;
 
-  pthread_mutex_init( &proc->mutex_prach, NULL);
-  pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
-  pthread_mutex_init( &proc->mutex_synch,NULL);
-  pthread_mutex_init( &proc->mutex_FH,NULL);
-  pthread_mutex_init( &proc->mutex_FH1,NULL);
   pthread_mutex_init( &proc->mutex_emulateRF,NULL);
-  pthread_mutex_init( &proc->mutex_gNBs, NULL);
-  pthread_cond_init( &proc->cond_prach, NULL);
-  pthread_cond_init( &proc->cond_FH, NULL);
-  pthread_cond_init( &proc->cond_FH1, NULL);
   pthread_cond_init( &proc->cond_emulateRF, NULL);
-  pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
-  pthread_cond_init( &proc->cond_synch,NULL);
-  pthread_cond_init( &proc->cond_gNBs, NULL);
   threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX );
 
-  if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)
-    threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT );
-
   if(emulate_rf)
     threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT );
 
-  if (ru->function == NGFI_RRU_IF4p5) {
-    threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT );
-    ///tmp deactivation of synch thread
-    //    if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru);
-
-    if ((ru->if_timing == synch_to_other) ||
-        (ru->function == NGFI_RRU_IF5) ||
-        (ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT );
-
-    snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx );
-    pthread_setname_np( proc->pthread_FH, name );
-  } else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF
-    LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__);
-    threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT );
-  }
-
   if (get_thread_worker_conf() == WORKER_ENABLE) {
     if (ru->feprx) nr_init_feprx_thread(ru);
 
@@ -1890,46 +1490,9 @@ void init_RU_proc(RU_t *ru) {
 void kill_NR_RU_proc(int inst) {
   RU_t *ru = RC.ru[inst];
   RU_proc_t *proc = &ru->proc;
-  pthread_mutex_lock(&proc->mutex_FH);
-  proc->instance_cnt_FH = 0;
-  pthread_mutex_unlock(&proc->mutex_FH);
-  pthread_cond_signal(&proc->cond_FH);
-  pthread_mutex_lock(&proc->mutex_prach);
-  proc->instance_cnt_prach = 0;
-  pthread_mutex_unlock(&proc->mutex_prach);
-  pthread_cond_signal(&proc->cond_prach);
-  pthread_mutex_lock(&proc->mutex_synch);
-  proc->instance_cnt_synch = 0;
-  pthread_mutex_unlock(&proc->mutex_synch);
-  pthread_cond_signal(&proc->cond_synch);
-  pthread_mutex_lock(&proc->mutex_gNBs);
-  proc->instance_cnt_gNBs = 0;
-  pthread_mutex_unlock(&proc->mutex_gNBs);
-  pthread_cond_signal(&proc->cond_gNBs);
-  pthread_mutex_lock(&proc->mutex_asynch_rxtx);
-  proc->instance_cnt_asynch_rxtx = 0;
-  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
-  pthread_cond_signal(&proc->cond_asynch_rxtx);
   LOG_D(PHY, "Joining pthread_FH\n");
   pthread_join(proc->pthread_FH, NULL);
 
-  if (ru->function == NGFI_RRU_IF4p5) {
-    LOG_D(PHY, "Joining pthread_prach\n");
-    pthread_join(proc->pthread_prach, NULL);
-
-    if (ru->is_slave) {
-      LOG_D(PHY, "Joining pthread_\n");
-      pthread_join(proc->pthread_synch, NULL);
-    }
-
-    if ((ru->if_timing == synch_to_other) ||
-        (ru->function == NGFI_RRU_IF5) ||
-        (ru->function == NGFI_RRU_IF4p5)) {
-      LOG_D(PHY, "Joining pthread_asynch_rxtx\n");
-      pthread_join(proc->pthread_asynch_rxtx, NULL);
-    }
-  }
-
   if (get_nprocs() >= 2) {
     if (ru->feprx) {
       pthread_mutex_lock(&proc->mutex_fep);
@@ -1958,17 +1521,6 @@ void kill_NR_RU_proc(int inst) {
     LOG_D(PHY, "Joining ru_stats_thread\n");
     pthread_join(ru->ru_stats_thread, NULL);
   }
-
-  pthread_mutex_destroy(&proc->mutex_prach);
-  pthread_mutex_destroy(&proc->mutex_asynch_rxtx);
-  pthread_mutex_destroy(&proc->mutex_synch);
-  pthread_mutex_destroy(&proc->mutex_FH);
-  pthread_mutex_destroy(&proc->mutex_gNBs);
-  pthread_cond_destroy(&proc->cond_prach);
-  pthread_cond_destroy(&proc->cond_FH);
-  pthread_cond_destroy(&proc->cond_asynch_rxtx);
-  pthread_cond_destroy(&proc->cond_synch);
-  pthread_cond_destroy(&proc->cond_gNBs);
 }
 
 int check_capabilities(RU_t *ru,RRU_capabilities_t *cap)
diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c
index 924c32b8a7cddc7d09f06b68f811b1b315ad6f65..69fc3c554dd1df290d2fb0e02528ace55c3e3df3 100644
--- a/executables/nr-softmodem.c
+++ b/executables/nr-softmodem.c
@@ -136,9 +136,6 @@ double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
 
 double rx_gain_off = 0.0;
 
-double sample_rate=30.72e6;
-double bw = 10.0e6;
-
 static int tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
 
 
@@ -476,93 +473,6 @@ void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs],
   }
 }
 
-/*
-void init_openair0(void) {
-
-  int card;
-  int i;
-
-  for (card=0; card<MAX_CARDS; card++) {
-
-    openair0_cfg[card].mmapped_dma=mmapped_dma;
-    openair0_cfg[card].configFilename = NULL;
-
-    if(config[0]->rf_config.dl_carrier_bandwidth.value == 100) {
-      if (frame_parms[0]->threequarter_fs) {
-  openair0_cfg[card].sample_rate=23.04e6;
-  openair0_cfg[card].samples_per_frame = 230400;
-  openair0_cfg[card].tx_bw = 10e6;
-  openair0_cfg[card].rx_bw = 10e6;
-      } else {
-  openair0_cfg[card].sample_rate=30.72e6;
-  openair0_cfg[card].samples_per_frame = 307200;
-  openair0_cfg[card].tx_bw = 10e6;
-  openair0_cfg[card].rx_bw = 10e6;
-      }
-    } else if(config[0]->rf_config.dl_carrier_bandwidth.value == 50) {
-      openair0_cfg[card].sample_rate=15.36e6;
-      openair0_cfg[card].samples_per_frame = 153600;
-      openair0_cfg[card].tx_bw = 5e6;
-      openair0_cfg[card].rx_bw = 5e6;
-    } else if (config[0]->rf_config.dl_carrier_bandwidth.value == 25) {
-      openair0_cfg[card].sample_rate=7.68e6;
-      openair0_cfg[card].samples_per_frame = 76800;
-      openair0_cfg[card].tx_bw = 2.5e6;
-      openair0_cfg[card].rx_bw = 2.5e6;
-    } else if (config[0]->rf_config.dl_carrier_bandwidth.value == 6) {
-      openair0_cfg[card].sample_rate=1.92e6;
-      openair0_cfg[card].samples_per_frame = 19200;
-      openair0_cfg[card].tx_bw = 1.5e6;
-      openair0_cfg[card].rx_bw = 1.5e6;
-    }
-
-
-    if (config[0]->subframe_config.duplex_mode.value==TDD)
-      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
-    else //FDD
-      openair0_cfg[card].duplex_mode = duplex_mode_FDD;
-
-    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
-     RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value,
-     RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value );
-    openair0_cfg[card].Mod_id = 0;
-
-    openair0_cfg[card].num_rb_dl=config[0]->rf_config.dl_carrier_bandwidth.value;
-
-    openair0_cfg[card].clock_source = clock_source;
-
-
-    openair0_cfg[card].tx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value );
-    openair0_cfg[card].rx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value );
-
-    for (i=0; i<4; i++) {
-
-      if (i<openair0_cfg[card].tx_num_channels)
-  openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i] ;
-      else
-  openair0_cfg[card].tx_freq[i]=0.0;
-
-      if (i<openair0_cfg[card].rx_num_channels)
-  openair0_cfg[card].rx_freq[i] =downlink_frequency[0][i] + uplink_frequency_offset[0][i] ;
-      else
-  openair0_cfg[card].rx_freq[i]=0.0;
-
-      openair0_cfg[card].autocal[i] = 1;
-      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
-      openair0_cfg[card].rx_gain[i] = RC.gNB[0]->rx_total_gain_dB;
-
-
-      openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
-      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
-       card,i, openair0_cfg[card].tx_gain[i],
-       openair0_cfg[card].rx_gain[i],
-       openair0_cfg[card].tx_freq[i],
-       openair0_cfg[card].rx_freq[i]);
-    }
-  } // for loop on cards
-}
-*/
-
 void wait_RUs(void) {
   LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
   // wait for all RUs to be configured over fronthaul
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index 6be23582b18983c76ef2bc954bb8dd6eb01e1000..f175ab49807255b91b033b2c7184a4829e6a1c17 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -237,43 +237,6 @@ static void UE_synch(void *arg) {
               openair0_cfg[UE->rf_map.card].rx_freq[0],
               openair0_cfg[UE->rf_map.card].tx_freq[0]);
 
-        // reconfigure for potentially different bandwidth
-        switch(UE->frame_parms.N_RB_DL) {
-          case 6:
-            openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
-            openair0_cfg[UE->rf_map.card].rx_bw          =.96e6;
-            openair0_cfg[UE->rf_map.card].tx_bw          =.96e6;
-            //            openair0_cfg[0].rx_gain[0] -= 12;
-            break;
-
-          case 25:
-            openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
-            openair0_cfg[UE->rf_map.card].rx_bw          =2.5e6;
-            openair0_cfg[UE->rf_map.card].tx_bw          =2.5e6;
-            //            openair0_cfg[0].rx_gain[0] -= 6;
-            break;
-
-          case 50:
-            openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
-            openair0_cfg[UE->rf_map.card].rx_bw          =5.0e6;
-            openair0_cfg[UE->rf_map.card].tx_bw          =5.0e6;
-            //            openair0_cfg[0].rx_gain[0] -= 3;
-            break;
-
-          case 100:
-            openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
-            openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
-            openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
-            //            openair0_cfg[0].rx_gain[0] -= 0;
-            break;
-
-          case 66:
-            openair0_cfg[UE->rf_map.card].sample_rate=122.88e6;
-            openair0_cfg[UE->rf_map.card].rx_bw=100.e6;
-            openair0_cfg[UE->rf_map.card].tx_bw=100.e6;
-            break;
-        }
-
         if (UE->mode != loop_through_memory) {
           UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
           //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
@@ -703,16 +666,23 @@ void *UE_thread(void *arg) {
 
     int flags = 0;
     int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - RX_NB_TH;
-    uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
-    uint8_t num_UL_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots +
-                           (mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0);
-    uint8_t first_tx_slot = tdd_period - num_UL_slots;
-    if (slot_tx_usrp%tdd_period==first_tx_slot)
-      flags=2;
-    else     if (slot_tx_usrp%tdd_period==first_tx_slot+num_UL_slots-1)
-      flags = 3;
-    else     if (slot_tx_usrp%tdd_period>first_tx_slot)
+
+    if (openair0_cfg[0].duplex_mode == duplex_mode_TDD) {
+
+      uint8_t    tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
+      int   nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
+      uint8_t  num_UL_slots = nrofUplinkSlots + (nrofUplinkSlots != 0);
+      uint8_t first_tx_slot = tdd_period - num_UL_slots;
+
+      if (slot_tx_usrp % tdd_period == first_tx_slot)
+        flags = 2;
+      else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1)
+        flags = 3;
+      else if (slot_tx_usrp % tdd_period > first_tx_slot)
+        flags = 1;
+    } else {
       flags = 1;
+    }
 
     if (flags || IS_SOFTMODEM_RFSIM)
       AssertFatal( writeBlockSize ==
diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c
index 5d651344d608e606bb6d7d76512c9fe730edd99d..2854457eeec7258bd02509901cf5f72773d49269 100644
--- a/executables/nr-uesoftmodem.c
+++ b/executables/nr-uesoftmodem.c
@@ -145,7 +145,6 @@ int          chain_offset = 0;
 int           card_offset = 0;
 uint64_t num_missed_slots = 0; // counter for the number of missed slots
 int     transmission_mode = 1;
-int            numerology = 0;
 int        usrp_tx_thread = 0;
 int           oaisim_flag = 0;
 int            emulate_rf = 0;
@@ -316,92 +315,10 @@ void init_openair0(void) {
 
   for (card=0; card<MAX_CARDS; card++) {
     uint64_t dl_carrier, ul_carrier;
-    openair0_cfg[card].configFilename = NULL;
-    openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs;
-    numerology = frame_parms->numerology_index;
-
-    if(frame_parms->N_RB_DL == 66) {
-      if (numerology==3) {
-          openair0_cfg[card].sample_rate=122.88e6;
-          openair0_cfg[card].samples_per_frame = 1228800;
-        } else {
-          LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n");
-          exit(-1);
-        }
-    }else if(frame_parms->N_RB_DL == 32) {
-      if (numerology==3) {
-          openair0_cfg[card].sample_rate=61.44e6;
-          openair0_cfg[card].samples_per_frame = 614400;
-        } else {
-          LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n");
-          exit(-1);
-        }
-    }else if(frame_parms->N_RB_DL == 217) {
-      if (numerology==1) {
-        if (frame_parms->threequarter_fs) {
-          openair0_cfg[card].sample_rate=92.16e6;
-          openair0_cfg[card].samples_per_frame = 921600;
-        }
-        else {
-          openair0_cfg[card].sample_rate=122.88e6;
-          openair0_cfg[card].samples_per_frame = 1228800;
-        }
-      } else {
-        LOG_E(PHY,"Unsupported numerology!\n");
-        exit(-1);
-      }
-    } else if(frame_parms->N_RB_DL == 273) {
-      if (numerology==1) {
-        if (frame_parms->threequarter_fs) {
-          AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n");
-        }
-        else {
-          openair0_cfg[card].sample_rate=122.88e6;
-          openair0_cfg[card].samples_per_frame = 1228800;
-        }
-      } else {
-        LOG_E(PHY,"Unsupported numerology!\n");
-        exit(-1);
-      }
-    } else if(frame_parms->N_RB_DL == 106) {
-      if (numerology==0) {
-        if (frame_parms->threequarter_fs) {
-          openair0_cfg[card].sample_rate=23.04e6;
-          openair0_cfg[card].samples_per_frame = 230400;
-        } else {
-          openair0_cfg[card].sample_rate=30.72e6;
-          openair0_cfg[card].samples_per_frame = 307200;
-        }
-      } else if (numerology==1) {
-        if (frame_parms->threequarter_fs) {
-          openair0_cfg[card].sample_rate=46.08e6;
-          openair0_cfg[card].samples_per_frame = 460800;
-	}
-	else {
-          openair0_cfg[card].sample_rate=61.44e6;
-          openair0_cfg[card].samples_per_frame = 614400;
-        }
-      } else if (numerology==2) {
-        openair0_cfg[card].sample_rate=122.88e6;
-        openair0_cfg[card].samples_per_frame = 1228800;
-      } else {
-        LOG_E(PHY,"Unsupported numerology!\n");
-        exit(-1);
-      }
-    } else if(frame_parms->N_RB_DL == 50) {
-      openair0_cfg[card].sample_rate=15.36e6;
-      openair0_cfg[card].samples_per_frame = 153600;
-    } else if (frame_parms->N_RB_DL == 25) {
-      openair0_cfg[card].sample_rate=7.68e6;
-      openair0_cfg[card].samples_per_frame = 76800;
-    } else if (frame_parms->N_RB_DL == 6) {
-      openair0_cfg[card].sample_rate=1.92e6;
-      openair0_cfg[card].samples_per_frame = 19200;
-    }
-    else {
-      LOG_E(PHY,"Unknown NB_RB %d!\n",frame_parms->N_RB_DL);
-      exit(-1);
-    }
+    openair0_cfg[card].configFilename    = NULL;
+    openair0_cfg[card].threequarter_fs   = frame_parms->threequarter_fs;
+    openair0_cfg[card].sample_rate       = frame_parms->samples_per_subframe * 1e3;
+    openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame;
 
     if (frame_parms->frame_type==TDD)
       openair0_cfg[card].duplex_mode = duplex_mode_TDD;
@@ -415,8 +332,9 @@ void init_openair0(void) {
     openair0_cfg[card].tx_num_channels = min(2, frame_parms->nb_antennas_tx);
     openair0_cfg[card].rx_num_channels = min(2, frame_parms->nb_antennas_rx);
 
-    LOG_I(PHY, "HW: Configuring card %d, tx/rx num_channels %d/%d, duplex_mode %s\n",
+    LOG_I(PHY, "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n",
       card,
+      openair0_cfg[card].sample_rate,
       openair0_cfg[card].tx_num_channels,
       openair0_cfg[card].rx_num_channels,
       duplex_mode[openair0_cfg[card].duplex_mode]);
@@ -531,7 +449,8 @@ int main( int argc, char **argv ) {
     fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;
 
     nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]);
-    init_symbol_rotation(&UE[CC_id]->frame_parms, UE[CC_id]->frame_parms.dl_CarrierFreq);
+
+    init_symbol_rotation(&UE[CC_id]->frame_parms);
     init_nr_ue_vars(UE[CC_id], 0, abstraction_flag);
 
     #ifdef FR2_TEST
diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h
index 60a761c732a8bdbb3ad710516285ac6e9dec1d8b..7a7be1de966909c23d3f2e61b6a9a9712b954d31 100644
--- a/executables/softmodem-common.h
+++ b/executables/softmodem-common.h
@@ -244,6 +244,13 @@ extern char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr);
 extern void set_softmodem_sighandler(void);
 extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
 extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
+extern uint16_t sl_ahead;
+extern uint16_t sf_ahead;
+extern volatile int  oai_exit;
+
+void tx_func(void *param);
+void rx_func(void *param);
+void ru_tx_func(void *param);
 extern uint8_t nfapi_mode;
 #ifdef __cplusplus
 }
diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c
index 92057186e26cd1b70c367a03895dfaefb8debe87..e744fcbb24a901d93781971dfb8f7e1c183a2bf4 100644
--- a/nfapi/oai_integration/nfapi_pnf.c
+++ b/nfapi/oai_integration/nfapi_pnf.c
@@ -2406,36 +2406,3 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) {
   //free(ind.rx_indication_body.rx_pdu_list);
   return retval;
 }
-
-//NR UPLINK INDICATION
-
-int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) {
-  ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
-  ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION;
-  return nfapi_pnf_p7_nr_rx_data_ind(p7_config_g, ind);
-}
-
-int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) {
-  ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
-  ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION;
-  return nfapi_pnf_p7_nr_crc_ind(p7_config_g, ind);
-}
-
-int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) {
-  ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
-  ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION;
-  return nfapi_pnf_p7_nr_srs_ind(p7_config_g, ind);
-}
-
-int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) {
-  ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
-  ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION;
-  return nfapi_pnf_p7_nr_uci_ind(p7_config_g, ind);
-}
-
-int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) {
-  ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
-  ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION;
-  return nfapi_pnf_p7_nr_rach_ind(p7_config_g, ind);
-}
-
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 85f1efa3f49c0b6bc4a1c21ee645e0edcfa2c86a..bc5e7af45fb98e4c50c938457fed1afec386e7f0 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
@@ -1516,11 +1516,10 @@ typedef struct
 
 typedef struct
 {
-  nfapi_p7_message_header_t header;
   uint16_t sfn;
   uint16_t slot;
   uint16_t number_of_pdus;
-  nfapi_nr_rx_data_pdu_t *pdu_list; //changed from pointer to struct - gokul
+  nfapi_nr_rx_data_pdu_t* pdu_list;
 
 } nfapi_nr_rx_data_indication_t;
 
@@ -1543,7 +1542,6 @@ typedef struct
 
 typedef struct
 {
-  nfapi_p7_message_header_t header;
   uint16_t sfn;
   uint16_t slot;
   uint16_t number_crcs;
@@ -1681,7 +1679,6 @@ typedef struct
 
 typedef struct
 {
-  nfapi_p7_message_header_t header;
   uint16_t sfn;
   uint16_t slot;
   uint16_t num_ucis;
@@ -1718,7 +1715,6 @@ typedef struct
 
 typedef struct
 {
-  nfapi_p7_message_header_t header;
   uint16_t sfn;
   uint16_t slot;
   uint8_t number_of_pdus;
@@ -1751,7 +1747,6 @@ typedef struct{
 
 typedef struct
 {
-  nfapi_p7_message_header_t header;
   uint16_t sfn;
   uint16_t slot;
   uint8_t number_of_pdus;
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
index a97e4ccaaf60d82349913726654fc4c702ebdba6..5f8e6b52b4f727b192c5f5b624be55a1ee5733dc 100755
--- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
@@ -307,7 +307,6 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac
 
 static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
 {
-	printf("packing pdsch pdu. \n");
 	nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv;
 
 	// TODO: resolve the packaging of array (currently sending a single element)
@@ -3354,308 +3353,6 @@ static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_
 }
 
 
-//NR UPLINK indication function packing
-
-//RX DATA INDICATION 
-
-static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
-{
-	nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv;
-
-	if(!(push32(value->handle, ppWritePackedMsg, end) &&
-	 	 push16(value->rnti, ppWritePackedMsg, end) &&
-		 push8(value->harq_id, ppWritePackedMsg, end) &&
-		 push16(value->pdu_length, ppWritePackedMsg, end) &&
-		 push8(value->ul_cqi, ppWritePackedMsg, end) &&
-		 push16(value->timing_advance, ppWritePackedMsg, end) && 
-		 push16(value->rssi, ppWritePackedMsg, end) 
-		 ))
-		  return 0;
-
-	return 1;
-}
-
-
-static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
-{
-	nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg;
-
-	if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end)
-		))
-			return 0;
-
-	for(int i=0; i<pNfapiMsg->number_of_pdus;i++)	
-	{
-		if(!pack_nr_rx_data_indication_body(pNfapiMsg->pdu_list,ppWritePackedMsg,end))
-		return 0;
-	}
-
-return 1;
-}
-
-//NR CRC INDICATION
-
-static uint8_t pack_nr_crc_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
-{
-	nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv;
-
-	if(!(push32(value->handle, ppWritePackedMsg, end) &&
-	 	 push16(value->rnti, ppWritePackedMsg, end) &&
-		 push8(value->harq_id, ppWritePackedMsg, end) &&
-		 push8(value->tb_crc_status, ppWritePackedMsg, end) &&
-		 push16(value->num_cb, ppWritePackedMsg, end) &&
-		 //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8)
-		 push8(value->ul_cqi, ppWritePackedMsg, end) && 
-		 push16(value->timing_advance, ppWritePackedMsg, end) &&
-		 push16(value->rssi, ppWritePackedMsg, end)
-		 ))
-		  return 0;
-
-	return 1;
-}
-
-static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
-{
-	nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg;
-
-	if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end)
-		))
-			return 0;
-
-	for(int i=0; i<pNfapiMsg->number_crcs;i++)	
-	{
-		if(!pack_nr_crc_indication_body(pNfapiMsg->crc_list,ppWritePackedMsg,end))
-		return 0;
-	}
-
-return 1;
-}
-
-//SRS INDICATION
-
-static uint8_t pack_nr_srs_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
-{
-	nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv;
-
-	if(!(push32(value->handle, ppWritePackedMsg, end) &&
-	 	 push16(value->rnti, ppWritePackedMsg, end) &&
-		 push16(value->timing_advance, ppWritePackedMsg, end) &&
-		 push8(value->num_symbols, ppWritePackedMsg, end) &&
-		 push8(value->wide_band_snr, ppWritePackedMsg, end) &&
-		 push8(value->num_reported_symbols, ppWritePackedMsg, end) && 
-		 push8(value->reported_symbol_list->num_rbs, ppWritePackedMsg, end)
-		 ))
-		  return 0;
-	for(int i = 0; i < value->reported_symbol_list->num_rbs; i++)
-	{
-		if(!(push8(value->reported_symbol_list->rb_list->rb_snr, ppWritePackedMsg, end)
-			))
-			return 0;
-	}
-	return 1;
-}
-
-static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
-{
-	nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg;
-
-	if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end)
-		))
-			return 0;
-
-	for(int i=0; i<pNfapiMsg->number_of_pdus;i++)	
-	{
-		if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end))
-		return 0;
-	}
-
-return 1;
-}
-
-//RACH INDICATION
-
-static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
-{
-	nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv;
-
-	if(!(push16(value->phy_cell_id, ppWritePackedMsg, end) &&
-	 	 push8(value->symbol_index, ppWritePackedMsg, end) &&
-		 push8(value->slot_index, ppWritePackedMsg, end) &&
-		 push8(value->freq_index, ppWritePackedMsg, end) &&
-		 push8(value->avg_rssi, ppWritePackedMsg, end) &&
-		 push8(value->avg_snr, ppWritePackedMsg, end) && 
-		 push8(value->num_preamble, ppWritePackedMsg, end)
-		 ))
-		  return 0;
-	for(int i = 0; i < value->num_preamble; i++)
-	{
-		if(!(push8(value->preamble_list->preamble_index, ppWritePackedMsg, end) &&
-			push16(value->preamble_list->timing_advance, ppWritePackedMsg, end) &&
-			push32(value->preamble_list->preamble_pwr, ppWritePackedMsg, end)
-			))
-			return 0;
-	}
-	return 1;
-}
-
-static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
-{
-	nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg;
-
-	if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end)
-		))
-			return 0;
-
-	for(int i=0; i<pNfapiMsg->number_of_pdus;i++)	
-	{
-		if(!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end))
-		return 0;
-	}
-
-return 1;
-}
-
-
-//UCI INDICATION
-
-static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) {
-	nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv;
-
-	if(!(push8(value->pduBitmap, ppWritePackedMsg, end) &&
-	 	 push32(value->handle, ppWritePackedMsg, end) &&
-		 push16(value->rnti, ppWritePackedMsg, end) &&
-		 push8(value->pucch_format, ppWritePackedMsg, end) &&
-		 push8(value->ul_cqi, ppWritePackedMsg, end) &&
-		 push16(value->timing_advance, ppWritePackedMsg, end) && 
-		 push16(value->rssi, ppWritePackedMsg, end)
-		 ))
-		  return 0;
-	if (value->pduBitmap & 0x01) { //SR
-		if(!(push8(value->sr->sr_indication, ppWritePackedMsg, end) &&
-	 	 push8(value->sr->sr_confidence_level, ppWritePackedMsg, end) 
-		 ))
-		  return 0;
-	}
-
-	if (((value->pduBitmap >> 1) & 0x01)) { //HARQ
-		if(!(push8(value->harq->num_harq, ppWritePackedMsg, end) &&
-	 	 push8(value->harq->harq_confidence_level, ppWritePackedMsg, end) 
-		 ))
-			return 0;
-
-		for(int i=0; i<value->harq->num_harq;i++)	
-		{
-			if(!(push8(value->harq->harq_list[i].harq_value, ppWritePackedMsg, end)
-			))
-			return 0;
-		}
-	}
-
-	return 1;
-}
-
-static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) {
-	nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv;
-
-	if(!(push8(value->pduBitmap, ppWritePackedMsg, end) &&
-	 	 push32(value->handle, ppWritePackedMsg, end) &&
-		 push16(value->rnti, ppWritePackedMsg, end) &&
-		 push8(value->pucch_format, ppWritePackedMsg, end) &&
-		 push8(value->ul_cqi, ppWritePackedMsg, end) &&
-		 push16(value->timing_advance, ppWritePackedMsg, end) && 
-		 push16(value->rssi, ppWritePackedMsg, end)
-		 ))
-		  return 0;
-
-	if (value->pduBitmap & 0x01) { //SR
-		if(!(push8(value->sr.sr_bit_len, ppWritePackedMsg, end) &&
-	 	 pusharray8(value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, ppWritePackedMsg, end) 
-		 ))
-		  return 0;
-	}
-
-	if (((value->pduBitmap >> 1) & 0x01)) { //HARQ
-		if(!(push8(value->harq.harq_crc, ppWritePackedMsg, end) &&
-			push8(value->harq.harq_bit_len, ppWritePackedMsg, end) &&
-	 	 	pusharray8(value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, ppWritePackedMsg, end) 
-			))
-			return 0;
-	}
-
-	if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1
-		if(!(push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end) &&
-			push8(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end) &&
-	 	 	pusharray8(value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, ppWritePackedMsg, end) 
-			))
-			return 0;
-	}
-
-	if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2
-		if(!(push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end) &&
-			push8(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end) &&
-	 	 	pusharray8(value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, ppWritePackedMsg, end) 
-			))
-			return 0;
-	}
-
-	return 1;
-}
-
-static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
-{
-	nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv;
-
-	if(!(push16(value->pdu_type, ppWritePackedMsg, end) &&
-		push16(value->pdu_size, ppWritePackedMsg, end)
-		))
-		return 0;
-	
-	switch (value->pdu_type) {
-      case NFAPI_NR_UCI_PUSCH_PDU_TYPE:
-        printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n");
-        break;
-
-      case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: {
-        nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1;
-        pack_nr_uci_pucch_0_1(uci_pdu, ppWritePackedMsg, end);
-        break;
-      }
-      case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: {
-        nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4;
-        pack_nr_uci_pucch_2_3_4(uci_pdu, ppWritePackedMsg, end);
-        break;
-    	}
-	}
-
-	return 1;
-}
-
-static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
-{
-	nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg;
-
-	if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->slot , ppWritePackedMsg, end) &&
-		push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end)
-		))
-			return 0;
-
-	for(int i=0; i<pNfapiMsg->num_ucis;i++)	
-	{
-		if(!pack_nr_uci_indication_body(&(pNfapiMsg->uci_list[i]),ppWritePackedMsg,end))
-		return 0;
-	}
-
-return 1;
-}
 
 // Main pack function - public
 
@@ -3700,7 +3397,6 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe
 	{
 		case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST:
 			result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config);
-			printf("result of pack dl_tti_req is %d. \n",result);
 			break;
 
 		case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST:
@@ -3721,24 +3417,49 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe
 			result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
 
-		case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION:
-			result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config);
+		case NFAPI_HARQ_INDICATION:
+			result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_CRC_INDICATION:
+			result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_RX_ULSCH_INDICATION:
+                        //printf("RX ULSCH\n");
+			result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_RACH_INDICATION:
+			result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_SRS_INDICATION:
+			result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_RX_SR_INDICATION:
+			result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
 
-		case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION:
-			result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config);
+		case NFAPI_RX_CQI_INDICATION:
+			result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
 
-		case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION:
-			result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config);
+		case NFAPI_LBT_DL_CONFIG_REQUEST:
+			result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
 
-		case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION:
-			result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config);
+		case NFAPI_LBT_DL_INDICATION:
+			result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
 
-		case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION:
-			result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config);
+		case NFAPI_NB_HARQ_INDICATION:
+			result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_NRACH_INDICATION:
+			result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
 
 		case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC:
@@ -3854,6 +3575,7 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu
 	switch (pMessageHeader->message_id)
 	{
 		case NFAPI_DL_CONFIG_REQUEST:
+                  //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__);
 			result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
 
@@ -3861,6 +3583,7 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu
 			result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
         case NFAPI_TX_REQUEST:
+            //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__);
 			result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
 		case NFAPI_HI_DCI0_REQUEST:
@@ -3884,6 +3607,7 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu
 			break;
 
 		case NFAPI_RX_ULSCH_INDICATION:
+                        //printf("RX ULSCH\n");
 			result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
 
@@ -6348,334 +6072,6 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
 	return 1;
 }
 
-
-//UNPACK NR UPLINK INDICATION FUNCTIONS 
-
-//RX DATA INDICATION 
-
-static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
-{
-	nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv;
-
-	if(!(pull32(ppReadPackedMsg, &value->handle, end) &&
-	 	 pull16(ppReadPackedMsg, &value->rnti, end) &&
-		 pull8(ppReadPackedMsg, &value->harq_id, end) &&
-		 pull16(ppReadPackedMsg, &value->pdu_length, end) &&
-		 pull8(ppReadPackedMsg, &value->ul_cqi, end) &&
-		 pull16(ppReadPackedMsg, &value->timing_advance, end) && 
-		 pull16(ppReadPackedMsg, &value->rssi, end) 
-		 ))
-		  return 0;
-	return 1;
-}
-
-
-static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
-{	
-	// uint8_t *ptr = *ppReadPackedMsg;
-	// printf("\n Read P7 message rx data indication unpack: ");
-	// while(ptr < end){
-	// 	printf(" %d ", *ptr);
-	// 	ptr++;
-	// }
-	// printf("\n");
-	nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg;
-	
-	printf("\n");
-	if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) &&
-		pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) &&
-		pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end)
-		))
-			return 0;
-
-	for(int i=0; i<pNfapiMsg->number_of_pdus;i++)	
-	{
-		if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list, ppReadPackedMsg, end))
-		return 0;
-	}
-
-return 1;
-}
-
-//NR CRC INDICATION
-
-static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
-{	
-	nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv;
-
-	if(!(pull32(ppReadPackedMsg, &value->handle, end) &&
-	 	 pull16(ppReadPackedMsg, &value->rnti, end) &&
-		 pull8(ppReadPackedMsg, &value->harq_id, end) &&
-		 pull8(ppReadPackedMsg, &value->tb_crc_status, end) &&
-		 pull16(ppReadPackedMsg, &value->num_cb, end) &&
-		 //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8)
-		 pull8(ppReadPackedMsg, &value->ul_cqi, end) && 
-		 pull16(ppReadPackedMsg, &value->timing_advance, end) &&
-		 pull16(ppReadPackedMsg, &value->rssi, end)
-		 ))
-		  return 0;
-
-	return 1;
-}
-
-static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
-{
-	uint8_t *ptr = *ppReadPackedMsg;
-	// printf("\n Read P7 message indication unpack: ");
-	// while(ptr < end){
-	// 	printf(" %d ", *ptr);
-	// 	ptr++;
-	// }
-	// printf("\n");
-	nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg;
-
-	if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) &&
-		pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) &&
-		pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end)
-		))
-			return 0;
-
-	for(int i=0; i<pNfapiMsg->number_crcs;i++)	
-	{
-		if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list,ppReadPackedMsg,end))
-		return 0;
-	}
-
-return 1;
-}
-
-//SRS INDICATION
-
-static uint8_t unpack_nr_srs_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
-{
-	nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv;
-
-	if(!(pull32(ppReadPackedMsg, &value->handle, end) &&
-	 	 pull16(ppReadPackedMsg, &value->rnti, end) &&
-		 pull16(ppReadPackedMsg, &value->timing_advance, end) &&
-		 pull8(ppReadPackedMsg, &value->num_symbols, end) &&
-		 pull8(ppReadPackedMsg, &value->wide_band_snr, end) &&
-		 pull8(ppReadPackedMsg, &value->num_reported_symbols, end) && 
-		 pull16(ppReadPackedMsg, &value->reported_symbol_list->num_rbs, end)
-		 ))
-		  return 0;
-	for(int i = 0; i < value->reported_symbol_list->num_rbs; i++)
-	{
-		if(!(pull8(ppReadPackedMsg, &value->reported_symbol_list->rb_list->rb_snr, end)
-			))
-			return 0;
-	}
-	return 1;
-}
-
-static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
-{
-	nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg;
-
-	if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn , end) &&
-		pull16(ppReadPackedMsg,&pNfapiMsg->slot , end) &&
-		pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end)
-		))
-			return 0;
-
-	for(int i=0; i<pNfapiMsg->number_of_pdus;i++)	
-	{
-		if(!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end))
-		return 0;
-	}
-
-return 1;
-}
-
-//NR RACH
-
-static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
-{
-	nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv;
-
-	if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) &&
-	 	 pull8(ppReadPackedMsg, &value->symbol_index, end) &&
-		 pull8(ppReadPackedMsg, &value->slot_index, end) &&
-		 pull8(ppReadPackedMsg, &value->freq_index, end) &&
-		 pull8(ppReadPackedMsg, &value->avg_rssi, end) &&
-		 pull8(ppReadPackedMsg, &value->avg_snr, end) && 
-		 pull8(ppReadPackedMsg, &value->num_preamble, end)
-		 ))
-		  return 0;
-	for(int i = 0; i < value->num_preamble; i++)
-	{
-		if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) &&
-			pull16(ppReadPackedMsg, &value->preamble_list->timing_advance, end) &&
-			pull32(ppReadPackedMsg, &value->preamble_list->preamble_pwr, end)
-			))
-			return 0;
-	}
-	return 1;
-}
-
-static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) {
-
-	nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg;
-	if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) &&
-		pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) &&
-		pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end)
-		))
-			return 0;
-
-	for(int i=0; i< pNfapiMsg->number_of_pdus;i++)	
-	{
-		if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end))
-		return 0;
-	}
-
-return 1;
-}
-
-//NR UCI 
-
-static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) {
-	nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv;
-
-	uint8_t *ptr = *ppReadPackedMsg;
-	printf("\n Read P7 message uci_0_1 indication unpack: ");
-	while(ptr < end){
-		printf(" %d ", *ptr);
-		ptr++;
-	}
-	printf("\n");
-
-	if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) &&
-	 	 pull32(ppReadPackedMsg, &value->handle, end) &&
-		 pull16(ppReadPackedMsg, &value->rnti, end) &&
-		 pull8(ppReadPackedMsg, &value->pucch_format, end) &&
-		 pull8(ppReadPackedMsg, &value->ul_cqi, end) &&
-		 pull16(ppReadPackedMsg, &value->timing_advance, end) && 
-		 pull16(ppReadPackedMsg, &value->rssi, end)
-		 ))
-		  return 0;
-	if (value->pduBitmap & 0x01) { //SR
-		if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) &&
-	 	 pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) 
-		 ))
-		  return 0;
-	}
-
-	// if (((value->pduBitmap >> 1) & 0x01)) { //HARQ
-	// 	uint8_t* temp; //&value->harq->num_harq &value->harq->harq_confidence_level &value->harq->harq_list[0].harq_value
-	// 	temp = (uint8_t*) malloc(sizeof(uint8_t));
-	// 	//printf("value->harq->num_harq = %d \n", value->harq->num_harq);
-	// 	// if(!(pull8(ppReadPackedMsg, temp, end) &&
-	//  	//  pull8(ppReadPackedMsg, temp, end) 
-	// 	//  ))
-	// 	// 	return 0;
-
-	// 	// for(int i=0; i<1;i++)	
-	// 	// {
-	// 	// 	if(!(pull8(ppReadPackedMsg, temp, end) //review - gokul
-	// 	// 	))
-	// 	// 	return 0;
-	// 	// }
-	// }
-
-	return 1;
-}
-
-
-static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) {
-	nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv;
-
-	if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) &&
-	 	 pull32(ppReadPackedMsg, &value->handle, end) &&
-		 pull16(ppReadPackedMsg, &value->rnti, end) &&
-		 pull8(ppReadPackedMsg, &value->pucch_format, end) &&
-		 pull8(ppReadPackedMsg, &value->ul_cqi, end) &&
-		 pull16(ppReadPackedMsg, &value->timing_advance, end) && 
-		 pull16(ppReadPackedMsg, &value->rssi, end)
-		 ))
-		  return 0;
-	if (value->pduBitmap & 0x01) { //SR
-		if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end) &&
-	 	 pullarray8(ppReadPackedMsg, value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, end) 
-		 ))
-		  return 0;
-	}
-
-	if (((value->pduBitmap >> 1) & 0x01)) { //HARQ
-		if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end) &&
-			pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end) &&
-	 	 	pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, end) 
-			))
-			return 0;
-	}
-
-	if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1
-		if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end) &&
-			pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end) &&
-	 	 	pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, end) 
-			))
-			return 0;
-	}
-
-	if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2
-		if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end) &&
-			pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end) &&
-	 	 	pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, end) 
-			))
-			return 0;
-	}
-
-	return 1;
-}
-
-static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
-{
-	nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv;
-
-	if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) &&
-		pull16(ppReadPackedMsg, &value->pdu_size, end)
-		))
-		return 0;
-	
-	switch (value->pdu_type) {
-      case NFAPI_NR_UCI_PUSCH_PDU_TYPE:
-        printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n");
-        break;
-
-      case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: {
-        nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1;
-        unpack_nr_uci_pucch_0_1(&uci_pdu, ppReadPackedMsg, end);
-		break;
-        }
-      case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: {
-        nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4;
-        unpack_nr_uci_pucch_2_3_4(&uci_pdu, ppReadPackedMsg, end);
-        break;
-    	}
-	}	
-
-	return 1;	
-}
-
-static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
-{
-	nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg;
-
-	if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) &&
-		pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) &&
-		pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end)
-		))
-			return 0;
-
-	for(int i=0; i<pNfapiMsg->num_ucis;i++)	
-	{
-		if(!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list,ppReadPackedMsg,end))
-		return 0;
-	}
-
-return 1;
-}
-
-
 static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
 {
     uint8_t proceed = 1;
@@ -8301,32 +7697,62 @@ static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBuf
 			if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t))
 				retLen = sizeof(nfapi_nr_tx_data_request_t);
 			break;
-		
-		case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION:
-			if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t))
-				retLen = sizeof(nfapi_nr_rx_data_indication_t);
+
+		case NFAPI_HARQ_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_harq_indication_t))
+				retLen = sizeof(nfapi_harq_indication_t);
 			break;
-		
-		case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION:
-			if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t))
-				retLen = sizeof(nfapi_nr_crc_indication_t);
+
+		case NFAPI_CRC_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_crc_indication_t))
+				retLen = sizeof(nfapi_crc_indication_t);
 			break;
 
-		case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION:
-			if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t))
-				retLen = sizeof(nfapi_nr_rach_indication_t);
+		case NFAPI_RX_ULSCH_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_rx_indication_t))
+				retLen = sizeof(nfapi_rx_indication_t);
 			break;
-		
-		case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION:
-			if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t))
-				retLen = sizeof(nfapi_nr_uci_indication_t);
+
+		case NFAPI_RACH_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_rach_indication_t))
+				retLen = sizeof(nfapi_rach_indication_t);
 			break;
-		
-		case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION:
-			if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t))
-				retLen = sizeof(nfapi_nr_srs_indication_t);
+
+		case NFAPI_SRS_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_srs_indication_t))
+				retLen = sizeof(nfapi_srs_indication_t);
 			break;
-		
+
+		case NFAPI_RX_SR_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_sr_indication_t))
+				retLen = sizeof(nfapi_sr_indication_t);
+			break;
+
+		case NFAPI_RX_CQI_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t))
+				retLen = sizeof(nfapi_cqi_indication_t);
+			break;
+
+		case NFAPI_LBT_DL_CONFIG_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t))
+				retLen = sizeof(nfapi_lbt_dl_config_request_t);
+			break;
+
+		case NFAPI_LBT_DL_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t))
+				retLen = sizeof(nfapi_lbt_dl_indication_t);
+			break;
+	
+		case NFAPI_NB_HARQ_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t))
+				retLen = sizeof(nfapi_nb_harq_indication_t);
+			break;
+			
+		case NFAPI_NRACH_INDICATION:
+			if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t))
+				retLen = sizeof(nfapi_nrach_indication_t);
+			break;			
+			
 		case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC:
 			if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t))
 				retLen = sizeof(nfapi_nr_dl_node_sync_t);
@@ -8636,15 +8062,15 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *
 		NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen);
 		return -1;
 	}
-  
-    // uint8_t *ptr = pMessageBuf;
-	// printf("\n Read P7 message unpack: ");
-	// while(ptr < end){
-	// 	printf(" %d ", *ptr);
-	// 	ptr++;
-	// }
-	// printf("\n");
-
+  /*
+    uint8_t *ptr = pMessageBuf;
+	printf("\n Read P7 message unpack: ");
+	while(ptr < end){
+		printf(" %d ", *ptr);
+		ptr++;
+	}
+	printf("\n");
+*/
 	// clean the supplied buffer for - tag value blanking
 	(void)memset(pUnpackedBuf, 0, unpackedBufLen);
 
@@ -8710,41 +8136,83 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *
 				return -1;
 			break;
 
-		case  NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION:
-			if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen))
-				result = unpack_nr_rx_data_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+		case NFAPI_HARQ_INDICATION:
+			if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen))
+				result = unpack_harq_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_CRC_INDICATION:
+			if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen))
+				result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_RX_ULSCH_INDICATION:
+			if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen))
+				result = unpack_rx_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
+		case NFAPI_RACH_INDICATION:
+			if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen))
+				result = unpack_rach_indication(&pReadPackedMessage,  end, pMessageHeader, config);
 			else
 				return -1;
 			break;
 
-		case  NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION:
-			if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen))
-				result = unpack_nr_crc_indication(&pReadPackedMessage,end , pMessageHeader, config);
+		case NFAPI_SRS_INDICATION:
+			if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen))
+				result = unpack_srs_indication(&pReadPackedMessage,  end, pMessageHeader, config);
 			else
 				return -1;
 			break;
 
-		case  NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION:
-			if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen))
-				result = unpack_nr_uci_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+		case NFAPI_RX_SR_INDICATION:
+			if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen))
+				result = unpack_sr_indication(&pReadPackedMessage,  end, pMessageHeader, config);
 			else
 				return -1;
 			break;
 
-		case  NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION:
-			if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen))
-				result = unpack_nr_srs_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+		case NFAPI_RX_CQI_INDICATION:
+			if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen))
+				result = unpack_cqi_indication(&pReadPackedMessage,  end, pMessageHeader, config);
 			else
 				return -1;
 			break;
 
-		case  NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION:
-			if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen))
-				result = unpack_nr_rach_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+		case NFAPI_LBT_DL_CONFIG_REQUEST:
+			if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen))
+				result = unpack_lbt_dl_config_request(&pReadPackedMessage,  end, pMessageHeader, config);
 			else
 				return -1;
 			break;
 
+		case NFAPI_LBT_DL_INDICATION:
+			if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen))
+				result = unpack_lbt_dl_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+			
+		case NFAPI_NB_HARQ_INDICATION:
+			if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen))
+				result = unpack_nb_harq_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;	
+			
+		case NFAPI_NRACH_INDICATION:
+			if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen))
+				result = unpack_nrach_indication(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+			
 		case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC:
 			if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen))
 				result = unpack_nr_dl_node_sync(&pReadPackedMessage,  end, pMessageHeader, config);
diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c
index 14b4846846d3123156dc0c01b9241f2787ca7a6a..3511ed2fb9314a18a0b5251552e7713299a7c396 100644
--- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c
+++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c
@@ -1572,7 +1572,7 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name,
 	{ 	
 		
 		NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec,  (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window);
-		
+		//NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec,  (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window);
 	}//Need to add more cases
 	
 
diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c
index 88aa1391cb4bc37cb8661390bf87ca781b152e39..efcb60ce9632e366927ca4cb6c4af18bdcc28775 100644
--- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c
+++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c
@@ -175,7 +175,17 @@ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t
 	pnf_p7_t* _this = (pnf_p7_t*)(config);
 	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t));
 }
+int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind)
+{
+	if(config == NULL || ind == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
+		return -1;
+	}
 
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+	return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t));
+}
 int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind)
 {
 	if(config == NULL || ind == NULL)
@@ -255,65 +265,3 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re
 
 	return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t));
 }
-
-//NR UPLINK INDICATION 
-
-int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind)
-{
-	if(config == NULL || ind == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
-		return -1;
-	}
-
-	pnf_p7_t* _this = (pnf_p7_t*)(config);
-	return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t));
-}
-
-int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind)
-{
-	if(config == NULL || ind == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
-		return -1;
-	}
-
-	pnf_p7_t* _this = (pnf_p7_t*)(config);
-	return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t));
-}
-
-int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind)
-{
-	if(config == NULL || ind == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
-		return -1;
-	}
-
-	pnf_p7_t* _this = (pnf_p7_t*)(config);
-	return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t));
-}
-
-int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind)
-{
-	if(config == NULL || ind == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
-		return -1;
-	}
-
-	pnf_p7_t* _this = (pnf_p7_t*)(config);
-	return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t));
-}
-
-int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind)
-{
-	if(config == NULL || ind == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__);
-		return -1;
-	}
-
-	pnf_p7_t* _this = (pnf_p7_t*)(config);
-	return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t));
-}
diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h
index ad1c5e7944295028eab74897ae8db264d836e989..248faf83697fcd8ac2cc70cbbc91030f86167d67 100644
--- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h
+++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h
@@ -24,8 +24,6 @@
 #define TIMEHR_USEC(_time_hr) ((uint32_t)(_time_hr) & 0xFFFFF)
 #define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF))
 
-
-
 typedef struct {
 	uint8_t* buffer;
 	uint16_t length;
diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c
index 453f0f3769889735ae52b4e1351e6970f20257d7..39f7899d77ffaeaf723447d378a94678e8e6f998 100644
--- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c
+++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c
@@ -461,7 +461,6 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u
 	{
 		NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno);
 	}
-
 	return 0;
 }
 
@@ -677,7 +676,6 @@ int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_inf
 	//dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr);
 	dl_node_sync.t1 = calculate_nr_t1(p7_info->sfn,p7_info->slot, vnf_p7->slot_start_time_hr);
 	dl_node_sync.delta_sfn_slot = 0;
-
 	return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header);	
 }
 
@@ -1453,102 +1451,8 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
 		phy->previous_t1 = ind.t1;
 		phy->previous_t2 = ind.t2;
 	}
-}
-
-//NR HANDLES FOR UPLINK MESSAGES
-
-void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
-{
-	// ensure it's valid
-	if (pRecvMsg == NULL || vnf_p7 == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
-	}
-	else
-	{
-		nfapi_nr_rx_data_indication_t ind;
-	
-		if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
-		{
-			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
-		}
-
-	}
-}
 
-void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
-{
-	// ensure it's valid
-	if (pRecvMsg == NULL || vnf_p7 == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
-	}
-	else
-	{
-		nfapi_nr_crc_indication_t ind;
-	
-		if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
-		{
-			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
-		}
-		
-	}
-}
-
-void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
-{
-	// ensure it's valid
-	if (pRecvMsg == NULL || vnf_p7 == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
-	}
-	else
-	{
-		nfapi_nr_srs_indication_t ind;
-	
-		if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
-		{
-			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
-		}
-		
-	}
-}
-
-void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
-{
-	// ensure it's valid
-	if (pRecvMsg == NULL || vnf_p7 == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
-	}
-	else
-	{
-		nfapi_nr_uci_indication_t ind;
-	
-		if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
-		{
-			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
-		}
-	}
-}
 
-void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
-{
-	// ensure it's valid
-	if (pRecvMsg == NULL || vnf_p7 == NULL)
-	{
-		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
-	}
-	else
-	{
-		nfapi_nr_rach_indication_t ind;
-	
-		if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0)
-		{
-			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
-		}
-		
-	}
 }
 
 void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
@@ -2131,26 +2035,46 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7
 			vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7);
 			break;
 			
-		case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION:
-			vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7);
+		case NFAPI_HARQ_INDICATION:
+			vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7);
 			break;
 	
-		case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION:
-			vnf_handle_nr_crc_indication(pRecvMsg, recvMsgLen, vnf_p7);
+		case NFAPI_CRC_INDICATION:
+			vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7);
 			break;
 	
-		case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION:
-			vnf_handle_nr_uci_indication(pRecvMsg, recvMsgLen, vnf_p7);
+		case NFAPI_RX_ULSCH_INDICATION:
+			vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7);
 			break;
 	
-		case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION:
-			vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7);
+		case NFAPI_RACH_INDICATION:
+			vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7);
 			break;
 	
-		case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION:
-			vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7);
+		case NFAPI_SRS_INDICATION:
+			vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7);
 			break;
 
+		case NFAPI_RX_SR_INDICATION:
+			vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+
+		case NFAPI_RX_CQI_INDICATION:
+			vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+			
+		case NFAPI_LBT_DL_INDICATION:
+			vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+			
+		case NFAPI_NB_HARQ_INDICATION:
+			vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+			
+		case NFAPI_NRACH_INDICATION:
+			vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7);
+			break;			
+
 		case NFAPI_UE_RELEASE_RESPONSE:
 			vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7);
 			break;
diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c
index 3fa1f035fdc102e6c9a11d8032a7529ecb0e59ce..aba91d0d28ceeac5b4e73ed78e5b994bd78428cd 100644
--- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c
+++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c
@@ -26,8 +26,12 @@
 
 #include "vnf_p7.h"
 
+#include "common/ran_context.h"
+
+#include "openair1/PHY/defs_gNB.h"
 #define FAPI2_IP_DSCP	0
 
+extern RAN_CONTEXT_t RC;
 
 nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create()
 {
@@ -93,6 +97,7 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs)
 // send indications to mac
 int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config)
 {
+	uint16_t vnf_frame; uint8_t vnf_slot;
 	if(config == 0)
 		return -1;
 
@@ -145,7 +150,7 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config)
 
 	//struct timespec original_pselect_timeout;
 	struct timespec pselect_timeout;
-	pselect_timeout.tv_sec = 0;
+	pselect_timeout.tv_sec = 0; 
 	pselect_timeout.tv_nsec = 500000; // ns in a 0.5 ms
 	//pselect_timeout.tv_nsec = 500000;
 
@@ -257,7 +262,8 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config)
 
 //long wraps = pselect_timeout.tv_nsec % 1e9;
 
-
+			// pselect_timeout.tv_sec = 100; // 0
+			// pselect_timeout.tv_nsec = 0;//500000; // ns in a 0.5 ms
 			selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL);
 		//	selectRetval = pselect(120, &rfds, NULL, NULL, &pselect_timeout, NULL);
 
@@ -388,6 +394,8 @@ NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d]
 			selectRetval = 0;
 		}
 
+		nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections;
+		uint8_t ul_p7_count = 0;
 		if(selectRetval == 0)
 		{
 			//vnf_p7->sf_start_time_hr = vnf_get_current_time_hr();
@@ -395,7 +403,7 @@ NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d]
 struct timespec current_time;
 	clock_gettime(CLOCK_MONOTONIC, &current_time);
 			// pselect timed out
-			nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections;
+			
 			while(curr != 0)
 			{
 				if (curr->slot == 19)
@@ -410,17 +418,49 @@ struct timespec current_time;
 				{
 				curr->slot++;
 				}
+				//printf("Frame = %d, slot = %d in VNF main loop. n",curr->sfn,curr->slot);
+				vnf_frame = curr->sfn; vnf_slot = curr->slot;
+
+				struct timespec curr_time;
+			clock_gettime(CLOCK_MONOTONIC, &curr_time);
+				//printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",vnf_frame,vnf_slot,curr_time.tv_sec,curr_time.tv_nsec);
+
 				vnf_nr_sync(vnf_p7, curr);	
 				curr = curr->next;	
 			}
 			send_mac_slot_indications(vnf_p7);
+			
+
+
+			// // Call the scheduler
+			// 	struct PHY_VARS_gNB_s *gNB = RC.gNB[0];
+			// 	pthread_mutex_lock(&gNB->UL_INFO_mutex);
+			// 	gNB->UL_INFO.frame     = vnf_frame;
+			// 	gNB->UL_INFO.slot      = vnf_slot;
+
+			// 	gNB->UL_INFO.module_id = gNB->Mod_id;
+			// 	gNB->UL_INFO.CC_id     = gNB->CC_id;
+			// 	gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
+			// 	pthread_mutex_unlock(&gNB->UL_INFO_mutex);
 		}
 		else if(selectRetval > 0)
 		{
 			// have a p7 message
 			if(FD_ISSET(vnf_p7->socket, &rfds))
-			{
+			{	
+			
 				vnf_nr_p7_read_dispatch_message(vnf_p7); 
+
+				// Call the scheduler
+				struct PHY_VARS_gNB_s *gNB = RC.gNB[0];
+				pthread_mutex_lock(&gNB->UL_INFO_mutex);
+				gNB->UL_INFO.frame     = vnf_frame;
+				gNB->UL_INFO.slot      = vnf_slot;
+
+				gNB->UL_INFO.module_id = gNB->Mod_id;
+				gNB->UL_INFO.CC_id     = gNB->CC_id;
+				gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
+				pthread_mutex_unlock(&gNB->UL_INFO_mutex);
 			}
 		}
 		else
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index d00bc903157d8f4ea6ea04615ff7d8f67c3bbf92..0e6b253c2b4215911d1dc9ac5aaafe27caa217c5 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -20,6 +20,7 @@
  */
 
 #include "executables/nr-softmodem-common.h"
+#include "common/utils/nr/nr_common.h"
 #include "PHY/defs_gNB.h"
 #include "PHY/phy_extern.h"
 #include "PHY/NR_REFSIG/nr_refsig.h"
@@ -45,10 +46,42 @@
 
 #include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
 
-/*
-extern uint32_t from_nrarfcn(int nr_bandP,uint32_t dl_nrarfcn);
-extern openair0_config_t openair0_cfg[MAX_CARDS];
-*/
+static
+uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex)
+{
+  const uint64_t dl_freq_khz = downlink_frequency / 1000;
+  const int32_t  delta_duplex_khz = delta_duplex / 1000;
+
+  uint64_t center_freq_diff_khz = 999999999999999999; // 2^64
+  uint16_t current_band = 0;
+
+  for (int ind = 0; ind < nr_bandtable_size; ind++) {
+
+    LOG_D(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min, nr_bandtable[ind].ul_min);
+
+    if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max)
+      continue;
+
+    int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min;
+
+    if (current_offset_khz != delta_duplex_khz)
+      continue;
+
+    uint64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2;
+
+    if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){
+      current_band = nr_bandtable[ind].band;
+      center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz);
+    }
+  }
+
+  LOG_I(PHY, "DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n",
+        downlink_frequency, current_band, downlink_frequency+delta_duplex);
+
+  AssertFatal(current_band != 0, "Can't find EUTRA band for frequency %"PRIu64" and duplex_spacing %u\n", downlink_frequency, delta_duplex);
+
+  return current_band;
+}
 
 int l1_north_init_gNB() {
 
@@ -431,8 +464,8 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,
 
   gNB->mac_enabled   = 1;
   if (mu==1) {
-    fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
-    fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
+    fp->dl_CarrierFreq = 3600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
+    fp->ul_CarrierFreq = 3600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
     fp->nr_band = 78;
     //  fp->threequarter_fs= 0;
   } else if (mu==3) {
@@ -455,7 +488,6 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
   uint8_t short_sequence, num_sequences, rootSequenceIndex, fd_occasion;
   NR_DL_FRAME_PARMS *fp = &RC.gNB[Mod_id]->frame_parms;
   nfapi_nr_config_request_scf_t *gNB_config = &RC.gNB[Mod_id]->gNB_config;
-  int32_t dlul_offset = 0;
 
   memcpy((void*)gNB_config,phy_config->cfg,sizeof(*phy_config->cfg));
   RC.gNB[Mod_id]->mac_enabled     = 1;
@@ -466,16 +498,9 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
   uint64_t ul_bw_khz = (12*gNB_config->carrier_config.ul_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<<gNB_config->ssb_config.scs_common.value);
   fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ;
 
-  //fp->nr_band = *RC.nrmac[Mod_id]->common_channels[0].ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
-  lte_frame_type_t frame_type = 0; // FDD
-  
-  get_band(fp->dl_CarrierFreq,&fp->nr_band,&dlul_offset,&frame_type); //RC.nrmac[Mod_id] cannot be accessed in NFAPI
+  int32_t dlul_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq;
+  fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset);
 
-  get_delta_duplex(fp->nr_band, gNB_config->ssb_config.scs_common.value, &dlul_offset);
-  dlul_offset *= 1000;
-
-  AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + dlul_offset), "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + dlul_offset);
-  
   LOG_I(PHY, "DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, dlul_offset);
 
   fp->threequarter_fs = openair0_cfg[0].threequarter_fs;
@@ -504,7 +529,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
 //  }
   RC.gNB[Mod_id]->configured     = 1;
 
-  init_symbol_rotation(fp,fp->dl_CarrierFreq);
+  init_symbol_rotation(fp);
 
   LOG_I(PHY,"gNB %d configured\n",Mod_id);
 }
diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c
index 8bcc58160ff01021fd38801909ccb95a5e1639b5..3132fb99605c96cd16960c64658ef36f930ce756 100644
--- a/openair1/PHY/INIT/nr_init_ue.c
+++ b/openair1/PHY/INIT/nr_init_ue.c
@@ -507,50 +507,36 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){
   if (fp->frame_type == FDD) {
     ue->N_TA_offset = 0;
   } else {
-    int N_RB = fp->N_RB_DL;
     int N_TA_offset = fp->ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples  for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2
-    double factor = 1;
+
+    double factor = 1.0;
     switch (fp->numerology_index) {
       case 0: //15 kHz scs
         AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n");
-        if (N_RB <= 25) factor = .25;      // 7.68 Ms/s
-        else if (N_RB <=50) factor = .5;   // 15.36 Ms/s
-        else if (N_RB <=75) factor = 1.0;  // 30.72 Ms/s
-        else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s
-        else AssertFatal(1==0, "Too many PRBS for mu=0\n");
+        factor = fp->samples_per_subframe / 30720.0;
         break;
       case 1: //30 kHz sc
         AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n");
-        if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s
-        else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s
+        factor = fp->samples_per_subframe / 30720.0;
         break;
       case 2: //60 kHz scs
         AssertFatal(1==0, "scs_common should not be 60 kHz\n");
         break;
       case 3: //120 kHz scs
         AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n");
+        factor = fp->samples_per_subframe / 61440.0;
         break;
       case 4: //240 kHz scs
-        AssertFatal(1==0, "scs_common should not be 60 kHz\n");
-        if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s
-        else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s
-        else AssertFatal(1==0, "N_RB %d is too big for curretn FR2 implementation\n", N_RB);
+        AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n");
+        factor = fp->samples_per_subframe / 61440.0;
         break;
-
-      if (N_RB == 100)
-        ue->N_TA_offset = 624;
-      else if (N_RB == 50)
-        ue->N_TA_offset = 624/2;
-      else if (N_RB == 25)
-        ue->N_TA_offset = 624/4;
+      default:
+        AssertFatal(1==0, "Invalid scs_common!\n");
     }
 
-    if (fp->threequarter_fs == 1)
-      factor = factor*.75;
-
     ue->N_TA_offset = (int)(N_TA_offset * factor);
 
-    LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d)\n", ue->Mod_id, ue->N_TA_offset, factor, fp->ul_CarrierFreq, N_RB);
+    LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d, mu %d)\n", ue->Mod_id, ue->N_TA_offset, factor, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index);
   }
 }
 
diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c
index ba4147e5cdbec204adc746698dc37694a49c0c71..bacc671adc62c0824444aea59c404e94ad03fdc9 100644
--- a/openair1/PHY/INIT/nr_parms.c
+++ b/openair1/PHY/INIT/nr_parms.c
@@ -75,9 +75,8 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp)
   return symbol;
 }
 
-void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw)
+void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL)
 {
-
   switch(mu) {
 
     case NR_MU_0: //15kHz scs
@@ -99,108 +98,17 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw)
 	else
 	  AssertFatal(1==0,"NR Operating Band n%d not available for SS block SCS with mu=%d\n", fp->nr_band, mu);
       }
-
-      switch(bw){
-        case 5:
-        case 15:
-        case 20:
-        case 25:
-        case 30:
-        case 40: //40 MHz
-          if (fp->threequarter_fs) {
-            fp->ofdm_symbol_size = 1536;
-            fp->first_carrier_offset = 900; //1536 - ( (106*12) / 2 )
-            fp->nb_prefix_samples0 = 132;
-            fp->nb_prefix_samples = 108;
-          }
-          else {
-            fp->ofdm_symbol_size = 2048;
-            fp->first_carrier_offset = 1412; //2048 - ( (106*12) / 2 )
-            fp->nb_prefix_samples0 = 176;
-            fp->nb_prefix_samples = 144;
-          }
-          break;
-
-        case 50:
-        case 60:
-        case 70:
-
-        case 80: //80 MHz
-          if (fp->threequarter_fs) {
-            fp->ofdm_symbol_size = 3072;
-            fp->first_carrier_offset = 1770; //3072 - ( (217*12) / 2 )
-            fp->nb_prefix_samples0 = 264;
-            fp->nb_prefix_samples = 216;
-          }
-	  else {
-	    fp->ofdm_symbol_size = 4096;
-	    fp->first_carrier_offset = 2794; //4096 - ( (217*12) / 2 )
-	    fp->nb_prefix_samples0 = 352;
-	    fp->nb_prefix_samples = 288;
-	  }
-          break;
-
-        case 90:
-	  AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for %d MHz band and MU %d\n",bw,mu); 
-	  fp->ofdm_symbol_size = 4096;
-	  fp->first_carrier_offset = 2626; //4096 - ( (245*12) / 2 )
-	  fp->nb_prefix_samples0 = 352;
-	  fp->nb_prefix_samples = 288;
-	  break;
-        case 100:
-	  AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for %d MHz band and MU %d\n",bw,mu); 
-	  fp->ofdm_symbol_size = 4096;
-	  fp->first_carrier_offset = 2458; //4096 - ( (273*12) / 2 )
-	  fp->nb_prefix_samples0 = 352;
-	  fp->nb_prefix_samples = 288;
-	  break;
-      default:
-        AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp);
-      }
       break;
 
     case NR_MU_2: //60kHz scs
       fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_2];
       fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_2];
-
-      switch(bw){ //FR1 bands only
-        case 10:
-        case 15:
-        case 20:
-        case 25:
-        case 30:
-        case 40:
-        case 50:
-        case 60:
-        case 70:
-        case 80:
-        case 90:
-        case 100:
-      default:
-        AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp);
-      }
       break;
 
     case NR_MU_3:
       fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_3];
       fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_3];
       fp->ssb_type = nr_ssb_type_D;
-      switch(bw){
-        case 100:
-          fp->ofdm_symbol_size = 1024;
-          fp->first_carrier_offset = 628; //1024 - ( (66*12) / 2 )
-          fp->nb_prefix_samples0 = 136;
-          fp->nb_prefix_samples = 72;
-          break;
-        case 50:
-          fp->ofdm_symbol_size = 512;
-          fp->first_carrier_offset = 320; //1024 - ( (66*12) / 2 )
-          fp->nb_prefix_samples0 = 68;
-          fp->nb_prefix_samples = 36;
-          break;
-      default:
-        AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp);
-      }
       break;
 
     case NR_MU_4:
@@ -209,9 +117,21 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw)
       fp->ssb_type = nr_ssb_type_E;
       break;
 
-  default:
-    AssertFatal(1==0,"Invalid numerology index %d", mu);
+    default:
+      AssertFatal(1==0,"Invalid numerology index %d", mu);
   }
+
+  if(fp->threequarter_fs)
+    fp->ofdm_symbol_size = 3 * 128;
+  else
+    fp->ofdm_symbol_size = 4 * 128;
+
+  while(fp->ofdm_symbol_size < N_RB_DL * 12)
+    fp->ofdm_symbol_size <<= 1;
+
+  fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2);
+  fp->nb_prefix_samples    = fp->ofdm_symbol_size / 128 * 9;
+  fp->nb_prefix_samples0   = fp->ofdm_symbol_size / 128 * (9 + (1 << mu));
 }
 
 uint32_t get_samples_per_slot(int slot, NR_DL_FRAME_PARMS* fp)
@@ -280,7 +200,7 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg,
   fp->half_frame_bit = 0;  // half frame bit initialized to 0 here
   fp->numerology_index = mu;
 
-  set_scs_parameters(fp, mu, cfg->carrier_config.dl_bandwidth.value);
+  set_scs_parameters(fp, mu, fp->N_RB_DL);
 
   fp->slots_per_frame = 10* fp->slots_per_subframe;
 
@@ -352,9 +272,8 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
   fp->N_RB_UL = config->carrier_config.ul_grid_size[fp->numerology_index];
   fp->N_RB_DL = config->carrier_config.dl_grid_size[fp->numerology_index];
 
-  int32_t uplink_frequency_offset = 0;
-  get_delta_duplex(fp->nr_band, fp->numerology_index, &uplink_frequency_offset);
-  get_frame_type(fp->nr_band, fp->numerology_index, &fp->frame_type);
+  fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index);
+  int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index);
   uplink_frequency_offset *= 1000;
 
   LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset);
@@ -374,7 +293,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
 
   fp->Ncp = Ncp;
 
-  set_scs_parameters(fp,fp->numerology_index,config->carrier_config.dl_bandwidth);
+  set_scs_parameters(fp, fp->numerology_index, fp->N_RB_DL);
 
   fp->slots_per_frame = 10* fp->slots_per_subframe;
   fp->symbols_per_slot = ((Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats
diff --git a/openair1/PHY/MODULATION/modulation_UE.h b/openair1/PHY/MODULATION/modulation_UE.h
index 72a1334fe99be0e88f67a26480897e74bc8bbbfa..20fdaa7ad84f0fef7433432c7ac0c847f9fd1f99 100644
--- a/openair1/PHY/MODULATION/modulation_UE.h
+++ b/openair1/PHY/MODULATION/modulation_UE.h
@@ -51,16 +51,13 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue,
 int nr_slot_fep(PHY_VARS_NR_UE *phy_vars_ue,
                 UE_nr_rxtx_proc_t *proc,
                 unsigned char l,
-                unsigned char Ns,
-                int sample_offset,
-                int no_prefix);
+                unsigned char Ns);
 
 int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
                           UE_nr_rxtx_proc_t *proc,
                           unsigned char symbol,
                           unsigned char Ns,
-                          int sample_offset,
-                          int no_prefix);
+                          int sample_offset);
 
 int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue,
                    unsigned char l,
diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c
index ed9a859fb64673c67faded9b0e33d4948b567a22..f12dcfc01bee9eddd3a76be29125925cf440ec42 100644
--- a/openair1/PHY/MODULATION/nr_modulation.c
+++ b/openair1/PHY/MODULATION/nr_modulation.c
@@ -591,35 +591,63 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH)
 }
 
 
-void init_symbol_rotation(NR_DL_FRAME_PARMS *fp,uint64_t CarrierFreq) {
+void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) {
+
+  uint64_t dl_CarrierFreq = fp->dl_CarrierFreq;
+  uint64_t ul_CarrierFreq = fp->ul_CarrierFreq;
+  double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq};
 
   const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10;
   const double Tc=(1/480e3/4096);
   const double Nu=2048*64*(1/(float)(1<<fp->numerology_index));
-  const double f0= (double)CarrierFreq;
   const double Ncp0=16*64 + (144*64*(1/(float)(1<<fp->numerology_index)));
   const double Ncp1=(144*64*(1/(float)(1<<fp->numerology_index)));
-  double tl=0,poff,exp_re,exp_im;
-  double Ncp,Ncpm1=Ncp0;
-
-  poff = 2*M_PI*((Ncp0*Tc))*f0;
-  exp_re = cos(poff);
-  exp_im = sin(-poff);
-  fp->symbol_rotation[0]=(int16_t)floor(exp_re*32767);
-  fp->symbol_rotation[1]=(int16_t)floor(exp_im*32767);
-  LOG_I(PHY,"Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n",f0,nsymb);
-  LOG_I(PHY,"Symbol rotation %d/%d => (%d,%d)\n",0,nsymb,fp->symbol_rotation[0],fp->symbol_rotation[1]);
-  for (int l=1;l<nsymb;l++) {
-    if (l==(7*(1<<fp->numerology_index))) Ncp=Ncp0;
-    else Ncp=Ncp1;
-    tl += (Nu+Ncpm1)*Tc;					     
-    poff = 2*M_PI*(tl + (Ncp*Tc))*f0;
-    exp_re = cos(poff);
-    exp_im = sin(-poff);
-    fp->symbol_rotation[l<<1]=(int16_t)floor(exp_re*32767);
-    fp->symbol_rotation[1+(l<<1)]=(int16_t)floor(exp_im*32767);
-    LOG_I(PHY,"Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",l,nsymb,tl,fp->symbol_rotation[l<<1],fp->symbol_rotation[1+(l<<1)],
-	  (poff/2/M_PI)-floor(poff/2/M_PI));
-    Ncpm1=Ncp;
+
+  for (uint8_t ll = 0; ll < 2; ll++){
+
+    double f0 = f[ll];
+    double Ncpm1 = Ncp0;
+    int16_t *symbol_rotation = fp->symbol_rotation[ll];
+
+    double tl = 0;
+    double poff = 2 * M_PI * ((Ncp0 * Tc)) * f0;
+    double exp_re = cos(poff);
+    double exp_im = sin(-poff);
+    symbol_rotation[0] = (int16_t)floor(exp_re * 32767);
+    symbol_rotation[1] = (int16_t)floor(exp_im * 32767);
+    LOG_I(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb);
+    LOG_I(PHY, "Symbol rotation %d/%d => (%d,%d)\n",
+      0,
+      nsymb,
+      symbol_rotation[0],
+      symbol_rotation[1]);
+
+    for (int l = 1; l < nsymb; l++) {
+
+      double Ncp;
+      if (l == (7 * (1 << fp->numerology_index))) {
+        Ncp = Ncp0;
+      } else {
+        Ncp = Ncp1;
+      }
+
+      tl += (Nu + Ncpm1) * Tc;
+      poff = 2 * M_PI * (tl + (Ncp * Tc)) * f0;
+      exp_re = cos(poff);
+      exp_im = sin(-poff);
+      symbol_rotation[l<<1] = (int16_t)floor(exp_re * 32767);
+      symbol_rotation[1 + (l<<1)] = (int16_t)floor(exp_im * 32767);
+
+      LOG_I(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",
+        l,
+        nsymb,
+        tl,
+        symbol_rotation[l<<1],
+        symbol_rotation[1 + (l<<1)],
+        (poff / 2 / M_PI) - floor(poff / 2 / M_PI));
+
+      Ncpm1 = Ncp;
+
+    }
   }
 }
diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h
index 3d2be905ac48bfba1ba236a64dbc08030057c17f..841073a1af56a84edd7501cfa46cb7e3bf98a6b9 100644
--- a/openair1/PHY/MODULATION/nr_modulation.h
+++ b/openair1/PHY/MODULATION/nr_modulation.h
@@ -74,7 +74,6 @@ void nr_ue_layer_mapping(NR_UE_ULSCH_t **ulsch_ue,
 \param symbol symbol within slot (0..12/14)
 \param Ns Slot number (0..19)
 \param sample_offset offset within rxdata (points to beginning of subframe)
-\param no_prefix if 1 prefix is removed by HW
 */
 
 int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms,
@@ -82,8 +81,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms,
                    int32_t *rxdataF,
                    unsigned char symbol,
                    unsigned char Ns,
-                   int sample_offset,
-                   int no_prefix);
+                   int sample_offset);
 
 /*!
 \brief This function implements the dft transform precoding in PUSCH
@@ -110,7 +108,7 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
 		       int nsymb,
 		       int length);
 
-void init_symbol_rotation(NR_DL_FRAME_PARMS *fp,uint64_t CarrierFreq);
+void init_symbol_rotation(NR_DL_FRAME_PARMS *fp);
 
 void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms,
 			  int32_t *rxdataF,
diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c
index 2d86b46742449b308ee24c93de1225b5ebe19a66..8cf9f05b9b63acd4bd4bab2e0f0296013a279302 100644
--- a/openair1/PHY/MODULATION/ofdm_mod.c
+++ b/openair1/PHY/MODULATION/ofdm_mod.c
@@ -306,15 +306,23 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp,
 		       int length) {
   int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot;
 
+  int16_t *symbol_rotation = fp->symbol_rotation[0];
+
   for (int sidx=0;sidx<nsymb;sidx++) {
+
     LOG_D(PHY,"Rotating symbol %d, slot %d, symbol_subframe_index %d, length %d (%d,%d)\n",
-	  first_symbol+sidx,slot,sidx+first_symbol+symb_offset,length,
-	  fp->symbol_rotation[2*(sidx+first_symbol+symb_offset)],fp->symbol_rotation[1+2*(sidx+first_symbol+symb_offset)]);
-    rotate_cpx_vector(trxdata+(sidx*length*2),
-		      &fp->symbol_rotation[2*(sidx+first_symbol+symb_offset)],
-		      trxdata+(sidx*length*2),
-		      length,
-		      15);
+      first_symbol + sidx,
+      slot,
+      sidx + first_symbol + symb_offset,
+      length,
+      symbol_rotation[2 * (sidx + first_symbol + symb_offset)],
+      symbol_rotation[1 + 2 * (sidx + first_symbol + symb_offset)]);
+
+    rotate_cpx_vector(trxdata + (sidx * length * 2),
+                      &symbol_rotation[2 * (sidx + first_symbol + symb_offset)],
+                      trxdata + (sidx * length * 2),
+                      length,
+                      15);
   }
 }
 		       
diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c
index 60b28d4ad18da254f99854369c028e134d014c1a..0be635ba0b052175c614ee5b858f96b079fa4612 100644
--- a/openair1/PHY/MODULATION/slot_fep_nr.c
+++ b/openair1/PHY/MODULATION/slot_fep_nr.c
@@ -29,364 +29,229 @@
 
 //#define DEBUG_FEP
 
-#define SOFFSET 0
-
 /*#ifdef LOG_I
 #undef LOG_I
 #define LOG_I(A,B...) printf(A)
 #endif*/
 
-int nr_slot_fep(PHY_VARS_NR_UE *ue,
-                UE_nr_rxtx_proc_t *proc,
-                unsigned char symbol,
-                unsigned char Ns,
-                int sample_offset,
-                int no_prefix)
+dft_size_idx_t get_dft_size_idx(uint16_t ofdm_symbol_size)
 {
-  NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
-  NR_UE_COMMON *common_vars   = &ue->common_vars;
-  unsigned char aa;
-  unsigned int nb_prefix_samples;
-  unsigned int nb_prefix_samples0;
-  unsigned int abs_symbol;
-  if (ue->is_synchronized) {
-    nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples);
-    nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0);
-  }
-  else {
-    nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples);
-    nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples);
-  }
-  //unsigned int subframe_offset;//,subframe_offset_F;
-  unsigned int slot_offset;
-  //int i;
-  unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10;
-  unsigned int rx_offset;
-
-
-  dft_size_idx_t dftsize;
-  int tmp_dft_in[8192] __attribute__ ((aligned (32)));  // This is for misalignment issues for 6 and 15 PRBs
-
-  switch (frame_parms->ofdm_symbol_size) {
+  switch (ofdm_symbol_size) {
   case 128:
-    dftsize = DFT_128;
-    break;
+    return DFT_128;
 
   case 256:
-    dftsize = DFT_256;
-    break;
+    return DFT_256;
 
   case 512:
-    dftsize = DFT_512;
-    break;
+    return DFT_512;
 
   case 1024:
-    dftsize = DFT_1024;
-    break;
+    return DFT_1024;
 
   case 1536:
-    dftsize = DFT_1536;
-    break;
+    return DFT_1536;
 
   case 2048:
-    dftsize = DFT_2048;
-    break;
+    return DFT_2048;
 
   case 3072:
-    dftsize = DFT_3072;
-    break;
+    return DFT_3072;
 
   case 4096:
-    dftsize = DFT_4096;
-    break;
+    return DFT_4096;
+
+  case 6144:
+    return DFT_6144;
 
   case 8192:
-    dftsize = DFT_8192;
-    break;
+    return DFT_8192;
 
   default:
     printf("unsupported ofdm symbol size \n");
     assert(0);
   }
 
-  if (no_prefix) {
-    slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot) * (Ns);
-  } else {
-    slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0);
-  }
+  return DFT_SIZE_IDXTABLESIZE;
+}
 
-  /*if (l<0 || l>=7-frame_parms->Ncp) {
-    printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp);
-    return(-1);
-    }*/
+int nr_slot_fep(PHY_VARS_NR_UE *ue,
+                UE_nr_rxtx_proc_t *proc,
+                unsigned char symbol,
+                unsigned char Ns)
+{
+  NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
+  NR_UE_COMMON *common_vars      = &ue->common_vars;
 
-  if (Ns<0 || Ns>(frame_parms->slots_per_frame-1)) {
-    printf("slot_fep: Ns must be between 0 and %d\n",frame_parms->slots_per_frame-1);
-    return(-1);
+  AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1);
+  AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame-1);
+
+  unsigned int nb_prefix_samples;
+  unsigned int nb_prefix_samples0;
+  if (ue->is_synchronized) {
+    nb_prefix_samples  = frame_parms->nb_prefix_samples;
+    nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
+  } else {
+    nb_prefix_samples  = frame_parms->nb_prefix_samples;
+    nb_prefix_samples0 = frame_parms->nb_prefix_samples;
   }
 
-  for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
-    memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int));
+  dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size);
+  // This is for misalignment issues
+  int32_t tmp_dft_in[8192] __attribute__ ((aligned (32)));
 
-    rx_offset = sample_offset + slot_offset - SOFFSET;
-    // Align with 256 bit
-    //    rx_offset = rx_offset&0xfffffff8;
+  unsigned int rx_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0);
+  unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol;
+  for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
+    rx_offset += (idx_symb%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
+  rx_offset += frame_parms->ofdm_symbol_size * symbol;
+
+  // use OFDM symbol from within 1/8th of the CP to avoid ISI
+  rx_offset -= nb_prefix_samples / 8;
 
 #ifdef DEBUG_FEP
-      //  if (ue->frame <100)
-    /*LOG_I(PHY,*/printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n",
-			 Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples);
+  //  if (ue->frame <100)
+  printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u\n",
+         Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset);
 #endif
 
-    abs_symbol = Ns * frame_parms->symbols_per_slot + symbol;
-    
-    for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb < abs_symbol; idx_symb++)
-      rx_offset += (idx_symb%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
-
-    rx_offset += frame_parms->ofdm_symbol_size * symbol;
-
-    if (abs_symbol%(0x7<<frame_parms->numerology_index)) {
-
-      rx_offset += nb_prefix_samples;
-      if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size))
-        memcpy((short*) &common_vars->rxdata[aa][frame_length_samples],
-               (short*) &common_vars->rxdata[aa][0],
-               frame_parms->ofdm_symbol_size*sizeof(int));
-
-      if ((rx_offset&7)!=0) {  // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs
-        memcpy((void *)tmp_dft_in,
-               (void *) &common_vars->rxdata[aa][rx_offset % frame_length_samples],
-               frame_parms->ofdm_symbol_size*sizeof(int));
-        dft(dftsize,(int16_t *)tmp_dft_in,
-            (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
-      } else { // use dft input from RX buffer directly
-#if UE_TIMING_TRACE
-          start_meas(&ue->rx_dft_stats);
-#endif
+  for (unsigned char aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
+    memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
 
-        dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
-            (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
-#if UE_TIMING_TRACE
-        stop_meas(&ue->rx_dft_stats);
-#endif
-      }
-    } else {
+    int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset];
+
+    // if input to dft is not 256-bit aligned
+    if ((rx_offset & 7) != 0) {
+      memcpy((void *)&tmp_dft_in[0],
+             (void *)&common_vars->rxdata[aa][rx_offset],
+             frame_parms->ofdm_symbol_size * sizeof(int32_t));
+
+      rxdata_ptr = (int16_t *)tmp_dft_in;
+    }
 
-      rx_offset += nb_prefix_samples0;
-      if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size))
-        memcpy((void *) &common_vars->rxdata[aa][frame_length_samples],
-               (void *) &common_vars->rxdata[aa][0],
-               frame_parms->ofdm_symbol_size*sizeof(int));
 #if UE_TIMING_TRACE
-      start_meas(&ue->rx_dft_stats);
+    start_meas(&ue->rx_dft_stats);
 #endif
 
-      if ((rx_offset&7)!=0) {  // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs
-        memcpy((void *)tmp_dft_in,
-               (void *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
-               frame_parms->ofdm_symbol_size*sizeof(int));
-        dft(dftsize,(int16_t *)tmp_dft_in,
-            (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
-      } else { // use dft input from RX buffer directly
-
-        dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
-            (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
-      }
+    dft(dftsize,
+        rxdata_ptr,
+        (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
+        1);
+
 #if UE_TIMING_TRACE
-      stop_meas(&ue->rx_dft_stats);
+    stop_meas(&ue->rx_dft_stats);
 #endif
 
-
-    }
+    int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
+    int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol+symb_offset];
+    ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
 
 #ifdef DEBUG_FEP
     //  if (ue->frame <100)
-    printf("slot_fep: symbol %d rx_offset %u\n", symbol, rx_offset);
+    printf("slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset,
+	   symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]);
 #endif
-    
-    int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
-    int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset];
-    ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
+
     rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
 		      (int16_t*)&rot2,
 		      (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
 		      frame_parms->ofdm_symbol_size,
 		      15);
-    
   }
-  
 
 #ifdef DEBUG_FEP
   printf("slot_fep: done\n");
 #endif
-  return(0);
+
+  return 0;
 }
 
 int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
                           UE_nr_rxtx_proc_t *proc,
                           unsigned char symbol,
                           unsigned char Ns,
-                          int sample_offset,
-                          int no_prefix)
+                          int sample_offset)
 {
   NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
   NR_UE_COMMON *common_vars   = &ue->common_vars;
-  unsigned char aa;
+
+  AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1);
+  AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame-1);
+
   unsigned int nb_prefix_samples;
   unsigned int nb_prefix_samples0;
-  unsigned int abs_symbol;
   if (ue->is_synchronized) {
-    nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples);
-    nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0);
+    nb_prefix_samples  = frame_parms->nb_prefix_samples;
+    nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
   }
   else {
-    nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples);
-    nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples);
+    nb_prefix_samples  = frame_parms->nb_prefix_samples;
+    nb_prefix_samples0 = frame_parms->nb_prefix_samples;
   }
-  //unsigned int subframe_offset;//,subframe_offset_F;
-  unsigned int slot_offset;
-  //int i;
-  unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10;
-  unsigned int rx_offset;
-
-
-  dft_size_idx_t dftsize;
-  int tmp_dft_in[8192] __attribute__ ((aligned (32)));  // This is for misalignment issues for 6 and 15 PRBs
-
-  switch (frame_parms->ofdm_symbol_size) {
-  case 128:
-    dftsize = DFT_128;
-    break;
-
-  case 256:
-    dftsize = DFT_256;
-    break;
-
-  case 512:
-    dftsize = DFT_512;
-    break;
+  unsigned int frame_length_samples = frame_parms->samples_per_frame;
 
-  case 1024:
-    dftsize = DFT_1024;
-    break;
+  dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size);
+  // This is for misalignment issues
+  int32_t tmp_dft_in[8192] __attribute__ ((aligned (32)));
 
-  case 1536:
-    dftsize = DFT_1536;
-    break;
-
-  case 2048:
-    dftsize = DFT_2048;
-    break;
+  unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0);
+  unsigned int rx_offset   = sample_offset + slot_offset;
+  unsigned int abs_symbol  = Ns * frame_parms->symbols_per_slot + symbol;
+  for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++)
+    rx_offset += (abs_symbol%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
+  rx_offset += frame_parms->ofdm_symbol_size * symbol;
 
-  case 3072:
-    dftsize = DFT_3072;
-    break;
+#ifdef DEBUG_FEP
+  //  if (ue->frame <100)
+  printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n",
+         Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples);
+#endif
 
-  case 4096:
-    dftsize = DFT_4096;
-    break;
+  for (unsigned char aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
+    memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
 
-  case 8192:
-    dftsize = DFT_8192;
-    break;
+    int16_t *rxdata_ptr;
 
-  default:
-    printf("unsupported ofdm symbol size \n");
-    assert(0);
-  }
-
-  if (no_prefix) {
-    slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot) * (Ns);
-  } else {
-    slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0);
-  }
+    if (frame_length_samples - rx_offset < frame_parms->ofdm_symbol_size) {
 
-  /*if (l<0 || l>=7-frame_parms->Ncp) {
-    printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp);
-    return(-1);
-    }*/
+      memcpy((void *)&tmp_dft_in[0],
+             (void *)&common_vars->rxdata[aa][rx_offset],
+             (frame_length_samples - rx_offset) * sizeof(int32_t));
+      memcpy((void *)&tmp_dft_in[frame_length_samples - rx_offset],
+             (void *)&common_vars->rxdata[aa][0],
+             (frame_parms->ofdm_symbol_size - (frame_length_samples - rx_offset)) * sizeof(int32_t));
+      rxdata_ptr = (int16_t *)&tmp_dft_in[0];
 
-  if (Ns<0 || Ns>(frame_parms->slots_per_frame-1)) {
-    printf("slot_fep: Ns must be between 0 and %d\n",frame_parms->slots_per_frame-1);
-    return(-1);
-  }
+    } else if ((rx_offset & 7) != 0) {
 
-  for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
-    memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int));
+      // if input to dft is not 256-bit aligned
+      memcpy((void *)&tmp_dft_in[0],
+             (void *)&common_vars->rxdata[aa][rx_offset],
+             frame_parms->ofdm_symbol_size * sizeof(int32_t));
+      rxdata_ptr = (int16_t *)&tmp_dft_in[0];
 
-    rx_offset = sample_offset + slot_offset - SOFFSET;
-    // Align with 256 bit
-    //    rx_offset = rx_offset&0xfffffff8;
-
-#ifdef DEBUG_FEP
-      //  if (ue->frame <100)
-    /*LOG_I(PHY,*/printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n",
-    		Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples);
-#endif
+    } else {
 
-    abs_symbol = Ns * frame_parms->symbols_per_slot + symbol;
-    
-    for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb < abs_symbol; idx_symb++)
-      rx_offset += (abs_symbol%(0x7<<frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0;
-
-    rx_offset += frame_parms->ofdm_symbol_size * symbol;
-
-    if (abs_symbol%(0x7<<frame_parms->numerology_index)) {
-
-      rx_offset += nb_prefix_samples;
-      if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size))
-        memcpy((short*) &common_vars->rxdata[aa][frame_length_samples],
-               (short*) &common_vars->rxdata[aa][0],
-               frame_parms->ofdm_symbol_size*sizeof(int));
-
-      if ((rx_offset&7)!=0) {  // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs
-        memcpy((void *)tmp_dft_in,
-               (void *) &common_vars->rxdata[aa][rx_offset],
-               frame_parms->ofdm_symbol_size*sizeof(int));
-        dft(dftsize,(int16_t *)tmp_dft_in,
-            (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
-      } else { // use dft input from RX buffer directly
-#if UE_TIMING_TRACE
-          start_meas(&ue->rx_dft_stats);
-#endif
+      // use dft input from RX buffer directly
+      rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset];
 
+    }
 
-        dft(dftsize,(int16_t *) &common_vars->rxdata[aa][rx_offset],
-            (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
 #if UE_TIMING_TRACE
-        stop_meas(&ue->rx_dft_stats);
+    start_meas(&ue->rx_dft_stats);
 #endif
-      }
-    } else {
 
-      rx_offset += nb_prefix_samples0;
-      if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size))
-        memcpy((void *) &common_vars->rxdata[aa][frame_length_samples],
-               (void *) &common_vars->rxdata[aa][0],
-               frame_parms->ofdm_symbol_size*sizeof(int));
-#if UE_TIMING_TRACE
-      start_meas(&ue->rx_dft_stats);
-#endif
+    dft(dftsize,
+        rxdata_ptr,
+        (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
+        1);
 
-      if ((rx_offset&7)!=0) {  // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs
-        memcpy((void *)tmp_dft_in,
-               (void *) &common_vars->rxdata[aa][rx_offset],
-               frame_parms->ofdm_symbol_size*sizeof(int));
-        dft(dftsize,(int16_t *)tmp_dft_in,
-            (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
-      } else { // use dft input from RX buffer directly
-        dft(dftsize,(int16_t *) &common_vars->rxdata[aa][rx_offset],
-            (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
-      }
 #if UE_TIMING_TRACE
-      stop_meas(&ue->rx_dft_stats);
+    stop_meas(&ue->rx_dft_stats);
 #endif
 
-
-    }
-
     int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
-    int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset];
+    int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol + symb_offset];
     ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
 
 #ifdef DEBUG_FEP
@@ -400,14 +265,13 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
 		      (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],
 		      frame_parms->ofdm_symbol_size,
 		      15);
-    
   }
 
-
 #ifdef DEBUG_FEP
   printf("slot_fep: done\n");
 #endif
-  return(0);
+
+  return 0;
 }
 
 
@@ -416,89 +280,60 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms,
                    int32_t *rxdataF,
                    unsigned char symbol,
                    unsigned char Ns,
-                   int sample_offset,
-                   int no_prefix)
+                   int sample_offset)
 {
-  int32_t slot_offset, rxdata_offset;
-
-  unsigned int nb_prefix_samples  = (no_prefix ? 0 : frame_parms->nb_prefix_samples);
-  unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0);
+  unsigned int nb_prefix_samples  = frame_parms->nb_prefix_samples;
+  unsigned int nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
   
-  int tmp_dft_in[8192] __attribute__ ((aligned (32)));
+  dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size);
+  // This is for misalignment issues
+  int32_t tmp_dft_in[8192] __attribute__ ((aligned (32)));
 
-  dft_size_idx_t dftsize;
+  unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0);
 
-  switch (frame_parms->ofdm_symbol_size) {
-    case 128:
-      dftsize = DFT_128;
-      break;
+  // offset of first OFDM symbol
+  int32_t rxdata_offset = slot_offset + nb_prefix_samples0;
+  // offset of n-th OFDM symbol
+  rxdata_offset += symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples);
+  // use OFDM symbol from within 1/8th of the CP to avoid ISI
+  rxdata_offset -= nb_prefix_samples / 8;
 
-    case 256:
-      dftsize = DFT_256;
-      break;
+  int16_t *rxdata_ptr;
 
-    case 512:
-      dftsize = DFT_512;
-      break;
+  if(sample_offset > rxdata_offset) {
 
-    case 1024:
-      dftsize = DFT_1024;
-      break;
+    memcpy((void *)&tmp_dft_in[0],
+           (void *)&rxdata[frame_parms->samples_per_frame - sample_offset + rxdata_offset],
+           (sample_offset - rxdata_offset) * sizeof(int32_t));
+    memcpy((void *)&tmp_dft_in[sample_offset - rxdata_offset],
+           (void *)&rxdata[0],
+           (frame_parms->ofdm_symbol_size - sample_offset + rxdata_offset) * sizeof(int32_t));
+    rxdata_ptr = (int16_t *)&tmp_dft_in[0];
 
-    case 1536:
-      dftsize = DFT_1536;
-      break;
+  } else if (((rxdata_offset - sample_offset) & 7) != 0) {
 
-    case 2048:
-      dftsize = DFT_2048;
-      break;
+    // if input to dft is not 256-bit aligned
+    memcpy((void *)&tmp_dft_in[0],
+           (void *)&rxdata[rxdata_offset - sample_offset],
+           (frame_parms->ofdm_symbol_size) * sizeof(int32_t));
+    rxdata_ptr = (int16_t *)&tmp_dft_in[0];
 
-    case 4096:
-      dftsize = DFT_4096;
-      break;
+  } else {
 
-    case 8192:
-      dftsize = DFT_8192;
-      break;
+    // use dft input from RX buffer directly
+    rxdata_ptr = (int16_t *)&rxdata[rxdata_offset - sample_offset];
 
-    default:
-      dftsize = DFT_512;
-      break;
   }
-  
-  slot_offset   = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0);
 
-  if(symbol == 0)
-    rxdata_offset = slot_offset + nb_prefix_samples0 - SOFFSET;
-  else
-    rxdata_offset = slot_offset + nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples)) - SOFFSET;
-
-  if(sample_offset>rxdata_offset) {
-    memcpy1((void *)tmp_dft_in,
-           (void *) &rxdata[frame_parms->samples_per_frame-sample_offset+rxdata_offset],
-           (sample_offset-rxdata_offset)*sizeof(int));
-
-    memcpy1((void *)&tmp_dft_in[sample_offset-rxdata_offset],
-           (void *) &rxdata[0],
-           (frame_parms->ofdm_symbol_size-sample_offset+rxdata_offset)*sizeof(int));
-
-    dft(dftsize,(int16_t *)&tmp_dft_in,
-        (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1);
-  }
-  else {
-    //dft(dftsize,(int16_t *)&rxdata[rxdata_offset-sample_offset],
-      //  (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1);
-    memcpy((void *)tmp_dft_in,
-           (void *) &rxdata[rxdata_offset-sample_offset],
-           (frame_parms->ofdm_symbol_size)*sizeof(int));
-    dft(dftsize,(int16_t *)&tmp_dft_in,
-        (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1);
-  }
+  dft(dftsize,
+      rxdata_ptr,
+      (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size],
+      1);
 
   // clear DC carrier from OFDM symbols
   rxdataF[symbol * frame_parms->ofdm_symbol_size] = 0;
 
-  return(0);
+  return 0;
 }
 
 void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms,
@@ -513,7 +348,7 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms,
 
   for (int symbol=0;symbol<nsymb;symbol++) {
     
-    uint32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset];
+    uint32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[1])[symbol + symb_offset];
     ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1];
     LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]);
     rotate_cpx_vector((int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol],
diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c
index ec55eabf313378d49dc68a57d70c3e55e4dae520..a54aec7bc2f3946c755e38fa65ad1f41b0ca9121 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c
@@ -37,22 +37,20 @@
 
 int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id)
 {
-  int temp, i, aa, max_pos = 0, max_val = 0;
-  short Re, Im;
-  uint8_t cyclic_shift = 0;
+  int i, aa, max_pos = 0, max_val = 0;
   
   NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
   NR_gNB_PUSCH *gNB_pusch_vars   = gNB->pusch_vars[UE_id];
   int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time;
   
-  int sync_pos = (frame_parms->ofdm_symbol_size - cyclic_shift*frame_parms->ofdm_symbol_size/12) % (frame_parms->ofdm_symbol_size);
+  int sync_pos = frame_parms->nb_prefix_samples / 8;
 
   for (i = 0; i < frame_parms->ofdm_symbol_size; i++) {
-    temp = 0;
+    int temp = 0;
 
     for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
-      Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)];
-      Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)];
+      short Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)];
+      short Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)];
       temp += (Re*Re/2) + (Im*Im/2);      
     }
 
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
index 38b35dcf6d39a93969b7b3f1ee3cbb73158e7622..10ac23bef0b769d870352ae8ba5d7b964a0df10c 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
@@ -61,8 +61,6 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
   debug_ch_est = fopen("debug_ch_est.txt","w");
 #endif
 
-  //uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1];
-
   uint8_t nushift;
   int **ul_ch_estimates  = gNB->pusch_vars[ul_id]->ul_ch_estimates;
   int **rxdataF = gNB->common_vars.rxdataF;
@@ -79,12 +77,17 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
 
   uint16_t nb_rb_pusch = pusch_pdu->rb_size;
 
-/*
 #ifdef DEBUG_CH
-  printf("PUSCH Channel Estimation : ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n", ,ch_offset,symbol_offset,gNB->frame_parms.ofdm_symbol_size,
-         gNB->frame_parms.Ncp,l,Ns,k, symbol);
+  LOG_D(PHY, "In %s: ch_offset %d, symbol_offset %d OFDM size %d, Ns = %d, k = %d symbol %d\n",
+        __FUNCTION__,
+        ch_offset,
+        symbol_offset,
+        gNB->frame_parms.ofdm_symbol_size,
+        Ns,
+        k,
+        symbol);
 #endif
-*/
+
   switch (nushift) {
    case 0:
          fl = filt8_l0;
@@ -124,9 +127,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
 
   //------------------generate DMRS------------------//
 
-  if (pusch_pdu->transform_precoding == transform_precoder_disabled) 
+  if (pusch_pdu->transform_precoding == transform_precoder_disabled) {
     nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, pusch_pdu->rb_start*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type);
-  
+  }
   else {  // if transform precoding or SC-FDMA is enabled in Uplink
 
     // NR_SC_FDMA supports type1 DMRS so only 6 DMRS REs per RB possible
@@ -151,11 +154,15 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
   //------------------------------------------------//
 
 
-
 #ifdef DEBUG_PUSCH
-  for (int i=0;i<(6*nb_rb_pusch);i++)
-    printf("%d+j*(%d)\n",((int16_t*)pilot)[2*i],((int16_t*)pilot)[1+(2*i)]);
+  for (int i = 0; i < (6 * nb_rb_pusch); i++) {
+    LOG_I(PHY, "In %s: %d + j*(%d)\n",
+      __FUNCTION__,
+      ((int16_t*)pilot)[2 * i],
+      ((int16_t*)pilot)[1 + (2 * i)]);
+  }
 #endif
+
   for (aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {
 
     re_offset = k;   /* Initializing the Resource element offset for each Rx antenna */
@@ -167,11 +174,11 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
     memset(ul_ch,0,4*(gNB->frame_parms.ofdm_symbol_size));
 
 #ifdef DEBUG_PUSCH
-    printf("symbol_offset %d, nushift %d\n",symbol_offset,nushift);
-    printf("ch est pilot addr %p RB_DL %d\n",&pilot[0], gNB->frame_parms.N_RB_UL);
-    printf("bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n",bwp_start_subcarrier,k,gNB->frame_parms.first_carrier_offset,nb_rb_pusch);
-    printf("rxF addr %p p %d\n", rxF,p);
-    printf("ul_ch addr %p nushift %d\n",ul_ch,nushift);
+    LOG_I(PHY, "In %s symbol_offset %d, nushift %d\n", __FUNCTION__, symbol_offset, nushift);
+    LOG_I(PHY, "In %s ch est pilot addr %p, N_RB_UL %d\n", __FUNCTION__, &pilot[0], gNB->frame_parms.N_RB_UL);
+    LOG_I(PHY, "In %s bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k, gNB->frame_parms.first_carrier_offset, nb_rb_pusch);
+    LOG_I(PHY, "In %s rxF addr %p p %d\n", __FUNCTION__, rxF, p);
+    LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift);
 #endif
     //if ((gNB->frame_parms.N_RB_UL&1)==0) {
 
@@ -182,9 +189,18 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
       ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
 
 #ifdef DEBUG_PUSCH
-      printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
-      printf("pilot 0 : rxF - > (%d,%d) (%d)  ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
-      printf("data 0 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
+      LOG_I(PHY, "In %s ch 0 %d\n", __FUNCTION__, ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
+      LOG_I(PHY, "In %s pilot 0 : rxF - > (%d,%d) (%d)  ch -> (%d,%d) (%d), pil -> (%d,%d) \n",
+        __FUNCTION__,
+        rxF[0],
+        rxF[1],
+        dBc(rxF[0],rxF[1]),
+        ch[0],
+        ch[1],
+        dBc(ch[0],ch[1]),
+        pil[0],
+        pil[1]);
+      LOG_I(PHY, "In %s data 0 : rxF - > (%d,%d) (%d)\n", __FUNCTION__, rxF[2], rxF[3], dBc(rxF[2],rxF[3]));
 #endif
 
       multadd_real_vector_complex_scalar(fl,
@@ -201,9 +217,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
       ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
 
 #ifdef DEBUG_PUSCH
-      printf("pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
-      printf("data 1 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
+      LOG_I(PHY, "In %s pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",
+        __FUNCTION__,
+        rxF[0],
+        rxF[1],
+        dBc(rxF[0],rxF[1]),
+        ch[0],
+        ch[1],
+        dBc(ch[0],ch[1]),
+        pil[0],
+        pil[1]);
+      LOG_I(PHY, "In %s data 1 : rxF - > (%d,%d) (%d)\n",
+        __FUNCTION__,
+        rxF[2],
+        rxF[3],
+        dBc(rxF[2],rxF[3]));
 #endif
+
       multadd_real_vector_complex_scalar(fml,
                                          ch,
                                          ul_ch,
@@ -217,9 +247,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
       ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
 
 #ifdef DEBUG_PUSCH
-      printf("pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
-      printf("data 2 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
+      LOG_I(PHY, "In %s pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",
+        __FUNCTION__,
+        rxF[0],
+        rxF[1],
+        dBc(rxF[0],rxF[1]),
+        ch[0],
+        ch[1],
+        dBc(ch[0],ch[1]),
+        pil[0],
+        pil[1]);
+      LOG_I(PHY, "In %s data 2 : rxF - > (%d,%d) (%d)\n",
+        __FUNCTION__,
+        rxF[2],
+        rxF[3],
+        dBc(rxF[2],rxF[3]));
 #endif
+
       multadd_real_vector_complex_scalar(fmm,
                                          ch,
                                          ul_ch,
diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c
index 5d62f9dbb9b8f1736904ff62d98a614a59204d20..5a4b1adbb84ff7dc7a273f223606d058e7ce615d 100644
--- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c
+++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c
@@ -40,9 +40,9 @@
 #include "PHY/defs_gNB.h"
 
 /*Table 7.4.1.1.2-1/2 from 38.211 */
-int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1}};
+int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}};
 int wt1[8][2] = {{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1}};
-int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1},{1,1},{1,-1},{1,1},{1,1}};
+int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}};
 int wt2[12][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1}};
 
 // complex conjugate of mod table
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
index 1cce5e117465f125538e57f48f1cd2d6f3fdf8a3..66fc987f6db298b8ecefc6a36c758ff52d5f975b 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
@@ -147,19 +147,18 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
     uint16_t n_dmrs;
     if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) {
       nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData;
-      n_dmrs = ((rel15->rbSize+rel15->rbStart)*6)<<1;
     }
     else {
       nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData;
-      n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1;
     }
+    n_dmrs = (rel15->rbSize+rel15->rbStart)*nb_re_dmrs;
 
     uint16_t dmrs_symbol_map = rel15->dlDmrsSymbPos;//single DMRS: 010000100 Double DMRS 110001100
     uint8_t dmrs_len = get_num_dmrs(rel15->dlDmrsSymbPos);
     uint16_t nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs*dmrs_len-xOverhead)*rel15->rbSize*rel15->nrOfLayers;
     uint8_t Qm = rel15->qamModOrder[0];
     uint32_t encoded_length = nb_re*Qm;
-    int16_t mod_dmrs[14][n_dmrs] __attribute__ ((aligned(16)));
+    int16_t mod_dmrs[14][n_dmrs<<1] __attribute__ ((aligned(16)));
 
     /* PTRS */
     uint16_t beta_ptrs = 1;
@@ -271,10 +270,10 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
     /// DMRS QPSK modulation
     for (int l=rel15->StartSymbolIndex; l<rel15->StartSymbolIndex+rel15->NrOfSymbols; l++) {
       if (rel15->dlDmrsSymbPos & (1 << l)) {
-        nr_modulation(pdsch_dmrs[l][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
+        nr_modulation(pdsch_dmrs[l][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
 
 #ifdef DEBUG_DLSCH
-        printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs>>1, dmrs_Type);
+        printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs, dmrs_Type);
         for (int i=0; i<n_dmrs>>4; i++) {
           for (int j=0; j<8; j++) {
             printf("%d %d\t", mod_dmrs[l][((i<<3)+j)<<1], mod_dmrs[l][(((i<<3)+j)<<1)+1]);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c
index b5a3c061e9f4abbacd35d07186819a59209e106d..64b14091d6298c6e70e9de4d7862d652391050cd 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_prach.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c
@@ -301,205 +301,300 @@ void rx_nr_prach_ru(RU_t *ru,
 
     // do DFT
     if (mu==1) {
-    if (fp->N_RB_UL <= 100)
-      AssertFatal(1==0,"N_RB_UL %d not support for NR PRACH yet\n",fp->N_RB_UL);
-    else if (fp->N_RB_UL < 137) {
-      if (fp->threequarter_fs==0) { 
-	//40 MHz @ 61.44 Ms/s 
-	//50 MHz @ 61.44 Ms/s
-	prach2 = prach[aa] + (Ncp<<2); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 to bring to 61.44 Ms/s
-	if (prach_sequence_length == 0) {
-	  if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
-            dftlen=49152;
-            dft(DFT_49152,prach2,rxsigF[aa],1);
+      switch(fp->samples_per_subframe) {
+        case 15360:
+          // 10, 15 MHz @ 15.36 Ms/s
+          prach2 = prach[aa] + (1*Ncp); // Ncp is for 30.72 Ms/s, so divide by 2 to bring to 15.36 Ms/s and multiply by 2 for I/Q
+          if (prach_sequence_length == 0) {
+            if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
+              dftlen=12288;
+              dft(DFT_12288,prach2,rxsigF[aa],1);
+            }
+            if (prachFormat == 1 || prachFormat == 2) {
+              dft(DFT_12288,prach2+24576,rxsigF[aa]+24576,1);
+              reps++;
+            }
+            if (prachFormat == 2) {
+              dft(DFT_12288,prach2+(24576*2),rxsigF[aa]+(24576*2),1);
+              dft(DFT_12288,prach2+(24576*3),rxsigF[aa]+(24576*3),1);
+              reps+=2;
+            }
+            if (prachFormat == 3) {
+              dftlen=3072;
+              for (int i=0;i<4;i++) dft(DFT_3072,prach2+(i*3072*2),rxsigF[aa]+(i*3072*2),1);
+              reps=4;
+            }
+          } else { // 839 sequence
+            if (prachStartSymbol == 0) prach2+=16; // 8 samples @ 15.36 Ms/s in first symbol of each half subframe (15/30 kHz only)
+
+            dftlen=512;
+            dft(DFT_512,prach2,rxsigF[aa],1);
+            if (prachFormat != 9/*C0*/) {
+              dft(DFT_512,prach2+1024,rxsigF[aa]+1024,1);
+              reps++;
+            }
+            if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
+              dft(DFT_512,prach2+1024*2,rxsigF[aa]+1024*2,1);
+              dft(DFT_512,prach2+1024*3,rxsigF[aa]+1024*3,1);
+              reps+=2;
+            }
+            if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
+              dft(DFT_512,prach2+1024*4,rxsigF[aa]+1024*4,1);
+              dft(DFT_512,prach2+1024*5,rxsigF[aa]+1024*5,1);
+              reps+=2;
+            }
+            if (prachFormat == 8/*B4*/) {
+              for (int i=6;i<12;i++) dft(DFT_512,prach2+(1024*i),rxsigF[aa]+(1024*i),1);
+              reps+=6;
+            }
           }
-	  if (prachFormat == 1 || prachFormat == 2) {
-            dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1);
-	    reps++;
-	  }
-	  if (prachFormat == 2) {
-	    dft(DFT_49152,prach2+(98304*2),rxsigF[aa]+(98304*2),1);
-	    dft(DFT_49152,prach2+(98304*3),rxsigF[aa]+(98304*3),1);
-	    reps+=2;
-	  }
-	  if (prachFormat == 3) {
-            dftlen=12288;
-	    for (int i=0;i<4;i++) dft(DFT_12288,prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1);
-	    reps=4;
-	  }
-	}// 839 sequence
-	else {
-	  if (prachStartSymbol == 0)
-	    prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) 
-
-	  dftlen=2048;
-	  dft(DFT_2048,prach2,rxsigF[aa],1);
-	  if (prachFormat != 9/*C0*/) { 
-	    dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1);
-	    reps++;
-	  }
-	  if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
-	    dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1);
-	    dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1);
-	    reps+=2;
-	  }
-	  if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
-	    dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1);
-	    dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1);
-	    reps+=2;
-	  } 
-	  if (prachFormat == 8/*B4*/) {
-	    for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1);
-	    reps+=6;
-	  }
-	}
-      } else { // threequarter sampling
-	//	40 MHz @ 46.08 Ms/s
-	prach2 = prach[aa] + (3*Ncp); // 46.08 is 1.5 * 30.72, times 2 for I/Q
-	if (prach_sequence_length == 0) {
-	  AssertFatal(fp->N_RB_UL <= 107,"cannot do 108..136 PRBs with 3/4 sampling\n");
-	  if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
-            dftlen=36864;
-            dft(DFT_36864,prach2,rxsigF[aa],1);
-	    reps++;
-	  }
-	  if (prachFormat == 1 || prachFormat == 2) {
-	    dft(DFT_36864,prach2+73728,rxsigF[aa]+73728,1);
-	    reps++;
-	  }
-	  if (prachFormat == 2) {
-            dft(DFT_36864,prach2+(73728*2),rxsigF[aa]+(73728*2),1);
-	    dft(DFT_36864,prach2+(73728*3),rxsigF[aa]+(73728*3),1);
-	    reps+=2;
-	  }
-	  if (prachFormat == 3) {
-	    dftlen=9216;
-	    for (int i=0;i<4;i++) dft(DFT_9216,prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1);
-	    reps=4;
-	  }
-	} else {
-	  if (prachStartSymbol == 0) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only)
-	  dftlen=1536;
-	  dft(DFT_1536,prach2,rxsigF[aa],1);
-	  if (prachFormat != 9/*C0*/) {
-	    dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1);
-	    reps++;
-	  }
-	  
-	  if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
-	    dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1);
-	    dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1);
-	    reps+=2;
-	  } 
-	  if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
-	    dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1);
-	    dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1);
-	    reps+=2;
-	  } 
-	  if (prachFormat == 8/*B4*/) {
-	    for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1);
-	    reps+=6;
-	  }
-	} // short format
-      } // 3/4 sampling
-    } // <=50 MHz BW
-    else if (fp->N_RB_UL <= 273) {
-      if (fp->threequarter_fs==0) {
-	prach2 = prach[aa] + (Ncp<<3); 
-	//80,90,100 MHz @ 122.88 Ms/s 
-
-	if (prach_sequence_length == 0) {	
-	  if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
-            dftlen=98304;
-            dft(DFT_98304,prach2,rxsigF[aa],1);
+          break;
+
+        case 30720:
+          // 20, 25, 30 MHz @ 30.72 Ms/s
+          prach2 = prach[aa] + (2*Ncp); // Ncp is for 30.72 Ms/s, so just multiply by 2 for I/Q
+          if (prach_sequence_length == 0) {
+            if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
+              dftlen=24576;
+              dft(DFT_24576,prach2,rxsigF[aa],1);
+            }
+            if (prachFormat == 1 || prachFormat == 2) {
+              dft(DFT_24576,prach2+49152,rxsigF[aa]+49152,1);
+              reps++;
+            }
+            if (prachFormat == 2) {
+              dft(DFT_24576,prach2+(49152*2),rxsigF[aa]+(49152*2),1);
+              dft(DFT_24576,prach2+(49152*3),rxsigF[aa]+(49152*3),1);
+              reps+=2;
+            }
+            if (prachFormat == 3) {
+              dftlen=6144;
+              for (int i=0;i<4;i++) dft(DFT_6144,prach2+(i*6144*2),rxsigF[aa]+(i*6144*2),1);
+              reps=4;
+            }
+          } else { // 839 sequence
+            if (prachStartSymbol == 0) prach2+=32; // 16 samples @ 30.72 Ms/s in first symbol of each half subframe (15/30 kHz only)
+
+            dftlen=1024;
+            dft(DFT_1024,prach2,rxsigF[aa],1);
+            if (prachFormat != 9/*C0*/) {
+              dft(DFT_1024,prach2+2048,rxsigF[aa]+2048,1);
+              reps++;
+            }
+            if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
+              dft(DFT_1024,prach2+2048*2,rxsigF[aa]+2048*2,1);
+              dft(DFT_1024,prach2+2048*3,rxsigF[aa]+2048*3,1);
+              reps+=2;
+            }
+            if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
+              dft(DFT_1024,prach2+2048*4,rxsigF[aa]+2048*4,1);
+              dft(DFT_1024,prach2+2048*5,rxsigF[aa]+2048*5,1);
+              reps+=2;
+            }
+            if (prachFormat == 8/*B4*/) {
+              for (int i=6;i<12;i++) dft(DFT_1024,prach2+(2048*i),rxsigF[aa]+(2048*i),1);
+              reps+=6;
+            }
           }
-	  if (prachFormat == 1 || prachFormat == 2) {
-	    dft(DFT_98304,prach2+196608,rxsigF[aa]+196608,1);
-	    reps++;
-	  }
-	  if (prachFormat == 2) {
-	    dft(DFT_98304,prach2+(196608*2),rxsigF[aa]+(196608*2),1);
-	    dft(DFT_98304,prach2+(196608*3),rxsigF[aa]+(196608*3),1);
-	    reps+=2;
-	  }
-	  if (prachFormat == 3) {
-            dftlen=24576;
-	    for (int i=0;i<4;i++) dft(DFT_24576,prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1);
-	    reps=4;
-	  }
-	}
-	else {
-	  if (prachStartSymbol == 0) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) 
-
-	  dftlen=4096;
-	  dft(DFT_4096,prach2,rxsigF[aa],1);
-	  if (prachFormat != 9/*C0*/) { 
-	    dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1);
-	    reps++;
-	  }
-	  
-	  if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
-	    dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1);
-	    dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1);
-	    reps+=2;
-	  } 
-	  if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
-	    dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1);
-	    dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1);
-	    reps+=2;
-	  } 
-	  if (prachFormat == 8/*B4*/) {
-	    for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1);
-	    reps+=6;
-	  }
-	}
-      } else {
-	AssertFatal(fp->N_RB_UL <= 217,"cannot do more than 217 PRBs with 3/4 sampling\n");
-	prach2 = prach[aa] + (6*Ncp);
-	//	80 MHz @ 92.16 Ms/s
-	if (prach_sequence_length == 0) {
-	  if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
-            dftlen=73728;
-	    dft(DFT_73728,prach2,rxsigF[aa],1);
-	    reps++;
-	  }
-	  if (prachFormat == 1 || prachFormat == 2) {
-	    dft(DFT_73728,prach2+(2*73728),rxsigF[aa]+(2*73728),1);
-	    reps++;
-	  }
-	  if (prachFormat == 3) {
-            dftlen=18432;
-	    for (int i=0;i<4;i++) dft(DFT_18432,prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1);
-	    reps=4;
-	  }
-	} else {
-	  if (prachStartSymbol == 0) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) 
-
-	  dftlen=3072;
-	  dft(DFT_3072,prach2,rxsigF[aa],1);
-	  if (prachFormat != 9/*C0*/) {
-	    dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1);
-	    reps++;
-	  }
-	  
-	  if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
-	    dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1);
-	    dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1);
-	    reps+=2;
-	  } 
-	  if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
-	    dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1);
-	    dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1);
-	    reps+=2;
-	  } 
-	  if (prachFormat == 8/*B4*/) {
-	    for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1);
-	    reps+=6;
-	  }
-	}
+          break;
+
+        case 61440:
+          // 40, 50, 60 MHz @ 61.44 Ms/s
+          prach2 = prach[aa] + (4*Ncp); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 to bring to 61.44 Ms/s
+          if (prach_sequence_length == 0) {
+            if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
+              dftlen=49152;
+              dft(DFT_49152,prach2,rxsigF[aa],1);
+            }
+            if (prachFormat == 1 || prachFormat == 2) {
+              dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1);
+              reps++;
+            }
+            if (prachFormat == 2) {
+              dft(DFT_49152,prach2+(98304*2),rxsigF[aa]+(98304*2),1);
+              dft(DFT_49152,prach2+(98304*3),rxsigF[aa]+(98304*3),1);
+              reps+=2;
+            }
+            if (prachFormat == 3) {
+              dftlen=12288;
+              for (int i=0;i<4;i++) dft(DFT_12288,prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1);
+              reps=4;
+            }
+          } else { // 839 sequence
+            if (prachStartSymbol == 0) prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only)
+
+            dftlen=2048;
+            dft(DFT_2048,prach2,rxsigF[aa],1);
+            if (prachFormat != 9/*C0*/) {
+              dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1);
+              reps++;
+            }
+            if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
+              dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1);
+              dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1);
+              reps+=2;
+            }
+            if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
+              dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1);
+              dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1);
+              reps+=2;
+            }
+            if (prachFormat == 8/*B4*/) {
+              for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1);
+              reps+=6;
+            }
+          }
+          break;
+
+        case 46080:
+          // 40 MHz @ 46.08 Ms/s
+          prach2 = prach[aa] + (3*Ncp); // 46.08 is 1.5 * 30.72, times 2 for I/Q
+          if (prach_sequence_length == 0) {
+            if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
+              dftlen=36864;
+              dft(DFT_36864,prach2,rxsigF[aa],1);
+            }
+            if (prachFormat == 1 || prachFormat == 2) {
+              dft(DFT_36864,prach2+73728,rxsigF[aa]+73728,1);
+              reps++;
+            }
+            if (prachFormat == 2) {
+              dft(DFT_36864,prach2+(73728*2),rxsigF[aa]+(73728*2),1);
+              dft(DFT_36864,prach2+(73728*3),rxsigF[aa]+(73728*3),1);
+              reps+=2;
+            }
+            if (prachFormat == 3) {
+              dftlen=9216;
+              for (int i=0;i<4;i++) dft(DFT_9216,prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1);
+              reps=4;
+            }
+          } else { // 839 sequence
+            if (prachStartSymbol == 0) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only)
+
+            dftlen=1536;
+            dft(DFT_1536,prach2,rxsigF[aa],1);
+            if (prachFormat != 9/*C0*/) {
+              dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1);
+              reps++;
+            }
+            if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
+              dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1);
+              dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1);
+              reps+=2;
+            }
+            if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
+              dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1);
+              dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1);
+              reps+=2;
+            }
+            if (prachFormat == 8/*B4*/) {
+              for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1);
+              reps+=6;
+            }
+          }
+          break;
+
+        case 122880:
+          // 70, 80, 90, 100 MHz @ 122.88 Ms/s
+          prach2 = prach[aa] + (8*Ncp);
+          if (prach_sequence_length == 0) {
+            if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
+              dftlen=98304;
+              dft(DFT_98304,prach2,rxsigF[aa],1);
+            }
+            if (prachFormat == 1 || prachFormat == 2) {
+              dft(DFT_98304,prach2+196608,rxsigF[aa]+196608,1);
+              reps++;
+            }
+            if (prachFormat == 2) {
+              dft(DFT_98304,prach2+(196608*2),rxsigF[aa]+(196608*2),1);
+              dft(DFT_98304,prach2+(196608*3),rxsigF[aa]+(196608*3),1);
+              reps+=2;
+            }
+            if (prachFormat == 3) {
+              dftlen=24576;
+              for (int i=0;i<4;i++) dft(DFT_24576,prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1);
+              reps=4;
+            }
+          } else { // 839 sequence
+            if (prachStartSymbol == 0) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only)
+
+            dftlen=4096;
+            dft(DFT_4096,prach2,rxsigF[aa],1);
+            if (prachFormat != 9/*C0*/) {
+              dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1);
+              reps++;
+            }
+
+            if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
+              dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1);
+              dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1);
+              reps+=2;
+            }
+            if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
+              dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1);
+              dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1);
+              reps+=2;
+            }
+            if (prachFormat == 8/*B4*/) {
+              for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1);
+              reps+=6;
+            }
+          }
+          break;
+
+        case 92160:
+          // 80, 90 MHz @ 92.16 Ms/s
+          prach2 = prach[aa] + (6*Ncp);
+          if (prach_sequence_length == 0) {
+            if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) {
+              dftlen=73728;
+              dft(DFT_73728,prach2,rxsigF[aa],1);
+            }
+            if (prachFormat == 1 || prachFormat == 2) {
+              dft(DFT_73728,prach2+147456,rxsigF[aa]+147456,1);
+              reps++;
+            }
+            if (prachFormat == 2) {
+              dft(DFT_73728,prach2+(147456*2),rxsigF[aa]+(147456*2),1);
+              dft(DFT_73728,prach2+(147456*3),rxsigF[aa]+(147456*3),1);
+              reps+=2;
+            }
+            if (prachFormat == 3) {
+              dftlen=18432;
+              for (int i=0;i<4;i++) dft(DFT_18432,prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1);
+              reps=4;
+            }
+          } else {
+            if (prachStartSymbol == 0) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only)
+
+            dftlen=3072;
+            dft(DFT_3072,prach2,rxsigF[aa],1);
+            if (prachFormat != 9/*C0*/) {
+              dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1);
+              reps++;
+            }
+
+            if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {
+              dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1);
+              dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1);
+              reps+=2;
+            }
+            if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {
+              dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1);
+              dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1);
+              reps+=2;
+            }
+            if (prachFormat == 8/*B4*/) {
+              for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1);
+              reps+=6;
+            }
+          }
+          break;
+        default:
+          AssertFatal(1==0,"sample_rate %f MHz not support for NR PRACH yet\n", fp->samples_per_subframe / 1000.0);
       }
     }
-    }
     else if (mu==3) {
       if (fp->threequarter_fs) {
 	AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
index 42d6cfad7a3e7ac19c3128fe86317628bc46269c..dd8627f0e0c3f4255db9505c8255326e2f1be795 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
@@ -345,6 +345,7 @@ void nr_ulsch_extract_rbs_single(int32_t **rxdataF,
 
     n = 0;
     k_prime = 0;
+    rxF_ext_index = ul_ch0_ext_index = ul_ch0_index = 0; /* In RX Antenna(aarx) loop, Reset the index */
 
     if (is_dmrs_symbol == 0) {
       //
diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c
index 3d2f27476a7e0baa439acfcf6578fe64c62e9a33..239ae1d6d72844e141766f4f07104837b009923f 100644
--- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c
+++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c
@@ -1611,7 +1611,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
   re_offset = (12*pucch_pdu->prb_start) + (12*pucch_pdu->bwp_start) + frame_parms->first_carrier_offset;
   // estimate CQI for MAC (from antenna port 0 only)
   int SNRtimes10 = dB_fixed_times10(signal_energy_nodc(&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset],12*pucch_pdu->prb_size)) - (10*gNB->measurements.n0_power_tot_dB);
-  int cqi;
+  int cqi,bit_left;
   if (SNRtimes10 < -640) cqi=0;
   else if (SNRtimes10 >  635) cqi=255;
   else cqi=(640+SNRtimes10)/5;
@@ -1635,7 +1635,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
       uci_pdu->harq.harq_payload[i] = decodedPayload[0] & 255;
       decodedPayload[0]>>=8;
     }
-    uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<<(pucch_pdu->bit_len_harq&7))-1);
+    bit_left = pucch_pdu->bit_len_harq-((harq_bytes-1)<<3);
+    uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<<bit_left)-1);
     decodedPayload[0] >>= pucch_pdu->bit_len_harq;
   }
   
@@ -1649,6 +1650,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
   // csi
   if (pucch_pdu->bit_len_csi_part1>0) {
     uci_pdu->pduBitmap|=4;
+    uci_pdu->csi_part1.csi_part1_bit_len=pucch_pdu->bit_len_csi_part1;
     int csi_part1_bytes=pucch_pdu->bit_len_csi_part1>>3;
     if ((pucch_pdu->bit_len_csi_part1&7) > 0) csi_part1_bytes++;
     uci_pdu->csi_part1.csi_part1_payload = (uint8_t*)malloc(csi_part1_bytes);
@@ -1658,7 +1660,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
       uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & 255;
       decodedPayload[0]>>=8;
     }
-    uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<<(pucch_pdu->bit_len_csi_part1&7))-1);
+    bit_left = pucch_pdu->bit_len_csi_part1-((csi_part1_bytes-1)<<3);
+    uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<<bit_left)-1);
     decodedPayload[0] >>= pucch_pdu->bit_len_csi_part1;
   }
   
diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
index bfec64820b1300d18a6edc463f8e5c1237e4f10f..8176514eb4195b8879bf0a1cfcc9ff5e7109363f 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
@@ -158,7 +158,6 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
     if ((reg % reg_bundle_size_L) == 0) r++;
   }
 
-
   // Get cce_list indices by reg_idx in ascending order
   int f_bundle_j_list_id = 0;
   int f_bundle_j_list_ord[NR_MAX_PDCCH_AGG_LEVEL] = {};
@@ -175,7 +174,6 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr,
     }
   }
 
-
   for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++) {
 
     f_reg = (f_bundle_j_list_ord[reg/6]*reg_bundle_size_L)+(reg%reg_bundle_size_L);
@@ -404,11 +402,12 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF,
     c_rb = 0;
     for (int rb=0;rb<coreset_nbr_rb;rb++,c_rb++) {
       c_rb_by6 = c_rb/6;
+
       // skip zeros in frequency domain bitmap
       while ((coreset_freq_dom[c_rb_by6>>3] & (1<<(7-(c_rb_by6&7)))) == 0) {
-	  c_rb+=6;
-	  c_rb_by6 = c_rb/6;
-	}
+        c_rb+=6;
+        c_rb_by6 = c_rb/6;
+      }
 
       LOG_DDD("c_rb=%d\n",c_rb);
       rxF=NULL;
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
index 68a206e7c746ec709312e4cb29bee5e7824ff4c3..853a3f61cfbef8ea139203443dfaa45bb1cf3edd 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c
@@ -38,6 +38,31 @@
 
 //#define DEBUG_LLR_SIC
 
+void PrintIntrinsics(char *s, char *dtype, void *x) {
+  if (strcmp(dtype,"int") == 0) {
+    int *tempb = (int *)x;
+    printf("%s: [%d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]);
+  }
+  if (strcmp(dtype,"short") == 0) {
+    short *tempb = (short *)x;
+  printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3],
+                                                      tempb[4], tempb[5], tempb[6], tempb[7]);
+  }
+  if (strcmp(dtype,"char") == 0) {
+    char *tempb = (char *)x;
+    printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]\n", s,
+                 tempb[0], tempb[1], tempb[2], tempb[3], tempb[4], tempb[5], tempb[6], tempb[7],
+                 tempb[8], tempb[9],tempb[10],tempb[11],tempb[12],tempb[13],tempb[14],tempb[15]);
+  }
+  if (strcmp(dtype,"float") == 0) {
+      float *tempb = (float *)x;
+      printf("%s: [%f, %f, %f, %f]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]);
+  }
+  if (strcmp(dtype,"double") == 0) {
+      double *tempb = (double *)x;
+      printf("%s: [%f, %f]\n", s, tempb[0], tempb[1]);
+  }
+}
 
 int16_t nr_zeros[8] __attribute__ ((aligned(16))) = {0,0,0,0,0,0,0,0};
 int16_t nr_ones[8] __attribute__ ((aligned(16))) = {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};
@@ -734,20 +759,45 @@ void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms,
   for (i=0; i<len; i++) {
 
 #if defined(__x86_64__) || defined(__i386)
+    PrintIntrinsics("rxF", "short", &rxF[i]);
+    PrintIntrinsics("ch_mag", "short", &ch_mag[i]);
+
     xmm0 = _mm_abs_epi16(rxF[i]);
+    PrintIntrinsics("xmm0", "short", &xmm0);
+
     xmm0 = _mm_subs_epi16(ch_mag[i],xmm0);
+    PrintIntrinsics("xmm0", "short", &xmm0);
 
     // lambda_1=y_R, lambda_2=|y_R|-|h|^2, lamda_3=y_I, lambda_4=|y_I|-|h|^2
     llr128[0] = _mm_unpacklo_epi32(rxF[i],xmm0);
+    PrintIntrinsics("llr128[0]", "int", &llr128[0]);
+
     llr128[1] = _mm_unpackhi_epi32(rxF[i],xmm0);
+    PrintIntrinsics("llr128[1]", "int", &llr128[1]);
+
     llr32[0] = _mm_extract_epi32(llr128[0],0); //((uint32_t *)&llr128[0])[0];
+    printf("llr32[0] = %d\n", llr32[0]);
+
     llr32[1] = _mm_extract_epi32(llr128[0],1); //((uint32_t *)&llr128[0])[1];
+    printf("llr32[1] = %d\n", llr32[1]);
+
     llr32[2] = _mm_extract_epi32(llr128[0],2); //((uint32_t *)&llr128[0])[2];
+    printf("llr32[2] = %d\n", llr32[2]);
+
     llr32[3] = _mm_extract_epi32(llr128[0],3); //((uint32_t *)&llr128[0])[3];
+    printf("llr32[3] = %d\n", llr32[3]);
+
     llr32[4] = _mm_extract_epi32(llr128[1],0); //((uint32_t *)&llr128[1])[0];
+    printf("llr32[4] = %d\n", llr32[4]);
+
     llr32[5] = _mm_extract_epi32(llr128[1],1); //((uint32_t *)&llr128[1])[1];
+    printf("llr32[5] = %d\n", llr32[5]);
+
     llr32[6] = _mm_extract_epi32(llr128[1],2); //((uint32_t *)&llr128[1])[2];
+    printf("llr32[6] = %d\n", llr32[6]);
+
     llr32[7] = _mm_extract_epi32(llr128[1],3); //((uint32_t *)&llr128[1])[3];
+    printf("llr32[7] = %d\n", llr32[7]);
     llr32+=8;
 #elif defined(__arm__)
     xmm0 = vabsq_s16(rxF[i]);
@@ -8689,4 +8739,4 @@ int nr_dlsch_64qam_64qam_llr(NR_DL_FRAME_PARMS *frame_parms,
   //*llr16p = (short *)llr16;
 
   return(0);
-}
+}
\ No newline at end of file
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
index 13270c5c4b4c06030566d45debb76e53f58b272a..189ad53efaf99b4769ad5e01268d46d854f0f99b 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
@@ -289,8 +289,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames)
                               proc,
                               i,
                               0,
-                              is*fp->samples_per_frame+ue->ssb_offset,
-                              0);
+                              is*fp->samples_per_frame+ue->ssb_offset);
 
 #ifdef DEBUG_INITIAL_SYNCH
       LOG_I(PHY,"Calling sss detection (normal CP)\n");
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c
index 3ab88dac0a5aeb804ec4e45667b3ef0ccdefd19c..0ba02c6bac8564182d02483343d3b6ae3d1aabac 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c
@@ -244,87 +244,83 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
    *********************************************************/
 
   if (mu==1) {
-  if (fp->N_RB_UL <= 100)
-    AssertFatal(1 == 0, "N_RB_UL %d not support for NR PRACH yet\n", fp->N_RB_UL);
-  else if (fp->N_RB_UL < 137) {
-    if (fp->threequarter_fs == 0) {
-      //40 MHz @ 61.44 Ms/s
-      //50 MHz @ 61.44 Ms/s
+    switch(fp->samples_per_subframe) {
+    case 15360:
+      // 10, 15 MHz @ 15.36 Ms/s
       if (prach_sequence_length == 0) {
         if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2)
-            dftlen = 49152;
+          dftlen = 12288;
         if (prach_fmt_id == 3)
-            dftlen = 12288;
-      } // 839 sequence
-      else {
-        switch (mu){
-          case 1:
-            dftlen = 2048;
-            break;
-          default:
-            AssertFatal(1 == 0, "Shouldn't get here\n");
-            break;
-        }
+          dftlen = 3072;
+      } else { // 839 sequence
+        dftlen = 512;
+      }
+      break;
+
+    case 30720:
+      // 20, 25, 30 MHz @ 30.72 Ms/s
+      if (prach_sequence_length == 0) {
+        if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2)
+          dftlen = 24576;
+        if (prach_fmt_id == 3)
+          dftlen = 6144;
+      } else { // 839 sequence
+        dftlen = 1024;
       }
-    } else { // threequarter sampling
-      //  40 MHz @ 46.08 Ms/s
+      break;
+
+    case 46080:
+      // 40 MHz @ 46.08 Ms/s
       if (prach_sequence_length == 0) {
-        AssertFatal(fp->N_RB_UL <= 107, "cannot do 108..136 PRBs with 3/4 sampling\n");
         if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2)
           dftlen = 36864;
         if (prach_fmt_id == 3)
           dftlen = 9216;
-      } else {
-        switch (mu){
-          case 1:
-            dftlen = 1536;
-          break;
-          default:
-            AssertFatal(1 == 0, "Shouldn't get here\n");
-            break;
-        }
-      } // short format
-    } // 3/4 sampling
-  } // <=50 MHz BW
-  else if (fp->N_RB_UL <= 273) {
-    if (fp->threequarter_fs == 0) {
-    //80,90,100 MHz @ 122.88 Ms/s
+      } else { // 839 sequence
+        dftlen = 1536;
+      }
+      break;
+
+    case 61440:
+      // 40, 50, 60 MHz @ 61.44 Ms/s
       if (prach_sequence_length == 0) {
         if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2)
-          dftlen = 98304;
+          dftlen = 49152;
         if (prach_fmt_id == 3)
-          dftlen = 24576;
+          dftlen = 12288;
+      } else { // 839 sequence
+        dftlen = 2048;
       }
-    } else { // threequarter sampling
-      switch (mu){
-        case 1:
-          dftlen = 4096;
-          break;
-        default:
-          AssertFatal(1 == 0, "Shouldn't get here\n");
-          break;
+      break;
+
+    case 92160:
+      // 50, 60, 70, 80, 90 MHz @ 92.16 Ms/s
+      if (prach_sequence_length == 0) {
+        if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2)
+          dftlen = 73728;
+        if (prach_fmt_id == 3)
+          dftlen = 18432;
+      } else { // 839 sequence
+        dftlen = 3072;
       }
-    }
-  } else {
-    AssertFatal(fp->N_RB_UL <= 217, "cannot do more than 217 PRBs with 3/4 sampling\n");
-    //  80 MHz @ 92.16 Ms/s
-    if (prach_sequence_length == 0) {
-      if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2)
-        dftlen = 73728;
-      if (prach_fmt_id == 3)
-        dftlen = 18432;
-    } else {
-      switch (mu){
-        case 1:
-          dftlen = 3072;
-          break;
-        default:
-          AssertFatal(1 == 0, "Shouldn't get here\n");
-          break;
+      break;
+
+    case 122880:
+      // 70, 80, 90, 100 MHz @ 122.88 Ms/s
+      if (prach_sequence_length == 0) {
+        if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2)
+          dftlen = 98304;
+        if (prach_fmt_id == 3)
+          dftlen = 24576;
+      } else { // 839 sequence
+        dftlen = 4096;
       }
+      break;
+
+    default:
+      AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu);
     }
   }
-  }
   else if (mu==3) {
     if (fp->threequarter_fs) 
       AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu);
@@ -425,15 +421,16 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
   uint8_t  use_extended_prach_prefix = 0;
   if(fp->numerology_index == 0) {
     if (prachStartSymbol == 0 || prachStartSymbol == 7)
-	  use_extended_prach_prefix = 1;
+      use_extended_prach_prefix = 1;
   }
   else {
     if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0)
-	  use_extended_prach_prefix = 1;
+      use_extended_prach_prefix = 1;
   }
-    
-  if (fp->N_RB_UL <= 34) { //32 PRB case 61.44Msps
-    if (fp->threequarter_fs == 0) {
+
+  if (mu == 3) {
+    switch (fp->samples_per_subframe) {
+    case 61440: // 32 PRB case, 61.44 Msps
       Ncp<<=1; //to account for 61.44Mbps
       // This is after cyclic prefix 
       prach2 = prach+(Ncp<<1); //times 2 for complex samples
@@ -491,13 +488,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (512*12)+Ncp;
 	}		
       }
-    }
-    else
-      AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL);
-   
-  }
-  else if (fp->N_RB_UL <= 68) {//66 PRB case, 122.88 Msps 
-    if (fp->threequarter_fs == 0) {
+      break;
+
+    case 122880: // 66 PRB case, 122.88 Msps
       Ncp<<=2; //to account for 122.88Mbps
       // This is after cyclic prefix 
       prach2 = prach+(Ncp<<1); //times 2 for complex samples
@@ -555,13 +548,211 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (1024*12)+Ncp;
 	}	
       }
+      break;
+
+    default:
+      AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu);
     }
-    else
-      AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL);
-  }
-  else if (fp->N_RB_UL < 137) { // 46.08 or 61.44 Ms/s
-    if (fp->threequarter_fs == 0) { // full sampling @ 61.44 Ms/s
-      Ncp<<=1; //to account for 61.44Mbps 
+  } else if (mu == 1) {
+    switch (fp->samples_per_subframe) {
+    case 15360: // full sampling @ 15.36 Ms/s
+      Ncp = Ncp/2; // to account for 15.36 Ms/s
+      // This is after cyclic prefix
+      prach2 = prach+(2*Ncp); // times 2 for complex samples
+      if (prach_sequence_length == 0){
+        if (prach_fmt_id == 0) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s
+          idft(IDFT_12288,prachF,prach2,1);
+          // here we have | empty  | Prach12288 |
+          memmove(prach,prach+(12288<<1),(Ncp<<2));
+          // here we have | Prefix | Prach12288 |
+          prach_len = 12288+Ncp;
+        } else if (prach_fmt_id == 1) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s
+          idft(IDFT_12288,prachF,prach2,1);
+          // here we have | empty  | Prach12288 | empty12288 |
+          memmove(prach2+(12288<<1),prach2,(12288<<2));
+          // here we have | empty  | Prach12288 | Prach12288 |
+          memmove(prach,prach+(12288<<2),(Ncp<<2));
+          // here we have | Prefix | Prach12288 | Prach12288 |
+          prach_len = (12288*2)+Ncp;
+        } else if (prach_fmt_id == 2) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s
+          idft(IDFT_12288,prachF,prach2,1);
+          // here we have | empty  | Prach12288 | empty12288 | empty12288 | empty12288 |
+          memmove(prach2+(12288<<1),prach2,(12288<<2));
+          // here we have | empty  | Prach12288 | Prach12288 | empty12288 | empty12288 |
+          memmove(prach2+(12288<<2),prach2,(12288<<3));
+          // here we have | empty  | Prach12288 | Prach12288 | Prach12288 | Prach12288 |
+          memmove(prach,prach+(12288<<3),(Ncp<<2));
+          // here we have | Prefix | Prach12288 | Prach12288 | Prach12288 | Prach12288 |
+          prach_len = (12288*4)+Ncp;
+        } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s, 3072 samples @ 15.36 Ms/s
+          idft(IDFT_3072,prachF,prach2,1);
+          // here we have | empty  | Prach3072 | empty3072 | empty3072 | empty3072 |
+          memmove(prach2+(3072<<1),prach2,(3072<<2));
+          // here we have | empty  | Prach3072 | Prach3072 | empty3072 | empty3072 |
+          memmove(prach2+(3072<<2),prach2,(3072<<3));
+          // here we have | empty  | Prach3072 | Prach3072 | Prach3072 | Prach3072 |
+          memmove(prach,prach+(3072<<3),(Ncp<<2));
+          // here we have | Prefix | Prach3072 | Prach3072 | Prach3072 | Prach3072 |
+          prach_len = (3072*4)+Ncp;
+        }
+      } else { // short PRACH sequence
+	if (use_extended_prach_prefix)
+	  Ncp += 8; // 16*kappa, kappa=0.5 for 15.36 Ms/s
+	prach2 = prach+(2*Ncp); // times 2 for complex samples
+        if (prach_fmt_id == 9) {
+          idft(IDFT_512,prachF,prach2,1);
+          // here we have | empty  | Prach512 |
+          memmove(prach,prach+(512<<1),(Ncp<<2));
+          // here we have | Prefix | Prach512 |
+          prach_len = (512*1)+Ncp;
+        } else if (prach_fmt_id == 4 || prach_fmt_id == 7) {
+          idft(IDFT_512,prachF,prach2,1);
+          // here we have | empty  | Prach512 | empty512 |
+          memmove(prach2+(512<<1),prach2,(512<<2));
+          // here we have | empty  | Prach512 | Prach512 |
+          memmove(prach,prach+(512<<1),(Ncp<<2));
+          // here we have | Prefix | Prach512 | Prach512 |
+          prach_len = (512*2)+Ncp;
+        } else if (prach_fmt_id == 5) { // 4x512
+          idft(IDFT_512,prachF,prach2,1);
+          // here we have | empty  | Prach512 | empty512 | empty512 | empty512 |
+          memmove(prach2+(512<<1),prach2,(512<<2));
+          // here we have | empty  | Prach512 | Prach512 | empty512 | empty512 |
+          memmove(prach2+(512<<2),prach2,(512<<3));
+          // here we have | empty  | Prach512 | Prach512 | Prach512 | Prach512 |
+          memmove(prach,prach+(512<<1),(Ncp<<2));
+          // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 |
+          prach_len = (512*4)+Ncp;
+        } else if (prach_fmt_id == 6) { // 6x512
+          idft(IDFT_512,prachF,prach2,1);
+          // here we have | empty  | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 |
+          memmove(prach2+(512<<1),prach2,(512<<2));
+          // here we have | empty  | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 |
+          memmove(prach2+(512<<2),prach2,(512<<3));
+          // here we have | empty  | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 |
+          memmove(prach2+(512<<3),prach2,(512<<3));
+          // here we have | empty  | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 |
+          memmove(prach,prach+(512<<1),(Ncp<<2));
+          // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 |
+          prach_len = (512*6)+Ncp;
+        } else if (prach_fmt_id == 8) { // 12x512
+          idft(IDFT_512,prachF,prach2,1);
+          // here we have | empty  | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 |
+          memmove(prach2+(512<<1),prach2,(512<<2));
+          // here we have | empty  | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 |
+          memmove(prach2+(512<<2),prach2,(512<<3));
+          // here we have | empty  | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 |
+          memmove(prach2+(512<<3),prach2,(512<<3));
+          // here we have | empty  | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 |
+          memmove(prach2+(512<<1)*6,prach2,(512<<2)*6);
+          // here we have | empty  | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 |
+          memmove(prach,prach+(512<<1),(Ncp<<2));
+          // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 |
+          prach_len = (512*12)+Ncp;
+        }
+      }
+      break;
+
+    case 30720: // full sampling @ 30.72 Ms/s
+      Ncp = Ncp*1; // to account for 30.72 Ms/s
+      // This is after cyclic prefix
+      prach2 = prach+(2*Ncp); // times 2 for complex samples
+      if (prach_sequence_length == 0){
+        if (prach_fmt_id == 0) { // 24576 samples @ 30.72 Ms/s
+          idft(IDFT_24576,prachF,prach2,1);
+          // here we have | empty  | Prach24576 |
+          memmove(prach,prach+(24576<<1),(Ncp<<2));
+          // here we have | Prefix | Prach24576 |
+          prach_len = 24576+Ncp;
+        } else if (prach_fmt_id == 1) { // 24576 samples @ 30.72 Ms/s
+          idft(IDFT_24576,prachF,prach2,1);
+          // here we have | empty  | Prach24576 | empty24576 |
+          memmove(prach2+(24576<<1),prach2,(24576<<2));
+          // here we have | empty  | Prach24576 | Prach24576 |
+          memmove(prach,prach+(24576<<2),(Ncp<<2));
+          // here we have | Prefix | Prach24576 | Prach24576 |
+          prach_len = (24576*2)+Ncp;
+        } else if (prach_fmt_id == 2) { // 24576 samples @ 30.72 Ms/s
+          idft(IDFT_24576,prachF,prach2,1);
+          // here we have | empty  | Prach24576 | empty24576 | empty24576 | empty24576 |
+          memmove(prach2+(24576<<1),prach2,(24576<<2));
+          // here we have | empty  | Prach24576 | Prach24576 | empty24576 | empty24576 |
+          memmove(prach2+(24576<<2),prach2,(24576<<3));
+          // here we have | empty  | Prach24576 | Prach24576 | Prach24576 | Prach24576 |
+          memmove(prach,prach+(24576<<3),(Ncp<<2));
+          // here we have | Prefix | Prach24576 | Prach24576 | Prach24576 | Prach24576 |
+          prach_len = (24576*4)+Ncp;
+        } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s
+          idft(IDFT_6144,prachF,prach2,1);
+          // here we have | empty  | Prach6144 | empty6144 | empty6144 | empty6144 |
+          memmove(prach2+(6144<<1),prach2,(6144<<2));
+          // here we have | empty  | Prach6144 | Prach6144 | empty6144 | empty6144 |
+          memmove(prach2+(6144<<2),prach2,(6144<<3));
+          // here we have | empty  | Prach6144 | Prach6144 | Prach6144 | Prach6144 |
+          memmove(prach,prach+(6144<<3),(Ncp<<2));
+          // here we have | Prefix | Prach6144 | Prach6144 | Prach6144 | Prach6144 |
+          prach_len = (6144*4)+Ncp;
+        }
+      } else { // short PRACH sequence
+	if (use_extended_prach_prefix)
+	  Ncp += 16; // 16*kappa, kappa=1 for 30.72Msps
+	prach2 = prach+(2*Ncp); // times 2 for complex samples
+        if (prach_fmt_id == 9) {
+          idft(IDFT_1024,prachF,prach2,1);
+          // here we have | empty  | Prach1024 |
+          memmove(prach,prach+(1024<<1),(Ncp<<2));
+          // here we have | Prefix | Prach1024 |
+          prach_len = (1024*1)+Ncp;
+        } else if (prach_fmt_id == 4 || prach_fmt_id == 7) {
+          idft(IDFT_1024,prachF,prach2,1);
+          // here we have | empty  | Prach1024 | empty1024 |
+          memmove(prach2+(1024<<1),prach2,(1024<<2));
+          // here we have | empty  | Prach1024 | Prach1024 |
+          memmove(prach,prach+(1024<<1),(Ncp<<2));
+          // here we have | Prefix | Prach1024 | Prach1024 |
+          prach_len = (1024*2)+Ncp;
+        } else if (prach_fmt_id == 5) { // 4x1024
+          idft(IDFT_1024,prachF,prach2,1);
+          // here we have | empty  | Prach1024 | empty1024 | empty1024 | empty1024 |
+          memmove(prach2+(1024<<1),prach2,(1024<<2));
+          // here we have | empty  | Prach1024 | Prach1024 | empty1024 | empty1024 |
+          memmove(prach2+(1024<<2),prach2,(1024<<3));
+          // here we have | empty  | Prach1024 | Prach1024 | Prach1024 | Prach1024 |
+          memmove(prach,prach+(1024<<1),(Ncp<<2));
+          // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 |
+          prach_len = (1024*4)+Ncp;
+        } else if (prach_fmt_id == 6) { // 6x1024
+          idft(IDFT_1024,prachF,prach2,1);
+          // here we have | empty  | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 |
+          memmove(prach2+(1024<<1),prach2,(1024<<2));
+          // here we have | empty  | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 |
+          memmove(prach2+(1024<<2),prach2,(1024<<3));
+          // here we have | empty  | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 |
+          memmove(prach2+(1024<<3),prach2,(1024<<3));
+          // here we have | empty  | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 |
+          memmove(prach,prach+(1024<<1),(Ncp<<2));
+          // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 |
+          prach_len = (1024*6)+Ncp;
+        } else if (prach_fmt_id == 8) { // 12x1024
+          idft(IDFT_1024,prachF,prach2,1);
+          // here we have | empty  | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 |
+          memmove(prach2+(1024<<1),prach2,(1024<<2));
+          // here we have | empty  | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 |
+          memmove(prach2+(1024<<2),prach2,(1024<<3));
+          // here we have | empty  | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 |
+          memmove(prach2+(1024<<3),prach2,(1024<<3));
+          // here we have | empty  | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 |
+          memmove(prach2+(1024<<1)*6,prach2,(1024<<2)*6);
+          // here we have | empty  | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 |
+          memmove(prach,prach+(1024<<1),(Ncp<<2));
+          // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 |
+          prach_len = (1024*12)+Ncp;
+        }
+      }
+      break;
+
+    case 61440: // full sampling @ 61.44 Ms/s
+      Ncp = Ncp*2; // to account for 61.44 Ms/s
       // This is after cyclic prefix 
       prach2 = prach+(Ncp<<1); //times 2 for complex samples
       if (prach_sequence_length == 0){
@@ -587,7 +778,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           memmove(prach,prach+(49152<<3),(Ncp<<2));
           // here we have |Prefix | Prach49152 | Prach49152| Prach49152 | Prach49152
           prach_len = (49152*4)+Ncp;
-        } else if (prach_fmt_id == 3) { // //6144 samples @ 30.72 Ms/s, 12288 samples @ 61.44 Ms/s
+        } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s, 12288 samples @ 61.44 Ms/s
           idft(IDFT_12288,prachF,prach2,1);
           memmove(prach2+(12288<<1),prach2,(12288<<2));
           // here we have |empty | Prach12288 | Prach12288| empty12288 | empty12288
@@ -649,7 +840,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (2048*12)+Ncp;
         }
       }
-    } else {  // threequarter sampling @ 46.08 Ms/s
+      break;
+
+    case 46080: // threequarter sampling @ 46.08 Ms/s
       Ncp = (Ncp*3)/2;
       prach2 = prach+(Ncp<<1);
       if (prach_sequence_length == 0){
@@ -738,9 +931,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (1536*12)+Ncp;
         }
       }
-    }
-  } else if (fp->N_RB_UL <= 273) {// 92.16 or 122.88 Ms/s
-    if (fp->threequarter_fs == 0) { // full sampling @ 122.88 Ms/s
+      break;
+
+    case 122880: // full sampling @ 122.88 Ms/s
       Ncp<<=2; //to account for 122.88Mbps
       // This is after cyclic prefix
       prach2 = prach+(Ncp<<1); //times 2 for complex samples
@@ -828,7 +1021,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (4096*12)+Ncp;
         }
       }
-    } else { // three quarter sampling @ 92.16 Ms/s
+      break;
+
+    case 92160: // three quarter sampling @ 92.16 Ms/s
       Ncp = (Ncp*3); //to account for 92.16 Msps
       prach2 = prach+(Ncp<<1); //times 2 for complex samples
       if (prach_sequence_length == 0){
@@ -915,6 +1110,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (3072*12)+Ncp;
         }
       }
+      break;
+
+    default:
+      AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu);
     }
   }
 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
index 464bcfcfbaddd92866d334bc8714d9c3bac508c0..aa32ecc8c9dc5c32a9abaf306ff0027f5fa3b1c3 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
@@ -105,6 +105,8 @@ typedef struct {
   uint8_t O_ACK;
   /// Index of current HARQ round for this ULSCH
   uint8_t round;
+  /// Last Ndi for this harq process
+  uint8_t ndi;
   /// pointer to pdu from MAC interface (TS 36.212 V15.4.0, Sec 5.1 p. 8)
   unsigned char *a;
   /// Pointer to the payload + CRC 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c
index 7cf64b28bb3d13361f81df11b9de66a12b991595..76fc5f298fbed056abcbfad05d5ef2d3f4adad0c 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c
@@ -78,13 +78,15 @@ void nr_rf_card_config(openair0_config_t *openair0_cfg,
 
     openair0_cfg->autocal[i] = 1;
 
-    LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f, tx_freq %f Hz, rx_freq %f Hz\n",
-      i,
-      rf_chain,
-      openair0_cfg->tx_gain[i],
-      openair0_cfg->rx_gain[i],
-      openair0_cfg->tx_freq[i],
-      openair0_cfg->rx_freq[i]);
+    if (i < openair0_cfg->rx_num_channels) {
+      LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f, tx_freq %f Hz, rx_freq %f Hz\n",
+        i,
+        rf_chain,
+        openair0_cfg->tx_gain[i],
+        openair0_cfg->rx_gain[i],
+        openair0_cfg->tx_freq[i],
+        openair0_cfg->rx_freq[i]);
+    }
 
   }
 }
\ No newline at end of file
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
index f6a346aee9759aa8230a0458bdb58bf38fbd7b7f..abb14e834b63a7be0d2eff86df310db39c97bce2 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
@@ -202,7 +202,6 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL,
       for (i=0; i<number_of_harq_pids; i++) {
         ulsch->harq_processes[i]->round=0;
       }
-
       return(ulsch);
     }
   }
@@ -257,7 +256,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
   Ilbrm = 0;
   Tbslbrm = 950984; //max tbs
   Coderate = 0.0;
-  harq_process->round = nr_rv_round_map_ue[harq_process->pusch_pdu.pusch_data.rv_index];
 
 ///////////
 /////////////////////////////////////////////////////////////////////////////////////////  
@@ -267,8 +265,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
   LOG_D(PHY,"ulsch coding nb_rb %d, Nl = %d\n", nb_rb, harq_process->pusch_pdu.nrOfLayers);
   LOG_D(PHY,"ulsch coding A %d G %d mod_order %d\n", A,G, mod_order);
 
-  //  if (harq_process->Ndi == 1) {  // this is a new packet
-  if (harq_process->round == 0) {  // this is a new packet
+  if (harq_process->ndi != harq_process->pusch_pdu.pusch_data.new_data_indicator) {  // this is a new packet
 #ifdef DEBUG_ULSCH_CODING
   printf("encoding thinks this is a new packet \n");
 #endif
@@ -415,7 +412,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
 
 ///////////
 ///////////////////////////////////////////////////////////////////////////////
-
+    harq_process->ndi = harq_process->pusch_pdu.pusch_data.new_data_indicator;
   }
   F = harq_process->F;
   Kr = harq_process->K;
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
index 208901f289ce13ac05bb95b41fc2bcc2f7bb4a08..3d8c975a5c9bb286cbe5049b15e195bd8f6da663 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
@@ -496,13 +496,19 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
   int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot;
   for(ap = 0; ap < Nl; ap++) {
     for (int s=0;s<NR_NUMBER_OF_SYMBOLS_PER_SLOT;s++){
-      LOG_D(PHY,"rotating txdataF symbol %d (%d) => (%d.%d)\n",
-	    s,s+symb_offset,frame_parms->symbol_rotation[2*(s+symb_offset)],frame_parms->symbol_rotation[1+(2*(s+symb_offset))]);
-      rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s],
-			&frame_parms->symbol_rotation[2*(s+symb_offset)],
-			(int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s],
-			frame_parms->ofdm_symbol_size,
-			15);
+
+      LOG_D(PHY,"In %s: rotating txdataF symbol %d (%d) => (%d.%d)\n",
+        __FUNCTION__,
+        s,
+        s + symb_offset,
+        frame_parms->symbol_rotation[1][2 * (s + symb_offset)],
+        frame_parms->symbol_rotation[1][1 + (2 * (s + symb_offset))]);
+
+      rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s],
+                        &frame_parms->symbol_rotation[1][2 * (s + symb_offset)],
+                        (int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s],
+                        frame_parms->ofdm_symbol_size,
+                        15);
     }
   }
 
diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c
index cb6152385260942df9ebe89fd11ae3bd0f5cafa0..b45c1abf0b580fa187fec265ec5cd987d909660a 100644
--- a/openair1/PHY/TOOLS/nr_phy_scope.c
+++ b/openair1/PHY/TOOLS/nr_phy_scope.c
@@ -282,30 +282,6 @@ static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const in
   graph->iteration++;
 }
 
-static void genericLogPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) {
-  float *values, *time;
-  oai_xygraph_getbuff(graph, &time, &values, len, 0);
-
-  for (int ant=0; ant<nb_ant; ant++) {
-    if (data[ant] != NULL) {
-      float *values, *time;
-      oai_xygraph_getbuff(graph, &time, &values, len, ant);
-
-      for (int i=0; i<len; i+=8) {
-        float *vals=values+i;
-        const scopeSample_t *in=&(data[ant][i]);
-
-        // TRY AUTOMATIC simd BY GCC
-        for (int k=0; k<8; k++ ) {
-          vals[k] = 10*log10(1.0+SquaredNorm(in[k]));
-        }
-      }
-
-      oai_xygraph(graph,time,values, len, ant, 10);
-    }
-  }
-}
-
 static void genericPowerPerAntena(OAIgraph_t  *graph, const int nb_ant, const scopeSample_t **data, const int len) {
   float *values, *time;
   oai_xygraph_getbuff(graph, &time, &values, len, 0);
diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h
index b465a51a2addf00ebc78da6e0c1d5f5cc079100c..885f955a2a8fe8b9144e7e05b41606fd0ab70b53 100644
--- a/openair1/PHY/defs_RU.h
+++ b/openair1/PHY/defs_RU.h
@@ -741,4 +741,10 @@ typedef struct RRU_config_s {
   MBSFN_config_t MBSFN_config[8];
 } RRU_config_t;
 
+typedef struct processingData_RU {
+  int frame_tx;
+  int slot_tx;
+  openair0_timestamp timestamp_tx;
+  RU_t *ru;
+} processingData_RU_t;
 #endif //__PHY_DEFS_RU__H__
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index b7923adb0b2098734ab79623bb9cc997e6a777a0..822f4c39862c8f0588a5798d3b2890eefc3bc58f 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -830,6 +830,9 @@ typedef struct PHY_VARS_gNB_s {
   time_stats_t ulsch_freq_offset_estimation_stats;
   */
   notifiedFIFO_t *respDecode;
+  notifiedFIFO_t *resp_L1;
+  notifiedFIFO_t *resp_L1_tx;
+  notifiedFIFO_t *resp_RU_tx;
   tpool_t *threadPool;
   int nbDecode;
   uint8_t pusch_proc_threads;
@@ -871,4 +874,13 @@ union ldpcReqUnion {
   uint64_t p;
 };
 
+typedef struct processingData_L1 {
+  int frame_rx;
+  int frame_tx;
+  int slot_rx;
+  int slot_tx;
+  openair0_timestamp timestamp_tx;
+  PHY_VARS_gNB *gNB;
+} processingData_L1_t;
+
 #endif
diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h
index 18c7dd413b5d8cc0c18cde16a2a017855ee9b59d..398252c37b9dbfb03e6f56cef77b0127102e6336 100644
--- a/openair1/PHY/defs_nr_common.h
+++ b/openair1/PHY/defs_nr_common.h
@@ -327,7 +327,8 @@ struct NR_DL_FRAME_PARMS {
   /// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
   lte_prefix_type_t Ncp;
   /// sequence which is computed based on carrier frequency and numerology to rotate/derotate each OFDM symbol according to Section 5.3 in 38.211
-  int16_t symbol_rotation[224*2];
+  /// First dimension is for the direction of the link (0 DL, 1 UL)
+  int16_t symbol_rotation[2][224*2];
   /// shift of pilot position in one RB
   uint8_t nushift;
   /// SRS configuration from TS 38.331 RRC
@@ -368,20 +369,4 @@ struct NR_DL_FRAME_PARMS {
 #define KHz (1000UL)
 #define MHz (1000*KHz)
 
-typedef struct nr_bandentry_s {
-  int16_t band;
-  uint64_t ul_min;
-  uint64_t ul_max;
-  uint64_t dl_min;
-  uint64_t dl_max;
-  uint64_t step_size;
-  uint64_t N_OFFs_DL;
-  uint8_t deltaf_raster;
-} nr_bandentry_t;
-
-typedef struct nr_band_info_s {
-  int nbands;
-  nr_bandentry_t band_info[100];
-} nr_band_info_t;
-
 #endif
diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c
index 2aa09dea80d9979aa80fe6053a799adfe37376ff..5909db8bea310395757b010bb3c78e625b8b9476 100644
--- a/openair1/SCHED_NR/fapi_nr_l1.c
+++ b/openair1/SCHED_NR/fapi_nr_l1.c
@@ -131,6 +131,7 @@ void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
 
 void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
   
+  //if(NFAPI_MODE == NFAPI_MODE_VNF)
   PHY_VARS_gNB *gNB;
   // copy data from L2 interface into L1 structures
   module_id_t                   Mod_id       = Sched_INFO->module_id;
@@ -250,7 +251,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
     {
       Sched_INFO->DL_req->SFN = frame;
       Sched_INFO->DL_req->Slot = slot;
-      printf("DL tti Frame = %d, slot = %d. \n",frame,slot);
+      //printf("DL tti Frame = %d, slot = %d. \n",frame,slot);
       oai_nfapi_dl_tti_req(Sched_INFO->DL_req);
     }
     if (Sched_INFO->TX_req->Number_of_PDUs > 0)
diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c
index a78b1f48056ffa09963ef58045b1f7fd06852d30..9a71f96815e6e588145eba46ddd845be2df4479f 100644
--- a/openair1/SCHED_NR/nr_ru_procedures.c
+++ b/openair1/SCHED_NR/nr_ru_procedures.c
@@ -520,8 +520,7 @@ void nr_fep0(RU_t *ru, int first_half) {
                      ru->common.rxdataF[aa],
                      l,
                      proc->tti_rx,
-                     ru->N_TA_offset,
-                     0);
+                     ru->N_TA_offset);
     }
   }
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+proc->tti_rx, 0);
@@ -657,8 +656,7 @@ void nr_fep_full(RU_t *ru, int slot) {
                      ru->common.rxdataF[aa],
                      l,
                      proc->tti_rx,
-                     ru->N_TA_offset,
-                     0);
+                     ru->N_TA_offset);
     }
   }
 
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 7e7aff0a09541936337e0a7b0a4b493f7f7a9c7e..2617c4686e38c5a0897f140f4e7aae6834dccc93 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -367,7 +367,6 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id,
 
   int timing_advance_update, cqi;
   int sync_pos;
-  uint16_t mu = gNB->frame_parms.numerology_index;
   NR_gNB_ULSCH_t                       *ulsch                 = gNB->ulsch[ULSCH_id][0];
   NR_UL_gNB_HARQ_t                     *harq_process          = ulsch->harq_processes[harq_pid];
 
@@ -375,18 +374,10 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id,
 
   //  pdu->data                              = gNB->ulsch[ULSCH_id+1][0]->harq_processes[harq_pid]->b;
   sync_pos                               = nr_est_timing_advance_pusch(gNB, ULSCH_id); // estimate timing advance for MAC
-  timing_advance_update                  = sync_pos * (1 << mu);                    // scale by the used scs numerology
 
   // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size
-  switch (gNB->frame_parms.N_RB_DL) {
-    case 106: timing_advance_update /= 16; break;
-    case 217: timing_advance_update /= 32; break;
-    case 245: timing_advance_update /= 32; break;
-    case 273: timing_advance_update /= 32; break;
-    case 66:  timing_advance_update /= 12; break;
-    case 32:  timing_advance_update /= 12; break;
-    default: AssertFatal(0==1,"No case defined for PRB %d to calculate timing_advance_update\n",gNB->frame_parms.N_RB_DL);
-  }
+  uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048;
+  timing_advance_update = sync_pos / bw_scaling;
 
   // put timing advance command in 0..63 range
   timing_advance_update += 31;
@@ -517,15 +508,12 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
   unsigned char aa;
 
   for(symbol = 0; symbol < (gNB->frame_parms.Ncp==EXTENDED?12:14); symbol++) {
-    // nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0);
-
     for (aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) {
       nr_slot_fep_ul(&gNB->frame_parms,
                      gNB->common_vars.rxdata[aa],
                      gNB->common_vars.rxdataF[aa],
                      symbol,
                      slot_rx,
-                     0,
                      0);
     }
   }
@@ -542,6 +530,9 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
 }
 
 void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
+  /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */
+  int pucch_decode_done = 0;
+  int pusch_decode_done = 0;
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1);
   LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx);
@@ -566,6 +557,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
 	  (pucch->frame == frame_rx) &&
 	  (pucch->slot == slot_rx) ) {
 
+        pucch_decode_done = 1;
+
         nfapi_nr_pucch_pdu_t  *pucch_pdu = &pucch->pucch_pdu;
         uint16_t num_ucis;
         switch (pucch_pdu->format_type) {
@@ -657,7 +650,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
           }
 #endif
 
-T(T_BENETEL, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], 2048*4*14));
+          pusch_decode_done = 1;
 
           uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index;
           uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols;
@@ -686,5 +679,9 @@ T(T_BENETEL, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF
   // figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS
   if ((frame_rx&127) == 0 && slot_rx==19) dump_pusch_stats(gNB);
 
+  if (pucch_decode_done || pusch_decode_done) {
+    T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4));
+  }
+
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0);
 }
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index f516ad863947d5c2d5e05d857adf43980f2db7e3..14c174c2c0de140244d22ac5c409b97d978fd633 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -132,6 +132,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
   }
 
   switch (pdu_type){
+    case FAPI_NR_RX_PDU_TYPE_SIB:
     case FAPI_NR_RX_PDU_TYPE_DLSCH:
     case FAPI_NR_RX_PDU_TYPE_RAR:
       harq_pid = dlsch0->current_harq_pid;
@@ -202,20 +203,15 @@ uint8_t get_ra_PreambleIndex(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_id){
 
 }
 
-
-// scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size
-uint16_t get_bw_scaling(uint16_t nb_rb){
-  uint16_t bw_scaling;
-  switch (nb_rb) {
-    case 32:  bw_scaling =  4; break;
-    case 66:  bw_scaling =  8; break;
-    case 106: bw_scaling = 16; break;
-    case 217: bw_scaling = 32; break;
-    case 245: bw_scaling = 32; break;
-    case 273: bw_scaling = 32; break;
-    default: abort();
-  }
-  return bw_scaling;
+// convert time factor "16 * 64 * T_c / (2^mu)" in N_TA calculation in TS38.213 section 4.2 to samples by multiplying with samples per second
+//   16 * 64 * T_c            / (2^mu) * samples_per_second
+// = 16 * T_s                 / (2^mu) * samples_per_second
+// = 16 * 1 / (15 kHz * 2048) / (2^mu) * (15 kHz * 2^mu * ofdm_symbol_size)
+// = 16 * 1 /           2048           *                  ofdm_symbol_size
+// = 16 * ofdm_symbol_size / 2048
+static inline
+uint16_t get_bw_scaling(uint16_t ofdm_symbol_size){
+  return 16 * ofdm_symbol_size / 2048;
 }
 
 // UL time alignment procedures:
@@ -233,38 +229,18 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){
 
     if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) {
 
-      uint8_t numerology = ue->frame_parms.numerology_index;
-      uint16_t bwp_ul_NB_RB = ue->frame_parms.N_RB_UL;
-      int factor_mu = 1 << numerology;
-      uint16_t bw_scaling = get_bw_scaling(bwp_ul_NB_RB);
-
-      LOG_D(PHY, "In %s: applying timing advance -- frame %d -- slot %d -- UE_mode %d\n", __FUNCTION__, frame_tx, slot_tx, ue->UE_mode[gNB_id]);
-
-      if (ue->UE_mode[gNB_id] == RA_RESPONSE){
-
-        ue->timing_advance = ul_time_alignment->ta_command * bw_scaling / factor_mu;
-
-        LOG_D(PHY, "In %s: [UE %d] [%d.%d] Received (RAR) timing advance command %d new value is %u \n",
-          __FUNCTION__,
-          ue->Mod_id,
-          frame_tx,
-          slot_tx,
-          ul_time_alignment->ta_command,
-          ue->timing_advance);
-
-      } else if (ue->UE_mode[gNB_id] == PUSCH){
+      uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
+      uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size);
 
-        ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling / factor_mu;
+      ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling;
 
-        LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n",
-          __FUNCTION__,
-          ue->Mod_id,
-          frame_tx,
-          slot_tx,
-          ul_time_alignment->ta_command,
-          ue->timing_advance);
-
-      }
+      LOG_I(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n",
+        __FUNCTION__,
+        ue->Mod_id,
+        frame_tx,
+        slot_tx,
+        ul_time_alignment->ta_command,
+        ue->timing_advance);
 
       ul_time_alignment->ta_frame = -1;
       ul_time_alignment->ta_slot = -1;
@@ -927,33 +903,19 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
   int nr_slot_rx = proc->nr_slot_rx;
   int ret=0, ret1=0;
   NR_UE_PDSCH *pdsch_vars;
-  uint8_t is_cw0_active = 0;
-  uint8_t is_cw1_active = 0;
-  uint8_t dmrs_type, nb_re_dmrs;
   uint16_t dmrs_len = get_num_dmrs(dlsch0->harq_processes[dlsch0->current_harq_pid]->dlDmrsSymbPos);
-  uint16_t nb_symb_sch = 9;
   nr_downlink_indication_t dl_indication;
   fapi_nr_rx_indication_t rx_ind;
   uint16_t number_pdus = 1;
   // params for UL time alignment procedure
   NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[eNB_id];
-  uint16_t slots_per_frame = ue->frame_parms.slots_per_frame;
-  uint16_t slots_per_subframe = ue->frame_parms.slots_per_subframe;
-  uint8_t numerology = ue->frame_parms.numerology_index, mapping_type_ul, mapping_type_dl;
-  int ul_tx_timing_adjustment, N_TA_max, factor_mu, N_t_1, N_t_2, N_1, N_2, d_1_1 = 0, d_2_1, d;
-  uint8_t d_2_2 = 0;// set to 0 because there is only 1 BWP
-                    // TODO this should corresponds to the switching time as defined in
-                    // TS 38.133
-  uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
-  uint16_t nb_prefix_samples = ue->frame_parms.nb_prefix_samples;
-  uint32_t t_subframe = 1; // subframe duration of 1 msec
-  uint16_t start_symbol;
-  float tc_factor;
-
-  is_cw0_active = dlsch0->harq_processes[harq_pid]->status;
-  nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols;
-  start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol;
-  dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType;
+
+  uint8_t is_cw0_active = dlsch0->harq_processes[harq_pid]->status;
+  uint16_t nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols;
+  uint16_t start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol;
+  uint8_t dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType;
+
+  uint8_t nb_re_dmrs;
   if (dmrs_type==NFAPI_NR_DMRS_TYPE1) {
     nb_re_dmrs = 6*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups;
   }
@@ -961,6 +923,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
     nb_re_dmrs = 4*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups;
   }
 
+  uint8_t is_cw1_active = 0;
   if(dlsch1)
     is_cw1_active = dlsch1->harq_processes[harq_pid]->status;
 
@@ -1208,7 +1171,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
             nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, eNB_id, ue, dlsch0, number_pdus);
             break;
           case SI_PDSCH:
-            rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_SIB;
+            nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id);
+            nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, eNB_id, ue, dlsch0, number_pdus);
             break;
           default:
             break;
@@ -1222,53 +1186,29 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
         }
       }
 
-      // TODO CRC check for CW0
-
-      // Check CRC for CW 0
-      /*if (ret == (1+dlsch0->max_turbo_iterations)) {
-        *dlsch_errors=*dlsch_errors+1;
-        if(dlsch0->rnti != 0xffff){
-          LOG_D(PHY,"[UE  %d][PDSCH %x/%d] AbsSubframe %d.%d : DLSCH CW0 in error (rv %d,round %d, mcs %d,TBS %d)\n",
-          ue->Mod_id,dlsch0->rnti,
-          harq_pid,frame_rx,nr_slot_rx,
-          dlsch0->harq_processes[harq_pid]->rvidx,
-          dlsch0->harq_processes[harq_pid]->round,
-          dlsch0->harq_processes[harq_pid]->mcs,
-          dlsch0->harq_processes[harq_pid]->TBS);
-        }
-      } else {
-        if(dlsch0->rnti != 0xffff){
-          LOG_D(PHY,"[UE  %d][PDSCH %x/%d] AbsSubframe %d.%d : Received DLSCH CW0 (rv %d,round %d, mcs %d,TBS %d)\n",
-          ue->Mod_id,dlsch0->rnti,
-          harq_pid,frame_rx,nr_slot_rx,
-          dlsch0->harq_processes[harq_pid]->rvidx,
-          dlsch0->harq_processes[harq_pid]->round,
-          dlsch0->harq_processes[harq_pid]->mcs,
-          dlsch0->harq_processes[harq_pid]->TBS);
-        }
-        if ( LOG_DEBUGFLAG(DEBUG_UE_PHYPROC)){
-          int j;
-          LOG_D(PHY,"dlsch harq_pid %d (rx): \n",dlsch0->current_harq_pid);
-
-          for (j=0; j<dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS>>3; j++)
-            LOG_T(PHY,"%x.",dlsch0->harq_processes[dlsch0->current_harq_pid]->b[j]);
-          LOG_T(PHY,"\n");
-      }*/
-
       if (ue->mac_enabled == 1) {
 
-        uint16_t bw_scaling = get_bw_scaling(ue->frame_parms.N_RB_DL);
-
         /* Time Alignment procedure
         // - UE processing capability 1
         // - Setting the TA update to be applied after the reception of the TA command
         // - Timing adjustment computed according to TS 38.213 section 4.2
         // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are
         //   computed according to sections 5.3 and 6.4 of TS 38.214 */
-        factor_mu = 1 << numerology;
-        N_TA_max = 3846 * bw_scaling / factor_mu;
+        const int numerology = ue->frame_parms.numerology_index;
+        const int ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
+        const int nb_prefix_samples = ue->frame_parms.nb_prefix_samples;
+        const int samples_per_subframe = ue->frame_parms.samples_per_subframe;
+        const int slots_per_frame = ue->frame_parms.slots_per_frame;
+        const int slots_per_subframe = ue->frame_parms.slots_per_subframe;
+
+        const double tc_factor = 1.0 / samples_per_subframe;
+        const uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size);
+
+        const int Ta_max = 3846; // Max value of 12 bits TA Command
+        const double N_TA_max = Ta_max * bw_scaling * tc_factor;
 
         /* PDSCH decoding time N_1 for processing capability 1 */
+        int N_1;
         if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos0)
           N_1 = pdsch_N_1_capability_1[numerology][1];
         else if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos1 || ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == 2) // TODO set to pdsch_dmrs_pos2 when available
@@ -1277,12 +1217,12 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
           N_1 = pdsch_N_1_capability_1[numerology][3];
 
         /* PUSCH preapration time N_2 for processing capability 1 */
-        N_2 = pusch_N_2_timing_capability_1[numerology][1];
-        mapping_type_dl = ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[0]->mappingType;
-        mapping_type_ul = ue->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType;
+        const int N_2 = pusch_N_2_timing_capability_1[numerology][1];
 
         /* d_1_1 depending on the number of PDSCH symbols allocated */
-        d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH
+        const int d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH
+        int d_1_1 = 0;
+        mappingType_t mapping_type_dl = ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[0]->mappingType;
         if (mapping_type_dl == typeA)
          if (nb_symb_sch + start_symbol < 7)
           d_1_1 = 7 - (nb_symb_sch + start_symbol);
@@ -1297,22 +1237,26 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
           }
 
         /* d_2_1 */
+        int d_2_1;
+        mappingType_t mapping_type_ul = ue->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType;
         if (mapping_type_ul == typeB && start_symbol != 0)
           d_2_1 = 0;
         else
           d_2_1 = 1;
 
+        /* d_2_2 */
+        const double d_2_2 = 0.0; // set to 0 because there is only 1 BWP: TODO this should corresponds to the switching time as defined in TS 38.133
+
         /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time
         // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */
-        N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) / factor_mu;
-        N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) / factor_mu;
+        double N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor;
+        double N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor;
         if (N_t_2 < d_2_2) N_t_2 = d_2_2;
 
         /* Time alignment procedure */
-        // N_t_1 + N_t_2 + N_TA_max is in unit of Ts, therefore must be converted to Tc
         // N_t_1 + N_t_2 + N_TA_max must be in msec
-        tc_factor = 64 * 0.509 * 10e-7;
-        ul_tx_timing_adjustment = 1 + ceil(slots_per_subframe*((N_t_1 + N_t_2 + N_TA_max)*tc_factor + 0.5)/t_subframe);
+        const double t_subframe = 1.0; // subframe duration of 1 msec
+        const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe);
 
         if (ul_time_alignment->apply_ta == 1){
           ul_time_alignment->ta_slot = (nr_slot_rx + ul_tx_timing_adjustment) % slots_per_frame;
@@ -1326,13 +1270,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
           LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot);
         }
       }
-
-      /*ue->total_TBS[eNB_id] =  ue->total_TBS[eNB_id] + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS;
-      ue->total_received_bits[eNB_id] = ue->total_TBS[eNB_id] + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS;
-    }*/
-
-    // TODO CRC check for CW1
-
   }
 }
 
@@ -1736,9 +1673,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
       nr_slot_fep(ue,
                   proc,
                   (ue->symbol_offset+i)%(fp->symbols_per_slot),
-                  nr_slot_rx,
-                  0,
-                  0);
+                  nr_slot_rx);
 
 #if UE_TIMING_TRACE
       start_meas(&ue->dlsch_channel_estimation_stats);
@@ -1791,9 +1726,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
     nr_slot_fep(ue,
                 proc,
                 l,
-                nr_slot_rx,
-                0,
-                0);
+                nr_slot_rx);
 
     dci_cnt = 0;
     for(int n_ss = 0; n_ss<pdcch_vars->nb_search_space; n_ss++) {
@@ -1852,9 +1785,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
         nr_slot_fep(ue,
                     proc,
                     m,  //to be updated from higher layer
-                    nr_slot_rx,
-                    0,
-                    0);
+                    nr_slot_rx);
       }
     }
   } else {
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 678453539143a1a76faaccfaecc1d674fc9124c6..4c6a02b69f16829834c0ba3b3b24c0fd81ad489a 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -79,8 +79,8 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
 
 double cpuf;
 
-int sf_ahead=4 ;
-int sl_ahead=0;
+uint16_t sf_ahead=4 ;
+uint16_t sl_ahead=0;
 //uint8_t nfapi_mode = 0;
 uint64_t downlink_frequency[MAX_NUM_CCs][4];
 
@@ -97,6 +97,21 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t     module_id,
   return 0;
 }
 
+void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
+{
+  return;
+}
+
+int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
+                              const int         CC_id,
+                              const uint8_t     gNB_id,
+                              const frame_t     frameP,
+                              const rb_id_t     Srb_id,
+                              uint8_t           *buffer_pP)
+{
+  return 0;
+}
+
 void
 rrc_data_ind(
   const protocol_ctxt_t *const ctxt_pP,
@@ -185,14 +200,11 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0);
 int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0);  }
 int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0);  }
 
-int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) {
-  return 0;
-}
-
 // needed for some functions
 openair0_config_t openair0_cfg[MAX_CARDS];
 void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg);
 void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dmrs_arg);
+extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration 
 
 /* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs from command line of
    dlsim, does not search for CCE/PUCCH occasion but simply sets to 0 */
@@ -248,7 +260,10 @@ int main(int argc, char **argv)
   int i,aa;//,l;
   double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0;
   uint8_t snr1set=0;
-  float roundStats[50];
+  double roundStats[500] = {0};
+  double blerStats[500] = {0};
+  double berStats[500] = {0};
+  double snrStats[500] = {0};
   float effRate;
   //float psnr;
   float eff_tp_check = 0.7;
@@ -659,6 +674,7 @@ int main(int argc, char **argv)
   rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon));
 
   NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon;
+  NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
   NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup));
   prepare_scc(rrc.carrier.servingcellconfigcommon);
   uint64_t ssb_bitmap;
@@ -666,13 +682,18 @@ int main(int argc, char **argv)
 
   fix_scc(scc,ssb_bitmap);
 
-  fill_default_secondaryCellGroup(scc,
-				  secondaryCellGroup,
-				  0,
-				  1,
-				  n_tx,
-				  0);
+  prepare_scd(scd);
 
+  fill_default_secondaryCellGroup(scc,
+                                  scd,
+                                  secondaryCellGroup,
+                                  0,
+                                  1,
+                                  n_tx,
+                                  0);
+
+  /* RRC parameter validation for secondaryCellGroup */
+  fix_scd(scd);
   /* -U option modify DMRS */
   if(modify_dmrs) {
     update_dmrs_config(secondaryCellGroup, NULL,dmrs_arg);
@@ -1114,7 +1135,9 @@ int main(int argc, char **argv)
       if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round;
     } // noise trials
 
+    blerStats[snrRun] = (float) n_errors / (float) n_trials;
     roundStats[snrRun]/=((float)n_trials);
+    berStats[snrRun] = (double)errors_scrambling/available_bits/n_trials;
     effRate /= n_trials;
     printf("*****************************************\n");
     printf("SNR %f, (false positive %f)\n", SNR,
@@ -1122,7 +1145,7 @@ int main(int argc, char **argv)
     printf("*****************************************\n");
     printf("\n");
     dump_pdsch_stats(gNB);
-    printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS);
+    printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, BLER %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],berStats[snrRun],blerStats[snrRun],effRate,effRate/TBS*100,TBS);
     printf("\n");
 
     if (print_perf==1) {
@@ -1187,15 +1210,19 @@ int main(int argc, char **argv)
       break;
     }
 
-    //if ((float)n_errors/(float)n_trials <= target_error_rate) {
     if (effRate > (eff_tp_check*TBS)) {
       printf("PDSCH test OK\n");
       break;
     }
 
+    snrStats[snrRun] = SNR;
     snrRun++;
   } // NSR
 
+  LOG_M("dlsimStats.m","SNR",snrStats,snrRun,1,7);
+  LOG_MM("dlsimStats.m","BLER",blerStats,snrRun,1,7);
+  LOG_MM("dlsimStats.m","BER",berStats,snrRun,1,7);
+  LOG_MM("dlsimStats.m","rounds",roundStats,snrRun,1,7);
   /*if (n_trials>1) {
     printf("HARQ stats:\nSNR\tRounds\n");
     psnr = snr0;
diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h
index 8004fbb6b5be4dce9e4d1d7f3dc24e44e0a9f1f0..b78b42db9119ebaad952d1adbd9a91b6722f6ac1 100644
--- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h
+++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h
@@ -55,19 +55,6 @@ signed char quantize(double D, double x, unsigned char B) {
   return ((char) qxd);
 }
 
-
-int8_t
-mac_rrc_data_req_ue(
-  const module_id_t Mod_idP,
-  const int         CC_id,
-  const frame_t     frameP,
-  const rb_id_t     Srb_id,
-  const uint8_t     Nb_tb,
-  uint8_t    *const buffer_pP,
-  const mac_enb_index_t eNB_indexP,
-  const uint8_t     mbsfn_sync_area
-		    ) { return(0);}
-
 int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {return(0);}
 //NR_IF_Module_t *NR_IF_Module_init(int Mod_id){return(NULL);}
 int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); }
@@ -235,6 +222,7 @@ void fill_scc(NR_ServingCellConfigCommon_t *scc,uint64_t *ssb_bitmap,int N_RB_DL
 
 void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap);
 void prepare_scc(NR_ServingCellConfigCommon_t *scc);
+void prepare_scd(NR_ServingCellConfig_t *scd);
 ngap_gNB_config_t ngap_config;
 uint32_t ngap_generate_gNB_id(void) {return 0;}
 void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { return;}
diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c
index 2512988371dc6bbab29b3ecb3b685df0322850c8..a3c25011970097f68483b98f2f24e96ff54de5a0 100644
--- a/openair1/SIMULATION/NR_PHY/pbchsim.c
+++ b/openair1/SIMULATION/NR_PHY/pbchsim.c
@@ -101,8 +101,8 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB,
   //gNB_config->subframe_config.dl_cyclic_prefix_type.value = (fp->Ncp == NORMAL) ? NFAPI_CP_NORMAL : NFAPI_CP_EXTENDED;
 
   gNB->mac_enabled   = 1;
-  fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
-  fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
+  fp->dl_CarrierFreq = 3600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
+  fp->ul_CarrierFreq = 3600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
   if (mu>2) fp->nr_band = 257;
   else fp->nr_band = 78;
   fp->threequarter_fs= 0;
@@ -111,7 +111,7 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB,
 
   nr_init_frame_parms(gNB_config, fp);
 
-  init_symbol_rotation(fp,fp->dl_CarrierFreq);
+  init_symbol_rotation(fp);
 
   gNB->configured    = 1;
   LOG_I(PHY,"gNB configured\n");
@@ -540,7 +540,7 @@ int main(int argc, char **argv)
   if (input_fd==NULL) {
     gNB->pbch_configured = 1;
  
-    gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0;
+    gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33;
 
     for (int slot=0;slot<frame_parms->slots_per_frame;slot++) {
     	for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++)
@@ -692,9 +692,7 @@ int main(int argc, char **argv)
           nr_slot_fep(UE,
                       &proc,
                       i%frame_parms->symbols_per_slot,
-                      ssb_slot,
-                      0,
-                      0);
+                      ssb_slot);
 
           nr_pbch_channel_estimation(UE,&proc,0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf);
 
@@ -718,9 +716,9 @@ int main(int argc, char **argv)
  
 	  payload_ret = (UE->pbch_vars[0]->xtra_byte == gNB_xtra_byte);
 	  for (i=0;i<3;i++){
-	    payload_ret += (UE->pbch_vars[0]->decoded_output[i] == (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)));
+	    payload_ret += (UE->pbch_vars[0]->decoded_output[i] == ((gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff));
 	  } 
-	  //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->rx_ind.rx_indication_body->mib_pdu.additional_bits);
+	  //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->pbch_vars[0]->xtra_byte);
 	  //printf("ret %d\n", payload_ret);
 	  if (payload_ret!=4) 
 	    n_errors_payload++;
diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c
index c90bcf1395d9dbd7755b30a3bd3b0b8c503de9e9..74ca8d9184691881684e42ebaffda07b7f459915 100644
--- a/openair1/SIMULATION/NR_PHY/prachsim.c
+++ b/openair1/SIMULATION/NR_PHY/prachsim.c
@@ -64,7 +64,7 @@ double cpuf;
 extern uint16_t prach_root_sequence_map0_3[838];
 openair0_config_t openair0_cfg[MAX_CARDS];
 //uint8_t nfapi_mode=0;
-int sl_ahead = 0;
+uint16_t sl_ahead = 0;
 
 //void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe);
 
@@ -132,13 +132,24 @@ nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(
 
 int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) {return 0;}
 
-// Dummy function to avoid linking error at compilation of nr-prachsim
-int is_x2ap_enabled(void)
+void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
+{
+  return;
+}
+
+int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
+                              const int         CC_id,
+                              const uint8_t     gNB_id,
+                              const frame_t     frameP,
+                              const rb_id_t     Srb_id,
+                              uint8_t           *buffer_pP)
 {
   return 0;
 }
 
-int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) {
+// Dummy function to avoid linking error at compilation of nr-prachsim
+int is_x2ap_enabled(void)
+{
   return 0;
 }
 
@@ -454,7 +465,10 @@ int main(int argc, char **argv){
 
   nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions);
 
-  uint64_t absoluteFrequencyPointA = (mu==1 ? 640000 : 2070833);
+  uint64_t absoluteFrequencyPointA = to_nrarfcn(frame_parms->nr_band,
+				       frame_parms->dl_CarrierFreq,
+				       frame_parms->numerology_index,
+				       frame_parms->N_RB_UL*(180e3)*(1 << frame_parms->numerology_index));
 
   uint8_t subframe = slot/frame_parms->slots_per_subframe;
   
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index 443ee6e1c0ccef6c04e347c99f8365902dc456ee..d8fef539ba14147766f74a14d91c26388fa058e1 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -75,13 +75,14 @@ PHY_VARS_NR_UE *UE;
 RAN_CONTEXT_t RC;
 int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
 
-int sf_ahead=4 ;
+uint16_t sf_ahead=4 ;
 int slot_ahead=6 ;
-int sl_ahead=0;
+uint16_t sl_ahead=0;
 double cpuf;
 //uint8_t nfapi_mode = 0;
 uint64_t downlink_frequency[MAX_NUM_CCs][4];
 
+extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration
 
 int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index,
                               const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) { return 0; }
@@ -155,15 +156,27 @@ int is_x2ap_enabled(void)
   return 0;
 }
 
-//nFAPI P7 dummy functions 
+void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
+{
+  return;
+}
+
+int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
+                              const int         CC_id,
+                              const uint8_t     gNB_id,
+                              const frame_t     frameP,
+                              const rb_id_t     Srb_id,
+                              uint8_t           *buffer_pP)
+{
+  return 0;
+}
+
+//nFAPI P7 dummy functions
 
 int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0);  }
 int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0);  }
 int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0);  }
 int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0);  }
-int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) {
-  return 0;
-}
 
 int nr_derive_key(int alg_type, uint8_t alg_id,
                const uint8_t key[32], uint8_t **out)
@@ -607,8 +620,8 @@ int main(int argc, char **argv)
   frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
 
 
-  frame_parms->nb_antennas_tx = n_tx;
-  frame_parms->nb_antennas_rx = n_rx;
+  //frame_parms->nb_antennas_tx = n_tx;
+  //frame_parms->nb_antennas_rx = n_rx;
   frame_parms->N_RB_DL = N_RB_DL;
   frame_parms->N_RB_UL = N_RB_UL;
   frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL;
@@ -626,6 +639,7 @@ int main(int argc, char **argv)
   rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon));
 
   NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon;
+  NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
   NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup));
   prepare_scc(rrc.carrier.servingcellconfigcommon);
   uint64_t ssb_bitmap;
@@ -633,7 +647,10 @@ int main(int argc, char **argv)
 
   fix_scc(scc,ssb_bitmap);
 
+  prepare_scd(scd);
+
   fill_default_secondaryCellGroup(scc,
+                                  scd,
 				  secondaryCellGroup,
 				  0,
 				  1,
@@ -642,11 +659,14 @@ int main(int argc, char **argv)
 
   // xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
 
+  /* RRC parameter validation for secondaryCellGroup */
+  fix_scd(scd);
+
   AssertFatal((gNB->if_inst         = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
 
   gNB->if_inst->NR_PHY_config_req      = nr_phy_config_request;
   // common configuration
-  rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL);
+  rrc_mac_config_req_gNB(0,0,n_rx,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL);
   // UE dedicated configuration
   rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
   phy_init_nr_gNB(gNB,0,0);
@@ -1053,70 +1073,69 @@ int main(int argc, char **argv)
       }
 
 
-      nr_fill_ulsch(gNB,frame,slot,pusch_pdu);
+      //nr_fill_ulsch(gNB,frame,slot,pusch_pdu); // Not needed as its its already filled as apart of "nr_schedule_response(Sched_INFO);"
 
       for (int i=0;i<(TBS/8);i++) ulsch_ue[0]->harq_processes[harq_pid]->a[i]=i&0xff;
       if (input_fd == NULL) {
 
-	  // set FAPI parameters for UE, put them in the scheduled response and call
-	  nr_ue_scheduled_response(&scheduled_response);
-	  
-	  
-	  /////////////////////////phy_procedures_nr_ue_TX///////////////////////
-	  ///////////
-	  
-	  phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id);
-	  
-	  
-	  if (n_trials==1) {
-	    LOG_M("txsig0.m","txs0", UE->common_vars.txdata[0],frame_parms->samples_per_subframe*10,1,1);
-	    LOG_M("txsig0F.m","txs0F", UE->common_vars.txdataF[0],frame_parms->ofdm_symbol_size*14,1,1);
-	  }
-	  ///////////
-	  ////////////////////////////////////////////////////
-	  tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
-	  
-	  txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0],
-				frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples);
+        // set FAPI parameters for UE, put them in the scheduled response and call
+        nr_ue_scheduled_response(&scheduled_response);
+
+
+        /////////////////////////phy_procedures_nr_ue_TX///////////////////////
+        ///////////
+
+        phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id);
+
+
+        if (n_trials==1) {
+          LOG_M("txsig0.m","txs0", UE->common_vars.txdata[0],frame_parms->samples_per_subframe*10,1,1);
+          LOG_M("txsig0F.m","txs0F", UE->common_vars.txdataF[0],frame_parms->ofdm_symbol_size*14,1,1);
+        }
+        ///////////
+        ////////////////////////////////////////////////////
+        tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
+
+        txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0],
+                              frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples);
       }	
       else n_trials = 1;
 
       if (input_fd == NULL ) {
 
-	sigma_dB = 10 * log10((double)txlev * ((double)frame_parms->ofdm_symbol_size/(12*nb_rb))) - SNR;;
-	sigma    = pow(10,sigma_dB/10);
+        sigma_dB = 10 * log10((double)txlev * ((double)frame_parms->ofdm_symbol_size/(12*nb_rb))) - SNR;;
+        sigma    = pow(10,sigma_dB/10);
 
 
-	if(n_trials==1) printf("sigma %f (%f dB), txlev %f (factor %f)\n",sigma,sigma_dB,10*log10((double)txlev),(double)(double)frame_parms->ofdm_symbol_size/(12*nb_rb));
+        if(n_trials==1) printf("sigma %f (%f dB), txlev %f (factor %f)\n",sigma,sigma_dB,10*log10((double)txlev),(double)(double)
+                                frame_parms->ofdm_symbol_size/(12*nb_rb));
 
-	for (i=0; i<slot_length; i++) {
-	  for (int aa=0; aa<1; aa++) {
-	    s_re[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)]);
-	    s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)+1]);
-	  }
-	}
-	
+        for (i=0; i<slot_length; i++) {
+          for (int aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
+            s_re[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)]);
+            s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)+1]);
+          }
+        }
 
-	if (UE2gNB->max_Doppler == 0) {
-	  multipath_channel(UE2gNB,s_re,s_im,r_re,r_im,
-			    slot_length,0,(n_trials==1)?1:0);
-	} else {
-	  multipath_tv_channel(UE2gNB,s_re,s_im,r_re,r_im,
-			       2*slot_length,0);
-	}
-	for (i=0; i<slot_length; i++) {
-	  for (ap=0; ap<frame_parms->nb_antennas_rx; ap++) {
-	    ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)]   = (int16_t)((r_re[ap][i])   + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point
-	    ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)]   = (int16_t)((r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0)));
+
+        if (UE2gNB->max_Doppler == 0) {
+          multipath_channel(UE2gNB, s_re, s_im, r_re, r_im, slot_length, 0, (n_trials==1)?1:0);
+        } else {
+          multipath_tv_channel(UE2gNB, s_re, s_im, r_re, r_im, 2*slot_length, 0);
+        }
+        for (i=0; i<slot_length; i++) {
+          for (ap=0; ap<frame_parms->nb_antennas_rx; ap++) {
+            ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)   + (delay*2)] = (int16_t)((r_re[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point
+            ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0)));
             /* Add phase noise if enabled */
             if (pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
               phase_noise(ts, &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)],
                           &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1]);
             }
-	  }
-	}
+          }
+        }
 
-      }
+      } /*End input_fd */
 
 
       if(pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index 02f878ee2e2e9c788e156bf827e89e792bc1aca9..87f926b2060895e45ed95184be24800c01bbe5ca 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -42,6 +42,7 @@
 #include "LTE_SL-DiscResourcePool-r12.h"
 #include "NR_RACH-ConfigCommon.h"
 #include "NR_ServingCellConfigCommon.h"
+#include "NR_ServingCellConfig.h"
 //-------------------------------------------------------------------------------------------//
 // Messages for RRC logging
 #if defined(DISABLE_ITTI_XER_PRINT)
@@ -405,6 +406,7 @@ typedef struct NRRrcConfigurationReq_s {
   uint16_t                mnc[PLMN_LIST_MAX_SIZE];
   uint8_t                 mnc_digit_length[PLMN_LIST_MAX_SIZE];
   NR_ServingCellConfigCommon_t *scc;
+  NR_ServingCellConfig_t  *scd;
   int                     ssb_SubcarrierOffset;
   int                     pdsch_AntennaPorts;
   int                     pusch_TargetSNRx10;
diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h
index bd0788d2d0efd6353df7ea996e78dfddcbe62fa0..21513756867bf6b7d5769a689679d6b103e5cd6a 100644
--- a/openair2/COMMON/s1ap_messages_types.h
+++ b/openair2/COMMON/s1ap_messages_types.h
@@ -398,6 +398,11 @@ typedef struct s1ap_register_enb_req_s {
   /* Number of SCTP streams used for a mme association */
   uint16_t sctp_in_streams;
   uint16_t sctp_out_streams;
+  uint16_t s1_setuprsp_wait_timer;
+  uint16_t s1_setupreq_wait_timer;
+  uint16_t s1_setupreq_count;
+  uint16_t sctp_req_timer;
+  uint16_t sctp_req_count;
 } s1ap_register_enb_req_t;
 
 //-------------------------------------------------------------------------------------------//
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 6c709ea63b8818f436d83af51add83231184c296..d05fe7ac26d314bac5c80f5d7f8872597fa399bc 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -2429,6 +2429,65 @@ int RCconfig_S1(
                         "to\n"
                         "    tracking_area_code  =  1; // no string!!\n"
                         "    plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n");
+            if(*ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr <= 0xffff)
+            {
+              S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr;
+            }
+            else
+            {
+              LOG_E(S1AP, 
+                    "s1setup_rsp_timer value in conf file is invalid (%d). Default value is set.\n",
+                    *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr);
+              S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = 5;
+            }
+
+            if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr <= 0xffff)
+            {
+              S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr;
+            }
+            else
+            {
+              LOG_E(S1AP, 
+                    "s1setup_req_timer value in conf file is invalid (%d). Default value is set.\n",
+                    *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr);
+              S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = 5;
+            }
+
+            if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr <= 0xffff)
+            {
+              S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr;
+            }
+            else
+            {
+              LOG_E(S1AP, 
+                    "s1setup_req_count value in conf file is invalid (%d). Default value is set.\n",
+                    *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr);
+              S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = 0xffff;
+            }
+
+            if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr <= 0xffff)
+            {
+              S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr;
+            }
+            else
+            {
+              LOG_E(S1AP, 
+                    "sctp_req_timer value in conf file is invalid (%d). Default value is set.\n",
+                    *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr);
+              S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = 180;
+            }
+
+            if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr <= 0xffff)
+            {
+              S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr;
+            }
+            else
+            {
+              LOG_E(S1AP, 
+                    "sctp_req_count value in conf file is invalid (%d). Default value is set.\n",
+                    *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr);
+              S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = 0xffff;
+            }
             config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix);
 
             if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6) {
diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h
index de7e0bbdad96ba7a65cfe2691486faf37026ed4e..f26863414cbc26709c1c54300fc065cfc7274629 100644
--- a/openair2/ENB_APP/enb_paramdef.h
+++ b/openair2/ENB_APP/enb_paramdef.h
@@ -214,6 +214,11 @@ typedef enum {
 #define ENB_CONFIG_STRING_X2                            "enable_x2"
 #define ENB_CONFIG_STRING_ENB_M2                        "enable_enb_m2"
 #define ENB_CONFIG_STRING_MCE_M2                        "enable_mce_m2"
+#define ENB_CONFIG_STRING_S1SETUP_RSP_TIMER             "s1setup_rsp_timer"
+#define ENB_CONFIG_STRING_S1SETUP_REQ_TIMER             "s1setup_req_timer"
+#define ENB_CONFIG_STRING_S1SETUP_REQ_COUNT             "s1setup_req_count"
+#define ENB_CONFIG_STRING_SCTP_REQ_TIMER                "sctp_req_timer"
+#define ENB_CONFIG_STRING_SCTP_REQ_COUNT                "sctp_req_count"
 /*-----------------------------------------------------------------------------------------------------------------------------------------*/
 /*                                            cell configuration parameters                                                                */
 /*   optname                                   helpstr   paramflags    XXXptr        defXXXval                   type           numelt     */
@@ -239,6 +244,11 @@ typedef enum {
     {ENB_CONFIG_STRING_X2,                           NULL,   0,            strptr:NULL, defstrval:NULL,              TYPE_STRING,    0},  \
     {ENB_CONFIG_STRING_ENB_M2,                       NULL,   0,            strptr:NULL, defstrval:"no",              TYPE_STRING,    0},  \
     {ENB_CONFIG_STRING_MCE_M2,                       NULL,   0,            strptr:NULL, defstrval:"no",              TYPE_STRING,    0},  \
+    {ENB_CONFIG_STRING_S1SETUP_RSP_TIMER,            NULL,   0,            uptr:NULL,   defuintval:5,                TYPE_UINT,      0},  \
+    {ENB_CONFIG_STRING_S1SETUP_REQ_TIMER,            NULL,   0,            uptr:NULL,   defuintval:5,                TYPE_UINT,      0},  \
+    {ENB_CONFIG_STRING_S1SETUP_REQ_COUNT,            NULL,   0,            uptr:NULL,   defuintval:65535,            TYPE_UINT,      0},  \
+    {ENB_CONFIG_STRING_SCTP_REQ_TIMER,               NULL,   0,            uptr:NULL,   defuintval:180,              TYPE_UINT,      0},  \
+    {ENB_CONFIG_STRING_SCTP_REQ_COUNT,               NULL,   0,            uptr:NULL,   defuintval:65535,            TYPE_UINT,      0},  \
   }
 
 #define ENB_ENB_ID_IDX                  0
@@ -261,6 +271,11 @@ typedef enum {
 #define ENB_ENABLE_X2                   17
 #define ENB_ENABLE_ENB_M2               18
 #define ENB_ENABLE_MCE_M2               19
+#define ENB_S1SETUP_RSP_TIMER_IDX       20
+#define ENB_S1SETUP_REQ_TIMER_IDX       21
+#define ENB_S1SETUP_REQ_COUNT_IDX       22
+#define ENB_SCTP_REQ_TIMER_IDX          23
+#define ENB_SCTP_REQ_COUNT_IDX          24
 
 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
 #define ENBPARAMS_CHECK {                                           \
diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h
index 1f1d076e9d2c002ee21cf74e8f18798fcd6b604d..d05908e8edc9102ff7c7d6fd21ee28cf56985bb2 100644
--- a/openair2/GNB_APP/RRC_nr_paramsvalues.h
+++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h
@@ -211,6 +211,24 @@
 
 #define CARRIERBANDWIDTH_OKVALUES {11,18,24,25,31,32,38,51,52,65,66,78,79,93,106,107,121,132,133,135,160,162,189,216,217,245,264,270,273}
 
+/* Serving Cell Config Dedicated */
+#define GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED                     "servingCellConfigDedicated"
+#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0                           "dl_ptrsFreqDensity0_0"
+#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0                           "dl_ptrsFreqDensity1_0"
+#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0                           "dl_ptrsTimeDensity0_0"
+#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0                           "dl_ptrsTimeDensity1_0"
+#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0                           "dl_ptrsTimeDensity2_0"
+#define GNB_CONFIG_STRING_DLPTRSEPRERATIO_0                              "dl_ptrsEpreRatio_0"
+#define GNB_CONFIG_STRING_DLPTRSREOFFSET_0                               "dl_ptrsReOffset_0"
+#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0                           "ul_ptrsFreqDensity0_0"
+#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0                           "ul_ptrsFreqDensity1_0"
+#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0                           "ul_ptrsTimeDensity0_0"
+#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0                           "ul_ptrsTimeDensity1_0"
+#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0                           "ul_ptrsTimeDensity2_0"
+#define GNB_CONFIG_STRING_ULPTRSREOFFSET_0                               "ul_ptrsReOffset_0"
+#define GNB_CONFIG_STRING_ULPTRSMAXPORTS_0                               "ul_ptrsMaxPorts_0"
+#define GNB_CONFIG_STRING_ULPTRSPOWER_0                                  "ul_ptrsPower_0"
+
 /*--------------------------------------------------------------------------------------------------------------------*/
 /*                                            pdcch_ConfigSIB1 parameters                                             */
 /*--------------------------------------------------------------------------------------------------------------------*/
@@ -395,6 +413,26 @@
 {GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,i64ptr:&scc->ss_PBCH_BlockPower,defint64val:20,TYPE_INT64,0}, \
 {GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,defintval:-1,TYPE_INT64,0}}
 
+/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*                                     Serving Cell Config Dedicated configuration parameters                                                                                                     */
+/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+
+#define SCDPARAMS_DESC(scd) { \
+{GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[2],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_DLPTRSEPRERATIO_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio,defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_DLPTRSREOFFSET_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset,defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[2],defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_ULPTRSREOFFSET_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset,defint64val:-1,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_ULPTRSMAXPORTS_0,NULL,0,i64ptr:&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->maxNrofPorts,defint64val:0,TYPE_INT64,0}, \
+{GNB_CONFIG_STRING_ULPTRSPOWER_0,NULL,0,i64ptr:&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->ptrs_Power,defint64val:0,TYPE_INT64,0}}
 
 
 
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 957485a9923341f75b8373efc4a05fbd3a183d66..608827cc7aa6828990d2c578b8ad10c3453cfcfe 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -293,6 +293,171 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) {
   }
 }
 
+/* Function to allocate dedicated serving cell config strutures */
+void prepare_scd(NR_ServingCellConfig_t *scd) {
+  // Allocate downlink structures
+
+  scd->downlinkBWP_ToAddModList = CALLOC(1, sizeof(scd->downlinkBWP_ToAddModList));
+
+  // Downlink bandwidth part
+  NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp));
+  bwp->bwp_Id = 1;
+
+  // Allocate downlink dedicated bandwidth part and PDSCH structures
+  bwp->bwp_Dedicated = calloc(1, sizeof(*bwp->bwp_Dedicated));
+  bwp->bwp_Dedicated->pdsch_Config = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config));
+  bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup;
+  bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup));
+  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA));
+  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present = NR_SetupRelease_DMRS_DownlinkConfig_PR_setup;
+
+  // Allocate DL DMRS and PTRS configuration
+  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup));
+  NR_DMRS_DownlinkConfig_t *NR_DMRS_DownlinkCfg = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup;
+  NR_DMRS_DownlinkCfg->phaseTrackingRS=CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS));
+  NR_DMRS_DownlinkCfg->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup;
+  NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup));
+  NR_PTRS_DownlinkConfig_t *NR_PTRS_DownlinkCfg = NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup;
+  NR_PTRS_DownlinkCfg->frequencyDensity = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->frequencyDensity));
+  int *dl_rbs[2];
+  for (int i=0;i<2;i++) {
+    dl_rbs[i] = CALLOC(1, sizeof(*dl_rbs[i]));
+    *dl_rbs[i] = 0;
+    ASN_SEQUENCE_ADD(&NR_PTRS_DownlinkCfg->frequencyDensity->list, dl_rbs[i]);
+  }
+  NR_PTRS_DownlinkCfg->timeDensity = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->timeDensity));
+  int *dl_mcs[3];
+  for (int i=0;i<3;i++) {
+    dl_mcs[i] = CALLOC(1, sizeof(*dl_mcs[i]));
+    *dl_mcs[i] = 0;
+    ASN_SEQUENCE_ADD(&NR_PTRS_DownlinkCfg->timeDensity->list, dl_mcs[i]);
+  }
+  NR_PTRS_DownlinkCfg->epre_Ratio = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->epre_Ratio));
+  NR_PTRS_DownlinkCfg->resourceElementOffset = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->resourceElementOffset));
+  *NR_PTRS_DownlinkCfg->resourceElementOffset = 0;
+  ASN_SEQUENCE_ADD(&scd->downlinkBWP_ToAddModList->list,bwp);
+
+  // Allocate uplink structures
+
+  scd->uplinkConfig = CALLOC(1, sizeof(NR_UplinkConfig_t));
+  scd->uplinkConfig->uplinkBWP_ToAddModList = CALLOC(1, sizeof(scd->uplinkConfig->uplinkBWP_ToAddModList));
+
+  NR_PUSCH_Config_t *pusch_Config = CALLOC(1, sizeof(*pusch_Config));
+
+  // Allocate UL DMRS and PTRS structures
+  pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB));
+  pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup;
+  pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup));
+  NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup;
+  NR_DMRS_UplinkConfig->phaseTrackingRS = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS));
+  NR_DMRS_UplinkConfig->phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup;
+  NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup));
+  NR_PTRS_UplinkConfig_t *NR_PTRS_UplinkConfig = NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup;
+  NR_PTRS_UplinkConfig->transformPrecoderDisabled = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled));
+  NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity));
+  int *n_rbs[2];
+  for (int i=0;i<2;i++) {
+    n_rbs[i] = CALLOC(1, sizeof(*n_rbs[i]));
+    *n_rbs[i] = 0;
+    ASN_SEQUENCE_ADD(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity->list, n_rbs[i]);
+  }
+  NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity));
+  int *ptrs_mcs[3];
+  for (int i = 0; i < 3; i++) {
+    ptrs_mcs[i] = CALLOC(1, sizeof(*ptrs_mcs[i]));
+    *ptrs_mcs[i] = 0;
+    ASN_SEQUENCE_ADD(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity->list, ptrs_mcs[i]);
+  }
+  NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = CALLOC(1, sizeof(NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset));
+  *NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = 0;
+
+  // UL bandwidth part
+  NR_BWP_Uplink_t *ubwp = CALLOC(1, sizeof(*ubwp));
+  ubwp->bwp_Id = 1;
+  ubwp->bwp_Dedicated = CALLOC(1, sizeof(*ubwp->bwp_Dedicated));
+
+  ubwp->bwp_Dedicated->pusch_Config = CALLOC(1, sizeof(*ubwp->bwp_Dedicated->pusch_Config));
+  ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup;
+  ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config;
+
+  ASN_SEQUENCE_ADD(&scd->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp);
+}
+
+/* This function checks dedicated serving cell configuration and performs fixes as needed */ 
+void fix_scd(NR_ServingCellConfig_t *scd) {
+  // Check for DL PTRS parameters validity
+  if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) {
+    // If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present
+    for (int i = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.count-1; i >= 0; i--) {
+      if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] < 1)
+          || (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] > 276)) {
+        LOG_I(RRC, "DL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i);
+        free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS);
+        scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL;
+        break;
+      }
+    }
+  }
+  if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) {
+    // If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present
+    for (int i = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.count-1; i >= 0; i--) {
+      if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] < 0)
+          || (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] > 29)) {
+        LOG_I(RRC, "DL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i);
+        free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS);
+        scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL;
+        break;
+      }
+    }
+  }
+  if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) {
+    if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset > 2) {
+      LOG_I(RRC, "Freeing DL PTRS resourceElementOffset \n");
+      free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset);
+      scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = NULL;
+    }
+    if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio > 1) {
+      LOG_I(RRC, "Freeing DL PTRS epre_Ratio \n");
+      free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio);
+      scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = NULL;
+    }
+  }
+
+  if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) {
+    // If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present
+    for (int i = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.count-1; i >= 0; i--) {
+      if ((*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] < 1) 
+          || (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] > 276)) {
+        LOG_I(RRC, "UL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i);
+        free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS);
+        scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL;
+        break;
+      }
+    }
+  }
+
+  if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) {
+    // If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present
+    for (int i = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.count-1; i >= 0; i--) {
+      if ((*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] < 0)
+          || (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] > 29)) {
+        LOG_I(RRC, "UL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i);
+        free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS);
+        scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL;
+        break;
+      }
+    }
+  }
+  if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) {
+    // Check for UL PTRS parameters validity
+    if (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset > 2) {
+      LOG_I(RRC, "Freeing UL PTRS resourceElementOffset \n");
+      free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset);
+      scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset = NULL;
+    }
+  }
+}
+
 void RCconfig_nr_flexran()
 {
   uint16_t  i;
@@ -627,6 +792,13 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
   prepare_scc(scc);
   paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc);
   paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0};
+
+  // Serving Cell Config Dedicated
+  NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
+  memset((void*)scd,0,sizeof(NR_ServingCellConfig_t));
+  prepare_scd(scd);
+  paramdef_t SCDsParams[] = SCDPARAMS_DESC(scd);
+  paramlist_def_t SCDsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, NULL, 0};
    ////////// Physical parameters
 
 
@@ -700,6 +872,23 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
 	    (int)scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower);
       fix_scc(scc,ssb_bitmap);
     }
+
+    sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
+
+    config_getlist(&SCDsParamList, NULL, 0, aprefix);
+    if (SCDsParamList.numelt > 0) {    
+      sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, 0);
+      config_get( SCDsParams,sizeof(SCDsParams)/sizeof(paramdef_t),aprefix);  
+      LOG_I(RRC,"Read in ServingCellConfigDedicated UL (FreqDensity_0 %d, FreqDensity_1 %d, TimeDensity_0 %d, TimeDensity_1 %d, TimeDensity_2 %d, RE offset %d \n",
+      (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[0],
+      (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[1],
+      (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[0],
+      (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[1],
+      (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[2],
+      (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset);
+    }
+    fix_scd(scd);
+
     printf("NRRRC %d: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr));
     if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_mac") == 0) {
       
@@ -770,6 +959,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
         printf("pucch_TargetSNRx10 %d\n",*GNBParamList.paramarray[i][GNB_PUCCH_TARGETPOW_X10_IDX].iptr);
         NRRRC_CONFIGURATION_REQ (msg_p).pucch_TargetSNRx10 = *GNBParamList.paramarray[i][GNB_PUCCH_TARGETPOW_X10_IDX].iptr;
         NRRRC_CONFIGURATION_REQ (msg_p).scc = scc;
+        NRRRC_CONFIGURATION_REQ (msg_p).scd = scd;
 
 	  
       }//
diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h
index 1bae590a596ee5f9a72de893f695af6587cc6e0c..ae8522bc83488a128911fb60fb78d8cab613093c 100644
--- a/openair2/LAYER2/MAC/mac.h
+++ b/openair2/LAYER2/MAC/mac.h
@@ -490,7 +490,7 @@ typedef struct {
 
 /*! \brief Uplink SCH PDU Structure */
 typedef struct {
-  int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */
+  uint8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */
   uint16_t Pdu_size;
 } __attribute__ ((__packed__)) ULSCH_PDU;
 
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index 5d1b08bcf67450e29f2ac3f0d97e9f1ba9739d68..cdeb23c099885938a0083f146969c64ae79a66a1 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -31,6 +31,7 @@
  */
 
 #include "LAYER2/NR_MAC_gNB/mac_proto.h"
+#include "common/utils/nr/nr_common.h"
 #include <limits.h>
 
 #define reserved 0xffff
@@ -1220,6 +1221,11 @@ int get_nr_prach_occasion_info_from_index(uint8_t index,
     else { // FDD
       x = table_6_3_3_2_2_prachConfig_Index[index][2];
       s_map = table_6_3_3_2_2_prachConfig_Index[index][4];
+      for(int i = 0; i < 64 ; i++) {
+        if ( (s_map >> i) & 0x01) {
+          (*N_RA_sfn)++;
+        }
+      }
       *N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6];
       if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
         *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
@@ -1396,19 +1402,17 @@ int get_nr_prach_info_from_index(uint8_t index,
             if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1)
               format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1];
             *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8);
-            LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n",
-                  frame,
-                  slot,
-                  index,
-                  table_6_3_3_2_3_prachConfig_Index[index][6],
-                  pointa,
-                  mu,
-                  unpaired,
-                  *start_symbol,
-                  *N_t_slot,
-                  *N_dur,
-                  *N_RA_slot,
-                  *RA_sfn_index);
+            LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n", frame,
+              slot,
+              index, table_6_3_3_2_3_prachConfig_Index[index][6],
+              pointa,
+              mu,
+              unpaired,
+              *start_symbol,
+              *N_t_slot,
+              *N_dur,
+              *N_RA_slot,
+              *RA_sfn_index);
           }
           return 1;
         }
@@ -1429,6 +1433,11 @@ int get_nr_prach_info_from_index(uint8_t index,
             if ( (table_6_3_3_2_2_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) )
               return 0; // no prach in even slots @ 30kHz for 1 prach per subframe
           }
+          for(int i = 0; i <= subframe ; i++) {
+            if ( (s_map >> i) & 0x01) {
+              (*RA_sfn_index)++;
+            }
+          }
           if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){
             *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5];
             *N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7];
@@ -1567,79 +1576,6 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config,
   }
 }
 
-// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101)
-// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101)
-// Notes:
-// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL
-// - Frequencies are expressed in KHz
-// - col: NR_band ul_min  ul_max  dl_min  dl_max  step  N_OFFs_DL  deltaf_raster
-nr_bandentry_t nr_bandtable[] = {
-  {1,   1920000, 1980000, 2110000, 2170000, 20, 422000, 100},
-  {2,   1850000, 1910000, 1930000, 1990000, 20, 386000, 100},
-  {3,   1710000, 1785000, 1805000, 1880000, 20, 361000, 100},
-  {5,    824000,  849000,  869000,  894000, 20, 173800, 100},
-  {7,   2500000, 2570000, 2620000, 2690000, 20, 524000, 100},
-  {8,    880000,  915000,  925000,  960000, 20, 185000, 100},
-  {12,   698000,  716000,  729000,  746000, 20, 145800, 100},
-  {14,   788000,  798000,  758000,  768000, 20, 151600, 100},
-  {18,   815000,  830000,  860000,  875000, 20, 172000, 100},
-  {20,   832000,  862000,  791000,  821000, 20, 158200, 100},
-  {25,  1850000, 1915000, 1930000, 1995000, 20, 386000, 100},
-  {26,   814000,  849000,  859000,  894000, 20, 171800, 100},
-  {28,   703000,  758000,  758000,  813000, 20, 151600, 100},
-  {29,      000,     000,  717000,  728000, 20, 143400, 100},
-  {30,  2305000, 2315000, 2350000, 2360000, 20, 470000, 100},
-  {34,  2010000, 2025000, 2010000, 2025000, 20, 402000, 100},
-  {38,  2570000, 2620000, 2570000, 2630000, 20, 514000, 100},
-  {39,  1880000, 1920000, 1880000, 1920000, 20, 376000, 100},
-  {40,  2300000, 2400000, 2300000, 2400000, 20, 460000, 100},
-  {41,  2496000, 2690000, 2496000, 2690000,  3, 499200,  15},
-  {41,  2496000, 2690000, 2496000, 2690000,  6, 499200,  30},
-  {47,  5855000, 5925000, 5855000, 5925000,  1, 790334,  15},
-  //{48,  3550000, 3700000, 3550000, 3700000,  1, 636667,  15},
-  //{48,  3550000, 3700000, 3550000, 3700000,  2, 636668,  30},
-  {50,  1432000, 1517000, 1432000, 1517000, 20, 286400, 100},
-  {51,  1427000, 1432000, 1427000, 1432000, 20, 285400, 100},
-  {53,  2483500, 2495000, 2483500, 2495000, 20, 496700, 100},
-  {65,  1920000, 2010000, 2110000, 2200000, 20, 422000, 100},
-  {66,  1710000, 1780000, 2110000, 2200000, 20, 422000, 100},
-  {70,  1695000, 1710000, 1995000, 2020000, 20, 399000, 100},
-  {71,   663000,  698000,  617000,  652000, 20, 123400, 100},
-  {74,  1427000, 1470000, 1475000, 1518000, 20, 295000, 100},
-  {75,      000,     000, 1432000, 1517000, 20, 286400, 100},
-  {76,      000,     000, 1427000, 1432000, 20, 285400, 100},
-  {77,  3300000, 4200000, 3300000, 4200000,  1, 620000,  15},
-  {77,  3300000, 4200000, 3300000, 4200000,  2, 620000,  30},
-  {78,  3300000, 3800000, 3300000, 3800000,  1, 620000,  15},
-  {78,  3300000, 3800000, 3300000, 3800000,  2, 620000,  30},
-  {79,  4400010, 5000000, 4400010, 5000000,  1, 693334,  15},
-  {79,  4400010, 5000000, 4400010, 5000000,  2, 693334,  30},
-  {80,  1710000, 1785000,     000,     000, 20, 342000, 100},
-  {81,   880000,  915000,     000,     000, 20, 176000, 100},
-  {82,   832000,  862000,     000,     000, 20, 166400, 100},
-  {83,   703000,  748000,     000,     000, 20, 140600, 100},
-  {84,  1920000, 1980000,     000,     000, 20, 384000, 100},
-  {86,  1710000, 1785000,     000,     000, 20, 342000, 100},
-  {89,   824000,  849000,     000,     000, 20, 342000, 100},
-  {90,  2496000, 2690000, 2496000, 2690000, 3,  499200,  15},
-  {90,  2496000, 2690000, 2496000, 2690000, 6,  499200,  30},
-  {90,  2496000, 2690000, 2496000, 2690000, 20, 499200, 100},
-  {91,   832000,  862000, 1427000, 1432000, 20, 285400, 100},
-  {92,   832000,  862000, 1432000, 1517000, 20, 286400, 100},
-  {93,   880000,  915000, 1427000, 1432000, 20, 285400, 100},
-  {94,   880000,  915000, 1432000, 1517000, 20, 286400, 100},
-  {95,  2010000, 2025000,     000,     000, 20, 402000, 100},
-  {257,26500020,29500000,26500020,29500000,  1,2054166,  60},
-  {257,26500080,29500000,26500080,29500000,  2,2054167, 120},
-  {258,24250080,27500000,24250080,27500000,  1,2016667,  60},
-  {258,24250080,27500000,24250080,27500000,  2,2016667, 120},
-  {260,37000020,40000000,37000020,40000000,  1,2229166,  60},
-  {260,37000080,40000000,37000080,40000000,  2,2229167, 120},
-  {261,27500040,28350000,27500040,28350000,  1,2070833,  60},
-  {261,27500040,28350000,27500040,28350000,  2,2070833, 120}
-};
-
-
 // TS 38.211 Table 6.4.1.1.3-3: PUSCH DMRS positions l' within a slot for single-symbol DMRS and intra-slot frequency hopping disabled.
 // The first 4 colomns are PUSCH mapping type A and the last 4 colomns are PUSCH mapping type B.
 // When l' = l0, it is represented by 1
@@ -1680,11 +1616,9 @@ int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l [12][8] = {
 {1,         1025,          -1,         -1,          1,        513,        -1,         -1},       //14              // (DMRS l' position)
 };
 
-#define NR_BANDTABLE_SIZE (sizeof(nr_bandtable)/sizeof(nr_bandentry_t))
-
 // Returns the corresponding row index of the NR table
-int get_nr_table_idx(int nr_bandP, uint8_t scs_index){
-
+int get_nr_table_idx(int nr_bandP, uint8_t scs_index)
+{
   int i, j;
   int scs_khz = 15 << scs_index;
   int supplementary_bands[] = {29,75,76,80,81,82,83,84,86,89,95};
@@ -1695,8 +1629,8 @@ int get_nr_table_idx(int nr_bandP, uint8_t scs_index){
       AssertFatal(0 == 1, "Band %d is a supplementary band (%d). This is not supported yet.\n", nr_bandP, supplementary_bands[j]);
   }
 
-  AssertFatal(nr_bandP <= nr_bandtable[NR_BANDTABLE_SIZE-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[NR_BANDTABLE_SIZE-1].band);
-  for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++);
+  AssertFatal(nr_bandP <= nr_bandtable[nr_bandtable_size-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[nr_bandtable_size-1].band);
+  for (i = 0; i < nr_bandtable_size && nr_bandtable[i].band != nr_bandP; i++);
 
   // selection of correct Deltaf raster according to SCS
   if ((nr_bandtable[i].deltaf_raster != 100) && (nr_bandtable[i].deltaf_raster != scs_khz))
@@ -1705,35 +1639,33 @@ int get_nr_table_idx(int nr_bandP, uint8_t scs_index){
   LOG_D(PHY, "NR band table index %d (Band %d, dl_min %lu, ul_min %lu)\n", i, nr_bandtable[i].band, nr_bandtable[i].dl_min,nr_bandtable[i].ul_min);
 
   return i;
-
 }
 
 // Computes the duplex spacing (either positive or negative) in KHz
-void get_delta_duplex(int nr_bandP, uint8_t scs_index, int32_t *delta_duplex){
-
+int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index)
+{
   int nr_table_idx = get_nr_table_idx(nr_bandP, scs_index);
 
-  *delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min);
+  int32_t delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min);
 
-  LOG_D(PHY, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", *delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band);
+  LOG_I(PHY, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band);
 
+  return delta_duplex;
 }
 
-void get_frame_type(uint16_t current_band,
-                    uint8_t scs_index,
-                    lte_frame_type_t *current_type){
-
-  int32_t current_offset;
-  get_delta_duplex(current_band, scs_index, &current_offset);
+lte_frame_type_t get_frame_type(uint16_t current_band, uint8_t scs_index)
+{
+  lte_frame_type_t current_type;
+  int32_t delta_duplex = get_delta_duplex(current_band, scs_index);
 
-  current_offset *= 1000;
-  if (current_offset == 0)
-    *current_type = TDD;
+  if (delta_duplex == 0)
+    current_type = TDD;
   else
-    *current_type = FDD;
+    current_type = FDD;
 
-  LOG_I(MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[*current_type], current_offset);
+  LOG_I(MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex);
 
+  return current_type;
 }
 
 uint16_t config_bandwidth(int mu, int nb_rb, int nr_band)
@@ -1911,7 +1843,6 @@ uint64_t from_nrarfcn(int nr_bandP,
   int deltaFglobal = 5;
   uint32_t N_REF_Offs = 0;
   uint64_t F_REF_Offs_khz = 0;
-  int32_t delta_duplex;
   uint64_t N_OFFs, frequency, freq_min;
   int i = get_nr_table_idx(nr_bandP, scs_index);
 
@@ -1926,7 +1857,7 @@ uint64_t from_nrarfcn(int nr_bandP,
     F_REF_Offs_khz = 24250080;
   }
 
-  get_delta_duplex(nr_bandP, scs_index, &delta_duplex);
+  int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index);
 
   if (delta_duplex <= 0){ // DL band >= UL band
     if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL
@@ -2836,11 +2767,15 @@ int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) {
   else return(slot_in_period <= slots1+scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0);    
 }
 
-int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) {
+int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slot, lte_frame_type_t frame_type) {
 
   int period,period1,period2=0;
 
-  if (scc->tdd_UL_DL_ConfigurationCommon==NULL) return(1);
+  // Note: condition on frame_type
+  // goal: the UL scheduler assumes mode is TDD therefore this hack is needed to make FDD work
+  if (scc->tdd_UL_DL_ConfigurationCommon == NULL || frame_type == FDD) {
+    return(1);
+  }
 
   if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 &&
       scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530)
@@ -3064,52 +2999,15 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config,
     valid = false;
     return valid;
   }
-  //printf("[MAC] PTRS is set  K= %u L= %u\n", *K_ptrs,1<<*L_ptrs);
-  return valid;
-}
-void get_band(uint64_t downlink_frequency,
-              uint16_t *current_band,
-              int32_t *current_offset,
-              lte_frame_type_t *current_type)
-{
-    int ind;
-    uint64_t center_frequency_khz;
-    uint64_t center_freq_diff_khz;
-    uint64_t dl_freq_khz = downlink_frequency/1000;
-
-    center_freq_diff_khz = 999999999999999999; // 2^64
-    *current_band = 0;
-
-    for ( ind=0;
-          ind < sizeof(nr_bandtable) / sizeof(nr_bandtable[0]);
-          ind++) {
 
-      LOG_I(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min,nr_bandtable[ind].ul_min);
-
-      if ( nr_bandtable[ind].dl_min <= dl_freq_khz && nr_bandtable[ind].dl_max >= dl_freq_khz ) {
-
-        center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min)/2;
-        if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){
-          *current_band = nr_bandtable[ind].band;
-	  *current_offset = (nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min)*1000;
-          center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz);
-
-	  if (*current_offset == 0)
-	    *current_type = TDD;
-	  else
-	    *current_type = FDD;
-        }
-      }
-    }
-
-    LOG_I( PHY, "DL frequency %"PRIu64": band %d, frame_type %d, UL frequency %"PRIu64"\n",
-         downlink_frequency, *current_band, *current_type, downlink_frequency+*current_offset);
-
-    AssertFatal(*current_band != 0,
-	    "Can't find EUTRA band for frequency %lu\n", downlink_frequency);
+  /* Moved below check from scheduler function to here */
+  if (*L_ptrs >= NrOfSymbols) {
+    valid = false;
+    return valid;
+  }
+  return valid;
 }
 
-
 uint32_t get_ssb_slot(uint32_t ssb_index){
   //  this function now only support f <= 3GHz
   return ssb_index & 0x3 ;
@@ -3480,3 +3378,79 @@ int get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDC
 
   return 0;
 }
+
+/* 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,
+                        uint8_t *K_ptrs, uint8_t *L_ptrs,
+                        uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower,
+                        uint8_t NrOfSymbols)
+{
+  bool valid = true;
+
+  /* as defined in T 38.214 6.2.3 */
+  if(rbSize < 3) {
+    valid = false;
+    return valid;
+  }
+  /* Check for Frequency Density values */
+  if(ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.count < 2) {
+    /* Default value for K_PTRS = 2 as defined in T 38.214 6.2.3 */
+    *K_ptrs = 2;
+  }
+  else {
+    *K_ptrs = get_K_ptrs(*ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[0],
+                         *ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[1],
+                         rbSize);
+  }
+  /* Check for time Density values */
+  if(ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.count < 3) {
+    *L_ptrs = 0;
+  }
+  else {
+    *L_ptrs = get_L_ptrs(*ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[0],
+                         *ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[1],
+                         *ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[2],
+                         mcsIndex,
+                         mcsTable);
+  }
+  
+  *reOffset  = *ul_ptrs_config->transformPrecoderDisabled->resourceElementOffset;
+  *maxNumPorts = ul_ptrs_config->transformPrecoderDisabled->maxNrofPorts;
+  *ulPower = ul_ptrs_config->transformPrecoderDisabled->ptrs_Power;
+  /* If either or both of the parameters PT-RS time density (LPT-RS) and PT-RS frequency density (KPT-RS), shown in Table
+   * 6.2.3.1-1 and Table 6.2.3.1-2, indicates that 'PT-RS not present', the UE shall assume that PT-RS is not present
+   */
+  if(*K_ptrs ==2  || *K_ptrs ==4 ) {
+    valid = true;
+  }
+  else {
+    valid = false;
+    return valid;
+  }
+  if(*L_ptrs ==0 || *L_ptrs ==1 || *L_ptrs ==2  ) {
+    valid = true;
+  }
+  else {
+    valid = false;
+    return valid;
+  }
+  /* PTRS is not present also :
+   * When the UE is receiving a PUSCH with allocation duration of 4 symbols and if LPT-RS is set to 4, the UE shall assume
+   * PT-RS is not transmitted
+   * When the UE is receiving a PUSCH with allocation duration of 2 symbols as defined in Clause 6.4.1.2.2 of [4, TS
+   * 38.211] and if LPT-RS is set to 2 or 4, the UE shall assume PT-RS is not transmitted.
+   */
+  if((NrOfSymbols == 4 && *L_ptrs ==2) || ((NrOfSymbols == 2 && *L_ptrs > 0))) {
+    valid = false;
+    return valid;
+  }
+
+  /* Moved below check from nr_ue_scheduler function to here */
+  if (*L_ptrs >= NrOfSymbols) {
+    valid = false;
+    return valid;
+  }
+  return valid;
+}
+
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
index 087d316567eaeddac443631d74c476b6cb193399..3e21131b699a1444723595eb003fb8945f3cf8ab 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
@@ -39,9 +39,9 @@
 
 uint16_t config_bandwidth(int mu, int nb_rb, int nr_band);
 
-void get_frame_type(uint16_t nr_bandP, uint8_t scs_index, lte_frame_type_t *current_type);
+lte_frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index);
 
-void get_delta_duplex(int nr_bandP, uint8_t scs_index, int32_t *delta_duplex);
+int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index);
 
 uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn);
 
@@ -51,7 +51,7 @@ int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,i
 
 int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP);
 
-int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP);
+int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slotP, lte_frame_type_t frame_type);
 
 uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc,
                      const NR_CellGroupConfig_t *secondaryCellGroup,
@@ -81,7 +81,7 @@ int get_nr_prach_info_from_index(uint8_t index,
                                  uint8_t *N_dur,
                                  uint16_t *RA_sfn_index,
                                  uint8_t *N_RA_slot,
-																 uint8_t *config_period);
+                                 uint8_t *config_period);
 
 int get_nr_prach_occasion_info_from_index(uint8_t index,
                                  uint32_t pointa,
@@ -140,8 +140,12 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config,
                         uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex,
                         uint8_t *nERatio,uint8_t *reOffset,
                         uint8_t NrOfSymbols);
-void get_band(uint64_t downlink_frequency, uint16_t *current_band, int32_t *current_offset, lte_frame_type_t *current_type);
 
+bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config,
+                        uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable,
+                        uint8_t *K_ptrs, uint8_t *L_ptrs,
+                        uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower,
+                        uint8_t NrOfSymbols);
 uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols);
 
 /* \brief Set the transform precoding according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16
diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index f6bd5436bc239fd132054f066ba9e762be47058d..fee2efc4a8175200f503bb38bd044b8b3f529c7c 100755
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -203,13 +203,12 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
   uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
   frequency_range_t  frequency_range = band<100?FR1:FR2;
  
-  lte_frame_type_t frame_type;
-  get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type);
+  mac->frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
 
   // cell config
 
   cfg->cell_config.phy_cell_id = *scc->physCellId;
-  cfg->cell_config.frame_duplex_type = frame_type;
+  cfg->cell_config.frame_duplex_type = mac->frame_type;
 
   // SSB config
   cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower;
@@ -313,7 +312,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
 
     cfg->prach_config.num_prach_fd_occasions_list[i].k1 = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart;
     cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig;
-    cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, frame_type,frequency_range);
+    cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, mac->frame_type, frequency_range);
     //cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences = ???
   }
 
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index dd0aa15c52a0c40b3236db207d70ddcb424faa1e..3e299d291e012f2c7f94efcfda47ac13b2058003 100755
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -325,6 +325,8 @@ typedef struct {
   NR_ControlResourceSet_t         *coreset[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP];
   NR_SearchSpace_t                *SSpace[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP][FAPI_NR_MAX_SS_PER_CORESET];
 
+  lte_frame_type_t frame_type;
+
   /*BWP*/
   // dedicated active DL BWP
   NR_BWP_Id_t DL_BWP_Id;
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
index c4909c138455b835b05cf8b92597a1b8c61b0949..14d1ea63fb68e9de5f04a7ab87cf1e594071c62b 100755
--- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
@@ -56,14 +56,14 @@ int8_t nr_ue_decode_mib(
     void *pduP, 
     uint16_t cell_id );
 
-/**\brief decode sib1 pdu in NR_UE, from if_module dl_ind
+/**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind
    \param module_id      module id
    \param cc_id          component carrier id
    \param gNB_index      gNB index
    \param sibs_mask      sibs mask
    \param pduP           pointer to pdu
    \param pdu_length     length of pdu */
-int8_t nr_ue_decode_sib1(module_id_t module_id,
+int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id,
                          int cc_id,
                          unsigned int gNB_index,
                          uint32_t sibs_mask,
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_vars.c b/openair2/LAYER2/NR_MAC_UE/mac_vars.c
index ecabdb870c7399667b1c1c57477f4585260e5025..383267090f553b052db2ff2ced66f556edbb4cab 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_vars.c
+++ b/openair2/LAYER2/NR_MAC_UE/mac_vars.c
@@ -32,7 +32,7 @@
 
 #include <stdint.h>
 
-const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC"};
+const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC", "NR_RNTI_SP_CSI", "NR_RNTI_SI"};
 const char *dci_formats[]={"1_0", "1_1", "2_0", "2_1", "2_2", "2_3", "0_0", "0_1"};
 
 // table_7_3_1_1_2_2_3_4_5 contains values for number of layers and precoding information for tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
index b4b63e0064721a1a89fb714883e6186f5020e0be..8f234cb5851efc563b23d5c2bc0e159115dc5287 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
@@ -35,6 +35,7 @@
 
 /* RRC */
 #include "NR_RACH-ConfigCommon.h"
+#include "RRC/NR_UE/rrc_proto.h"
 
 /* PHY */
 #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
@@ -514,7 +515,8 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
 
   uint8_t sdu_lcids[NB_RB_MAX] = {0};
   uint16_t sdu_lengths[NB_RB_MAX] = {0};
-  int TBS_bytes = 848, header_length_total=0, num_sdus, offset, mac_ce_len;
+  int num_sdus = 0;
+  int offset = 0;
 
   // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side
   if (!prach_resources->init_msg1) {
@@ -532,36 +534,27 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
 
       LOG_D(MAC, "RA not active. Checking for data to transmit from upper layers...\n");
 
-      payload = (uint8_t*) &mac->CCCH_pdu.payload;
-      mac_ce_len = 0;
+      uint8_t TBS_max = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT);
+      payload = (uint8_t*) mac->CCCH_pdu.payload;
+
       num_sdus = 1;
       post_padding = 1;
+      sdu_lcids[0] = lcid;
 
-      if (0){
-        // initialisation by RRC
-        // CCCH PDU
-        // size_sdu = (uint16_t) mac_rrc_data_req_ue(mod_id,
-        //                                           CC_id,
-        //                                           frame,
-        //                                           CCCH,
-        //                                           1,
-        //                                           mac_sdus,
-        //                                           gNB_id,
-        //                                           0);
-        LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu);
-      } else {
-        // fill ulsch_buffer with random data
-        for (int i = 0; i < TBS_bytes; i++){
-          mac_sdus[i] = (unsigned char) (lrand48()&0xff);
-        }
-        //Sending SDUs with size 1
-        //Initialize elements of sdu_lcids and sdu_lengths
-        sdu_lcids[0] = lcid;
-        sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len;
-        header_length_total += 2 + (sdu_lengths[0] >= 128);
-        size_sdu += sdu_lengths[0];
+      // initialisation by RRC
+
+      // TODO: To be removed after RA procedures fully implemented
+      if(get_softmodem_params()->do_ra) {
+        nr_rrc_ue_generate_RRCSetupRequest(mod_id,gNB_id);
       }
 
+      // CCCH PDU
+      size_sdu = (uint16_t) nr_mac_rrc_data_req_ue(mod_id, CC_id, gNB_id, frame, CCCH, mac_sdus);
+
+      sdu_lengths[0] = size_sdu;
+
+      LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu);
+
       if (size_sdu > 0) {
 
         LOG_D(MAC, "[UE %d][%d.%d]: starting initialisation Random Access Procedure...\n", mod_id, frame, nr_slot_tx);
@@ -589,12 +582,27 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
                                        post_padding,
                                        0);
 
+        AssertFatal(TBS_max > offset, "Frequency resources are not enough for Msg3!\n");
+
         // Padding: fill remainder with 0
         if (post_padding > 0){
-          for (int j = 0; j < (TBS_bytes - offset); j++)
-            payload[offset + j] = 0; // mac_pdu[offset + j] = 0;
+          for (int j = 0; j < (TBS_max - offset); j++)
+            payload[offset + j] = 0;
         }
-      } 
+      }
+
+      LOG_D(MAC,"size_sdu = %i\n", size_sdu);
+      LOG_D(MAC,"offset = %i\n", offset);
+      for(int k = 0; k < TBS_max; k++) {
+        LOG_D(MAC,"(%i): %i\n", k, prach_resources->Msg3[k]);
+      }
+
+      // Msg3 was initialized with TBS_max bytes because the RA_Msg3_size will only be known after
+      // receiving Msg2 (which contains the Msg3 resource reserve).
+      // Msg3 will be transmitted with RA_Msg3_size bytes, removing unnecessary 0s.
+      mac->ulsch_pdu.Pdu_size = TBS_max;
+      memcpy(mac->ulsch_pdu.payload, prach_resources->Msg3, TBS_max);
+
     } else if (ra->RA_window_cnt != -1) { // RACH is active
 
       LOG_D(MAC, "In %s [%d.%d] RA is active: RA window count %d, RA backoff count %d\n", __FUNCTION__, frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt);
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 64067e9d60df8b978b2885bf04c2bc7cb3468de5..cb104092f1398c207b7b413d473183c93e1a0a58 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -154,13 +154,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
   return 0;
 }
 
-int8_t nr_ue_decode_sib1(module_id_t module_id,
-                         int cc_id,
-                         unsigned int gNB_index,
-                         uint32_t sibs_mask,
-                         uint8_t *pduP,
-                         uint32_t pdu_len) {
-  LOG_D(MAC, "Decode sib1\n");
+int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id,
+                                int cc_id,
+                                unsigned int gNB_index,
+                                uint32_t sibs_mask,
+                                uint8_t *pduP,
+                                uint32_t pdu_len) {
+  LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n");
   nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
   return 0;
 }
@@ -583,7 +583,6 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
       }
 
     }
-
     break;
   }
 
@@ -814,7 +813,17 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
 
     dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH;
     dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti;
+
+    // FIXME: fix number of additional dmrs
+    if(pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition == NULL)
+      pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition=calloc(1,sizeof(*pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition));
+
     fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_1 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15;
+
+    dlsch_config_pdu_1_1->BWPSize = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+    dlsch_config_pdu_1_1->BWPStart = NRRIV2PRBOFFSET(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+    dlsch_config_pdu_1_1->SubcarrierSpacing = mac->DLbwp[0]->bwp_Common->genericParameters.subcarrierSpacing;
+
     /* IDENTIFIER_DCI_FORMATS */
     /* CARRIER_IND */
     /* BANDWIDTH_PART_IND */
@@ -1010,6 +1019,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
                                             &dlsch_config_pdu_1_1->PTRSReOffset, dlsch_config_pdu_1_1->number_symbols);
       if(valid_ptrs_setup==true) {
         dlsch_config_pdu_1_1->pduBitmap |= 0x1;
+        LOG_D(MAC, "DL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", dlsch_config_pdu_1_1->PTRSTimeDensity, dlsch_config_pdu_1_1->PTRSFreqDensity);
       }
     }
 
@@ -2230,7 +2240,7 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t
 
   // TA command
   ul_time_alignment->apply_ta = 1;
-  ul_time_alignment->ta_command = rar->TA2 + (rar->TA1 << 5);
+  ul_time_alignment->ta_command = 31 + rar->TA2 + (rar->TA1 << 5);
 
 #ifdef DEBUG_RAR
   // CSI
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index d6e1cba6df103f133a755501b0fb9258c0f12d05..ad1958ef339e74759495f9ebe18fcd261f0e579d 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -118,13 +118,14 @@ long get_k2(NR_UE_MAC_INST_t *mac, uint8_t time_domain_ind) {
  * This function returns the UL config corresponding to a given UL slot
  * from MAC instance .
  */
-fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot) {
+fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot)
+{
   //Check if request to access ul_config is for a UL slot
-  if (is_nr_UL_slot(mac->scc, slot) == 0) {
+  if (is_nr_UL_slot(mac->scc, slot, mac->frame_type) == 0) {
     LOG_W(MAC, "Slot %d is not a UL slot. %s called for wrong slot!!!\n", slot, __FUNCTION__);
     return NULL;
   }
-  
+
   // Calculate the index of the UL slot in mac->ul_config_request list. This is
   // based on the TDD pattern (slot configuration period) and number of UL+mixed
   // slots in the period. TS 38.213 Sec 11.1
@@ -560,20 +561,11 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
   } else if (dci) {
 
     int target_ss;
-    uint8_t  ptrs_time_density;
-    uint8_t  ptrs_freq_density;
-    nfapi_nr_ue_ptrs_ports_t ptrs_ports_list;
+    bool valid_ptrs_setup = 0;
     uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
     fapi_nr_pusch_config_dedicated_t *pusch_config_dedicated = &mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated;
     NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup;
 
-    // These should come from RRC config!!!
-    uint8_t  ptrs_mcs1          = 2;
-    uint8_t  ptrs_mcs2          = 4;
-    uint8_t  ptrs_mcs3          = 10;
-    uint16_t n_rb0              = 25;
-    uint16_t n_rb1              = 75;
-
     // Basic sanity check for MCS value to check for a false or erroneous DCI
     if (dci->mcs > 28) {
       LOG_W(MAC, "MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", dci->mcs);
@@ -689,12 +681,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
       pusch_config_pdu->absolute_delta_PUSCH = 4;
     }
 
-    ptrs_time_density  = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table);
-    ptrs_freq_density  = get_K_ptrs(n_rb0, n_rb1, pusch_config_pdu->rb_size);
-    // PTRS ports configuration
-    // TbD: ptrs_dmrs_port and ptrs_port_index are not initialised!
-    ptrs_ports_list.ptrs_re_offset = 0;
-
     /* DMRS */
     l_prime_mask = get_l_prime(pusch_config_pdu->nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1);
     if (pusch_config_pdu->transform_precoding == transform_precoder_disabled)
@@ -708,12 +694,20 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
     }
 
     /* PTRS */
-    pusch_config_pdu->pusch_ptrs.ptrs_time_density = ptrs_time_density;
-    pusch_config_pdu->pusch_ptrs.ptrs_freq_density = ptrs_freq_density;
-    pusch_config_pdu->pusch_ptrs.ptrs_ports_list   = &ptrs_ports_list;
-
-    if (1 << pusch_config_pdu->pusch_ptrs.ptrs_time_density >= pusch_config_pdu->nr_of_symbols) {
-      pusch_config_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
+    if (mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS != NULL) {
+      if (pusch_config_pdu->transform_precoding == transform_precoder_disabled) {
+        nfapi_nr_ue_ptrs_ports_t ptrs_ports_list;
+        pusch_config_pdu->pusch_ptrs.ptrs_ports_list = &ptrs_ports_list;
+        valid_ptrs_setup = set_ul_ptrs_values(mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup,
+                                              pusch_config_pdu->rb_size, pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table,
+                                              &pusch_config_pdu->pusch_ptrs.ptrs_freq_density,&pusch_config_pdu->pusch_ptrs.ptrs_time_density,
+                                              &pusch_config_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_config_pdu->pusch_ptrs.num_ptrs_ports,
+                                              &pusch_config_pdu->pusch_ptrs.ul_ptrs_power, pusch_config_pdu->nr_of_symbols);
+        if(valid_ptrs_setup==true) {
+          pusch_config_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS;
+        }
+        LOG_D(MAC, "UL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", pusch_config_pdu->pusch_ptrs.ptrs_time_density, pusch_config_pdu->pusch_ptrs.ptrs_freq_density);
+      }
     }
 
   }
@@ -889,34 +883,40 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
 
           uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size;
 
-          // Push data from MAC to PHY only when NDI toggles
-          if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){
-            // Getting IP traffic to be transmitted
-            data_existing = nr_ue_get_sdu(mod_id,
-                                          cc_id,
-                                          frame_tx,
-                                          slot_tx,
-                                          0,
-                                          ulsch_input_buffer,
-                                          TBS_bytes,
-                                          &access_mode);
-          }
+          if (ra->ra_state == WAIT_RAR){
+            memcpy(ulsch_input_buffer, mac->ulsch_pdu.payload, TBS_bytes);
+            LOG_D(NR_MAC,"[RAPROC] Msg3 to be transmitted:\n");
+            for (int k = 0; k < TBS_bytes; k++) {
+              LOG_D(NR_MAC,"(%i): 0x%x\n",k,mac->ulsch_pdu.payload[k]);
+            }
+          } else {
+            if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){
+              // Getting IP traffic to be transmitted
+              data_existing = nr_ue_get_sdu(mod_id,
+                                            cc_id,
+                                            frame_tx,
+                                            slot_tx,
+                                            0,
+                                            ulsch_input_buffer,
+                                            TBS_bytes,
+                                            &access_mode);
+            }
+
+            mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator;
+            //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
+            if (!IS_SOFTMODEM_NOS1 || !data_existing) {
+              //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
+              //and block this traffic from being forwarded to the upper layers at the gNB
+              LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes);
+
+              //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2)
+              //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should
+              //have a valid LCID (nr_process_mac_pdu function)
+              ulsch_input_buffer[0] = 0x31;
 
-          mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator;
-          //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
-          if (!IS_SOFTMODEM_NOS1 || !data_existing) {
-            //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
-            //and block this traffic from being forwarded to the upper layers at the gNB
-            LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes);
-
-            //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2)
-            //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should
-            //have a valid LCID (nr_process_mac_pdu function)
-            ulsch_input_buffer[0] = 0x31;
-
-            for (int i = 1; i < TBS_bytes; i++) {
-              ulsch_input_buffer[i] = (unsigned char) rand();
-              //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]);
+              for (int i = 1; i < TBS_bytes; i++) {
+                ulsch_input_buffer[i] = (unsigned char) rand();
+              }
             }
           }
 
@@ -1662,7 +1662,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
   ra->RA_offset = 2; // to compensate the rx frame offset at the gNB
   ra->generate_nr_prach = 0; // Reset flag for PRACH generation
 
-  if (is_nr_UL_slot(scc, slotP)) {
+  if (is_nr_UL_slot(scc, slotP, mac->frame_type)) {
 
     // WIP Need to get the proper selected ssb_idx
     //     Initial beam selection functionality is not available yet
@@ -1683,13 +1683,11 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
       format0 = format & 0xff;        // single PRACH format
       format1 = (format >> 8) & 0xff; // dual PRACH format
 
-      ul_config->sfn = frameP;
-      ul_config->slot = slotP;
-
-      ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH;
       prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu;
       memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu));
-      ul_config->number_pdus += 1;
+
+      fill_ul_config(ul_config, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH);
+
       LOG_D(PHY, "In %s: (%p) %d UL PDUs:\n", __FUNCTION__, ul_config, ul_config->number_pdus);
 
       ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig);
@@ -1767,11 +1765,10 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
             AssertFatal(1 == 0, "Invalid PRACH format");
         }
       } // if format1
+      fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id);
+      if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
+        mac->if_module->scheduled_response(&scheduled_response);
     } // is_nr_prach_slot
-
-    fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id);
-    if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
-      mac->if_module->scheduled_response(&scheduled_response);
   } // if is_nr_UL_slot
 }
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index bce07195562851925fb7901b74f79f6c9bb9a55a..39bad35af7b81df40569a569d84265727851d2f8 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -127,8 +127,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
   uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
   frequency_range_t frequency_range = band<100?FR1:FR2;
 
-  lte_frame_type_t frame_type;
-  get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type);
+  lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
   RC.nrmac[Mod_idP]->common_channels[0].frame_type = frame_type;
 
   // Cell configuration
@@ -311,8 +310,6 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
 
 }
 
-
-
 extern uint16_t sl_ahead;
 int rrc_mac_config_req_gNB(module_id_t Mod_idP, 
 			   int ssb_SubcarrierOffset,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index 4ada9eb9f3a5f70184f3f8a5cf69440867bf1a98..de9c64cd464fd239ea9ae07fa70701af1d06faae 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -66,11 +66,15 @@ void dump_mac_stats(gNB_MAC_INST *gNB)
   int num = 1;
   for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
     LOG_I(MAC, "UE ID %d RNTI %04x (%d/%d)\n", UE_id, UE_info->rnti[UE_id], num++, UE_info->num_UEs);
-    const NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
-    LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n",
+    NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
+    const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
+    LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d, average RSRP %d (%d meas)\n",
           UE_id,
           stats->dlsch_rounds[0], stats->dlsch_rounds[1],
-          stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors);
+          stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors,
+          avg_rsrp, stats->num_rsrp_meas);
+    stats->num_rsrp_meas = 0;
+    stats->cumul_rsrp = 0 ;
     LOG_I(MAC, "UE %d: dlsch_total_bytes %d\n", UE_id, stats->dlsch_total_bytes);
     LOG_I(MAC, "UE %d: ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n",
           UE_id,
@@ -365,7 +369,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
   /* send tick to RLC and RRC every ms */
   if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) {
     void nr_rlc_tick(int frame, int subframe);
+    void nr_pdcp_tick(int frame, int subframe);
     nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
+    nr_pdcp_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
     nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
   }
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index ac3a4e77d236626f371e93313d1c6105008da7bc..64867c5be5fb2bb4342b6dc3ab692849cd4937f7 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -245,7 +245,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
   nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][slotP];
   nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
 
-  if (is_nr_UL_slot(scc,slotP)) {
+  if (is_nr_UL_slot(scc, slotP, cc->frame_type)) {
+
     uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
     uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot;
     uint16_t RA_sfn_index = -1;
@@ -647,7 +648,8 @@ void nr_get_Msg3alloc(module_id_t module_id,
                       NR_RA_t *ra) {
 
   // msg3 is schedulend in mixed slot in the following TDD period
-  // for now we consider a TBS of 18 bytes
+
+  uint16_t msg3_nb_rb = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); // sdu has 6 or 8 bytes
 
   int mu = ubwp->bwp_Common->genericParameters.subcarrierSpacing;
   int StartSymbolIndex, NrOfSymbols, startSymbolAndLength, temp_slot;
@@ -677,21 +679,22 @@ void nr_get_Msg3alloc(module_id_t module_id,
   uint16_t *vrb_map_UL =
       &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE];
   const uint16_t bwpSize = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
-  /* search 18 free RBs */
+
+  /* search msg3_nb_rb free RBs */
   int rbSize = 0;
   int rbStart = 0;
-  while (rbSize < 18) {
+  while (rbSize < msg3_nb_rb) {
     rbStart += rbSize; /* last iteration rbSize was not enough, skip it */
     rbSize = 0;
     while (rbStart < bwpSize && vrb_map_UL[rbStart])
       rbStart++;
-    AssertFatal(rbStart < bwpSize - 18, "no space to allocate Msg 3 for RA!\n");
+    AssertFatal(rbStart < bwpSize - msg3_nb_rb, "no space to allocate Msg 3 for RA!\n");
     while (rbStart + rbSize < bwpSize
            && !vrb_map_UL[rbStart + rbSize]
-           && rbSize < 18)
+           && rbSize < msg3_nb_rb)
       rbSize++;
   }
-  ra->msg3_nb_rb = 18;
+  ra->msg3_nb_rb = msg3_nb_rb;
   ra->msg3_first_rb = rbStart;
 }
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
index 1de46aaea4504707b4f1305c78c165cb76aadff6..3f69cfbe7431b082bb3bcd2658ab753582d02509 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
@@ -235,6 +235,7 @@ void schedule_control_sib1(module_id_t module_id,
                            int time_domain_allocation,
                            uint8_t mcsTableIdx,
                            uint8_t mcs,
+                           uint8_t candidate_idx,
                            int num_total_bytes) {
 
   gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
@@ -266,13 +267,10 @@ void schedule_control_sib1(module_id_t module_id,
                                                           gNB_mac->sched_ctrlCommon->coreset,
                                                           gNB_mac->sched_ctrlCommon->aggregation_level,
                                                           0,
-                                                          0,
+                                                          candidate_idx,
                                                           nr_of_candidates);
 
-  if (gNB_mac->sched_ctrlCommon->cce_index < 0) {
-    LOG_E(MAC, "%s(): could not find CCE for coreset0\n", __func__);
-    return;
-  }
+  AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n");
 
   const uint16_t bwpSize = gNB_mac->type0_PDCCH_CSS_config.num_rbs;
   int rbStart = gNB_mac->type0_PDCCH_CSS_config.cset_start_rb;
@@ -301,9 +299,7 @@ void schedule_control_sib1(module_id_t module_id,
     TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx),
                          nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx),
                          rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3;
-
-    // FIXME: Something is not working in nr_modulation() for TBS = 84, so we need to skip it
-  } while ( (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes) || (TBS==84) );
+  } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes);
 
   gNB_mac->sched_ctrlCommon->rbSize = rbSize;
   gNB_mac->sched_ctrlCommon->rbStart = 0;
@@ -467,6 +463,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
   int time_domain_allocation = 0;
   uint8_t mcsTableIdx = 0;
   uint8_t mcs = 6;
+  uint8_t candidate_idx = 0;
 
   gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
 
@@ -482,7 +479,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
     for (int i=0;i<sib1_sdu_length;i++) LOG_D(MAC,"byte %d : %x\n",i,((uint8_t*)sib1_payload)[i]);
 
     // Configure sched_ctrlCommon for SIB1
-    schedule_control_sib1(module_idP, CC_id, time_domain_allocation, mcsTableIdx, mcs, sib1_sdu_length);
+    schedule_control_sib1(module_idP, CC_id, time_domain_allocation, mcsTableIdx, mcs, candidate_idx, sib1_sdu_length);
 
     // Calculate number of symbols
     int startSymbolIndex, nrOfSymbols;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index fb704dc964000a4f6e7d5368e9361957fe054c31..cf512653b72b33e1621ce8e211d57dce2ed5f189 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -1074,7 +1074,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
           size += 3;
         }
       }
-      else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) {
+      else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra || get_softmodem_params()->sa) {
         /* we will need the large header, phy-test typically allocates all
          * resources and fills to the last byte below */
         NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index 00e53dd21eb7ac945ba040d26050cb0afc572bb9..37cafff9cce4dfff11d8f0027d64a4dfa7281898 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -647,6 +647,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
   int res_found = 0;
 
   pucch_pdu->bit_len_harq = O_ack;
+  pucch_pdu->bit_len_csi_part1 = O_csi;
 
   uint16_t O_uci = O_csi + O_ack;
 
@@ -699,6 +700,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
     n_set = pucch_Config->resourceSetToAddModList->list.count; 
     AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n");
 
+    LOG_D(MAC, "UCI n_set= %d\n", n_set);
+
     N2 = 2;
     // procedure to select pucch resource id from resource sets according to 
     // number of uci bits and pucch resource indicator pucch_resource
@@ -1642,7 +1645,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secon
     add_nr_list(&UE_info->list, UE_id);
     memset(&UE_info->mac_stats[UE_id], 0, sizeof(NR_mac_stats_t));
     set_Y(UE_info->Y[UE_id], rntiP);
-    compute_csi_bitlen(secondaryCellGroup, UE_info, UE_id);
+    compute_csi_bitlen (secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE_info, UE_id, mod_idP);
     NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
     memset(sched_ctrl, 0, sizeof(*sched_ctrl));
     sched_ctrl->ta_frame = 0;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
index 3ae3707962c7e9434dd735427d84d1db592134ba..a6f7105769d96d1f31b3304454b121d5012ed69f 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -80,6 +80,42 @@ void nr_fill_nfapi_pucch(module_id_t mod_id,
                      pucch->sr_flag);
 }
 
+#define MIN_RSRP_VALUE -141
+#define MAX_NUM_SSB 128
+#define MAX_SSB_SCHED 8
+#define L1_RSRP_HYSTERIS 10 //considering 10 dBm as hysterisis for avoiding frequent SSB Beam Switching. !Fixme provide exact value if any
+//#define L1_DIFF_RSRP_STEP_SIZE 2
+
+int ssb_index_sorted[MAX_NUM_SSB] = {0};
+int ssb_rsrp_sorted[MAX_NUM_SSB] = {0};
+
+//Measured RSRP Values Table 10.1.16.1-1 from 36.133
+//Stored all the upper limits[Max RSRP Value of corresponding index]
+//stored -1 for invalid values
+int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = {
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //0 - 9
+    -1, -1, -1, -1, -1, -1, -140, -139, -138, -137, //10 - 19
+    -136, -135, -134, -133, -132, -131, -130, -129, -128, -127, //20 - 29
+    -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, //30 - 39
+    -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, //40 - 49
+    -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, //50 - 59
+    -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, //60 - 69
+    -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, //70 - 79
+    -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, //80 - 89
+    -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, //90 - 99
+    -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, //100 - 109
+    -46, -45, -44, -44, -1, -1, -1, -1, -1, -1, //110 - 119
+    -1, -1, -1, -1, -1, -1, -1, -1//120 - 127
+  };
+
+//Differential RSRP values Table 10.1.6.1-2 from 36.133
+//Stored the upper limits[MAX RSRP Value]
+int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = {
+  0, -2, -4, -6, -8, -10, -12, -14, -16, -18, //0 - 9
+  -20, -22, -24, -26, -28, -30 //10 - 15
+};
+
+
 void nr_schedule_pucch(int Mod_idP,
                        frame_t frameP,
                        sub_frame_t slotP) {
@@ -106,74 +142,293 @@ void nr_schedule_pucch(int Mod_idP,
 }
 
 
+//! Calculating number of bits set
+uint8_t number_of_bits_set (uint8_t buf,uint8_t * max_ri){
+  uint8_t nb_of_bits_set = 0;
+  uint8_t mask = 0xff;
+  uint8_t index = 0;
+
+  for (index=7; (buf & mask) && (index>=0)  ; index--){
+    if (buf & (1<<index))
+      nb_of_bits_set++;
+
+    mask>>=1;
+  }
+  *max_ri = 8-index;
+  return nb_of_bits_set;
+}
+
+
 //!TODO : same function can be written to handle csi_resources
-void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id) {
+void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_info, int UE_id, module_id_t Mod_idP){
   uint8_t csi_report_id = 0;
   uint8_t csi_resourceidx =0;
   uint8_t csi_ssb_idx =0;
-
-  NR_CSI_MeasConfig_t *csi_MeasConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
+  NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type;
   NR_CSI_ResourceConfigId_t csi_ResourceConfigId;
+
   for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
-    csi_ResourceConfigId=csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->resourcesForChannelMeasurement;
-    UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportQuantity.present;
+    struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
+		nr_csi_report_t *csi_report = &UE_info->csi_report_template[UE_id][csi_report_id];
+    csi_ResourceConfigId=csi_reportconfig->resourcesForChannelMeasurement;
+    reportQuantity_type = csi_reportconfig->reportQuantity.present;
+    csi_report->reportQuantity_type = reportQuantity_type;
 
     for ( csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {
-      if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_ResourceConfigId != csi_ResourceConfigId)
-	continue;
+      struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx];
+      if ( csi_resourceconfig->csi_ResourceConfigId != csi_ResourceConfigId)
+        continue;
       else {
-      //Finding the CSI_RS or SSB Resources
-        UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type= csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.present;
-        if (NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB ==UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type){
-          struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList__nzp_CSI_RS_SSB * nzp_CSI_RS_SSB = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB;
-
-          UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report = nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count:0;
-          UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = nzp_CSI_RS_SSB->csi_SSB_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count:0;
+        uint8_t nb_ssb_resources =0;
+        //Finding the CSI_RS or SSB Resources
+        if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type || 
+            NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type) {
+
+          if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == csi_reportconfig->groupBasedBeamReporting.present) {
+            if (NULL != csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
+              csi_report->CSI_report_bitlen.nb_ssbri_cri = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
+            else
+		/*! From Spec 38.331
+		 * nrofReportedRS
+		 * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE
+		 * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report.  
+		 * When the field is absent the UE applies the value 1
+		 */
+              csi_report->CSI_report_bitlen.nb_ssbri_cri= 1;
+          }else 
+	    csi_report->CSI_report_bitlen.nb_ssbri_cri= 2;
+
+          if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == csi_report->reportQuantity_type) {
+            for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
+              if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId ==
+                  *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){
+ 
+                ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig
+                nb_ssb_resources=  csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count;
+                csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.array;
+                csi_report->CSI_Index_list = NULL;
+								break;
+              }
+            }
+          } else /*if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type)*/{
+            for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
+              if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_ResourceSetId ==
+                  *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) {
+
+                ///For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212
+                nb_ssb_resources=  csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count;
+                csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.array;
+                csi_report->SSB_Index_list = NULL;
+                break;
+              }
+            }
+         }
+
+         if (nb_ssb_resources) {
+           csi_report->CSI_report_bitlen.cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources));
+           csi_report->CSI_report_bitlen.rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP 
+           csi_report->CSI_report_bitlen.diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
+         } else { 
+            csi_report->CSI_report_bitlen.cri_ssbri_bitlen =0;
+            csi_report->CSI_report_bitlen.rsrp_bitlen = 0;  
+            csi_report->CSI_report_bitlen.diff_rsrp_bitlen =0; 
+         }
+
+        LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d\n",
+               csi_report->CSI_report_bitlen.cri_ssbri_bitlen,
+               csi_report->CSI_report_bitlen.rsrp_bitlen,
+               csi_report->CSI_report_bitlen.diff_rsrp_bitlen);
         }
 
-        if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report){
-	  uint8_t nb_ssb_resources =0;
+        uint8_t ri_restriction;
+        uint8_t ri_bitlen;
+        uint8_t nb_allowed_ri;
+        uint8_t max_ri;
+
+        if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type ||
+            NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type ||
+            NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI==reportQuantity_type ||
+            NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI==reportQuantity_type||
+            NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1==reportQuantity_type){
+
           for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
-            if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId ==
-                *(csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { 
-              ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig
-              if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled ==
-                csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.present ) {
-	        if (NULL != csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
-                  UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri = *(csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
-                else
-                  /*! From Spec 38.331
-                  * nrofReportedRS
-                  * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE
-                  * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report.
-                  * When the field is absent the UE applies the value 1
-                  */
-                  UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 1;
-              } else
-                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 2;
-
-              nb_ssb_resources=  csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count;
-              if (nb_ssb_resources){
-                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources));
-                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP 
-                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
-              }
-              else{
-                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =0;
-                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 0;
-                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =0;
-              }
+            if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_ResourceSetId ==
+                *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) {
+              ///For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212
+              nb_ssb_resources=  csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count;
+              csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.array;
+              csi_report->SSB_Index_list = NULL;
+            }
+            break;
+          }
+          csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2 (nb_ssb_resources));
+
+          if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){
+
+            switch (RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value) {
+              case 1:;
+                csi_report->csi_meas_bitlen.ri_bitlen=0;
+                break;
+              case 2:
+		/*  From Spec 38.212 
+		 *  If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator
+		 *  values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6,
+		 *  TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause
+		 *  5.2.2.2.1 [6, TS 38.214].
+		 *
+		 *  But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to
+		 *  calculate RI for antennas equal or more than two.
+		 * */
+                 AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present");
+
+                 ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0];
+
+                 /* Replace dummy with the nrofCQIsPerReport from the CSIreport 
+                 config when equalent ASN structure present */
+                if (0==*(csi_reportconfig->dummy)){
+                  nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0), &max_ri);
+                  ri_bitlen = ceil(log2(nb_allowed_ri));
+                }
+                else{
+                  nb_allowed_ri = number_of_bits_set(ri_restriction, &max_ri);
+                  ri_bitlen = ceil(log2(nb_allowed_ri));
+                }
+                ri_bitlen = ri_bitlen<1?ri_bitlen:1; //from the spec 38.212 and table  6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel 
+                csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen;
+                break;
+              case 4:
+                AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present");
+
+                ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0];
+
+                /* Replace dummy with the nrofCQIsPerReport from the CSIreport 
+                config when equalent ASN structure present */
+                if (0==*(csi_reportconfig->dummy)){
+                  nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0), &max_ri);
+                  ri_bitlen = ceil(log2(nb_allowed_ri));
+                }
+                else{
+                  nb_allowed_ri = number_of_bits_set(ri_restriction,&max_ri);
+                  ri_bitlen = ceil(log2(nb_allowed_ri));
+                }
+                ri_bitlen = ri_bitlen<2?ri_bitlen:2; //from the spec 38.212 and table  6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel 
+                csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen;
+                break;
+              case 6:
+              case 8:
+                AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present");
+		 
+                ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0];
+
+                /* Replace dummy with the nrofCQIsPerReport from the CSIreport 
+                config when equalent ASN structure present */
+                if (0==*(csi_reportconfig->dummy)){
+                  nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0),&max_ri);
+                  ri_bitlen = ceil(log2(nb_allowed_ri));
+                }
+                else{
+                  nb_allowed_ri = number_of_bits_set(ri_restriction, &max_ri);
+                  ri_bitlen = ceil(log2(nb_allowed_ri));
+                }
+                csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen;
+                break;
+              default:
+                AssertFatal(RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value>8,"Number of antennas %d are out of range", RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value);
+            }
+          }
+          csi_report->csi_meas_bitlen.li_bitlen=0;
+          csi_report->csi_meas_bitlen.cqi_bitlen=0;
+          csi_report->csi_meas_bitlen.pmi_x1_bitlen=0;
+          csi_report->csi_meas_bitlen.pmi_x2_bitlen=0;
+        }
 
-              LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d\n",
-                     UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen,
-                     UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen,
-                     UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen);
-              break ;
+        if( NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type ){
+          if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){
+
+            switch (RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value) {
+              case 1:;
+                csi_report->csi_meas_bitlen.li_bitlen=0;
+                break;
+              case 2:
+              case 4:
+              case 6:
+              case 8:
+		/*  From Spec 38.212 
+		 *  If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator
+		 *  values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6,
+		 *  TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause
+		 *  5.2.2.2.1 [6, TS 38.214].
+		 *
+		 *  But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to
+		 *  calculate RI for antennas equal or more than two.
+		 * */
+		 //! TODO: The bit length of LI is as follows LI = log2(RI), Need to confirm wheather we should consider maximum RI can be reported from ri_restricted
+		 //        or we should consider reported RI. If we need to consider reported RI for calculating LI bit length then we need to modify the code.
+                csi_report->csi_meas_bitlen.li_bitlen=ceil(log2(max_ri))<2?ceil(log2(max_ri)):2;
+                break;
+              default:
+                AssertFatal(RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value>8,"Number of antennas %d are out of range", RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value);
+            }
+          }
+        }
+
+        if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type ||
+            NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type ||
+            NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI==reportQuantity_type ||
+            NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI==reportQuantity_type){
+
+          switch (RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value){
+            case 1:
+            case 2:
+            case 4:
+            case 6:
+            case 8:
+	        /*  From Spec 38.212 
+		 *  If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator
+		 *  values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6,
+		 *  TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause
+		 *  5.2.2.2.1 [6, TS 38.214].
+		 *
+		 *  But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to
+		 *  calculate RI for antennas equal or more than two.
+		 * */
+		 
+              if (max_ri > 4 && max_ri < 8){
+                if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){
+                  if (NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI==csi_reportconfig->reportFreqConfiguration->cqi_FormatIndicator)
+                    csi_report->csi_meas_bitlen.cqi_bitlen = 8;
+                  else 
+                    csi_report->csi_meas_bitlen.cqi_bitlen = 4;
+                }
+              }else{ //This condition will work even for type1-multipanel.
+                if (NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI==csi_reportconfig->reportFreqConfiguration->cqi_FormatIndicator)
+                  csi_report->csi_meas_bitlen.cqi_bitlen = 4;
+                else 
+                  csi_report->csi_meas_bitlen.cqi_bitlen = 2;
+              }
+              break;
+            default:
+              AssertFatal(RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value>8,"Number of antennas %d are out of range", RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value);
+          }
+        }
+        if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type ||
+            NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type){
+          if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){
+            switch (csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present){
+              case NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two:
+                if (max_ri ==1)
+                  csi_report->csi_meas_bitlen.pmi_x1_bitlen = 2;
+                else if (max_ri ==2)
+                  csi_report->csi_meas_bitlen.pmi_x1_bitlen = 1;
+                break;
+              default:
+                AssertFatal(csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present!=
+                            NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two,
+                            "Not handled Yet %d", csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present);
+		break;
             }
           }
         }
-        if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report)
-          AssertFatal(1==0,"Currently configuring only SSB beamreporting.");
         break;
       }
     }
@@ -181,12 +436,27 @@ void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t
 }
 
 
-uint16_t nr_get_csi_bitlen(const nr_csi_report_t *csi_report)
-{
-  const CRI_SSBRI_RSRP_bitlen_t *bitlen = &csi_report->CSI_report_bitlen[0];
-  return bitlen->cri_ssbri_bitlen * bitlen->nb_ssbri_cri
-         + bitlen->rsrp_bitlen
-         + bitlen->diff_rsrp_bitlen * (bitlen->nb_ssbri_cri - 1) * csi_report->nb_of_csi_ssb_report;
+uint16_t nr_get_csi_bitlen(int Mod_idP,
+                           int UE_id,
+                           uint8_t csi_report_id) {
+
+  uint16_t csi_bitlen =0;
+  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
+  L1_RSRP_bitlen_t * CSI_report_bitlen = NULL;
+  CSI_Meas_bitlen_t * csi_meas_bitlen = NULL;
+
+  if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP==UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type||
+      NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP==UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type){
+    CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements
+    csi_bitlen+= ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) +
+                  CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen * 
+                  (CSI_report_bitlen->nb_ssbri_cri -1 )));
+  } else{
+   csi_meas_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].csi_meas_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements
+   csi_bitlen+= (csi_meas_bitlen->cri_bitlen +csi_meas_bitlen->ri_bitlen+csi_meas_bitlen->li_bitlen+csi_meas_bitlen->cqi_bitlen+csi_meas_bitlen->pmi_x1_bitlen+csi_meas_bitlen->pmi_x2_bitlen);
+ }
+
+  return csi_bitlen;
 }
 
 
@@ -246,7 +516,7 @@ void nr_csi_meas_reporting(int Mod_idP,
       curr_pucch->ul_slot = sched_slot;
       curr_pucch->resource_indicator = res_index;
       curr_pucch->csi_bits +=
-          nr_get_csi_bitlen(&UE_info->csi_report_template[UE_id][csi_report_id]);
+          nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id);
 
       // going through the list of PUCCH resources to find the one indexed by resource_id
       uint16_t *vrb_map_UL = &RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
@@ -314,6 +584,375 @@ static void handle_dl_harq(module_id_t mod_id,
   }
 }
 
+int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, int Mod_idP, int UE_id) {
+  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
+  NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id] ;
+  int nb_tci_states = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.count;
+  NR_TCI_State_t *tci =NULL;
+  int i;
+
+  for(i=0; i<nb_tci_states && i<64; i++) {
+    tci = (NR_TCI_State_t *)secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.array[i];
+
+    if(tci != NULL) {
+      if(tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) {
+        if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t)
+          return tci->tci_StateId;  // returned TCI state ID
+      }
+      // if type2 is configured
+      else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) {
+        if(tci->qcl_Type2->referenceSignal.choice.ssb == ssb_index_t)
+          return tci->tci_StateId; // returned TCI state ID
+      } else LOG_I(MAC,"SSB index is not found in first 64 TCI states of TCI_statestoAddModList[%d]", i);
+    }
+  }
+
+  // tci state not identified in first 64 TCI States of PDSCH Config
+  return -1;
+}
+
+int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, int Mod_idP, int UE_id) {
+  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
+  NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id] ;
+  int nb_tci_states = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.count;
+  NR_TCI_State_t *tci =NULL;
+  NR_TCI_StateId_t *tci_id = NULL;
+  int bwp_id = 1;
+  NR_BWP_Downlink_t *bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1];
+  NR_ControlResourceSet_t *coreset = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1];
+  int i;
+  int flag = 0;
+  int tci_stateID = -1;
+
+  for(i=0; i<nb_tci_states && i<128; i++) {
+    tci = (NR_TCI_State_t *)secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.array[i];
+
+    if(tci != NULL && tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) {
+      if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t) {
+        flag = 1;
+        tci_stateID = tci->tci_StateId;
+        break;
+      } else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) {
+        flag = 1;
+        tci_stateID = tci->tci_StateId;
+        break;
+      }
+    }
+
+    if(flag != 0 && tci_stateID != -1 && coreset != NULL) {
+      for(i=0; i<64 && i<coreset->tci_StatesPDCCH_ToAddList->list.count; i++) {
+        tci_id = coreset->tci_StatesPDCCH_ToAddList->list.array[i];
+
+        if(tci_id != NULL && *tci_id == tci_stateID)
+          return tci_stateID;
+      }
+    }
+  }
+
+  // Need to implement once configuration is received
+  return -1;
+}
+
+//returns the measured RSRP value (upper limit)
+int get_measured_rsrp(uint8_t index) {
+  //if index is invalid returning minimum rsrp -140
+  if((index >= 0 && index <= 15) || index >= 114)
+    return MIN_RSRP_VALUE;
+
+  return L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index];
+}
+
+//returns the differential RSRP value (upper limit)
+int get_diff_rsrp(uint8_t index, int strongest_rsrp) {
+  if(strongest_rsrp != -1) {
+    return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index];
+  } else
+    return MIN_RSRP_VALUE;
+}
+
+//identifies the target SSB Beam index
+//keeps the required date for PDCCH and PDSCH TCI state activation/deactivation CE consutruction globally
+//handles triggering of PDCCH and PDSCH MAC CEs
+void tci_handling(module_id_t Mod_idP, int UE_id, frame_t frame, slot_t slot) {
+
+  int strongest_ssb_rsrp = 0;
+  int cqi_idx = 0;
+  int curr_ssb_beam_index = 0; //ToDo: yet to know how to identify the serving ssb beam index
+  uint8_t target_ssb_beam_index = curr_ssb_beam_index;
+  uint8_t is_triggering_ssb_beam_switch =0;
+  uint8_t ssb_idx = 0;
+  int pdsch_bwp_id =0;
+  int ssb_index[MAX_NUM_SSB] = {0};
+  int ssb_rsrp[MAX_NUM_SSB] = {0};
+  uint8_t idx = 0;
+  int bwp_id  = 1;
+  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
+  NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
+  NR_BWP_Downlink_t *bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1];
+  //bwp indicator
+  int n_dl_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count;
+  uint8_t nr_ssbri_cri = 0;
+  uint8_t nb_of_csi_ssb_report = UE_info->csi_report_template[UE_id][cqi_idx].nb_of_csi_ssb_report;
+  int better_rsrp_reported = -140-(-0); /*minimum_measured_RSRP_value - minimum_differntail_RSRP_value*///considering the minimum RSRP value as better RSRP initially
+  uint8_t diff_rsrp_idx = 0;
+  uint8_t i, j;
+  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+  NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
+
+  if (n_dl_bwp < 4)
+    pdsch_bwp_id = bwp_id;
+  else
+    pdsch_bwp_id = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212
+
+  /*Example:
+  CRI_SSBRI: 1 2 3 4| 5 6 7 8| 9 10 1 2|
+  nb_of_csi_ssb_report = 3 //3 sets as above
+  nr_ssbri_cri = 4 //each set has 4 elements
+  storing ssb indexes in ssb_index array as ssb_index[0] = 1 .. ssb_index[4] = 5
+  ssb_rsrp[0] = strongest rsrp in first set, ssb_rsrp[4] = strongest rsrp in second set, ..
+  idx: resource set index
+  */
+
+  //for all reported SSB
+  for (idx = 0; idx < nb_of_csi_ssb_report; idx++) {
+    nr_ssbri_cri = sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri;
+      //extracting the ssb indexes
+      for (ssb_idx = 0; ssb_idx < nr_ssbri_cri; ssb_idx++) {
+        ssb_index[idx * nb_of_csi_ssb_report + ssb_idx] = sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI[ssb_idx];
+      }
+
+      //if strongest measured RSRP is configured
+      strongest_ssb_rsrp = get_measured_rsrp(sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP);
+      // including ssb rsrp in mac stats
+      stats->cumul_rsrp += strongest_ssb_rsrp;
+      stats->num_rsrp_meas++;
+      ssb_rsrp[idx * nb_of_csi_ssb_report] = strongest_ssb_rsrp;
+      LOG_D(MAC,"ssb_rsrp = %d\n",strongest_ssb_rsrp);
+
+      //if current ssb rsrp is greater than better rsrp
+      if(ssb_rsrp[idx * nb_of_csi_ssb_report] > better_rsrp_reported) {
+        better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report];
+        target_ssb_beam_index = idx * nb_of_csi_ssb_report;
+      }
+
+      for(diff_rsrp_idx =1; diff_rsrp_idx < nr_ssbri_cri; diff_rsrp_idx++) {
+        ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] = get_diff_rsrp(sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx-1], strongest_ssb_rsrp);
+
+        //if current reported rsrp is greater than better rsrp
+        if(ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] > better_rsrp_reported) {
+          better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx];
+          target_ssb_beam_index = idx * nb_of_csi_ssb_report + diff_rsrp_idx;
+        }
+      }
+  }
+
+
+  if(ssb_index[target_ssb_beam_index] != ssb_index[curr_ssb_beam_index] && ssb_rsrp[target_ssb_beam_index] > ssb_rsrp[curr_ssb_beam_index]) {
+    if( ssb_rsrp[target_ssb_beam_index] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) {
+      is_triggering_ssb_beam_switch = 1;
+      LOG_D(MAC, "Triggering ssb beam switching using tci\n");
+    }
+  }
+
+  if(is_triggering_ssb_beam_switch) {
+    //filling pdcch tci state activativation mac ce structure fields
+    sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 1;
+    //OAI currently focusing on Non CA usecase hence 0 is considered as serving
+    //cell id
+    sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.servingCellId = 0; //0 for PCell as 38.331 v15.9.0 page 353 //serving cell id for which this MAC CE applies
+    sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId = 0; //coreset id for which the TCI State id is being indicated
+
+    /* 38.321 v15.8.0 page 66
+    TCI State ID: This field indicates the TCI state identified by TCI-StateId as specified in TS 38.331 [5] applicable
+    to the Control Resource Set identified by CORESET ID field.
+    If the field of CORESET ID is set to 0,
+      this field indicates a TCI-StateId for a TCI state of the first 64 TCI-states configured by tci-States-ToAddModList and tciStates-ToReleaseList in the PDSCH-Config in the active BWP.
+    If the field of CORESET ID is set to the other value than 0,
+     this field indicates a TCI-StateId configured by tci-StatesPDCCH-ToAddList and tciStatesPDCCH-ToReleaseList in the controlResourceSet identified by the indicated CORESET ID.
+    The length of the field is 7 bits
+     */
+    if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId == 0) {
+      int tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index[target_ssb_beam_index], Mod_idP, UE_id);
+
+      if( tci_state_id != -1)
+        sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id;
+      else {
+        //identify the best beam within first 64 TCI States of PDSCH
+        //Config TCI-states-to-addModList
+        int flag = 0;
+
+        for(i =0; ssb_index_sorted[i]!=0; i++) {
+          tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index_sorted[i], Mod_idP, UE_id) ;
+
+          if(tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) {
+            sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id;
+            flag = 1;
+            break;
+          }
+        }
+
+        if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) {
+          sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0;
+        }
+      }
+    } else {
+      int tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index[target_ssb_beam_index], Mod_idP, UE_id);
+
+      if (tci_state_id !=-1)
+        sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id;
+      else {
+        //identify the best beam within CORESET/PDCCH
+        ////Config TCI-states-to-addModList
+        int flag = 0;
+
+        for(i =0; ssb_index_sorted[i]!=0; i++) {
+          tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index_sorted[i], Mod_idP, UE_id);
+
+          if( tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) {
+            sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id;
+            flag = 1;
+            break;
+          }
+        }
+
+        if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) {
+          sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0;
+        }
+      }
+    }
+
+    sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1]->tci_PresentInDCI;
+
+    //filling pdsch tci state activation deactivation mac ce structure fields
+    if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI) {
+      sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.is_scheduled = 1;
+      /*
+      Serving Cell ID: This field indicates the identity of the Serving Cell for which the MAC CE applies
+      Considering only PCell exists. Serving cell index of PCell is always 0, hence configuring 0
+      */
+      sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.servingCellId = 0;
+      /*
+      BWP ID: This field indicates a DL BWP for which the MAC CE applies as the codepoint of the DCI bandwidth
+      part indicator field as specified in TS 38.212
+      */
+      sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.bwpId = pdsch_bwp_id;
+
+      /*
+       * TODO ssb_rsrp_sort() API yet to code to find 8 best beams, rrc configuration
+       * is required
+       */
+      for(i = 0; i<8; i++) {
+        sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i] = i;
+      }
+
+      sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.highestTciStateActivated = 8;
+
+      for(i = 0, j =0; i<MAX_TCI_STATES; i++) {
+        if(sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i]) {
+          sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.codepoint[j] = i;
+          j++;
+        }
+      }
+    }//tci_presentInDCI
+  }//is-triggering_beam_switch
+}//tci handling
+
+void reverse_n_bits(uint8_t *value, uint16_t bitlen) {
+  uint16_t j;
+  uint8_t i;
+  for(j = bitlen - 1,i = 0; j > i; j--, i++) {
+    if(((*value>>j)&1) != ((*value>>i)&1)) {
+      *value ^= (1<<j);
+      *value ^= (1<<i);
+    }
+  }
+}
+
+void extract_pucch_csi_report (NR_CSI_MeasConfig_t *csi_MeasConfig,
+                               const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu,
+                               frame_t frame,
+                               slot_t slot,
+                               int UE_id,
+                               module_id_t Mod_idP) {
+
+  /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */
+  uint8_t idx = 0;
+  uint8_t payload_size = ceil(((double)uci_pdu->csi_part1.csi_part1_bit_len)/8);
+  uint8_t *payload = uci_pdu->csi_part1.csi_part1_payload;
+  NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type = NR_CSI_ReportConfig__reportQuantity_PR_NOTHING;
+  NR_UE_info_t *UE_info = &(RC.nrmac[Mod_idP]->UE_info);
+  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+  uint8_t csi_report_id = 0;
+
+  UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = 0;
+  for ( csi_report_id =0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++ ) {
+    //Has to implement according to reportSlotConfig type
+    /*reportQuantity must be considered according to the current scheduled
+      CSI-ReportConfig if multiple CSI-ReportConfigs present*/
+    reportQuantity_type = UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type;
+    LOG_D(PHY,"SFN/SF:%d%d reportQuantity type = %d\n",frame,slot,reportQuantity_type);
+
+    if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type || 
+        NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type) {
+      uint8_t csi_ssb_idx = 0;
+      uint8_t diff_rsrp_idx = 0;
+      uint8_t cri_ssbri_bitlen = UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.cri_ssbri_bitlen;
+
+    /*! As per the spec 38.212 and table:  6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report
+     * the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE
+     * From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set
+     * From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1
+     */
+
+      /** from 38.214 sec 5.2.1.4.2
+      - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE is
+        not required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in
+        a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting
+
+      - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE is not
+      required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in a
+      single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB
+      resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with
+      multiple simultaneous spatial domain receive filter
+      */
+
+      idx = 0; //Since for SSB RSRP reporting in RRC can configure only one ssb resource set per one report config
+      sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri = UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.nb_ssbri_cri;
+
+      for (csi_ssb_idx = 0; csi_ssb_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri ; csi_ssb_idx++) {
+        if(cri_ssbri_bitlen > 1)
+          reverse_n_bits(payload, cri_ssbri_bitlen);
+
+        if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type)
+          sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = 
+            *(UE_info->csi_report_template[UE_id][csi_report_id].SSB_Index_list[cri_ssbri_bitlen>0?((*payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]);
+        else
+          sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = 
+            *(UE_info->csi_report_template[UE_id][csi_report_id].CSI_Index_list[cri_ssbri_bitlen>0?((*payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]);
+	  
+        *payload >>= cri_ssbri_bitlen;
+        LOG_D(PHY,"SSB_index = %d\n",sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx]);
+      }
+
+      reverse_n_bits(payload, 7);
+      sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP = (*payload) & 0x7f;
+      *payload >>= 7;
+
+      for ( diff_rsrp_idx =0; diff_rsrp_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri - 1; diff_rsrp_idx++ ) {
+        reverse_n_bits(payload,4);
+        sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx] = (*payload) & 0x0f;
+        *payload >>= 4;
+      }
+      UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report++;
+      LOG_D(MAC,"csi_payload size = %d, rsrp_id = %d\n",payload_size, sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP);
+    }
+  }
+
+  if ( !(reportQuantity_type)) 
+    AssertFatal(reportQuantity_type, "reportQuantity is not configured");
+
+}
+
 void handle_nr_uci_pucch_0_1(module_id_t mod_id,
                              frame_t frame,
                              sub_frame_t slot,
@@ -374,17 +1013,19 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
                                frame_t frame,
                                sub_frame_t slot,
                                const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234)
-{ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
-  UE_info->active[0] = 1;
-  UE_info->rnti[0] = uci_234->rnti;
-  int UE_id = find_nr_UE_id(mod_id, uci_234->rnti);
+{ int UE_id = find_nr_UE_id(mod_id, uci_234->rnti);
   if (UE_id < 0) {
     LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti);
     return;
   }
-  //NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
+  NR_CSI_MeasConfig_t *csi_MeasConfig = RC.nrmac[mod_id]->UE_info.secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
+  NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
   NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
-
+  if (NFAPI_MODE == NFAPI_MODE_PNF){
+  UE_info->active[0] = 1;
+  UE_info->rnti[0] = uci_234->rnti;
+  }
+  
   // tpc (power control)
   sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10,
                                 uci_234->ul_cqi,
@@ -422,6 +1063,15 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
   //     handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack);
   //   }
   // }
+  if ((uci_234->pduBitmap >> 2) & 0x01) {
+    //API to parse the csi report and store it into sched_ctrl
+    extract_pucch_csi_report (csi_MeasConfig, uci_234, frame, slot, UE_id, mod_id);
+    //TCI handling function
+    tci_handling(mod_id, UE_id,frame, slot);
+  }
+  if ((uci_234->pduBitmap >> 3) & 0x01) {
+    //@TODO:Handle CSI Report 2
+  }
 }
 
 
@@ -762,5 +1412,4 @@ uint16_t compute_pucch_prb_size(uint8_t format,
   else{
     AssertFatal(1==0,"Not yet implemented");
   }
-
 }
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 94aa4f5159d9c2024925b4b78efee9ae5bf7af5c..23d8f7677f048d76fe1fd6ca8f20c110b068a7f8 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -396,7 +396,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
         T_BUFFER(sduP, sdu_lenP));
 
     UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP;
-    LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d sduP %p\n",
+    LOG_D(NR_MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d sduP %p\n",
           gnb_mod_idP,
           harq_pid,
           CC_idP,
@@ -413,7 +413,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
       if (timing_advance != 0xffff)
         UE_scheduling_control->ta_update = timing_advance;
       UE_scheduling_control->ul_rssi = rssi;
-      LOG_D(MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
+      LOG_D(NR_MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
     }
     else{
       UE_scheduling_control->tpc0 = 1;
@@ -432,7 +432,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
 #endif
 
     if (sduP != NULL){
-      LOG_D(MAC, "Received PDU at MAC gNB \n");
+      LOG_D(NR_MAC, "Received PDU at MAC gNB \n");
 
       const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size;
       UE_scheduling_control->sched_ul_bytes -= tb_size;
@@ -469,7 +469,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
 
       // random access pusch with TC-RNTI
       if (ra->rnti != current_rnti) {
-        LOG_W(MAC,
+        LOG_W(NR_MAC,
               "expected TC-RNTI %04x to match current RNTI %04x\n",
               ra->rnti,
               current_rnti);
@@ -477,19 +477,25 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
       }
       const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti, ra->secondaryCellGroup);
       UE_info->UE_beam_index[UE_id] = ra->beam_id;
-      LOG_I(MAC,
+      LOG_I(NR_MAC,
             "[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
             "adding UE MAC Context UE_id %d/RNTI %04x\n",
             gnb_mod_idP,
             current_rnti,
             UE_id,
             ra->rnti);
+
+      LOG_D(NR_MAC,"[RAPROC] Received Msg3:\n");
+      for (int k = 0; k < sdu_lenP; k++) {
+        LOG_D(NR_MAC,"(%i): 0x%x\n",k,sduP[k]);
+      }
+
       // re-initialize ta update variables afrer RA procedure completion
       UE_info->UE_sched_ctrl[UE_id].ta_frame = frameP;
 
       free(ra->preambles.preamble_list);
       ra->state = RA_IDLE;
-      LOG_I(MAC,
+      LOG_I(NR_MAC,
             "reset RA state information for RA-RNTI %04x/index %d\n",
             ra->rnti,
             i);
@@ -1069,18 +1075,16 @@ void nr_schedule_ulsch(module_id_t module_id,
 
     /* PUSCH PTRS */
     if (ps->NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) {
-      // TODO to be fixed from RRC config
-      uint8_t ptrs_mcs1 = 2;  // higher layer parameter in PTRS-UplinkConfig
-      uint8_t ptrs_mcs2 = 4;  // higher layer parameter in PTRS-UplinkConfig
-      uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig
-      uint16_t n_rb0 = 25;    // higher layer parameter in PTRS-UplinkConfig
-      uint16_t n_rb1 = 75;    // higher layer parameter in PTRS-UplinkConfig
-      pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table);
-      pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size);
+      bool valid_ptrs_setup = false;
       pusch_pdu->pusch_ptrs.ptrs_ports_list   = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t));
-      pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0;
-
-      pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS
+      valid_ptrs_setup = set_ul_ptrs_values(ps->NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup,
+                                            pusch_pdu->rb_size, pusch_pdu->mcs_index, pusch_pdu->mcs_table,
+                                            &pusch_pdu->pusch_ptrs.ptrs_freq_density,&pusch_pdu->pusch_ptrs.ptrs_time_density,
+                                            &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_pdu->pusch_ptrs.num_ptrs_ports,
+                                            &pusch_pdu->pusch_ptrs.ul_ptrs_power, pusch_pdu->nr_of_symbols);
+      if (valid_ptrs_setup==true) {
+        pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS
+      }
     }
     else{
       pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
@@ -1144,4 +1148,4 @@ void nr_schedule_ulsch(module_id_t module_id,
 
     memset(sched_pusch, 0, sizeof(*sched_pusch));
   }
-}
\ No newline at end of file
+}
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 3502a11580cf75af67805070267e34d5044f1b0c..c1c7278338ca4cfffef48da017998ceeedd97e0a 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -73,6 +73,7 @@ void schedule_control_sib1(module_id_t module_id,
                            int time_domain_allocation,
                            uint8_t mcsTableIdx,
                            uint8_t mcs,
+                           uint8_t candidate_idx,
                            int num_total_bytes);
 
 void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP);
@@ -328,7 +329,7 @@ uint16_t compute_pucch_prb_size(uint8_t format,
                                 uint8_t n_symb,
                                 uint8_t n_re_ctrl);
 
-void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id);
+void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_info, int UE_id, module_id_t Mod_idP);
 
 int get_dlscs(nfapi_nr_config_request_t *cfg);
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c
index 8dc1303801a349378d3180dd23b6f3dfc45951f4..33e575d2b9ce2ff71bea5e7238faab3826c79e20 100644
--- a/openair2/LAYER2/NR_MAC_gNB/main.c
+++ b/openair2/LAYER2/NR_MAC_gNB/main.c
@@ -96,7 +96,7 @@ void mac_top_init_gNB(void)
     // These should be out of here later
     pdcp_layer_init();
 
-    if(IS_SOFTMODEM_NOS1 && !get_softmodem_params()->do_ra)
+    if(IS_SOFTMODEM_NOS1 && !(get_softmodem_params()->do_ra || get_softmodem_params()->sa) )
       nr_DRB_preconfiguration(0x1234);
 
     rrc_init_nr_global_param();
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index 63587d58a4f118935ff4f0e38477e25c8e46e3ec..ac583b52701d93314515a18025a9d794c394eb67 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -246,8 +246,17 @@ typedef struct pdcchStateInd {
   uint8_t servingCellId;
   uint8_t coresetId;
   uint8_t tciStateId;
+  bool tci_present_inDCI;
 } pdcchStateInd_t;
 
+typedef struct pucchSpatialRelation {
+  bool is_scheduled;
+  uint8_t servingCellId;
+  uint8_t bwpId;
+  uint8_t pucchResourceId;
+  bool s0tos7_actDeact[8];
+} pucchSpatialRelation_t;
+
 typedef struct SPCSIReportingpucch {
   bool is_scheduled;
   uint8_t servingCellId;
@@ -271,12 +280,14 @@ typedef struct pdschTciStatesActDeact {
   uint8_t bwpId;
   uint8_t highestTciStateActivated;
   bool tciStateActDeact[MAX_TCI_STATES];
+  uint8_t codepoint[8];
 } pdschTciStatesActDeact_t;
 
 typedef struct UE_info {
   sp_zp_csirs_t sp_zp_csi_rs;
   csi_rs_im_t csi_im;
   pdcchStateInd_t pdcch_state_ind;
+  pucchSpatialRelation_t pucch_spatial_relation;
   SPCSIReportingpucch_t SP_CSI_reporting_pucch;
   aperiodicCSI_triggerStateSelection_t aperi_CSI_trigger;
   pdschTciStatesActDeact_t pdsch_TCI_States_ActDeact;
@@ -352,6 +363,84 @@ typedef struct NR_UE_harq {
   uint32_t tb_size;
 } NR_UE_harq_t;
 
+//! fixme : need to enhace for the multiple TB CQI report
+
+
+//
+/*! As per spec 38.214 section 5.2.1.4.2
+ * - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE shall report in
+  a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting.
+ * - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE shall report in a
+  single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB
+  resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with
+  multiple simultaneous spatial domain receive filter
+*/
+#define MAX_NR_OF_REPORTED_RS 4
+
+typedef enum NR_CSI_Report_Config {
+  CSI_Report_PR_cri_ri_li_pmi_cqi_report,
+  CSI_Report_PR_ssb_cri_report
+} NR_CSI_Report_Config_PR;
+struct CRI_RI_LI_PMI_CQI {
+  uint8_t cri;
+  uint8_t ri;
+  uint8_t li;
+  uint8_t pmi_x1;
+  uint8_t pmi_x2;
+  uint8_t cqi;
+};
+
+typedef struct CRI_SSB_RSRP {
+  uint8_t nr_ssbri_cri;
+  uint8_t CRI_SSBRI[MAX_NR_OF_REPORTED_RS];
+  uint8_t RSRP;
+  uint8_t diff_RSRP[MAX_NR_OF_REPORTED_RS - 1];
+} CRI_SSB_RSRP_t;
+
+struct CSI_Report {
+  NR_CSI_Report_Config_PR present;
+  union Config_CSI_Report {
+    struct CRI_RI_LI_PMI_CQI cri_ri_li_pmi_cqi_report;
+    struct CRI_SSB_RSRP ssb_cri_report;
+  } choice;
+};
+
+#define MAX_SR_BITLEN 8
+
+typedef struct {
+  uint8_t nb_ssbri_cri;
+  uint8_t cri_ssbri_bitlen;
+  uint8_t rsrp_bitlen;
+  uint8_t diff_rsrp_bitlen;
+}L1_RSRP_bitlen_t;
+
+typedef struct{
+  uint8_t cri_bitlen;
+  uint8_t ri_bitlen;
+  uint8_t li_bitlen;
+  uint8_t pmi_x1_bitlen;
+  uint8_t pmi_x2_bitlen;
+  uint8_t cqi_bitlen;
+} CSI_Meas_bitlen_t;
+
+typedef struct nr_csi_report {
+  NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type;
+  long periodicity;
+  uint16_t offset;
+  long ** SSB_Index_list;
+  long ** CSI_Index_list;
+//  uint8_t nb_of_nzp_csi_report;
+  uint8_t nb_of_csi_ssb_report;
+  L1_RSRP_bitlen_t CSI_report_bitlen;
+  CSI_Meas_bitlen_t csi_meas_bitlen;
+} nr_csi_report_t;
+
+/*! As per the spec 38.212 and table:  6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report 
+  the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE
+  From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set 
+  From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1
+ */
+#define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16
 typedef struct NR_UE_old_sched {
   uint16_t rbSize;
   int time_domain_allocation;
@@ -376,26 +465,8 @@ typedef struct NR_UE_ul_harq {
   NR_sched_pusch_t sched_pusch;
 } NR_UE_ul_harq_t;
 
-
-typedef struct {
-  uint8_t nb_ssbri_cri;
-  uint8_t cri_ssbri_bitlen;
-  uint8_t rsrp_bitlen;
-  uint8_t diff_rsrp_bitlen;
-}CRI_SSBRI_RSRP_bitlen_t;
-
-
-#define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16
-typedef struct nr_csi_report {
-  NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type;
-  NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR CSI_Resource_type;
-  uint8_t nb_of_nzp_csi_report;
-  uint8_t nb_of_csi_ssb_report;
-  CRI_SSBRI_RSRP_bitlen_t CSI_report_bitlen[MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG];
-} nr_csi_report_t;
-
-
 /*! \brief scheduling control information set through an API */
+#define MAX_CSI_REPORTS 48
 typedef struct {
   /// total amount of data awaiting for this UE
   uint32_t num_total_bytes;
@@ -450,6 +521,8 @@ typedef struct {
   uint8_t tpc0;
   uint8_t tpc1;
   uint16_t ul_rssi;
+  uint8_t current_harq_pid;
+  struct CSI_Report CSI_report[MAX_CSI_REPORTS];
   /// information about every HARQ process
   NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES];
   /// HARQ processes that are free
@@ -487,6 +560,8 @@ typedef struct {
   int ulsch_total_bytes_scheduled;
   int ulsch_total_bytes_rx;
   int ulsch_current_bytes;
+  int cumul_rsrp;
+  uint8_t num_rsrp_meas;
 } NR_mac_stats_t;
 
 
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
index ffc669a46169740fdaf7cab79921a4864165f9e7..eda6888ecdc2e0c58dd70ce57f1a1638f31c1553 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
@@ -21,24 +21,222 @@
 
 #include "nr_pdcp_entity.h"
 
-#include "nr_pdcp_entity_drb_am.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
 #include "nr_pdcp_security_nea2.h"
+#include "nr_pdcp_sdu.h"
 
 #include "LOG/log.h"
 
-nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
-    int is_gnb, int rb_id,
-    void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
-                        char *buf, int size),
-    void *deliver_sdu_data,
-    void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity,
-                        char *buf, int size, int sdu_id),
-    void *deliver_pdu_data)
+static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity,
+                                    char *_buffer, int size)
 {
-  abort();
+  unsigned char    *buffer = (unsigned char *)_buffer;
+  nr_pdcp_sdu_t    *sdu;
+  int              rcvd_sn;
+  uint32_t         rcvd_hfn;
+  uint32_t         rcvd_count;
+  int              header_size;
+  int              integrity_size;
+  int              rx_deliv_sn;
+  uint32_t         rx_deliv_hfn;
+
+  if (size < 1) {
+    LOG_E(PDCP, "bad PDU received (size = %d)\n", size);
+    return;
+  }
+
+  if (!(buffer[0] & 0x80)) {
+    LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+
+  if (entity->sn_size == 12) {
+    rcvd_sn = (((unsigned char)buffer[0] & 0xf) <<  8) |
+                (unsigned char)buffer[1];
+    header_size = 2;
+  } else {
+    rcvd_sn = (((unsigned char)buffer[0] & 0x3) << 16) |
+               ((unsigned char)buffer[1]        <<  8) |
+                (unsigned char)buffer[2];
+    header_size = 3;
+  }
+
+  integrity_size = 0;
+
+  if (size < header_size + integrity_size + 1) {
+    LOG_E(PDCP, "bad PDU received (size = %d)\n", size);
+    return;
+  }
+
+  rx_deliv_sn  = entity->rx_deliv & entity->sn_max;
+  rx_deliv_hfn = (entity->rx_deliv >> entity->sn_size) & ~entity->sn_max;
+
+  if (rcvd_sn < rx_deliv_sn - entity->window_size) {
+    rcvd_hfn = rx_deliv_hfn + 1;
+  } else if (rcvd_sn >= rx_deliv_sn + entity->window_size) {
+    rcvd_hfn = rx_deliv_hfn - 1;
+  } else {
+    rcvd_hfn = rx_deliv_hfn;
+  }
+
+  rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn;
+
+  if (entity->has_ciphering)
+    entity->cipher(entity->security_context,
+                   (unsigned char *)buffer+header_size, size-header_size,
+                   entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1);
+
+  if (rcvd_count < entity->rx_deliv
+      || nr_pdcp_sdu_in_list(entity->rx_list, rcvd_count)) {
+    LOG_D(PDCP, "discard NR PDU rcvd_count=%d\n", rcvd_count);
+    return;
+  }
+
+  sdu = nr_pdcp_new_sdu(rcvd_count,
+                        (char *)buffer + header_size,
+                        size - header_size - integrity_size);
+  entity->rx_list = nr_pdcp_sdu_list_add(entity->rx_list, sdu);
+  entity->rx_size += size-header_size;
+
+  if (rcvd_count >= entity->rx_next) {
+    entity->rx_next = rcvd_count + 1;
+  }
+
+  /* TODO(?): out of order delivery */
+
+  if (rcvd_count == entity->rx_deliv) {
+    /* deliver all SDUs starting from rx_deliv up to discontinuity or end of list */
+    uint32_t count = entity->rx_deliv;
+    while (entity->rx_list != NULL && count == entity->rx_list->count) {
+      nr_pdcp_sdu_t *cur = entity->rx_list;
+      entity->deliver_sdu(entity->deliver_sdu_data, entity,
+                          cur->buffer, cur->size);
+      entity->rx_list = cur->next;
+      entity->rx_size -= cur->size;
+      nr_pdcp_free_sdu(cur);
+      count++;
+    }
+    entity->rx_deliv = count;
+  }
+
+  if (entity->t_reordering_start != 0 && entity->rx_deliv > entity->rx_reord) {
+    /* stop and reset t-Reordering */
+    entity->t_reordering_start = 0;
+  }
+
+  if (entity->t_reordering_start == 0 && entity->rx_deliv < entity->rx_next) {
+    entity->rx_reord = entity->rx_next;
+    entity->t_reordering_start = entity->t_current;
+  }
 }
 
-nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
+static void nr_pdcp_entity_recv_sdu(nr_pdcp_entity_t *entity,
+                                    char *buffer, int size, int sdu_id)
+{
+  uint32_t count;
+  int      sn;
+  int      header_size;
+  char     buf[size+3+4];
+
+  count = entity->tx_next;
+  sn = entity->tx_next & entity->sn_max;
+
+  if (entity->sn_size == 12) {
+    buf[0] = 0x80 | ((sn >> 8) & 0xf);
+    buf[1] = sn & 0xff;
+    header_size = 2;
+  } else {
+    buf[0] = 0x80 | ((sn >> 16) & 0x3);
+    buf[1] = (sn >> 8) & 0xff;
+    buf[2] = sn & 0xff;
+    header_size = 3;
+  }
+
+  memcpy(buf+header_size, buffer, size);
+
+  if (entity->has_ciphering)
+    entity->cipher(entity->security_context,
+                   (unsigned char *)buf+header_size, size,
+                   entity->rb_id, count, entity->is_gnb ? 1 : 0);
+
+  entity->tx_next++;
+
+  entity->deliver_pdu(entity->deliver_pdu_data, entity, buf,
+                      size+header_size, sdu_id);
+}
+
+static void nr_pdcp_entity_set_integrity_key(nr_pdcp_entity_t *entity,
+                                             char *key)
+{
+  memcpy(entity->integrity_key, key, 16);
+}
+
+static void check_t_reordering(nr_pdcp_entity_t *entity)
+{
+  uint32_t count;
+
+  if (entity->t_reordering_start == 0
+      || entity->t_current <= entity->t_reordering_start + entity->t_reordering)
+    return;
+
+  /* stop timer */
+  entity->t_reordering_start = 0;
+
+  /* deliver all SDUs with count < rx_reord */
+  while (entity->rx_list != NULL && entity->rx_list->count < entity->rx_reord) {
+    nr_pdcp_sdu_t *cur = entity->rx_list;
+    entity->deliver_sdu(entity->deliver_sdu_data, entity,
+                        cur->buffer, cur->size);
+    entity->rx_list = cur->next;
+    entity->rx_size -= cur->size;
+    nr_pdcp_free_sdu(cur);
+  }
+
+  /* deliver all SDUs starting from rx_reord up to discontinuity or end of list */
+  count = entity->rx_reord;
+  while (entity->rx_list != NULL && count == entity->rx_list->count) {
+    nr_pdcp_sdu_t *cur = entity->rx_list;
+    entity->deliver_sdu(entity->deliver_sdu_data, entity,
+                        cur->buffer, cur->size);
+    entity->rx_list = cur->next;
+    entity->rx_size -= cur->size;
+    nr_pdcp_free_sdu(cur);
+    count++;
+  }
+
+  entity->rx_deliv = count;
+
+  if (entity->rx_deliv < entity->rx_next) {
+    entity->rx_reord = entity->rx_next;
+    entity->t_reordering_start = entity->t_current;
+  }
+}
+
+void nr_pdcp_entity_set_time(struct nr_pdcp_entity_t *entity, uint64_t now)
+{
+  entity->t_current = now;
+
+  check_t_reordering(entity);
+}
+
+void nr_pdcp_entity_delete(nr_pdcp_entity_t *entity)
+{
+  nr_pdcp_sdu_t *cur = entity->rx_list;
+  while (cur != NULL) {
+    nr_pdcp_sdu_t *next = cur->next;
+    nr_pdcp_free_sdu(cur);
+    cur = next;
+  }
+  if (entity->free_security != NULL)
+    entity->free_security(entity->security_context);
+  free(entity);
+}
+
+nr_pdcp_entity_t *new_nr_pdcp_entity(
+    nr_pdcp_entity_type_t type,
     int is_gnb, int rb_id,
     void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
                         char *buf, int size),
@@ -54,52 +252,56 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
     unsigned char *ciphering_key,
     unsigned char *integrity_key)
 {
-  nr_pdcp_entity_drb_am_t *ret;
+  nr_pdcp_entity_t *ret;
 
-  ret = calloc(1, sizeof(nr_pdcp_entity_drb_am_t));
+  ret = calloc(1, sizeof(nr_pdcp_entity_t));
   if (ret == NULL) {
     LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__);
     exit(1);
   }
 
-  ret->common.recv_pdu          = nr_pdcp_entity_drb_am_recv_pdu;
-  ret->common.recv_sdu          = nr_pdcp_entity_drb_am_recv_sdu;
-  ret->common.set_integrity_key = nr_pdcp_entity_drb_am_set_integrity_key;
+  ret->type = type;
+
+  ret->recv_pdu          = nr_pdcp_entity_recv_pdu;
+  ret->recv_sdu          = nr_pdcp_entity_recv_sdu;
+  ret->set_integrity_key = nr_pdcp_entity_set_integrity_key;
+  ret->set_time          = nr_pdcp_entity_set_time;
 
-  ret->common.delete = nr_pdcp_entity_drb_am_delete;
+  ret->delete = nr_pdcp_entity_delete;
 
-  ret->common.deliver_sdu = deliver_sdu;
-  ret->common.deliver_sdu_data = deliver_sdu_data;
+  ret->deliver_sdu = deliver_sdu;
+  ret->deliver_sdu_data = deliver_sdu_data;
 
-  ret->common.deliver_pdu = deliver_pdu;
-  ret->common.deliver_pdu_data = deliver_pdu_data;
+  ret->deliver_pdu = deliver_pdu;
+  ret->deliver_pdu_data = deliver_pdu_data;
 
   ret->rb_id         = rb_id;
   ret->sn_size       = sn_size;
   ret->t_reordering  = t_reordering;
   ret->discard_timer = discard_timer;
 
-  ret->common.maximum_nr_pdcp_sn = (1 << sn_size) - 1;
+  ret->sn_max        = (1 << sn_size) - 1;
+  ret->window_size   = 1 << (sn_size - 1);
 
   if (ciphering_key != NULL && ciphering_algorithm != 0) {
     if (ciphering_algorithm != 2) {
       LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n");
       exit(1);
     }
-    ret->common.has_ciphering = 1;
-    ret->common.ciphering_algorithm = ciphering_algorithm;
-    memcpy(ret->common.ciphering_key, ciphering_key, 16);
+    ret->has_ciphering = 1;
+    ret->ciphering_algorithm = ciphering_algorithm;
+    memcpy(ret->ciphering_key, ciphering_key, 16);
 
-    ret->common.security_context = nr_pdcp_security_nea2_init(ciphering_key);
-    ret->common.cipher = nr_pdcp_security_nea2_cipher;
-    ret->common.free_security = nr_pdcp_security_nea2_free_security;
+    ret->security_context = nr_pdcp_security_nea2_init(ciphering_key);
+    ret->cipher = nr_pdcp_security_nea2_cipher;
+    ret->free_security = nr_pdcp_security_nea2_free_security;
   }
-  ret->common.is_gnb = is_gnb;
+  ret->is_gnb = is_gnb;
 
   if (integrity_key != NULL) {
     printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
     exit(1);
   }
 
-  return (nr_pdcp_entity_t *)ret;
+  return ret;
 }
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h
index 58d79835ecbc588524526887624ecea47c15632e..36e7a540c4d6736f0be73ba9303d710461133f31 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h
@@ -19,18 +19,29 @@
  *      contact@openairinterface.org
  */
 
-#include <stdint.h>
-
 #ifndef _NR_PDCP_ENTITY_H_
 #define _NR_PDCP_ENTITY_H_
 
+#include <stdint.h>
+
+#include "nr_pdcp_sdu.h"
+
+typedef enum {
+  NR_PDCP_DRB_AM,
+  NR_PDCP_DRB_UM,
+  NR_PDCP_SRB
+} nr_pdcp_entity_type_t;
+
 typedef struct nr_pdcp_entity_t {
+  nr_pdcp_entity_type_t type;
+
   /* functions provided by the PDCP module */
   void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size);
   void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size,
                    int sdu_id);
   void (*delete)(struct nr_pdcp_entity_t *entity);
   void (*set_integrity_key)(struct nr_pdcp_entity_t *entity, char *key);
+  void (*set_time)(struct nr_pdcp_entity_t *entity, uint64_t now);
 
   /* callbacks provided to the PDCP module */
   void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
@@ -39,9 +50,28 @@ typedef struct nr_pdcp_entity_t {
   void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity,
                       char *buf, int size, int sdu_id);
   void *deliver_pdu_data;
-  int tx_hfn;
-  int next_nr_pdcp_tx_sn;
-  int maximum_nr_pdcp_sn;
+
+  /* configuration variables */
+  int rb_id;
+
+  int sn_size;                  /* SN size, in bits */
+  int t_reordering;             /* unit: ms */
+  int discard_timer;            /* unit: ms */
+
+  int sn_max;                   /* (2^SN_size) - 1 */
+  int window_size;              /* 2^(SN_size - 1) */
+
+  /* state variables */
+  uint32_t tx_next;
+  uint32_t rx_next;
+  uint32_t rx_deliv;
+  uint32_t rx_reord;
+
+  /* set to the latest know time by the user of the module. Unit: ms */
+  uint64_t t_current;
+
+  /* timers (stores the ms of activation, 0 means not active) */
+  int t_reordering_start;
 
   /* security */
   int has_ciphering;
@@ -60,18 +90,15 @@ typedef struct nr_pdcp_entity_t {
    * pdcp entity is for a gnb or an ue
    */
   int is_gnb;
-} nr_pdcp_entity_t;
 
-nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
-    int is_gnb, int rb_id,
-    void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
-                        char *buf, int size),
-    void *deliver_sdu_data,
-    void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity,
-                        char *buf, int size, int sdu_id),
-    void *deliver_pdu_data);
+  /* rx management */
+  nr_pdcp_sdu_t *rx_list;
+  int           rx_size;
+  int           rx_maxsize;
+} nr_pdcp_entity_t;
 
-nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
+nr_pdcp_entity_t *new_nr_pdcp_entity(
+    nr_pdcp_entity_type_t type,
     int is_gnb, int rb_id,
     void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
                         char *buf, int size),
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
deleted file mode 100644
index 62881c184e8cf3f35198b54f2893e2b4c4bb3eeb..0000000000000000000000000000000000000000
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The OpenAirInterface Software Alliance licenses this file to You under
- * the OAI Public License, Version 1.1  (the "License"); you may not use this file
- * except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.openairinterface.org/?page_id=698
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *-------------------------------------------------------------------------------
- * For more information about the OpenAirInterface (OAI) Software Alliance:
- *      contact@openairinterface.org
- */
-
-#include "nr_pdcp_entity_drb_am.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "common/utils/LOG/log.h"
-
-void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size)
-{
-  nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
-  int sn;
-
-  if (size < 3) abort();
-
-  if (!(buffer[0] & 0x80))
-    LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
-
-  sn = (((unsigned char)buffer[0] & 0x3) << 16) |
-        ((unsigned char)buffer[1]        <<  8) |
-         (unsigned char)buffer[2];
-
-  if (entity->common.has_ciphering)
-    entity->common.cipher(entity->common.security_context, (unsigned char *)buffer+3, size-3,
-                          entity->rb_id, sn, entity->common.is_gnb ? 0 : 1);
-
-  entity->common.deliver_sdu(entity->common.deliver_sdu_data,
-                             (nr_pdcp_entity_t *)entity, buffer+3, size-3);
-}
-
-void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int size,
-                              int sdu_id)
-{
-  nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
-  int sn;
-  char buf[size+3];
-
-  sn = entity->common.next_nr_pdcp_tx_sn;
-
-  entity->common.next_nr_pdcp_tx_sn++;
-  if (entity->common.next_nr_pdcp_tx_sn > entity->common.maximum_nr_pdcp_sn) {
-    entity->common.next_nr_pdcp_tx_sn = 0;
-    entity->common.tx_hfn++;
-  }
-
-  buf[0] = 0x80 | ((sn >> 16) & 0x3);
-  buf[1] = (sn >> 8) & 0xff;
-  buf[2] = sn & 0xff;
-  memcpy(buf+3, buffer, size);
-
-  if (entity->common.has_ciphering)
-    entity->common.cipher(entity->common.security_context, (unsigned char *)buf+3, size,
-                          entity->rb_id, sn, entity->common.is_gnb ? 1 : 0);
-
-  entity->common.deliver_pdu(entity->common.deliver_pdu_data,
-                             (nr_pdcp_entity_t *)entity, buf, size+3, sdu_id);
-}
-
-void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *key)
-{
-  /* nothing to do */
-}
-
-void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity)
-{
-  nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
-  if (entity->common.free_security != NULL)
-    entity->common.free_security(entity->common.security_context);
-  free(entity);
-}
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
index f14d25b145a72c4b3534e05ff46cce5752478edc..ec48b0adae001e6f9d805f93cd92c8a2aee710df 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
@@ -24,6 +24,7 @@
 #endif
 #include "asn1_utils.h"
 #include "nr_pdcp_ue_manager.h"
+#include "nr_pdcp_timer_thread.h"
 #include "NR_RadioBearerConfig.h"
 #include "NR_RLC-BearerConfig.h"
 #include "NR_RLC-Config.h"
@@ -41,6 +42,11 @@
 
 static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager;
 
+/* TODO: handle time a bit more properly */
+static uint64_t nr_pdcp_current_time;
+static int      nr_pdcp_current_time_last_frame;
+static int      nr_pdcp_current_time_last_subframe;
+
 /* necessary globals for OAI, not used internally */
 hash_table_t  *pdcp_coll_p;
 static uint64_t pdcp_optmask;
@@ -339,6 +345,8 @@ void pdcp_layer_init(void)
 
   nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1);
   init_nr_rlc_data_req_queue();
+
+  nr_pdcp_init_timer_thread(nr_pdcp_ue_manager);
 }
 
 #include "nfapi/oai_integration/vendor_ext.h"
@@ -625,11 +633,11 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
     LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n",
           __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
   } else {
-    pdcp_drb = new_nr_pdcp_entity_drb_am(is_gnb, drb_id,
-                                         deliver_sdu_drb, ue, deliver_pdu_drb, ue,
-                                         sn_size_dl, t_reordering, discard_timer,
-                                         ciphering_algorithm, integrity_algorithm,
-                                         ciphering_key, integrity_key);
+    pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id,
+                                  deliver_sdu_drb, ue, deliver_pdu_drb, ue,
+                                  sn_size_dl, t_reordering, discard_timer,
+                                  ciphering_algorithm, integrity_algorithm,
+                                  ciphering_key, integrity_key);
     nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
 
     LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
@@ -768,7 +776,7 @@ void nr_DRB_preconfiguration(uint16_t crnti)
   drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config));
   drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb));
   drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer));
-  *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_ms30;
+  *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity;
   drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL));
   *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits;
   drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL));
@@ -976,3 +984,14 @@ void
 pdcp_mbms_run ( const protocol_ctxt_t *const  ctxt_pP){
   /* nothing to do */
 }
+
+void nr_pdcp_tick(int frame, int subframe)
+{
+  if (frame != nr_pdcp_current_time_last_frame ||
+      subframe != nr_pdcp_current_time_last_subframe) {
+    nr_pdcp_current_time_last_frame = frame;
+    nr_pdcp_current_time_last_subframe = subframe;
+    nr_pdcp_current_time++;
+    nr_pdcp_wakeup_timer_thread(nr_pdcp_current_time);
+  }
+}
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c
new file mode 100644
index 0000000000000000000000000000000000000000..47d95156e3db1982307c8410b37187673370d94f
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "nr_pdcp_sdu.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size)
+{
+  nr_pdcp_sdu_t *ret = calloc(1, sizeof(nr_pdcp_sdu_t));
+  if (ret == NULL)
+    exit(1);
+  ret->count = count;
+  ret->buffer = malloc(size);
+  if (ret->buffer == NULL)
+    exit(1);
+  memcpy(ret->buffer, buffer, size);
+  ret->size = size;
+  return ret;
+}
+
+nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu)
+{
+  nr_pdcp_sdu_t head;
+  nr_pdcp_sdu_t *cur;
+  nr_pdcp_sdu_t *prev;
+
+  head.next = l;
+  cur = l;
+  prev = &head;
+
+  /* order is by 'count' */
+  while (cur != NULL) {
+    /* check if 'sdu' is before 'cur' in the list */
+    if (sdu->count < cur->count)
+      break;
+    prev = cur;
+    cur = cur->next;
+  }
+  prev->next = sdu;
+  sdu->next = cur;
+  return head.next;
+}
+
+int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count)
+{
+  while (l != NULL) {
+    if (l->count == count)
+      return 1;
+    l = l->next;
+  }
+  return 0;
+}
+
+void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu)
+{
+  free(sdu->buffer);
+  free(sdu);
+}
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h
similarity index 58%
rename from openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h
rename to openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h
index d7c42e6a629281ddc36253894857e120d95f3e93..3d4e50a4ce38cc7493c7974bdb7004a5a10297fd 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h
@@ -19,23 +19,21 @@
  *      contact@openairinterface.org
  */
 
-#ifndef _NR_PDCP_ENTITY_DRB_AM_H_
-#define _NR_PDCP_ENTITY_DRB_AM_H_
+#ifndef _NR_PDCP_SDU_H_
+#define _NR_PDCP_SDU_H_
 
-#include "nr_pdcp_entity.h"
+#include <stdint.h>
 
-typedef struct {
-  nr_pdcp_entity_t common;
-  int rb_id;
-  int sn_size;               /* unit: bits */
-  int t_reordering;          /* unit: ms */
-  int discard_timer;         /* unit: ms, -1 means infinity */
-} nr_pdcp_entity_drb_am_t;
+typedef struct nr_pdcp_sdu_t {
+  uint32_t             count;
+  char                 *buffer;
+  int                  size;
+  struct nr_pdcp_sdu_t *next;
+} nr_pdcp_sdu_t;
 
-void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *entity, char *buffer, int size);
-void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *entity, char *buffer, int size,
-                                    int sdu_id);
-void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *entity, char *key);
-void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *entity);
+nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size);
+nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu);
+int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count);
+void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu);
 
-#endif /* _NR_PDCP_ENTITY_DRB_AM_H_ */
+#endif /* _NR_PDCP_SDU_H_ */
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c
new file mode 100644
index 0000000000000000000000000000000000000000..36e9b16024879db067a7784c66eb898e36527dc7
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "nr_pdcp_timer_thread.h"
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <stdint.h>
+
+#include "LOG/log.h"
+
+static pthread_mutex_t   timer_thread_mutex   = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t    timer_thread_cond    = PTHREAD_COND_INITIALIZER;
+static volatile uint64_t timer_thread_curtime = 0;
+
+static void *nr_pdcp_timer_thread(void *_nr_pdcp_ue_manager)
+{
+  nr_pdcp_ue_manager_t *nr_pdcp_ue_manager = (nr_pdcp_ue_manager_t *)_nr_pdcp_ue_manager;
+  nr_pdcp_ue_t         **ue_list;
+  int                  ue_count;
+  int                  i;
+  int                  j;
+  uint64_t             curtime = 0;
+
+  while (1) {
+    if (pthread_mutex_lock(&timer_thread_mutex) != 0) abort();
+    while (curtime == timer_thread_curtime)
+      if (pthread_cond_wait(&timer_thread_cond, &timer_thread_mutex) != 0) abort();
+    curtime = timer_thread_curtime;
+    if (pthread_mutex_unlock(&timer_thread_mutex) != 0) abort();
+
+    nr_pdcp_manager_lock(nr_pdcp_ue_manager);
+
+    ue_list  = nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager);
+    ue_count = nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager);
+    for (i = 0; i < ue_count; i++) {
+      for (j = 0; j < 2; j++) {
+        if (ue_list[i]->srb[j] != NULL)
+          ue_list[i]->srb[j]->set_time(ue_list[i]->srb[j], curtime);
+      }
+      for (j = 0; j < 5; j++) {
+        if (ue_list[i]->drb[j] != NULL)
+          ue_list[i]->drb[j]->set_time(ue_list[i]->drb[j], curtime);
+      }
+    }
+
+    nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
+  }
+
+  return NULL;
+}
+
+void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager)
+{
+  pthread_t t;
+
+  if (pthread_create(&t, NULL, nr_pdcp_timer_thread, nr_pdcp_ue_manager) != 0) {
+    LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
+    exit(1);
+  }
+}
+
+void nr_pdcp_wakeup_timer_thread(uint64_t time)
+{
+  if (pthread_mutex_lock(&timer_thread_mutex)) abort();
+  timer_thread_curtime = time;
+  if (pthread_cond_broadcast(&timer_thread_cond)) abort();
+  if (pthread_mutex_unlock(&timer_thread_mutex)) abort();
+}
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h
new file mode 100644
index 0000000000000000000000000000000000000000..db8282f940057393b099b4f9e50542838fb30991
--- /dev/null
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef _NR_PDCP_TIMER_THREAD_H_
+#define _NR_PDCP_TIMER_THREAD_H_
+
+#include "nr_pdcp_ue_manager.h"
+
+#include <stdint.h>
+
+void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager);
+void nr_pdcp_wakeup_timer_thread(uint64_t time);
+
+#endif /* _NR_PDCP_TIMER_THREAD_H_ */
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c
index ca51da3d5f13426993c9395cf3c06550fff9c4f5..f89a18f94e4a00ebc6d9654fd40c9e1a83e3499a 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c
@@ -189,6 +189,20 @@ void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity
   ue->drb[drb_id] = entity;
 }
 
+/* must be called with lock acquired */
+nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m)
+{
+  nr_pdcp_ue_manager_internal_t *m = _m;
+  return m->ue_list;
+}
+
+/* must be called with lock acquired */
+int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m)
+{
+  nr_pdcp_ue_manager_internal_t *m = _m;
+  return m->ue_count;
+}
+
 int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *_m)
 {
   nr_pdcp_ue_manager_internal_t *m = _m;
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h
index 0de2f024b3f53746ff12537dfb08da9ec8fef1b1..3329f856b7fb04a1f710b7ee95bc4276130547fa 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h
@@ -46,6 +46,9 @@ void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *m);
 nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *m, int rnti);
 void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *m, int rnti);
 
+nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m);
+int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m);
+
 /***********************************************************************/
 /* ue functions                                                        */
 /***********************************************************************/
diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
index 2e0abda556b655bfce90141b8f1faa80eb4c9393..5a090d4ffd9c4d022b1f479292780a7036833421 100644
--- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
+++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
@@ -43,7 +43,6 @@
 
 NR_IF_Module_t *if_inst[MAX_IF_MODULES];
 NR_Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs];
-
 extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind);
 extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind);
 extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind);
@@ -54,14 +53,7 @@ extern uint16_t sf_ahead;
 extern uint16_t sl_ahead;
 
 void handle_nr_rach(NR_UL_IND_t *UL_info) {
-  if(NFAPI_MODE == NFAPI_MODE_PNF) {
-    if (UL_info->rach_ind.number_of_pdus>0) {
-      //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf));
-      oai_nfapi_nr_rach_indication(&UL_info->rach_ind);
-      UL_info->rach_ind.number_of_pdus = 0;
-    }
-  }
-  else {
+
   if (UL_info->rach_ind.number_of_pdus>0) {
     LOG_I(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot);
     int npdus = UL_info->rach_ind.number_of_pdus;
@@ -82,19 +74,10 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) {
     }
   }
 }
-}
 
 
 void handle_nr_uci(NR_UL_IND_t *UL_info)
-{ 
-  if(NFAPI_MODE == NFAPI_MODE_PNF) {
-    if (UL_info->uci_ind.num_ucis>0) {
-      //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf));
-      //oai_nfapi_nr_uci_indication(&UL_info->uci_ind);
-      UL_info->uci_ind.num_ucis = 0;
-    }
-  }
-  else {
+{
   const module_id_t mod_id = UL_info->module_id;
   const frame_t frame = UL_info->frame;
   const sub_frame_t slot = UL_info->slot;
@@ -112,6 +95,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
         handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu);
         break;
       }
+
       case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: {
         const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4;
         handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu);
@@ -126,24 +110,10 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
   // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs
   RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0;
 }
-}
 
-void handle_nr_ulsch(NR_UL_IND_t *UL_info)
-{ 
-  if(NFAPI_MODE == NFAPI_MODE_PNF) {
-    if (UL_info->crc_ind.number_crcs>0) {
-      //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf));
-      oai_nfapi_nr_crc_indication(&UL_info->crc_ind);
-      UL_info->crc_ind.number_crcs = 0;
-    }
 
-    if (UL_info->rx_ind.number_of_pdus>0) {
-      //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf));
-      oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind);
-      UL_info->rx_ind.number_of_pdus = 0;
-    }
-  }
-  else {
+void handle_nr_ulsch(NR_UL_IND_t *UL_info)
+{
   if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) {
     for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) {
       for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) {
@@ -169,16 +139,17 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info)
               crc->tb_crc_status);
 
         /* if CRC passes, pass PDU, otherwise pass NULL as error indication */
-        nr_rx_sdu(UL_info->module_id,
-                  UL_info->CC_id,
-                  UL_info->rx_ind.sfn,
-                  UL_info->rx_ind.slot,
-                  rx->rnti,
-                  crc->tb_crc_status ? NULL : rx->pdu,
-                  rx->pdu_length,
-                  rx->timing_advance,
-                  rx->ul_cqi,
-                  rx->rssi);
+        //Gokul
+        // nr_rx_sdu(UL_info->module_id,
+        //           UL_info->CC_id,
+        //           UL_info->rx_ind.sfn,
+        //           UL_info->rx_ind.slot,
+        //           rx->rnti,
+        //           crc->tb_crc_status ? NULL : rx->pdu,
+        //           rx->pdu_length,
+        //           rx->timing_advance,
+        //           rx->ul_cqi,
+        //           rx->rssi);
         //handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc);
         break;
       } //    for (j=0;j<UL_info->crc_ind.number_crcs;j++)
@@ -198,11 +169,11 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info)
           UL_info->crc_ind.number_crcs,
           UL_info->rx_ind.sfn,
           UL_info->rx_ind.slot);
-    }
   }
 }
 
 void NR_UL_indication(NR_UL_IND_t *UL_info) {
+  //printf("Inside NR UL Indication. \n");
   AssertFatal(UL_info!=NULL,"UL_INFO is null\n");
 #ifdef DUMP_FAPI
   dump_ul(UL_info);
@@ -274,10 +245,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) {
         ifi->NR_Schedule_response(sched_info);
       }
 
-      LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n",
-	    sched_info->frame,
-	    sched_info->slot,
-	    sched_info->DL_req->dl_tti_request_body.nPDUs);
+      
     }
   }
 }
diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
index edaef6d1ce4b574f987a8d4392db4457eebc51c4..51d279b7d1b5c8730a0dd4fa65b51d0cd27f1734 100644
--- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
+++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
@@ -62,7 +62,7 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, ui
 
 //  L2 Abstraction Layer
 int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, uint8_t *pduP, uint32_t pdu_len){
-  return nr_ue_decode_sib1(module_id, cc_id, gNB_index, sibs_mask, pduP, pdu_len);
+  return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, sibs_mask, pduP, pdu_len);
 }
 
 //  L2 Abstraction Layer
@@ -90,7 +90,7 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){
 
   ret = nr_ue_scheduler(NULL, ul_info);
 
-  if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && get_softmodem_params()->do_ra)
+  if (is_nr_UL_slot(mac->scc, ul_info->slot_tx, mac->frame_type) && get_softmodem_params()->do_ra)
     nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->thread_id);
 
   switch(ret){
diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c
index d34b4164a204dbf299f28b6e02f15c5dd03beda8..0e6d5b580f910b0fe031f4b3ff2cec0a75d492a7 100644
--- a/openair2/RRC/LTE/rrc_eNB_S1AP.c
+++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c
@@ -782,21 +782,37 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
         S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei;
 
         if (r_mme->plmn_Identity != NULL) {
-          if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) {
-            /* Use first indicated PLMN MCC if it is defined */
-            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[selected_plmn_identity];
+          if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count == 3))
+          {
+            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = (*r_mme->plmn_Identity->mcc->list.array[0] & 0xf) * 100 +
+                                                                    (*r_mme->plmn_Identity->mcc->list.array[1] & 0xf) * 10 +
+                                                                    (*r_mme->plmn_Identity->mcc->list.array[2] & 0xf);
             LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n",
                   ctxt_pP->module_id,
                   S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc,
                   ue_context_pP->ue_context.rnti);
           }
-
-          if (r_mme->plmn_Identity->mnc.list.count > 0) {
-            /* Use first indicated PLMN MNC if it is defined */
-            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[selected_plmn_identity];
-            LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n",
+          if(r_mme->plmn_Identity->mnc.list.count == 3)
+          {
+            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 100 +
+                                                                    (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf) * 10 +
+                                                                    (*r_mme->plmn_Identity->mnc.list.array[2] & 0xf);
+            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 3;
+            LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n",
+                  ctxt_pP->module_id,
+                  S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc,
+                  S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len,
+                  ue_context_pP->ue_context.rnti);
+          }
+          else if(r_mme->plmn_Identity->mnc.list.count == 2)
+          {
+            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 10 +
+                                                                    (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf);
+            S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 2;
+            LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n",
                   ctxt_pP->module_id,
                   S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc,
+                  S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len,
                   ue_context_pP->ue_context.rnti);
           }
         } else { // end if plmn_Identity != NULL
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 6d876a0eefacbfa7dcb94474849e2a40fa186025..5aafbaee4c9e79b8c0f76bfd720e3aa59df68803 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -79,17 +79,19 @@ void fill_default_coresetZero(NR_ControlResourceSet_t *coreset0, NR_ServingCellC
 void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0);
 
 void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
-				     NR_CellGroupConfig_t *secondaryCellGroup,
-				     int scg_id,
-				     int servCellIndex,
-				     int n_physical_antenna_ports,
-				     int initial_csi_index);
+                                     NR_ServingCellConfig_t *servingcellconfigdedicated,
+                                     NR_CellGroupConfig_t *secondaryCellGroup,
+                                     int scg_id,
+                                     int servCellIndex,
+                                     int n_physical_antenna_ports,
+                                     int initial_csi_index);
 
 void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
-			   NR_RRCReconfiguration_IEs_t *reconfig,
-			   NR_CellGroupConfig_t *secondaryCellGroup,
-			   int n_physical_antenna_ports,
-			   int initial_csi_index);
+                           NR_ServingCellConfig_t *servingcellconfigdedicated,
+                           NR_RRCReconfiguration_IEs_t *reconfig,
+                           NR_CellGroupConfig_t *secondaryCellGroup,
+                           int n_physical_antenna_ports,
+                           int initial_csi_index);
 
 void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
                            int eps_bearer_id, int rb_id,
diff --git a/openair2/RRC/NR/nr_rrc_types.h b/openair2/RRC/NR/nr_rrc_types.h
index 02495591a91daab0602c8c5b631018caa8cf4e4f..61f90e35727dc8b2f638870bcc0b089dcd019881 100644
--- a/openair2/RRC/NR/nr_rrc_types.h
+++ b/openair2/RRC/NR/nr_rrc_types.h
@@ -32,11 +32,11 @@
 #define RRC_TYPES_NR_H_
 
 typedef enum Rrc_State_NR_e {
-  RRC_STATE_INACTIVE_NR=0,
-  RRC_STATE_IDLE_NR,
+  RRC_STATE_IDLE_NR=0,
+  RRC_STATE_INACTIVE_NR,
   RRC_STATE_CONNECTED_NR,
 
-  RRC_STATE_FIRST_NR = RRC_STATE_INACTIVE_NR,
+  RRC_STATE_FIRST_NR = RRC_STATE_IDLE_NR,
   RRC_STATE_LAST_NR = RRC_STATE_CONNECTED_NR,
 } Rrc_State_NR_t;
 
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 6d430d722370c71d0c0351e0a87fade5d2f49d2d..802337257bfbeb19ad385ae1f432773fa5dd8273 100755
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -277,6 +277,8 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration
       parse_CG_ConfigInfo(rrc,CG_ConfigInfo,NULL);
     } else {
       struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_allocate_new_UE_context(rrc);
+      ue_context_p->ue_context.spCellConfig = calloc(1, sizeof(struct NR_SpCellConfig));
+      ue_context_p->ue_context.spCellConfig->spCellConfigDedicated = configuration->scd;
       LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p);
       rrc_add_nsa_user(rrc,ue_context_p,NULL);
     }
@@ -631,7 +633,7 @@ rrc_gNB_generate_defaultRRCReconfiguration(
   DRB_config->pdcp_Config = calloc(1, sizeof(*DRB_config->pdcp_Config));
   DRB_config->pdcp_Config->drb = calloc(1,sizeof(*DRB_config->pdcp_Config->drb));
   DRB_config->pdcp_Config->drb->discardTimer = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->discardTimer));
-  *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_ms30;
+  *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity;
   DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL));
   *DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
   DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL));
diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c
index 5ea02c78322f1b9d377f9d127baf6f1d9a20e2e6..e9741aaf786af383c85bdf51ceafc045794722d5 100644
--- a/openair2/RRC/NR/rrc_gNB_nsa.c
+++ b/openair2/RRC/NR/rrc_gNB_nsa.c
@@ -238,11 +238,21 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
                           cipher_algo,
                           NR_SecurityConfig__keyToUse_secondary);
   }
-  fill_default_reconfig(carrier->servingcellconfigcommon,
+  if (ue_context_p->ue_context.spCellConfig) {
+    fill_default_reconfig(carrier->servingcellconfigcommon,
+                        ue_context_p->ue_context.spCellConfig->spCellConfigDedicated,
                         reconfig_ies,
                         ue_context_p->ue_context.secondaryCellGroup,
                         carrier->pdsch_AntennaPorts,
                         carrier->initial_csi_index[rrc->Nb_ue]);
+  } else {
+    fill_default_reconfig(carrier->servingcellconfigcommon,
+                        NULL,
+                        reconfig_ies,
+                        ue_context_p->ue_context.secondaryCellGroup,
+                        carrier->pdsch_AntennaPorts,
+                        carrier->initial_csi_index[rrc->Nb_ue]);
+  }
   ue_context_p->ue_id_rnti = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
   NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config));
   memset((void *)CG_Config,0,sizeof(*CG_Config));
@@ -327,7 +337,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
                               1024);
     X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3;
     itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding
-  } else if (get_softmodem_params()->do_ra) {
+  } else if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) {
     PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, ue_context_p->ue_id_rnti, 0, 0,rrc->module_id);
   }
 
diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c
index ab3f19227622cbcb9b26f3339bfc448fcdc32997..8f3993229e23442b0a199cfb174893b43c43cb7e 100644
--- a/openair2/RRC/NR/rrc_gNB_reconfig.c
+++ b/openair2/RRC/NR/rrc_gNB_reconfig.c
@@ -31,6 +31,7 @@
 #define RRC_GNB_NSA_C
 
 #include "NR_ServingCellConfigCommon.h"
+#include "NR_ServingCellConfig.h"
 #include "NR_RRCReconfiguration.h"
 #include "NR_RRCReconfiguration-IEs.h"
 #include "NR_CellGroupConfig.h"
@@ -135,7 +136,7 @@ void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0) {
   // FIXME: update values from TS38.213 Section 10.1 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE aggregation level for CSS sets configured by searchSpaceSIB1
   ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0;
   ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0;
-  ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1;
+  ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2;
   ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0;
   ss0->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0;
 
@@ -143,6 +144,7 @@ void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0) {
 }
 
 void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
+                                     NR_ServingCellConfig_t *servingcellconfigdedicated,
                                      NR_CellGroupConfig_t *secondaryCellGroup,
                                      int scg_id,
                                      int servCellIndex,
@@ -172,7 +174,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
   secondaryCellGroup->cellGroupId = scg_id;
   NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig));
   nr_rlc_bearer_init(RLC_BearerConfig);
-  if (get_softmodem_params()->do_ra)
+  if (get_softmodem_params()->do_ra || get_softmodem_params()->sa)
     nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional);
   else
     nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am);
@@ -285,7 +287,11 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
   secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1 = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1));
   secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1->t311 = NR_RLF_TimersAndConstants__ext1__t311_ms30000;
   secondaryCellGroup->spCellConfig->rlmInSyncOutOfSyncThreshold                   = NULL;
-  secondaryCellGroup->spCellConfig->spCellConfigDedicated = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated));
+  if (servingcellconfigdedicated) {
+    secondaryCellGroup->spCellConfig->spCellConfigDedicated = servingcellconfigdedicated;
+  } else {
+    secondaryCellGroup->spCellConfig->spCellConfigDedicated = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated));
+  }
   secondaryCellGroup->spCellConfig->spCellConfigDedicated->tdd_UL_DL_ConfigurationDedicated = NULL;
   secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP));
   secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdcch_Config=NULL;
@@ -460,9 +466,15 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
 #endif
 
  secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList= NULL;
- secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList));
+ 
+ NR_BWP_Downlink_t *bwp = NULL;
+ if (servingcellconfigdedicated) {
+   bwp=servingcellconfigdedicated->downlinkBWP_ToAddModList->list.array[0];
+ } else {
+   secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList));
 
- NR_BWP_Downlink_t *bwp=calloc(1,sizeof(*bwp));
+   bwp=calloc(1,sizeof(*bwp));
+ }
  bwp->bwp_Id=1;
  bwp->bwp_Common=calloc(1,sizeof(*bwp->bwp_Common));
  // copy common BWP size from initial BWP except for bandwdith
@@ -577,8 +589,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
    ASN_SEQUENCE_ADD(&bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,pdschi);
  }
 
- bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated));
-
+ if (!servingcellconfigdedicated) {
+   bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated));
+ }
  bwp->bwp_Dedicated->pdcch_Config=calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config));
  bwp->bwp_Dedicated->pdcch_Config->present = NR_SetupRelease_PDCCH_Config_PR_setup;
  bwp->bwp_Dedicated->pdcch_Config->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config->choice.setup));
@@ -626,113 +639,30 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
 
  bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToReleaseList = NULL;
 
- bwp->bwp_Dedicated->pdsch_Config = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config));
+ if (!servingcellconfigdedicated) {
+  bwp->bwp_Dedicated->pdsch_Config = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config));
 
   bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup;
   bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup));
-  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL;
   bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA));
   bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup;
 
- bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup));
+  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup));
+ }
+ bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL;
 
  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=NULL;
  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength=NULL;
  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID0=NULL;
  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID1=NULL;
- bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL;
-
+ if (!servingcellconfigdedicated) {
+   bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL;
+ }
  bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition));
  *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0;
 
- //bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=NULL;
  bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList));
 
-#if 0
- bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList));
-
- NR_TCI_State_t*tcid0=calloc(1,sizeof(*tcid0));
- tcid0->tci_StateId=0;
- tcid0->qcl_Type1.cell=NULL;
- tcid0->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid0->qcl_Type1.bwp_Id));
- *tcid0->qcl_Type1.bwp_Id=1;
- tcid0->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs;
- tcid0->qcl_Type1.referenceSignal.choice.csi_rs = 2;
- tcid0->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA;
- ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid0);
-
- NR_TCI_State_t*tcid1=calloc(1,sizeof(*tcid1));
- tcid1->tci_StateId=0;
- tcid1->qcl_Type1.cell=NULL;
- tcid1->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid1->qcl_Type1.bwp_Id));
- *tcid1->qcl_Type1.bwp_Id=1;
- tcid1->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs;
- tcid1->qcl_Type1.referenceSignal.choice.csi_rs = 6;
- tcid1->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA;
- ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid1);
-
- NR_TCI_State_t*tcid2=calloc(1,sizeof(*tcid2));
- tcid2->tci_StateId=2;
- tcid2->qcl_Type1.cell=NULL;
- tcid2->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid2->qcl_Type1.bwp_Id));
- *tcid2->qcl_Type1.bwp_Id=1;
- tcid2->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs;
- tcid2->qcl_Type1.referenceSignal.choice.csi_rs = 10;
- tcid2->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA;
- ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid2);
-
- NR_TCI_State_t*tcid3=calloc(1,sizeof(*tcid3));
- tcid3->tci_StateId=3;
- tcid3->qcl_Type1.cell=NULL;
- tcid3->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid3->qcl_Type1.bwp_Id));
- *tcid3->qcl_Type1.bwp_Id=1;
- tcid3->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs;
- tcid3->qcl_Type1.referenceSignal.choice.csi_rs = 14;
- tcid3->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA;
- ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid3);
-
- NR_TCI_State_t*tcid4=calloc(1,sizeof(*tcid4));
- tcid4->tci_StateId=4;
- tcid4->qcl_Type1.cell=NULL;
- tcid4->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid4->qcl_Type1.bwp_Id));
- *tcid4->qcl_Type1.bwp_Id=1;
- tcid4->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs;
- tcid4->qcl_Type1.referenceSignal.choice.csi_rs = 18;
- tcid4->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA;
- ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid4);
-
- NR_TCI_State_t*tcid5=calloc(1,sizeof(*tcid5));
- tcid5->tci_StateId=5;
- tcid5->qcl_Type1.cell=NULL;
- tcid5->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid5->qcl_Type1.bwp_Id));
- *tcid5->qcl_Type1.bwp_Id=1;
- tcid5->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs;
- tcid5->qcl_Type1.referenceSignal.choice.csi_rs = 22;
- tcid5->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA;
- ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid5);
-
- NR_TCI_State_t*tcid6=calloc(1,sizeof(*tcid6));
- tcid6->tci_StateId=6;
- tcid6->qcl_Type1.cell=NULL;
- tcid6->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid6->qcl_Type1.bwp_Id));
- *tcid6->qcl_Type1.bwp_Id=1;
- tcid6->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs;
- tcid6->qcl_Type1.referenceSignal.choice.csi_rs = 26;
- tcid6->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA;
- ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid6);
-
- NR_TCI_State_t*tcid7=calloc(1,sizeof(*tcid7));
- tcid7->tci_StateId=7;
- tcid7->qcl_Type1.cell=NULL;
- tcid7->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid7->qcl_Type1.bwp_Id));
- *tcid7->qcl_Type1.bwp_Id=1;
- tcid7->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs;
- tcid7->qcl_Type1.referenceSignal.choice.csi_rs = 30;
- tcid7->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA;
- ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid7);
-#endif
-
-
  n_ssb = 0;
  NR_TCI_State_t *tcid[64];
  for (int i=0;i<64;i++) {
@@ -828,8 +758,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  *bwp->bwp_Dedicated->radioLinkMonitoringConfig->choice.setup->beamFailureDetectionTimer = NR_RadioLinkMonitoringConfig__beamFailureDetectionTimer_pbfd2;
 #endif
  
- ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list,bwp);
-
+ if (!servingcellconfigdedicated) {
+   ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list,bwp);
+ }
  secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id));
  
  *secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id=1;
@@ -837,26 +768,38 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = NULL;
  secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id));
  *secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = 1;
- secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig));
+
+ if (!servingcellconfigdedicated) {
+   secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig));
+ }
 
  NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1,sizeof(*initialUplinkBWP));
  secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP = initialUplinkBWP;
  initialUplinkBWP->pucch_Config = NULL;
  initialUplinkBWP->pusch_Config = calloc(1,sizeof(*initialUplinkBWP->pusch_Config));
  initialUplinkBWP->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup;
- NR_PUSCH_Config_t *pusch_Config = calloc(1,sizeof(*pusch_Config));
+ NR_PUSCH_Config_t *pusch_Config = NULL;
+ if (servingcellconfigdedicated) {
+   pusch_Config = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup;
+ } else {
+   pusch_Config = calloc(1,sizeof(*pusch_Config));
+ }
  initialUplinkBWP->pusch_Config->choice.setup = pusch_Config;
  pusch_Config->txConfig=calloc(1,sizeof(*pusch_Config->txConfig));
  *pusch_Config->txConfig= NR_PUSCH_Config__txConfig_codebook;
  pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA = NULL;
- pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB));
- pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup;
- pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup));
+ if (!servingcellconfigdedicated) {
+  pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB));
+  pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup;
+  pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup));
+ }
  NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup;
  NR_DMRS_UplinkConfig->dmrs_Type = NULL;
  NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = calloc(1,sizeof(*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition));
  *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos0;
- NR_DMRS_UplinkConfig->phaseTrackingRS=NULL;
+ if (!servingcellconfigdedicated) {
+   NR_DMRS_UplinkConfig->phaseTrackingRS=NULL;
+ }
  NR_DMRS_UplinkConfig->maxLength=NULL;
  NR_DMRS_UplinkConfig->transformPrecodingDisabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingDisabled));
  NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0 = NULL;
@@ -903,7 +846,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  pusch_Config->tp_pi2BPSK=NULL;
 
  /*------------------------------TRANSFORM PRECODING- -----------------------------------------------------------------------*/
- 
+
  uint8_t transform_precoding = NR_PUSCH_Config__transformPrecoder_disabled;
 
  // TBD: configure this from .conf file, Dedicated params cannot yet be configured in .conf file.
@@ -918,20 +861,20 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
   if (servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder != NULL)
     transform_precoding = NR_PUSCH_Config__transformPrecoder_enabled;
  }
- else 
+ else
     transform_precoding = *pusch_Config->transformPrecoder;
-    
- 
+
+
  if (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled ) {
     /* Enable DMRS uplink config for transform precoding enabled */
     NR_DMRS_UplinkConfig->transformPrecodingEnabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingEnabled));
     NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity = NULL;
-    NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping = NULL; 
+    NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping = NULL;
     NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceHopping = NULL;
-    NR_DMRS_UplinkConfig->transformPrecodingEnabled->ext1 = NULL; 
+    NR_DMRS_UplinkConfig->transformPrecodingEnabled->ext1 = NULL;
 
     LOG_I(RRC,"TRANSFORM PRECODING ENABLED......\n");
- 
+
   }
  /*----------------------------------------------------------------------------------------------------------------------------*/ 
 
@@ -992,8 +935,13 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceToAddModList->list,srs_res0);
 
  secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList = NULL;
- secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList));
- NR_BWP_Uplink_t *ubwp = calloc(1,sizeof(*ubwp));
+ NR_BWP_Uplink_t *ubwp = NULL;
+ if (servingcellconfigdedicated) {
+   ubwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0];
+ } else {
+   secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList));
+   ubwp = calloc(1,sizeof(*ubwp));
+ }
  ubwp->bwp_Id=1;
  ubwp->bwp_Common = calloc(1,sizeof(*ubwp->bwp_Common));
  // copy bwp_Common from Initial UL BWP except for bandwidth
@@ -1006,7 +954,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  ubwp->bwp_Common->pusch_ConfigCommon = servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon;
  ubwp->bwp_Common->pucch_ConfigCommon = servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon;
  
- ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated));
+ if (!servingcellconfigdedicated) {
+   ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated));
+ }
  ubwp->bwp_Dedicated->pucch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pucch_Config));
  ubwp->bwp_Dedicated->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup;
  NR_PUCCH_Config_t *pucch_Config = calloc(1,sizeof(*pucch_Config));
@@ -1136,11 +1086,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  ASN_SEQUENCE_ADD(&pucch_Config->pucch_PowerControl->p0_Set->list,p00);
  pucch_Config->pucch_PowerControl->pathlossReferenceRSs = NULL;
 
- // copy pusch_Config from dedicated initialBWP
- ubwp->bwp_Dedicated->pusch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pusch_Config));
- ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup;
- ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config;
-
+ if (!servingcellconfigdedicated) {
+   // copy pusch_Config from dedicated initialBWP
+   ubwp->bwp_Dedicated->pusch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pusch_Config));
+   ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup;
+   ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config;
+ }
  ubwp->bwp_Dedicated->configuredGrantConfig = NULL;
  ubwp->bwp_Dedicated->srs_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->srs_Config));
  ubwp->bwp_Dedicated->srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup;
@@ -1148,7 +1099,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
 
  ubwp->bwp_Dedicated->beamFailureRecoveryConfig = NULL;
 
- ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp);
+ if (!servingcellconfigdedicated) {
+   ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp);
+ }
 
  secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id));
  *secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = 1;
@@ -1300,7 +1253,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  secondaryCellGroup->spCellConfig->spCellConfigDedicated->servingCellMO=NULL;
 
 }
+
 void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
+                           NR_ServingCellConfig_t *servingcellconfigdedicated,
                            NR_RRCReconfiguration_IEs_t *reconfig,
                            NR_CellGroupConfig_t *secondaryCellGroup,
                            int n_physical_antenna_ports,
@@ -1311,7 +1266,7 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
   // radioBearerConfig
   reconfig->radioBearerConfig=NULL;
   // secondaryCellGroup
-  fill_default_secondaryCellGroup(servingcellconfigcommon,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index);
+  fill_default_secondaryCellGroup(servingcellconfigcommon,servingcellconfigdedicated,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index);
   xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
 
   char scg_buffer[1024];
@@ -1347,7 +1302,7 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
   drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config));
   drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb));
   drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer));
-  *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_ms30;
+  *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity;
   drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL));
   *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
   drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL));
diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c
index 5ad6746696bb98b8829331336af83e9c5dc2b349..e21859ded88949799a20436b2e64eab801e0fc46 100644
--- a/openair2/RRC/NR_UE/L2_interface_ue.c
+++ b/openair2/RRC/NR_UE/L2_interface_ue.c
@@ -33,6 +33,7 @@
 #include "rrc_defs.h"
 #include "rrc_proto.h"
 #include "assertions.h"
+#include "rrc_vars.h"
 
 typedef uint32_t channel_t;
 
@@ -50,7 +51,7 @@ nr_mac_rrc_data_ind_ue(
         AssertFatal( nr_rrc_ue_decode_NR_BCCH_BCH_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-BCH error!\n");
         break;
       case NR_BCCH_DL_SCH:
-        AssertFatal( nr_rrc_ue_decode_NR_SIB1_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-DLSCH error!\n");
+        AssertFatal( nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len, 0, 0) == 0, "UE decode BCCH-DL-SCH error!\n");
         break;
       default:
         break;
@@ -59,13 +60,36 @@ nr_mac_rrc_data_ind_ue(
     return(0);
 }
 
-int8_t mac_rrc_nr_data_req_ue(const module_id_t Mod_idP,
+int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
                               const int         CC_id,
+                              const uint8_t     gNB_id,
                               const frame_t     frameP,
                               const rb_id_t     Srb_id,
-                              uint8_t *const    buffer_pP ){
+                              uint8_t           *buffer_pP){
 
-  // todo
+  switch(Srb_id){
+
+    case CCCH:
+
+      // TODO: Enable timer T300
+      //NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_active = 1;
+      //NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_cnt = 0;
+
+      LOG_D(NR_RRC, "nr_mac_rrc_data_req_ue: Payload size = %i\n", NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size);
+      memcpy(buffer_pP, (uint8_t*)NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.Payload, NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size);
+      for(int i = 0; i<NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size; i++) {
+        LOG_D(NR_RRC,"(%i): %i\n", i, buffer_pP[i]);
+      }
+
+      return NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size;
+
+    case DCCH:
+      AssertFatal(1==0, "SRB1 not implemented yet!\n");
+    case DCCH1:
+      AssertFatal(1==0, "SRB2 not implemented yet!\n");
+    default:
+      AssertFatal(1==0, "Invalid SRB id!\n");
+  }
 
   return 0;
 }
diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c
index 460dbf1d22b5f06a6ff41b9da7f2d2d370cec00a..f373d7423007fa9e159f615e4ac9de8e312159e2 100644
--- a/openair2/RRC/NR_UE/rrc_UE.c
+++ b/openair2/RRC/NR_UE/rrc_UE.c
@@ -414,6 +414,18 @@ NR_UE_RRC_INST_t* openair_rrc_top_init_ue_nr(char* rrc_config_path){
     for(nr_ue=0;nr_ue<NB_NR_UE_INST;nr_ue++){
       // fill UE-NR-Capability @ UE-CapabilityRAT-Container here.
       NR_UE_rrc_inst[nr_ue].selected_plmn_identity = 1;
+
+      // TODO: Put the appropriate list of SIBs
+      NR_UE_rrc_inst[nr_ue].requested_SI_List.buf = CALLOC(1,4);
+      NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[0] = SIB2 | SIB3 | SIB5;  // SIB2 - SIB9
+      NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[1] = 0;                   // SIB10 - SIB17
+      NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[2] = 0;                   // SIB18 - SIB25
+      NR_UE_rrc_inst[nr_ue].requested_SI_List.buf[3] = 0;                   // SIB26 - SIB32
+      NR_UE_rrc_inst[nr_ue].requested_SI_List.size= 4;
+      NR_UE_rrc_inst[nr_ue].requested_SI_List.bits_unused= 0;
+
+      NR_UE_rrc_inst[nr_ue].ra_trigger = RA_NOT_RUNNING;
+
       //  init RRC lists
       RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].RLC_Bearer_Config_list, NR_maxLC_ID);
       RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].SchedulingRequest_list, NR_maxNrofSR_ConfigPerCellGroup);
@@ -835,7 +847,7 @@ int nr_decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index
           // After SI is received, prepare RRCConnectionRequest
           if (NR_UE_rrc_inst[ctxt_pP->module_id].MBMS_flag < 3) // see -Q option
             if (AMF_MODE_ENABLED) {
-              rrc_ue_generate_RRCSetupRequest( ctxt_pP, gNB_index );
+              nr_rrc_ue_generate_RRCSetupRequest( ctxt_pP->module_id, gNB_index );
             }
 
           if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State == NR_RRC_IDLE) {
@@ -1029,205 +1041,120 @@ int nr_decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index
   return 0;
 }
 
-int nr_decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, const uint8_t rsrq, const uint8_t rsrp ) {
-  NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index];
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN );
-  LOG_I( RRC, "[UE %d] : Dumping SIB 1\n", ctxt_pP->module_id );
-  const int n = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count;
-  for (int i = 0; i < n; ++i) {
-    NR_PLMN_Identity_t *PLMN_identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[i]->plmn_IdentityList.list.array[0];
-    int mccdigits = PLMN_identity->mcc->list.count;
-    int mncdigits = PLMN_identity->mnc.list.count;
-
-    int mcc;
-    if (mccdigits == 2) {
-      mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1];
-    } else {
-      mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2];
-    }
+int8_t check_requested_SI_List(module_id_t module_id, BIT_STRING_t requested_SI_List, NR_SIB1_t sib1) {
 
-    int mnc;
-    if (mncdigits == 2) {
-      mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1];
-    } else {
-      mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2];
-    }
-
-    LOG_I( RRC, "PLMN %d MCC %0*d, MNC %0*d\n", i + 1, mccdigits, mcc, mncdigits, mnc);
-    // search internal table for provider name
-    int plmn_ind = 0;
+  if(sib1.si_SchedulingInfo) {
 
-    while (plmn_data[plmn_ind].mcc > 0) {
-      if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) {
-        LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short );
-        break;
-      }
+    bool SIB_to_request[32] = {};
 
-      plmn_ind++;
+    LOG_D(RRC, "SIBs broadcasting: ");
+    for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) {
+      printf("SIB%li  ", sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type + 2);
     }
-  }
-  LOG_I( RRC, "TAC 0x%04x\n",
-         ((sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->size == 2)?((sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->buf[0]<<8) + sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->buf[1]):0));
-  LOG_I( RRC, "cellReservedForOperatorUse                 : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse,
-         nr_SIBreserved(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse) );
-
-  LOG_I( RRC, "cellAccessRelatedInfo.cellIdentity         : raw:%"PRIu32" decoded:%02x.%02x.%02x.%02x\n",
-         BIT_STRING_to_uint32( &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity ),
-         sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[0],
-         sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[1],
-         sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[2],
-         sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[3] >> sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.bits_unused);
-  //LOG_I( RRC, "cellAccessRelatedInfo.cellBarred           : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.cellBarred, SIBbarred(sib1->cellAccessRelatedInfo.cellBarred) );
-  //LOG_I( RRC, "cellAccessRelatedInfo.intraFreqReselection : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.intraFreqReselection, SIBallowed(sib1->cellAccessRelatedInfo.intraFreqReselection) );
-  //LOG_I( RRC, "cellAccessRelatedInfo.csg_Indication       : %d\n", sib1->cellAccessRelatedInfo.csg_Indication );
-
-  //if (sib1->cellAccessRelatedInfo.csg_Identity)
-  //  LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity         : %"PRIu32"\n", BIT_STRING_to_uint32(sib1->cellAccessRelatedInfo.csg_Identity) );
-  //else
-  //  LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity         : not defined\n" );
-
-  LOG_I( RRC, "cellSelectionInfo.q_RxLevMin               : %ld\n", sib1->cellSelectionInfo->q_RxLevMin );
-
-  if (sib1->cellSelectionInfo->q_RxLevMinOffset)
-    LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset         : %ld\n", *sib1->cellSelectionInfo->q_RxLevMinOffset );
-  else
-    LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset         : not defined\n" );
+    printf("\n");
 
-  //if (sib1->p_Max)
-  //  LOG_I( RRC, "p_Max                                      : %ld\n", *sib1->p_Max );
-  //else
-  //  LOG_I( RRC, "p_Max                                      : not defined\n" );
+    LOG_D(RRC, "SIBs needed by UE: ");
+    for(int j = 0; j < 8*requested_SI_List.size; j++) {
+      if( ((requested_SI_List.buf[j/8]>>(j%8))&1) == 1) {
 
-  //LOG_I( RRC, "freqBandIndicator                          : %ld\n", sib1->freqBandIndicator );
+        printf("SIB%i  ", j + 2);
 
-  if (sib1->si_SchedulingInfo->schedulingInfoList.list.count > 0) {
-    for (int i=0; i<sib1->si_SchedulingInfo->schedulingInfoList.list.count; i++) {
-      LOG_I( RRC, "si_Periodicity[%d]                          : %s\n", i, SIBPeriod[min(sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->si_Periodicity,7)]);
+        SIB_to_request[j] = true;
+        for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) {
+          if(sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type == j) {
+            SIB_to_request[j] = false;
+            break;
+          }
+        }
 
-      if (sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count > 0) {
-        char temp[32 * sizeof(SIBType[0])] = {0}; // maxSIB==32
+      }
+    }
+    printf("\n");
 
-        for (int j=0; j<sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count; j++) {
-          sprintf( temp + j*sizeof(SIBType[0]), "%*s ", (int)sizeof(SIBType[0])-1, SIBType[min(sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.array[0]->type,11)] );
-        }
+    LOG_D(RRC, "SIBs to request by UE: ");
+    bool do_ra = false;
+    for(int j = 0; j < 8*requested_SI_List.size; j++) {
+      if(SIB_to_request[j]) {
+        printf("SIB%i  ", j + 2);
+        do_ra = true;
+      }
+    }
+    printf("\n");
 
-        LOG_I( RRC, "siSchedulingInfoSIBType[%d]                 : %s\n", i, temp );
+    if(do_ra) {
+
+      NR_UE_rrc_inst[module_id].ra_trigger = REQUEST_FOR_OTHER_SI;
+      get_softmodem_params()->do_ra = 1;
+
+      if(sib1.si_SchedulingInfo->si_RequestConfig) {
+        LOG_D(RRC, "Trigger contention-free RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger);
       } else {
-        LOG_I( RRC, "mapping list %d is null\n", i );
+        LOG_D(RRC, "Trigger contention-based RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger);
       }
+
     }
-  } else {
-    LOG_E( RRC, "siSchedulingInfoPeriod[0]                  : PROBLEM!!!\n" );
-    return -1;
-  }
 
-  if (sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon) {
-      //TODO
   }
 
-  LOG_I( RRC, "siWindowLength                             : %s\n", siWindowLength[min(sib1->si_SchedulingInfo->si_WindowLength,8)] );
-  //LOG_I( RRC, "systemInfoValueTag                         : %ld\n", sib1->systemInfoValueTag );
-  NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIperiod     = siPeriod_int[sib1->si_SchedulingInfo->schedulingInfoList.list.array[0]->si_Periodicity];
-  NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIwindowsize = siWindowLength_int[sib1->si_SchedulingInfo->si_WindowLength];
-  LOG_I( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params gNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
-         ctxt_pP->module_id, gNB_index, ctxt_pP->module_id );
-  //rrc_mac_config_req_ue
-  LOG_I(RRC,"Setting SIStatus bit 0 to 1\n");
-  NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus = 1;
-  //NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIB1systemInfoValueTag = sib1->systemInfoValueTag;
+  return 0;
+}
 
-  if (AMF_MODE_ENABLED) {
-    int cell_valid = 0;
-
-    //if (sib1->cellAccessRelatedInfo.cellBarred == LTE_SystemInformationBlockType1__cellAccessRelatedInfo__cellBarred_notBarred) {
-      /* Cell is not barred */
-      int plmn;
-      int plmn_number;
-      plmn_number = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count;
-
-      /* Compare requested PLMN and PLMNs from SIB1*/
-      for (plmn = 0; plmn < plmn_number; plmn++) {
-        NR_PLMN_Identity_t *plmn_Identity;
-        plmn_Identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[plmn]->plmn_IdentityList.list.array[0];
-
-        if (
-          (
-            (plmn_Identity->mcc == NULL)
-            ||
-            (
-              (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit1 == *(plmn_Identity->mcc->list.array[0])) &&
-              (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit2 == *(plmn_Identity->mcc->list.array[1])) &&
-              (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit3 == *(plmn_Identity->mcc->list.array[2]))
-            )
-          )
-          &&
-          (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit1 == *(plmn_Identity->mnc.list.array[0]))
-          &&
-          (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit2 == *(plmn_Identity->mnc.list.array[1]))
-          &&
-          (
-            ((NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == 0xf) && (plmn_Identity->mnc.list.count == 2))
-            ||
-            (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == *(plmn_Identity->mnc.list.array[2]))
-          )
-        ) {
-          /* PLMN match, send a confirmation to NAS */
-          MessageDef  *msg_p;
-          msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_CELL_SELECTION_CNF);
-          NAS_CELL_SELECTION_CNF (msg_p).errCode = AS_SUCCESS;
-          NAS_CELL_SELECTION_CNF (msg_p).cellID = BIT_STRING_to_uint32(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity);
-          NAS_CELL_SELECTION_CNF (msg_p).tac = BIT_STRING_to_uint16(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode);
-          NAS_CELL_SELECTION_CNF (msg_p).rat = 0xFF;
-          NAS_CELL_SELECTION_CNF (msg_p).rsrq = rsrq;
-          NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp;
-          itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p);
-          cell_valid = 1;
-          NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity = plmn + 1;
-          break;
-        }
-      }
-    //}
+int8_t nr_rrc_ue_generate_ra_msg(module_id_t module_id, uint8_t gNB_index) {
 
-    if (cell_valid == 0) {
-      /* Cell can not be used, ask PHY to try the next one */
-      MessageDef  *msg_p;
-      msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, PHY_FIND_NEXT_CELL_REQ);
-      itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p);
-      LOG_E(RRC,
-            "Synched with a cell, but PLMN doesn't match our SIM "
-            "(selected_plmn_identity %ld), the message PHY_FIND_NEXT_CELL_REQ "
-            "is sent but lost in current UE implementation!\n",
-            NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity);
-    }
+  switch(NR_UE_rrc_inst[module_id].ra_trigger){
+    case INITIAL_ACCESS_FROM_RRC_IDLE:
+      // After SIB1 is received, prepare RRCConnectionRequest
+      nr_rrc_ue_generate_RRCSetupRequest(module_id,gNB_index);
+      break;
+    case RRC_CONNECTION_REESTABLISHMENT:
+      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
+      break;
+    case DURING_HANDOVER:
+      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
+      break;
+    case NON_SYNCHRONISED:
+      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
+      break;
+    case TRANSITION_FROM_RRC_INACTIVE:
+      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
+      break;
+    case TO_ESTABLISH_TA:
+      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
+      break;
+    case REQUEST_FOR_OTHER_SI:
+      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
+      break;
+    case BEAM_FAILURE_RECOVERY:
+      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
+      break;
+    default:
+      AssertFatal(1==0, "Invalid ra_trigger value!\n");
+      break;
   }
 
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_OUT );
   return 0;
 }
 
-int nr_decode_BCCH_DLSCH_Message(
-  const protocol_ctxt_t *const ctxt_pP,
-  const uint8_t                gNB_index,
-  uint8_t               *const Sdu,
-  const uint8_t                Sdu_len,
-  const uint8_t                rsrq,
-  const uint8_t                rsrp ) {
+int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(
+    module_id_t module_id,
+    const uint8_t gNB_index,
+    uint8_t *const Sdu,
+    const uint8_t Sdu_len,
+    const uint8_t rsrq,
+    const uint8_t rsrp) {
+
   NR_BCCH_DL_SCH_Message_t *bcch_message = NULL;
-  NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index];
+  NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index];
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN );
 
-  if (((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 1) &&  // SIB1 received
-      (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count)) {
+  if (((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 1) &&  // SIB1 received
+      (NR_UE_rrc_inst[module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count)) {
     // to prevent memory bloating
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT );
     return 0;
   }
 
-  nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR );
-
-  if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
-    xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message,(void *)bcch_message );
-  }
+  nr_rrc_set_sub_state( module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR );
 
   asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
                             &asn_DEF_NR_BCCH_DL_SCH_Message,
@@ -1235,11 +1162,15 @@ int nr_decode_BCCH_DLSCH_Message(
                             (const void *)Sdu,
                             Sdu_len );
 
+  if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
+    xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message,(void *)bcch_message );
+  }
+
   if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
-    LOG_E( RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n",
-           ctxt_pP->module_id,
+    LOG_E( NR_RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n",
+           module_id,
            dec_rval.consumed );
-    log_dump(RRC, Sdu, Sdu_len, LOG_DUMP_CHAR,"   Received bytes:\n" );
+    log_dump(NR_RRC, Sdu, Sdu_len, LOG_DUMP_CHAR,"   Received bytes:\n" );
     // free the memory
     SEQUENCE_free( &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message, 1 );
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT );
@@ -1249,35 +1180,53 @@ int nr_decode_BCCH_DLSCH_Message(
   if (bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1) {
     switch (bcch_message->message.choice.c1->present) {
       case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1:
-        if ((ctxt_pP->frame % 2) == 0) {
-          // even frame
-          if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 0) {
-            NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index];
-            memcpy( (void *)sib1,
-                    (void *)bcch_message->message.choice.c1->choice.systemInformationBlockType1,
-                    sizeof(NR_SIB1_t) );
-            LOG_D( RRC, "[UE %"PRIu8"] Decoding First SIB1\n", ctxt_pP->module_id );
-            nr_decode_SIB1( ctxt_pP, gNB_index, rsrq, rsrp );
+        if ((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 0) {
+          NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index];
+          if(sib1 != NULL){
+            SEQUENCE_free(&asn_DEF_NR_SIB1, (void *)sib1, 1 );
           }
-        }
 
+          sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1;
+          if (*(int64_t*)sib1 != 1) {
+            NR_UE_rrc_inst[module_id].sib1[gNB_index] = sib1;
+            if( g_log->log_component[NR_RRC].level >= OAILOG_DEBUG ) {
+              xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) NR_UE_rrc_inst[module_id].sib1[gNB_index]);
+            }
+            LOG_I(NR_RRC, "SIB1 decoded\n");
+
+            // FIXME: improve condition for the RA trigger
+            // Check for on-demand not broadcasted SI
+            check_requested_SI_List(module_id, NR_UE_rrc_inst[module_id].requested_SI_List, *sib1);
+            if( nr_rrc_get_state(module_id) == RRC_STATE_IDLE_NR ) {
+              NR_UE_rrc_inst[module_id].ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE;
+              // TODO: remove flag after full RA procedures implemented
+              get_softmodem_params()->do_ra = 1;
+            }
+            nr_rrc_ue_generate_ra_msg(module_id,gNB_index);
+          } else {
+            LOG_E(NR_RRC, "SIB1 not decoded\n");
+          }
+        }
         break;
 
       case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation:
-        if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 1) {
+        if ((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 1) {
+          LOG_W(NR_RRC, "Decoding SI not implemented yet\n");
+          // TODO: Decode SI
+          /*
           // SIB1 with schedulingInfoList is available
-          NR_SystemInformation_t *si = NR_UE_rrc_inst[ctxt_pP->module_id].si[gNB_index];
+          NR_SystemInformation_t *si = NR_UE_rrc_inst[module_id].si[gNB_index];
+
           memcpy( si,
                   bcch_message->message.choice.c1->choice.systemInformation,
                   sizeof(NR_SystemInformation_t) );
-          LOG_I( RRC, "[UE %"PRIu8"] Decoding SI for frameP %"PRIu32"\n",
-                 ctxt_pP->module_id,
-                 ctxt_pP->frame );
+          LOG_I(NR_RRC, "[UE %"PRIu8"] Decoding SI\n", module_id);
           nr_decode_SI( ctxt_pP, gNB_index );
-          //if (nfapi_mode == 3)
-          //UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1;
-        }
 
+          if (nfapi_mode == 3)
+            UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1;
+           */
+        }
         break;
 
       case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
@@ -1286,10 +1235,10 @@ int nr_decode_BCCH_DLSCH_Message(
     }
   }
 
-  if (nr_rrc_get_sub_state(ctxt_pP->module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR) {
+  if (nr_rrc_get_sub_state(module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR) {
     //if ( (NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data != NULL) || (!AMF_MODE_ENABLED)) {
-      rrc_ue_generate_RRCSetupRequest(ctxt_pP, 0);
-      nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_CONNECTING );
+      nr_rrc_ue_generate_RRCSetupRequest(module_id, 0);
+      nr_rrc_set_sub_state( module_id, RRC_SUB_STATE_IDLE_CONNECTING );
     //}
   }
 
@@ -1489,41 +1438,6 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB
   return rval;
 }
 
-/*brief decode SIB1 message*/
-int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) {
-
-  NR_BCCH_DL_SCH_Message_t *bcch_message = NULL;
-
-  asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
-                                                  &asn_DEF_NR_BCCH_DL_SCH_Message,
-                                                  (void **)&bcch_message,
-                                                  (const void *)bufferP,
-                                                  buffer_len);
-
-  if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) {
-    LOG_D(RRC,"NR_BCCH_DL_SCH decode error\n");
-    SEQUENCE_free( &asn_DEF_NR_BCCH_DL_SCH_Message, (void *)bcch_message, 1 );
-    return -1;
-  }
-  else {
-    NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index];
-    if(sib1 != NULL){
-      SEQUENCE_free(&asn_DEF_NR_BCCH_BCH_Message, (void *)sib1, 1 );
-    }
-    sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1;
-    if (*(int64_t*)sib1 != 1) {
-      LOG_I(RRC, "SIB1 decoded\n");
-      if( g_log->log_component[RRC].level >= OAILOG_DEBUG  )
-        xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1);
-    }
-    else
-       LOG_E(PHY, "sib1 is starting by 8 times 0\n");
-  }
-
-  return 0;
-}
-
-
 // from NR SRB3
 int8_t nr_rrc_ue_decode_NR_DL_DCCH_Message(
   const module_id_t module_id,
@@ -1784,10 +1698,10 @@ nr_rrc_ue_process_securityModeCommand(
 }
 
 //-----------------------------------------------------------------------------
-void rrc_ue_generate_RRCSetupRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ) {
+void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) {
   uint8_t i=0,rv[6];
 
-  if(NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size ==0) {
+  if(NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size ==0) {
     // Get RRCConnectionRequest, fill random for now
     // Generate random byte stream for contention resolution
     for (i=0; i<6; i++) {
@@ -1801,16 +1715,16 @@ void rrc_ue_generate_RRCSetupRequest( const protocol_ctxt_t *const ctxt_pP, cons
     }
 
     LOG_T(NR_RRC,"\n");
-    NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size =
-      do_RRCSetupRequest(
-        ctxt_pP->module_id,
-        (uint8_t *)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload,
-        rv);
-    LOG_I(NR_RRC,"[UE %d] : Frame %d, Logical Channel UL-CCCH (SRB0), Generating RRCSetupRequest (bytes %d, eNB %d)\n",
-          ctxt_pP->module_id, ctxt_pP->frame, NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index);
-
-    for (i=0; i<NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size; i++) {
-      LOG_T(NR_RRC,"%x.",NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload[i]);
+    NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size =
+       do_RRCSetupRequest(
+         module_id,
+         (uint8_t *)NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.Payload,
+         rv);
+    LOG_I(NR_RRC,"[UE %d] : Logical Channel UL-CCCH (SRB0), Generating RRCSetupRequest (bytes %d, gNB %d)\n",
+          module_id, NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index);
+
+    for (i=0; i<NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size; i++) {
+      LOG_T(NR_RRC,"%x.",NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.Payload[i]);
     }
 
     LOG_T(NR_RRC,"\n");
@@ -2560,7 +2474,7 @@ void *rrc_nrue_task( void *args_p ) {
               NR_RRC_MAC_BCCH_DATA_IND (msg_p).frame, NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index);
         //      PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_NO, NOT_A_RNTI, RRC_MAC_BCCH_DATA_IND (msg_p).frame, 0);
         PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NOT_A_RNTI, NR_RRC_MAC_BCCH_DATA_IND (msg_p).frame, 0,NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index);
-        nr_decode_BCCH_DLSCH_Message (&ctxt,
+        nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message (ctxt.module_id,
                                    NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index,
                                    NR_RRC_MAC_BCCH_DATA_IND (msg_p).sdu,
                                    NR_RRC_MAC_BCCH_DATA_IND (msg_p).sdu_size,
diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h
index 52bd6c564a6013ac74e842bed79cd2fccc0047f9..f4ce4746573b5e7e93a0805b88ec269fd81c9fa5 100644
--- a/openair2/RRC/NR_UE/rrc_defs.h
+++ b/openair2/RRC/NR_UE/rrc_defs.h
@@ -77,6 +77,30 @@ typedef struct OAI_NR_UECapability_s {
   NR_UE_NR_Capability_t *UE_NR_Capability;
 } OAI_NR_UECapability_t;
 
+typedef enum requested_SI_List_e {
+  SIB2  = 1,
+  SIB3  = 2,
+  SIB4  = 4,
+  SIB5  = 8,
+  SIB6  = 16,
+  SIB7  = 32,
+  SIB8  = 64,
+  SIB9  = 128
+} requested_SI_List_t;
+
+// 3GPP TS 38.300 Section 9.2.6
+typedef enum RA_trigger_e {
+  RA_NOT_RUNNING,
+  INITIAL_ACCESS_FROM_RRC_IDLE,
+  RRC_CONNECTION_REESTABLISHMENT,
+  DURING_HANDOVER,
+  NON_SYNCHRONISED,
+  TRANSITION_FROM_RRC_INACTIVE,
+  TO_ESTABLISH_TA,
+  REQUEST_FOR_OTHER_SI,
+  BEAM_FAILURE_RECOVERY,
+} RA_trigger_t;
+
 typedef struct NR_UE_RRC_INST_s {
 
     NR_MeasConfig_t        *meas_config;
@@ -99,10 +123,13 @@ typedef struct NR_UE_RRC_INST_s {
     NR_SRB_INFO_TABLE_ENTRY        Srb2[NB_CNX_UE];
 
     uint8_t                        MBMS_flag;
-	OAI_NR_UECapability_t          *UECap;
-    uint8_t 					   *UECapability;
+	  OAI_NR_UECapability_t          *UECap;
+    uint8_t 					             *UECapability;
     uint8_t                        UECapability_size;
 
+    RA_trigger_t                   ra_trigger;
+    BIT_STRING_t                   requested_SI_List;
+
     NR_SystemInformation_t         *si[NB_CNX_UE];
     NR_SIB1_t                      *sib1[NB_CNX_UE];
     NR_SIB2_t                      *sib2[NB_CNX_UE];
diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h
index 401924844172addc98a54e43da71463080b8ce21..0acf6db634fd757c525fd442eb860f6164e65f9f 100644
--- a/openair2/RRC/NR_UE/rrc_proto.h
+++ b/openair2/RRC/NR_UE/rrc_proto.h
@@ -86,12 +86,14 @@ int8_t nr_rrc_ue_process_radio_bearer_config(NR_RadioBearerConfig_t *radio_beare
    \param sdu_len       length of buffer*/
 int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message(const module_id_t module_id, const uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len);
 
-/**\brief decode NR SIB1 message
+/**\brief decode NR BCCH-DLSCH (SI) messages
    \param module_idP    module id
    \param gNB_index     gNB index
-   \param sduP          pointer to buffer of ASN message
-   \param sdu_len       length of buffer*/
-int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len);
+   \param sduP          pointer to buffer of ASN message BCCH-DLSCH
+   \param sdu_len       length of buffer
+   \param rsrq          RSRQ
+   \param rsrp          RSRP*/
+int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(const module_id_t module_id, const uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len, const uint8_t rsrq, const uint8_t rsrp);
 
 /**\brief Decode NR DCCH from gNB, sent from lower layer through SRB3
    \param module_id  module id
@@ -112,24 +114,25 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, cons
 /**\brief
    \param module_id  module id
    \param CC_id      component carrier id
+   \param gNB_index  gNB index
    \param frame_t    frameP
    \param rb_id_t    SRB id
    \param buffer_pP  pointer to buffer*/
-int8_t mac_rrc_nr_data_req_ue(const module_id_t Mod_idP,
+int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP,
                               const int         CC_id,
+                              const uint8_t     gNB_id,
                               const frame_t     frameP,
                               const rb_id_t     Srb_id,
-                              uint8_t *const    buffer_pP);
-
+                              uint8_t           *buffer_pP);
 
 /**\brief RRC UE task.
    \param void *args_p Pointer on arguments to start the task. */
 void *rrc_nrue_task(void *args_p);
 
 /**\brief RRC UE generate RRCSetupRequest message.
-   \param ctxt_pP    protocol context 
+   \param module_id  module id
    \param gNB_index  gNB index  */
-void rrc_ue_generate_RRCSetupRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index );
+void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index);
 
 /** @}*/
 #endif
diff --git a/openair2/SIMULATION/NR_RRC/itti_sim.c b/openair2/SIMULATION/NR_RRC/itti_sim.c
index e11a92d6912164f28ec6666aea4345782a4f5e5b..9b35ea67210da994de39e89afa3b2fb78a0c2c78 100644
--- a/openair2/SIMULATION/NR_RRC/itti_sim.c
+++ b/openair2/SIMULATION/NR_RRC/itti_sim.c
@@ -624,7 +624,7 @@ int main( int argc, char **argv )
                                 0);
   NR_UE_rrc_inst[ctxt.module_id].Info[0].State = RRC_SI_RECEIVED;
 
-  rrc_ue_generate_RRCSetupRequest(&ctxt, 0);
+  nr_rrc_ue_generate_RRCSetupRequest(ctxt.module_id, 0);
 
   printf("Entering ITTI signals handler\n");
   itti_wait_tasks_end();
diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c
index fdce8678b0eacbee802ccdf6d72240d1f7653e87..7c3a89e7f4bff4b0a652f8224d1b94161b375cf0 100644
--- a/openair2/X2AP/x2ap_eNB_generate_messages.c
+++ b/openair2/X2AP/x2ap_eNB_generate_messages.c
@@ -1318,6 +1318,9 @@ MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length
 
             ASN_SEQUENCE_ADD(&servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.freqBandListNr, freq_band);
             switch (instance_p->N_RB_DL[i]) {
+            case 24:
+              servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb24;
+              break;
             case 32:
               servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb32;
               break;
diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c
index f0e0fa9c231b41c592560dee73a9f9756b25c790..1fb28ea05b2dd0c9a99b7c5383aa7f8ebbc83608 100644
--- a/openair2/X2AP/x2ap_eNB_handler.c
+++ b/openair2/X2AP/x2ap_eNB_handler.c
@@ -536,6 +536,14 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
     return -1;
   }
 
+  if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) ||
+     (x2ap_eNB_data->state == X2AP_ENB_STATE_READY))
+  
+  {
+    X2AP_ERROR("Received Unexpexted X2 Setup Response Message\n");
+    return -1;
+  }
+
   X2AP_DEBUG("Received a new X2 setup response\n");
 
   X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse,
@@ -662,6 +670,14 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
     return -1;
   }
 
+  if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) ||
+     (x2ap_eNB_data->state == X2AP_ENB_STATE_READY))
+  
+  {
+    X2AP_ERROR("Received Unexpexted X2 Setup Failure Message\n");
+    return -1;
+  }
+
   X2AP_DEBUG("Received a new X2 setup failure\n");
 
   X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupFailure_IEs_t, ie, x2SetupFailure,
@@ -730,6 +746,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
                              X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true);
   if (ie == NULL ) {
     X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
     return -1;
   }
 
@@ -750,7 +767,11 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
                                                //measResultListEUTRA.list.array[ncell_index]->physCellId;
   X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
                              X2AP_ProtocolIE_ID_id_GUMMEI_ID, true);
-
+  if (ie == NULL ) {
+    X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
+    return -1;
+  }
   TBCD_TO_MCC_MNC(&ie->value.choice.ECGI.pLMN_Identity, X2AP_HANDOVER_REQ(msg).ue_gummei.mcc,
                   X2AP_HANDOVER_REQ(msg).ue_gummei.mnc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len);
   OCTET_STRING_TO_INT8(&ie->value.choice.GUMMEI.mME_Code, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code);
@@ -761,6 +782,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
 
   if (ie == NULL ) {
     X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
     return -1;
   }
 
@@ -872,6 +894,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
 
   if (ie == NULL ) {
     X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
     return -1;
   }
 
@@ -882,6 +905,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
 
   if (ie == NULL ) {
     X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
     return -1;
   }
 
@@ -912,6 +936,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
 
   if (ie == NULL ) {
     X2AP_ERROR("%s %d: ie is a NULL pointer \n", __FILE__, __LINE__);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
     return -1;
   }else{
     if (ie->value.choice.E_RABs_Admitted_List.list.count > 0) {
@@ -959,6 +984,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
   X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
                              X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true);
 
+  if (ie == NULL ) {
+    X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
+    return -1;
+  }
+
   X2AP_TargeteNBtoSource_eNBTransparentContainer_t *c = &ie->value.choice.TargeteNBtoSource_eNBTransparentContainer;
 
   if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s */)
@@ -1012,6 +1043,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance,
 
   if (ie == NULL ) {
     X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
     return -1;
   }
 
@@ -1022,6 +1054,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance,
 
   if (ie == NULL ) {
     X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
+    itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
     return -1;
   }
 
diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c
index 4769380d187351786db5a36778efbe90b7a47912..847002ab446e03f78fab62b9f0d94fe189c9d937 100644
--- a/openair3/GTPV1-U/gtpv1u_eNB.c
+++ b/openair3/GTPV1-U/gtpv1u_eNB.c
@@ -1211,7 +1211,7 @@ int gtpv1u_eNB_init(void) {
   //gtpv1u_data_g.udp_data;
   RC.gtpv1u_data_g->seq_num         = 0;
   RC.gtpv1u_data_g->restart_counter = 0;
-
+  RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up = 0;
   /* Initializing GTPv1-U stack */
   if ((rc = nwGtpv1uInitialize(&RC.gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) {
     LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc);
diff --git a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c
index 8ac43cf7b13fd1c3e4c09a9c39db6e4649699c3d..637d930226dd5e61a79e5a914846d46940f58061 100644
--- a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c
+++ b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c
@@ -190,7 +190,6 @@ int decode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
     default:
       errorCodeDecoder = TLV_DECODE_UNEXPECTED_IEI;
       LOG_TRACE(WARNING, "DECODE_UNEXPECTED_IEI %x (4 bits)", ieiDecoded);
-      AssertFatal(0, " ");
       return TLV_DECODE_UNEXPECTED_IEI;
     }
   }
diff --git a/openair3/NAS/COMMON/IES/SupportedCodecList.c b/openair3/NAS/COMMON/IES/SupportedCodecList.c
index 3a69eee366a82822fa5edb2da8c3e48db92ea54c..15a2fecaa02358cbc5fb7624e261727caa0ded30 100644
--- a/openair3/NAS/COMMON/IES/SupportedCodecList.c
+++ b/openair3/NAS/COMMON/IES/SupportedCodecList.c
@@ -43,13 +43,17 @@ int decode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t
   CHECK_LENGTH_DECODER(len - decoded, ielen);
   supportedcodeclist->systemidentification = *(buffer + decoded);
   decoded++;
+  ielen--;
   supportedcodeclist->lengthofbitmap = *(buffer + decoded);
   decoded++;
+  ielen--;
   //IES_DECODE_U16(supportedcodeclist->codecbitmap, *(buffer + decoded));
   IES_DECODE_U16(buffer, decoded, supportedcodeclist->codecbitmap);
+  ielen=ielen -2;
 #if defined (NAS_DEBUG)
   dump_supported_codec_list_xml(supportedcodeclist, iei);
 #endif
+  decoded = decoded + ielen;
   return decoded;
 }
 int encode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t iei, uint8_t *buffer, uint32_t len)
diff --git a/openair3/NAS/UE/EMM/SAP/emm_as.c b/openair3/NAS/UE/EMM/SAP/emm_as.c
index 99a3763dea30efa3df76113fc35dcf447457845f..10b118eac0315e338e282ef192ed7397dcb6e538 100644
--- a/openair3/NAS/UE/EMM/SAP/emm_as.c
+++ b/openair3/NAS/UE/EMM/SAP/emm_as.c
@@ -443,14 +443,14 @@ static int _emm_as_data_ind(nas_user_t *user, const emm_as_data_t *msg, int *emm
                    EPS_MOBILITY_MANAGEMENT_MESSAGE) {
           /* Process EMM data */
           rc = _emm_as_recv(user, plain_msg, bytes, emm_cause);
+          free(plain_msg);
         } else if (header.protocol_discriminator ==
                    EPS_SESSION_MANAGEMENT_MESSAGE) {
           const OctetString data = {bytes, (uint8_t *)plain_msg};
           /* Foward ESM data to EPS session management */
           rc = lowerlayer_data_ind(user, &data);
+          free(plain_msg);
         }
-
-        free(plain_msg);
       }
     } else {
       /* Process successfull lower layer transfer indication */
diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c
index 67bfaf784e63bad0b37e960d662d7ef7693f310a..b27270fadc43fd89ed7d59d1742b792a30ca953a 100644
--- a/openair3/NAS/UE/EMM/SecurityModeControl.c
+++ b/openair3/NAS/UE/EMM/SecurityModeControl.c
@@ -296,16 +296,16 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi,
     else {
       /* Setup EMM cause code */
       emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED;
-
-      /* Release security mode control internal data */
-      if (security_data->kenb.value) {
-        free(security_data->kenb.value);
-        security_data->kenb.value = NULL;
-        security_data->kenb.length = 0;
-      }
     }
   }
 
+  /* Release security mode control internal data */
+  if (security_data->kenb.value) {
+    free(security_data->kenb.value);
+    security_data->kenb.value = NULL;
+    security_data->kenb.length = 0;
+  }
+
   /* Setup EMM procedure handler to be executed upon receiving
    * lower layer notification */
   rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL);
diff --git a/openair3/S1AP/s1ap_common.h b/openair3/S1AP/s1ap_common.h
index 77d03f4ae4b099471155dc774a208e432303d888..efac0201a31feaa1aa5dd5380e6ab5dcb7f2dd56 100644
--- a/openair3/S1AP/s1ap_common.h
+++ b/openair3/S1AP/s1ap_common.h
@@ -106,7 +106,12 @@ extern int asn1_xer_print;
     if (ie == NULL ) { \
       S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\
     } \
-    if (mandatory)  DevAssert(ie != NULL); \
+    if (mandatory) { \
+      if (ie == NULL) { \
+        S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\
+        return -1; \
+      } \
+    } \
   } while(0)
 /** \brief Function callback prototype.
  **/
diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c
index 31ea3359da1829217bb01c48103f34d18df6d058..e528c9e53eb4e87ca439deb2217a87d2a51710b4 100644
--- a/openair3/S1AP/s1ap_eNB.c
+++ b/openair3/S1AP/s1ap_eNB.c
@@ -73,6 +73,42 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
 
 void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
 
+static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p,
+                         s1ap_eNB_mme_data_t *s1ap_mme_data_p);
+void s1ap_eNB_timer_expired(instance_t                 instance,
+                            timer_has_expired_t   *msg_p);
+
+int s1ap_timer_setup(
+  uint32_t      interval_sec,
+  uint32_t      interval_us,
+  task_id_t     task_id,
+  int32_t       instance,
+  uint32_t      timer_kind,
+  timer_type_t  type,
+  void         *timer_arg,
+  long         *timer_id)
+{
+  uint32_t *timeoutArg=NULL;
+  int ret=0;
+  timeoutArg=malloc(sizeof(uint32_t));
+  *timeoutArg=timer_kind;
+  ret=timer_setup(interval_sec,
+                interval_us,
+                task_id,
+                instance,
+                type,
+                (void*)timeoutArg,
+                timer_id);
+  return ret;
+}
+
+int s1ap_timer_remove(long timer_id)
+{
+  int ret;
+  ret=timer_remove(timer_id);
+  return ret;
+}
+
 uint32_t s1ap_generate_eNB_id(void) {
   char    *out;
   char     hostname[50];
@@ -98,7 +134,7 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
   MessageDef                 *message_p                   = NULL;
   sctp_new_association_req_t *sctp_new_association_req_p  = NULL;
   s1ap_eNB_mme_data_t        *s1ap_mme_data_p             = NULL;
-  struct s1ap_eNB_mme_data_s *mme                         = NULL;
+//  struct s1ap_eNB_mme_data_s *mme                         = NULL;
   DevAssert(instance_p != NULL);
   DevAssert(mme_ip_address != NULL);
   message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_NEW_ASSOCIATION_REQ);
@@ -114,51 +150,32 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
          local_ip_addr,
          sizeof(*local_ip_addr));
   S1AP_INFO("[eNB %ld] check the mme registration state\n",instance_p->instance);
-  mme = NULL;
-
-  if ( mme == NULL ) {
-    /* Create new MME descriptor */
-    s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p));
-    DevAssert(s1ap_mme_data_p != NULL);
-    s1ap_mme_data_p->cnx_id                = s1ap_eNB_fetch_add_global_cnx_id();
-    sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id;
-    s1ap_mme_data_p->assoc_id          = -1;
-    s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num;
-    memcpy(&s1ap_mme_data_p->mme_s1_ip,
-    	   mme_ip_address,
-    	   sizeof(*mme_ip_address));
-    s1ap_mme_data_p->mme_port = mme_port;
-    for (int i = 0; i < broadcast_plmn_num; ++i)
-      s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i];
-
-    s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
-    STAILQ_INIT(&s1ap_mme_data_p->served_gummei);
-    /* Insert the new descriptor in list of known MME
-     * but not yet associated.
-     */
-    RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p);
-    s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
-    instance_p->s1ap_mme_nb ++;
-    instance_p->s1ap_mme_pending_nb ++;
-  } else if (mme->state == S1AP_ENB_STATE_WAITING) {
-    instance_p->s1ap_mme_pending_nb ++;
-    sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
-    S1AP_INFO("[eNB %ld] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n",
-              instance_p->instance,
-              mme->state, mme->cnx_id,
-              instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb);
-    /*s1ap_mme_data_p->cnx_id                = mme->cnx_id;
-    sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
-
-    s1ap_mme_data_p->assoc_id          = -1;
-    s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
-    */
-  } else {
-    S1AP_WARN("[eNB %ld] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n",
-              instance_p->instance,
-              mme->state, mme->cnx_id,
-              instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb);
-  }
+  /* Create new MME descriptor */
+  s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p));
+  DevAssert(s1ap_mme_data_p != NULL);
+  s1ap_mme_data_p->cnx_id                = s1ap_eNB_fetch_add_global_cnx_id();
+  sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id;
+  s1ap_mme_data_p->assoc_id          = -1;
+  s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num;
+  memcpy(&s1ap_mme_data_p->mme_s1_ip,
+         mme_ip_address,
+         sizeof(*mme_ip_address));
+  s1ap_mme_data_p->mme_port = mme_port;
+  for (int i = 0; i < broadcast_plmn_num; ++i)
+    s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i];
+
+  s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
+  STAILQ_INIT(&s1ap_mme_data_p->served_gummei);
+  /* Insert the new descriptor in list of known MME
+   * but not yet associated.
+   */
+  RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p);
+  s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED;
+  memcpy( &(s1ap_mme_data_p->mme_ip_address), mme_ip_address, sizeof(net_ip_address_t) );
+  s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD;
+  s1ap_mme_data_p->sctp_req_cnt++;
+  s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT;
+  instance_p->s1ap_mme_pending_nb ++;
 
   itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
 }
@@ -196,10 +213,10 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
     new_instance->eNB_id           = s1ap_register_eNB->eNB_id;
     new_instance->cell_type        = s1ap_register_eNB->cell_type;
     new_instance->tac              = s1ap_register_eNB->tac;
-    
+
     memcpy(&new_instance->eNB_s1_ip,
-	   &s1ap_register_eNB->enb_ip_address,
-	   sizeof(s1ap_register_eNB->enb_ip_address));
+       &s1ap_register_eNB->enb_ip_address,
+       sizeof(s1ap_register_eNB->enb_ip_address));
 
     for (int i = 0; i < s1ap_register_eNB->num_plmn; i++) {
       new_instance->mcc[i]              = s1ap_register_eNB->mcc[i];
@@ -207,6 +224,15 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
       new_instance->mnc_digit_length[i] = s1ap_register_eNB->mnc_digit_length[i];
     }
 
+    memcpy( &(new_instance->enb_ip_address), &(s1ap_register_eNB->enb_ip_address), sizeof(net_ip_address_t) );
+    new_instance->s1_setuprsp_wait_timer = s1ap_register_eNB->s1_setuprsp_wait_timer;
+    new_instance->s1_setupreq_wait_timer = s1ap_register_eNB->s1_setupreq_wait_timer;
+    new_instance->s1_setupreq_count = s1ap_register_eNB->s1_setupreq_count;
+    new_instance->sctp_req_timer = s1ap_register_eNB->sctp_req_timer;
+    new_instance->sctp_req_count = s1ap_register_eNB->sctp_req_count;
+    new_instance->sctp_in_streams = s1ap_register_eNB->sctp_in_streams;
+    new_instance->sctp_out_streams = s1ap_register_eNB->sctp_out_streams;
+
     new_instance->num_plmn         = s1ap_register_eNB->num_plmn;
     new_instance->default_drx      = s1ap_register_eNB->default_drx;
     /* Add the new instance to the list of eNB (meaningfull in virtual mode) */
@@ -217,8 +243,12 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
               s1ap_register_eNB->eNB_id);
   }
 
-  DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS,
-           S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0);
+  if( s1ap_register_eNB->nb_mme > S1AP_MAX_NB_MME_IP_ADDRESS )
+  {
+    S1AP_ERROR("Invalid MME number = %d\n ", s1ap_register_eNB->nb_mme);
+    s1ap_register_eNB->nb_mme = S1AP_MAX_NB_MME_IP_ADDRESS;
+  }
+  new_instance->s1ap_mme_nb = s1ap_register_eNB->nb_mme;
 
   /* Trying to connect to provided list of MME ip address */
   for (index = 0; index < s1ap_register_eNB->nb_mme; index++) {
@@ -250,28 +280,131 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
 void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
   s1ap_eNB_instance_t *instance_p;
   s1ap_eNB_mme_data_t *s1ap_mme_data_p;
+  s1ap_eNB_ue_context_t        *ue_p = NULL;
+  MessageDef                   *message_p = NULL;
+  uint32_t                     timer_kind = 0;
+  struct plmn_identity_s*      plmnInfo;
+  struct served_group_id_s*    groupInfo;
+  struct served_gummei_s*      gummeiInfo;
+  struct mme_code_s*           mmeCode;
+  int8_t                       cnt = 0;
+  unsigned                     enb_s1ap_id[NUMBER_OF_UE_MAX];
   DevAssert(sctp_new_association_resp != NULL);
   instance_p = s1ap_eNB_get_instance(instance);
   DevAssert(instance_p != NULL);
   s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1,
                                      sctp_new_association_resp->ulp_cnx_id);
   DevAssert(s1ap_mme_data_p != NULL);
-
-  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
-    S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
-              sctp_new_association_resp->sctp_state,
-              instance,
-              sctp_new_association_resp->ulp_cnx_id);
-    s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
-    return;
+  memset(enb_s1ap_id, 0, sizeof(enb_s1ap_id) );
+  if( s1ap_mme_data_p->timer_id != S1AP_TIMERID_INIT ) {
+    s1ap_timer_remove( s1ap_mme_data_p->timer_id );
+    s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT;
+  }
+  
+  if( sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED ) {
+    RB_FOREACH(ue_p, s1ap_ue_map, &instance_p->s1ap_ue_head) {
+      if( ue_p->mme_ref == s1ap_mme_data_p ) {
+        if(cnt < NUMBER_OF_UE_MAX) {
+          enb_s1ap_id[cnt] = ue_p->eNB_ue_s1ap_id;
+          cnt++;
+          
+          message_p = NULL;
+          message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND);
+          
+          if( message_p != NULL ) {
+            S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = ue_p->eNB_ue_s1ap_id;
+            
+            if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) {
+              S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id);
+            }
+          } else {
+            S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id);
+          }
+        }else{
+          S1AP_ERROR("s1ap_eNB_handle_sctp_association_resp: cnt %d > max\n", cnt);
+        }
+      }
+    }
+    for( ; cnt > 0 ; ) {
+      cnt--;
+      struct s1ap_eNB_ue_context_s *ue_context_p = NULL;
+      struct s1ap_eNB_ue_context_s *s1ap_ue_context_p = NULL;
+      ue_context_p = s1ap_eNB_get_ue_context(instance_p, (uint32_t)enb_s1ap_id[cnt]);
+      if (ue_context_p != NULL) {
+        s1ap_ue_context_p = RB_REMOVE(s1ap_ue_map, &instance_p->s1ap_ue_head, ue_context_p);
+        s1ap_eNB_free_ue_context(s1ap_ue_context_p);
+      }
+    }
+    s1ap_mme_data_p->mme_name = 0;
+    s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD;
+    s1ap_mme_data_p->nextstream = 0;
+    s1ap_mme_data_p->in_streams = 0;
+    s1ap_mme_data_p->out_streams = 0;
+    s1ap_mme_data_p->assoc_id = -1;
+    
+    while (!STAILQ_EMPTY(&s1ap_mme_data_p->served_gummei)) {
+      gummeiInfo = STAILQ_FIRST(&s1ap_mme_data_p->served_gummei);
+      STAILQ_REMOVE_HEAD(&s1ap_mme_data_p->served_gummei, next);
+
+      while (!STAILQ_EMPTY(&gummeiInfo->served_plmns)) {
+        plmnInfo = STAILQ_FIRST(&gummeiInfo->served_plmns);
+        STAILQ_REMOVE_HEAD(&gummeiInfo->served_plmns, next);
+        free(plmnInfo);
+      }
+      while (!STAILQ_EMPTY(&gummeiInfo->served_group_ids)) {
+        groupInfo = STAILQ_FIRST(&gummeiInfo->served_group_ids);
+        STAILQ_REMOVE_HEAD(&gummeiInfo->served_group_ids, next);
+        free(groupInfo);
+      }
+      while (!STAILQ_EMPTY(&gummeiInfo->mme_codes)) {
+        mmeCode = STAILQ_FIRST(&gummeiInfo->mme_codes);
+        STAILQ_REMOVE_HEAD(&gummeiInfo->mme_codes, next);
+        free(mmeCode);
+      }
+      free(gummeiInfo);
+    }
+    
+    STAILQ_INIT(&s1ap_mme_data_p->served_gummei);
+    
+    if( s1ap_mme_data_p->state == S1AP_ENB_STATE_DISCONNECTED ) {
+      if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) ||
+        (instance_p->sctp_req_count == 0xffff) ) {
+        timer_kind = s1ap_mme_data_p->cnx_id;
+        timer_kind = timer_kind | S1AP_MMEIND;
+        timer_kind = timer_kind | SCTP_REQ_WAIT;
+        
+        if( s1ap_timer_setup( instance_p->sctp_req_timer, 0, TASK_S1AP, instance_p->instance,
+          timer_kind, S1AP_TIMER_ONE_SHOT, NULL, &s1ap_mme_data_p->timer_id) < 0 ) {
+          S1AP_ERROR("Timer Start NG(SCTP retransmission wait timer) : MME=%d\n",s1ap_mme_data_p->cnx_id);
+          s1ap_sctp_req( instance_p, s1ap_mme_data_p );
+        }
+      } else {
+        S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id);
+      }
+    } else {
+      S1AP_ERROR("SCTP disconnection reception : MME = %d\n",s1ap_mme_data_p->cnx_id);
+
+      if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) ||
+          (instance_p->sctp_req_count == 0xffff) ) {
+        s1ap_sctp_req( instance_p, s1ap_mme_data_p );
+      } else {
+        S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id);
+      }
+      s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED;
+    }
+  } else {
+    /* Update parameters */
+    s1ap_mme_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
+    s1ap_mme_data_p->in_streams  = sctp_new_association_resp->in_streams;
+    s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;
+    /* Prepare new S1 Setup Request */
+    s1ap_mme_data_p->s1_setupreq_cnt = 0;
+    s1ap_mme_data_p->sctp_req_cnt = 0;
+    if (s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p) == -1) {
+      S1AP_ERROR("s1ap eNB generate s1 setup request failed\n");
+      return;
+    }
   }
-
-  /* Update parameters */
-  s1ap_mme_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
-  s1ap_mme_data_p->in_streams  = sctp_new_association_resp->in_streams;
-  s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;
-  /* Prepare new S1 Setup Request */
-  s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p);
 }
 
 static
@@ -282,13 +415,94 @@ void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) {
   mme_test_s1_notify_sctp_data_ind(sctp_data_ind->assoc_id, sctp_data_ind->stream,
                                    sctp_data_ind->buffer, sctp_data_ind->buffer_length);
 #else
-  s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream,
-                          sctp_data_ind->buffer, sctp_data_ind->buffer_length);
+  if (s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream,
+                          sctp_data_ind->buffer, sctp_data_ind->buffer_length) == -1) {
+    S1AP_ERROR("Failed to handle s1ap eNB message\n");
+  }
 #endif
   result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
   AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
 }
 
+void s1ap_eNB_timer_expired(
+  instance_t                instance,
+  timer_has_expired_t   *msg_p)
+{
+  uint32_t                  timer_kind = 0;
+  int16_t                   line_ind = 0;
+  s1ap_eNB_mme_data_t       *mme_desc_p = NULL;
+  uint32_t                  timer_ind = 0;
+  s1ap_eNB_instance_t       *instance_p = NULL;
+  long                      timer_id = S1AP_TIMERID_INIT;
+  
+  instance_p = s1ap_eNB_get_instance(instance);
+  if(msg_p->arg!=NULL){
+    timer_kind = *((uint32_t*)msg_p->arg);
+    free(msg_p->arg);
+  }else{
+    S1AP_ERROR("s1 timer timer_kind is NULL\n");
+    return;
+  }
+  line_ind = (int16_t)(timer_kind & S1AP_LINEIND);
+  timer_id = msg_p->timer_id;
+  
+  if( (timer_kind & S1AP_MMEIND) == S1AP_MMEIND ) {
+    mme_desc_p = s1ap_eNB_get_MME(instance_p, -1, line_ind);
+    if(mme_desc_p != NULL) {
+      if( timer_id == mme_desc_p->timer_id ) {
+        mme_desc_p->timer_id = S1AP_TIMERID_INIT;
+        timer_ind = timer_kind & S1AP_TIMERIND;
+        
+        switch(timer_ind)
+        {
+          case S1_SETRSP_WAIT:
+          {
+            if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) ||
+                (instance_p->s1_setupreq_count == 0xffff) ) {
+              s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p );
+            } else {
+              S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind);
+            }
+            break;
+          }
+          case S1_SETREQ_WAIT:
+          {
+            if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) ||
+                (instance_p->s1_setupreq_count == 0xffff) ) {
+              s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p );
+            } else {
+              S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind);
+            }
+            break;
+          }
+          case SCTP_REQ_WAIT:
+          {
+            if( (instance_p->sctp_req_count >= mme_desc_p->sctp_req_cnt) ||
+                (instance_p->sctp_req_count == 0xffff) ) {
+              s1ap_sctp_req( instance_p, mme_desc_p );
+            } else {
+              S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",line_ind);
+            }
+            break;
+          }
+          default:
+          {
+            S1AP_WARN("Invalid Timer indication\n");
+            break;
+          }
+        }
+      } else {
+        S1AP_DEBUG("Unmatch timer id\n");
+        return;
+      }
+    } else {
+      S1AP_WARN("Not applicable MME detected : connection id = %d\n", line_ind);
+      return;
+    }
+  }
+  return;
+}
+
 void s1ap_eNB_init(void) {
   S1AP_DEBUG("Starting S1AP layer\n");
   s1ap_eNB_prepare_internal_data();
@@ -412,6 +626,13 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) {
     }
     break;
 
+    case TIMER_HAS_EXPIRED:
+    {
+      s1ap_eNB_timer_expired(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
+                             &received_msg->ittiMsg.timer_has_expired);
+    }
+    break;
+
     default:
       S1AP_ERROR("Received unhandled message: %d:%s\n",
                  ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
@@ -452,6 +673,7 @@ static int s1ap_eNB_generate_s1_setup_request(
   uint8_t  *buffer = NULL;
   uint32_t  len = 0;
   int       ret = 0;
+  uint32_t  timer_kind = 0;
   DevAssert(instance_p != NULL);
   DevAssert(s1ap_mme_data_p != NULL);
   s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
@@ -526,6 +748,17 @@ static int s1ap_eNB_generate_s1_setup_request(
     return -1;
   }
 
+  timer_kind = s1ap_mme_data_p->cnx_id;
+  timer_kind = timer_kind | S1AP_MMEIND;
+  timer_kind = timer_kind | S1_SETRSP_WAIT;
+  
+  if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT,
+    NULL, &s1ap_mme_data_p->timer_id) < 0 )
+  {
+    S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id);
+  }
+  s1ap_mme_data_p->s1_setupreq_cnt++;
+
   /* Non UE-Associated signalling -> stream = 0 */
   s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0);
   return ret;
@@ -534,3 +767,55 @@ static int s1ap_eNB_generate_s1_setup_request(
 
 
 
+static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p,
+                         s1ap_eNB_mme_data_t *s1ap_mme_data_p)
+{
+  MessageDef                 *message_p                   = NULL;
+  sctp_new_association_req_t *sctp_new_association_req_p  = NULL;
+  
+  if( instance_p == NULL )
+  {
+      S1AP_ERROR("Invalid instance_p\n");
+      return -1;
+  }
+  
+  message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_NEW_ASSOCIATION_REQ);
+  sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req;
+  sctp_new_association_req_p->port = S1AP_PORT_NUMBER;
+  sctp_new_association_req_p->ppid = S1AP_SCTP_PPID;
+  sctp_new_association_req_p->in_streams  = instance_p->sctp_in_streams;
+  sctp_new_association_req_p->out_streams = instance_p->sctp_out_streams;
+  sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id;
+  
+  if( s1ap_mme_data_p->mme_ip_address.ipv4 != 0 ) {
+    memcpy(&sctp_new_association_req_p->remote_address,
+        &s1ap_mme_data_p->mme_ip_address,
+        sizeof(net_ip_address_t));
+    if( instance_p->enb_ip_address.ipv4 != 0 ) {
+      memcpy(&sctp_new_association_req_p->local_address,
+          &instance_p->enb_ip_address,
+          sizeof(net_ip_address_t));
+    } else {
+      S1AP_ERROR("Invalid IP Address Format V4(MME):V6\n");
+      return -1;
+    }
+  } else {
+    memcpy(&sctp_new_association_req_p->remote_address,
+        &s1ap_mme_data_p->mme_ip_address,
+        sizeof(net_ip_address_t));
+    if( instance_p->enb_ip_address.ipv6 != 0 ) {
+      memcpy(&sctp_new_association_req_p->local_address,
+          &instance_p->enb_ip_address,
+          sizeof(net_ip_address_t));
+    } else {
+      S1AP_ERROR("Invalid IP Address Format V6(MME):V4\n");
+      return -1;
+    }
+  }
+  
+  itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
+  
+  s1ap_mme_data_p->sctp_req_cnt++;
+  
+  return 0;
+}
diff --git a/openair3/S1AP/s1ap_eNB.h b/openair3/S1AP/s1ap_eNB.h
index 2abbc53ec992f288c14761eb31170e6134a046e0..21835872147d6cc25f982847307d9c52cf3296bc 100644
--- a/openair3/S1AP/s1ap_eNB.h
+++ b/openair3/S1AP/s1ap_eNB.h
@@ -30,6 +30,22 @@
 #ifndef S1AP_ENB_H_
 #define S1AP_ENB_H_
 
+#define S1AP_MMEIND     0x80000000
+#define S1AP_UEIND      0x00000000
+#define S1_SETRSP_WAIT  0x00010000
+#define S1_SETREQ_WAIT  0x00020000
+#define SCTP_REQ_WAIT   0x00030000
+#define S1AP_LINEIND    0x0000ffff
+#define S1AP_TIMERIND   0x00ff0000
+
+#define S1AP_TIMERID_INIT   0xffffffffffffffff
+
+typedef enum s1ap_timer_type_s {
+  S1AP_TIMER_PERIODIC,
+  S1AP_TIMER_ONE_SHOT,
+  S1AP_TIMER_TYPE_MAX,
+} s1ap_timer_type_t;
+
 typedef struct s1ap_eNB_config_s {
   // MME related params
   unsigned char mme_enabled;          ///< MME enabled ?
@@ -43,6 +59,7 @@ void *s1ap_eNB_process_itti_msg(void*);
 void  s1ap_eNB_init(void);
 void *s1ap_eNB_task(void *arg);
 
+int s1ap_timer_remove(long timer_id);
 uint32_t s1ap_generate_eNB_id(void);
 
 #endif /* S1AP_ENB_H_ */
diff --git a/openair3/S1AP/s1ap_eNB_decoder.c b/openair3/S1AP/s1ap_eNB_decoder.c
index 4635946a059446a3a9af91bab78e00e07de32773..14e4b49238555611bac2adcb2e8222d9837384de 100644
--- a/openair3/S1AP/s1ap_eNB_decoder.c
+++ b/openair3/S1AP/s1ap_eNB_decoder.c
@@ -89,8 +89,6 @@ static int s1ap_eNB_decode_initiating_message(S1AP_S1AP_PDU_t *pdu) {
     default:
       S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
                  (int)pdu->choice.initiatingMessage.procedureCode);
-      AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n",
-                   (int)pdu->choice.initiatingMessage.procedureCode);
       return -1;
   }
 
diff --git a/openair3/S1AP/s1ap_eNB_defs.h b/openair3/S1AP/s1ap_eNB_defs.h
index d8a8da8001a32dbff65913336829afec781a3ff5..ed0909d66e4be26147548d4a3eb0dc0338e7d865 100644
--- a/openair3/S1AP/s1ap_eNB_defs.h
+++ b/openair3/S1AP/s1ap_eNB_defs.h
@@ -165,6 +165,12 @@ typedef struct s1ap_eNB_mme_data_s {
 
   /* Only meaningfull in virtual mode */
   struct s1ap_eNB_instance_s *s1ap_eNB_instance;
+  
+  uint32_t nb_calls;
+  net_ip_address_t mme_ip_address;
+  long             timer_id;
+  uint16_t         s1_setupreq_cnt;
+  uint16_t         sctp_req_cnt;
 } s1ap_eNB_mme_data_t;
 
 typedef struct s1ap_eNB_instance_s {
@@ -217,6 +223,14 @@ typedef struct s1ap_eNB_instance_s {
 
   /* Default Paging DRX of the eNB as defined in TS 36.304 */
   paging_drx_t default_drx;
+  net_ip_address_t   enb_ip_address;
+  uint16_t           s1_setuprsp_wait_timer;
+  uint16_t           s1_setupreq_wait_timer;
+  uint16_t           s1_setupreq_count;
+  uint16_t           sctp_req_timer;
+  uint16_t           sctp_req_count;
+  uint16_t           sctp_in_streams;
+  uint16_t           sctp_out_streams;
 } s1ap_eNB_instance_t;
 
 typedef struct {
diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c
index 370d34868b577e7428a68d5e70ac49dad397124a..9ee3287b94f3b43a236b0d41ae85a79270682c00 100644
--- a/openair3/S1AP/s1ap_eNB_handlers.c
+++ b/openair3/S1AP/s1ap_eNB_handlers.c
@@ -38,6 +38,9 @@
 #include "s1ap_eNB_defs.h"
 #include "s1ap_eNB_handlers.h"
 #include "s1ap_eNB_decoder.h"
+#include "s1ap_eNB_encoder.h"
+
+#include "s1ap_eNB_itti_messaging.h"
 
 #include "s1ap_eNB_ue_context.h"
 #include "s1ap_eNB_trace.h"
@@ -109,6 +112,20 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t               as
     uint32_t               stream,
     S1AP_S1AP_PDU_t       *pdu);
 
+static int s1ap_eNB_snd_s1_setup_request(
+  s1ap_eNB_instance_t *instance_p,
+  s1ap_eNB_mme_data_t *s1ap_mme_data_p);
+
+int s1ap_timer_setup(
+  uint32_t      interval_sec,
+  uint32_t      interval_us,
+  task_id_t     task_id,
+  int32_t       instance,
+  uint32_t      timer_kind,
+  timer_type_t  type,
+  void         *timer_arg,
+  long         *timer_id);
+
 /* Handlers matrix. Only eNB related procedure present here */
 s1ap_message_decoded_callback messages_callback[][3] = {
   { 0, 0, 0 }, /* HandoverPreparation */
@@ -260,6 +277,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
   S1AP_S1SetupFailure_t      *container;
   S1AP_S1SetupFailureIEs_t   *ie;
   s1ap_eNB_mme_data_t        *mme_desc_p;
+  uint32_t                   interval_sec = 0;
+  uint32_t                   timer_kind = 0;
+  s1ap_eNB_instance_t        *instance_p;
+
   DevAssert(pdu != NULL);
   container = &pdu->choice.unsuccessfulOutcome.value.choice.S1SetupFailure;
 
@@ -270,7 +291,7 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
   }
 
   if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
-    S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing "
+    S1AP_ERROR("[SCTP %d] Received S1 setup failure for non existing "
                "MME context\n", assoc_id);
     return -1;
   }
@@ -278,6 +299,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
   S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container,
                              S1AP_ProtocolIE_ID_id_Cause,true);
 
+  if(ie == NULL) {
+    return -1;
+  }
+
   if ((ie->value.choice.Cause.present == S1AP_Cause_PR_misc) &&
       (ie->value.choice.Cause.choice.misc == S1AP_CauseMisc_unspecified)) {
     S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n");
@@ -285,8 +310,56 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t               assoc_id,
     S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n");
   }
 
-  mme_desc_p->state = S1AP_ENB_STATE_WAITING;
-  s1ap_handle_s1_setup_message(mme_desc_p, 0);
+  if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) {
+    s1ap_timer_remove( mme_desc_p->timer_id );
+    mme_desc_p->timer_id = S1AP_TIMERID_INIT;
+  }
+  instance_p = mme_desc_p->s1ap_eNB_instance;
+  if( ( instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) ||
+      ( instance_p->s1_setupreq_count == 0xffff) ) {
+    S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container,
+                               S1AP_ProtocolIE_ID_id_TimeToWait, false);
+    if( ie != NULL ) {
+      switch(ie->value.choice.TimeToWait)
+      {
+        case S1AP_TimeToWait_v1s:
+          interval_sec = 1;
+          break;
+        case S1AP_TimeToWait_v2s:
+          interval_sec = 2;
+          break;
+        case S1AP_TimeToWait_v5s:
+          interval_sec = 5;
+          break;
+        case S1AP_TimeToWait_v10s:
+          interval_sec = 10;
+          break;
+        case S1AP_TimeToWait_v20s:
+          interval_sec = 20;
+          break;
+        case S1AP_TimeToWait_v60s:
+          interval_sec = 60;
+          break;
+        default:
+          interval_sec = instance_p->s1_setupreq_wait_timer;
+          break;
+      }
+    } else {
+      interval_sec = instance_p->s1_setupreq_wait_timer;
+    }
+    
+    timer_kind = mme_desc_p->cnx_id;
+    timer_kind = timer_kind | S1AP_MMEIND;
+    timer_kind = timer_kind | S1_SETREQ_WAIT;
+    
+    if( s1ap_timer_setup(interval_sec, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT,
+      NULL, &mme_desc_p->timer_id) < 0 ) {
+      S1AP_ERROR("Timer Start NG(S1 Setup Request) : MME=%d\n",mme_desc_p->cnx_id);
+      s1ap_eNB_snd_s1_setup_request( instance_p, mme_desc_p );
+    }
+  } else {
+    S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",mme_desc_p->cnx_id);
+  }
   return 0;
 }
 
@@ -314,9 +387,27 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t               assoc_id,
     return -1;
   }
 
+  /* Set the capacity of this MME */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container,
+                             S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true);
+  if(ie == NULL) {
+    return -1;
+  }
+  mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity;
+
   S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container,
                              S1AP_ProtocolIE_ID_id_ServedGUMMEIs, true);
+  if(ie == NULL) {
+    return -1;
+  }
 
+  if( mme_desc_p->timer_id != S1AP_TIMERID_INIT )
+  {
+    s1ap_timer_remove( mme_desc_p->timer_id );
+    mme_desc_p->timer_id = S1AP_TIMERID_INIT;
+  }
+  mme_desc_p->s1_setupreq_cnt = 0;
+  mme_desc_p->sctp_req_cnt = 0;
   /* The list of served gummei can contain at most 8 elements.
    * LTE related gummei is the first element in the list, i.e with an id of 0.
    */
@@ -368,13 +459,7 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t               assoc_id,
 
     STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next);
   }
-
-  /* Set the capacity of this MME */
-  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container,
-                             S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true);
-
-  mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity;
-
+  
   /* Optionaly set the mme name */
   S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container,
                              S1AP_ProtocolIE_ID_id_MMEname, false);
@@ -392,7 +477,6 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t               assoc_id,
    */
   mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
   mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++;
-  s1ap_handle_s1_setup_message(mme_desc_p, 0);
   return 0;
 }
 
@@ -725,6 +809,9 @@ int s1ap_eNB_handle_error_indication(uint32_t         assoc_id,
                              S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false);
 
   if (ie) {
+    if( ie->value.choice.CriticalityDiagnostics.procedureCode ) {
+      S1AP_WARN("Received S1 Error indication CriticalityDiagnostics procedureCode = %ld\n", *ie->value.choice.CriticalityDiagnostics.procedureCode);
+    }
     // TODO continue
   }
 
@@ -807,9 +894,11 @@ int s1ap_eNB_handle_initial_context_request(uint32_t   assoc_id,
                       &(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl));
     /* id-E-RABToBeSetupListCtxtSUReq */
   } else {
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
+
   S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                              S1AP_ProtocolIE_ID_id_E_RABToBeSetupListCtxtSUReq, true);
 
@@ -852,6 +941,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t   assoc_id,
         item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability;
     } /* for i... */
   } else {/* ie != NULL */
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -865,6 +955,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t   assoc_id,
     S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms =
       BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms);
   } else {/* ie != NULL */
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -876,9 +967,10 @@ int s1ap_eNB_handle_initial_context_request(uint32_t   assoc_id,
     memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key,
            ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size);
   } else {/* ie != NULL */
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
-
+  
   /* id-NRUESecurityCapabilities */
   S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                              S1AP_ProtocolIE_ID_id_NRUESecurityCapabilities, false);
@@ -891,7 +983,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t   assoc_id,
     S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = 0;
     S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = 0;
   }
-
+  
   itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
 
   return 0;
@@ -918,6 +1010,13 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t   assoc_id,
     return -1;
   }
 
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container,
+                             S1AP_ProtocolIE_ID_id_Cause, true);
+  if( ie == NULL ) {
+    S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(Cause)\n" );
+    return -1;
+  }
+
   S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container,
                              S1AP_ProtocolIE_ID_id_UE_S1AP_IDs, true);
 
@@ -965,9 +1064,26 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t   assoc_id,
       //#warning "TODO mapping mme_ue_s1ap_id  enb_ue_s1ap_id?"
 
       case S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID:
-        mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID;
-        S1AP_ERROR("TO DO mapping mme_ue_s1ap_id  enb_ue_s1ap_id");
-        (void)mme_ue_s1ap_id; /* TODO: remove - it's to remove gcc warning about unused var */
+        mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.mME_UE_S1AP_ID;
+        
+        RB_FOREACH(ue_desc_p, s1ap_ue_map, &mme_desc_p->s1ap_eNB_instance->s1ap_ue_head)
+        {
+          if( ue_desc_p->mme_ue_s1ap_id == mme_ue_s1ap_id )
+          {
+            enb_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id;
+            
+            message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND);
+            S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id;
+            itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
+            
+            return 0;
+          }
+        }
+        S1AP_ERROR("[SCTP %d] Received UE context release command(mME_UE_S1AP_ID) for non "
+                   "existing UE context 0x%06lx\n",
+                   assoc_id,
+                   mme_ue_s1ap_id);
+        return -1;
 
       case S1AP_UE_S1AP_IDs_PR_NOTHING:
       default:
@@ -975,12 +1091,10 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t   assoc_id,
         return -1;
     }
   } else {
+    S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(UE_S1AP_IDs)\n" );
     return -1;
   }
 
-  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container,
-                             S1AP_ProtocolIE_ID_id_Cause, true);
-  /* TBD */
 }
 
 static
@@ -999,7 +1113,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t         assoc_id,
   container = &pdu->choice.initiatingMessage.value.choice.E_RABSetupRequest;
 
   if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
-    S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
+    S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non "
                "existing MME context\n", assoc_id);
     return -1;
   }
@@ -1026,7 +1140,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t         assoc_id,
 
   if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
                    enb_ue_s1ap_id)) == NULL) {
-    S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
+   S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non "
                "existing UE context 0x%06lx\n", assoc_id,
                enb_ue_s1ap_id);
     return -1;
@@ -1099,6 +1213,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t         assoc_id,
 
     itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
   } else {
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -1119,13 +1234,6 @@ int s1ap_eNB_handle_paging(uint32_t               assoc_id,
   // received Paging Message from MME
   S1AP_DEBUG("[SCTP %d] Received Paging Message From MME\n",assoc_id);
 
-  /* Paging procedure -> stream != 0 */
-  if (stream == 0) {
-    LOG_W(S1AP,"[SCTP %d] Received Paging procedure on stream (%d)\n",
-          assoc_id, stream);
-    return -1;
-  }
-
   if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
     S1AP_ERROR("[SCTP %d] Received Paging for non "
                "existing MME context\n", assoc_id);
@@ -1153,6 +1261,7 @@ int s1ap_eNB_handle_paging(uint32_t               assoc_id,
     S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code = 0;
     S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi = 0;
   } else {
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -1180,6 +1289,7 @@ int s1ap_eNB_handle_paging(uint32_t               assoc_id,
           if(i != ie->value.choice.UEPagingID.choice.iMSI.size - 1) {
             /* invalid paging_p->uePagingID.choise.iMSI.buffer */
             S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI error(i %d 0x0F)\n", assoc_id,i);
+            itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
             return -1;
           }
         } else {
@@ -1190,14 +1300,17 @@ int s1ap_eNB_handle_paging(uint32_t               assoc_id,
       if (S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length >= S1AP_IMSI_LENGTH) {
         /* invalid paging_p->uePagingID.choise.iMSI.size */
         S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI.size(%d) is over IMSI length(%d)\n", assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length, S1AP_IMSI_LENGTH);
+        itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
         return -1;
       }
     } else { /* of if (ie->value.choice.UEPagingID.present == S1AP_UEPagingID_PR_iMSI) */
       /* invalid paging_p->uePagingID.present */
       S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.present(%d) is unknown\n", assoc_id, ie->value.choice.UEPagingID.present);
+      itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
       return -1;
     }
   } else { /* of ie != NULL */
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -1230,6 +1343,7 @@ int s1ap_eNB_handle_paging(uint32_t               assoc_id,
       return -1;
     }
   } else {
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -1257,6 +1371,7 @@ int s1ap_eNB_handle_paging(uint32_t               assoc_id,
                  S1AP_PAGING_IND(message_p).tac[i]);
     }
   } else {
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -1351,6 +1466,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t               assoc_id,
         S1AP_E_RAB_MODIFY_RESP(message_p).e_rabs_failed[nb_of_e_rabs_failed].cause_value = S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id;
       }
     } else {
+      itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
       return -1;
     }
 
@@ -1403,6 +1519,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t               assoc_id,
 
     itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
   } else { /* of if (ie != NULL)*/
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -1476,22 +1593,6 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t               assoc_id,
   message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_E_RAB_RELEASE_COMMAND);
   S1AP_E_RAB_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id;
   S1AP_E_RAB_RELEASE_COMMAND(message_p).mme_ue_s1ap_id = mme_ue_s1ap_id;
-  /* id-NAS-PDU */
-  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container,
-                             S1AP_ProtocolIE_ID_id_NAS_PDU, false);
-
-  if(ie && ie->value.choice.NAS_PDU.size > 0) {
-    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size;
-    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer =
-      malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size);
-    memcpy(S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer,
-           ie->value.choice.NAS_PDU.buf,
-           ie->value.choice.NAS_PDU.size);
-  } else {
-    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = 0;
-    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL;
-  }
-
   /* id-E-RABToBeReleasedList */
   S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container,
                              S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true);
@@ -1506,9 +1607,25 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t               assoc_id,
       S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID);
     }
   } else {
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
+  /* id-NAS-PDU */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container,
+                             S1AP_ProtocolIE_ID_id_NAS_PDU, false);
+
+  if(ie && ie->value.choice.NAS_PDU.size > 0) {
+    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size;
+    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer =
+      malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size);
+    memcpy(S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer,
+           ie->value.choice.NAS_PDU.buf,
+           ie->value.choice.NAS_PDU.size);
+  } else {
+    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = 0;
+    S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL;
+  }
   itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
   return 0;
 }
@@ -1533,7 +1650,6 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t               assoc_id,
   if (stream == 0) {
     S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream (%d)\n",
                assoc_id, stream);
-    //return -1;
   }
 
   if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
@@ -1550,6 +1666,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t               assoc_id,
   if (ie == NULL) {
     S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
                "ie context is NULL\n", assoc_id);
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -1572,6 +1689,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t               assoc_id,
   if (ie == NULL) {
     S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
                "ie context is NULL\n", assoc_id);
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -1589,6 +1707,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t               assoc_id,
   if (ie == NULL) {
     S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
                "ie context is NULL\n", assoc_id);
+    itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
     return -1;
   }
 
@@ -1602,14 +1721,10 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t               assoc_id,
                              S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, false);
 
   if (ie) {
-    OCTET_STRING_TO_INT32 (
-      &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
-      S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul
-    );
-    OCTET_STRING_TO_INT32 (
-      &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
-      S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl
-    );
+    asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
+                      &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul);
+    asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
+                      &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl);
   } else {
     S1AP_WARN("UEAggregateMaximumBitrate not supported\n");
     S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0;
@@ -1688,9 +1803,8 @@ int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t               assoc_
   pathSwitchRequestFailure = &pdu->choice.unsuccessfulOutcome.value.choice.PathSwitchRequestFailure;
 
   if (stream != 0) {
-    S1AP_ERROR("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n",
+    S1AP_WARN("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n",
                assoc_id, stream);
-    return -1;
   }
 
   if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
@@ -1754,3 +1868,144 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t               as
 	return 0;
 }
 
+//-----------------------------------------------------------------------------
+/*
+* eNB generate a S1 setup request towards MME
+*/
+static int s1ap_eNB_snd_s1_setup_request(
+  s1ap_eNB_instance_t *instance_p,
+  s1ap_eNB_mme_data_t *s1ap_mme_data_p)
+//-----------------------------------------------------------------------------
+{
+  S1AP_S1AP_PDU_t            pdu;
+  S1AP_S1SetupRequest_t     *out = NULL;
+  S1AP_S1SetupRequestIEs_t   *ie = NULL;
+  S1AP_SupportedTAs_Item_t   *ta = NULL;
+  S1AP_PLMNidentity_t      *plmn = NULL;
+  uint8_t  *buffer = NULL;
+  uint32_t  len = 0;
+  int       ret = 0;
+  uint32_t                 timer_kind = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(s1ap_mme_data_p != NULL);
+  s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
+  /* Prepare the S1AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_S1Setup;
+  pdu.choice.initiatingMessage.criticality = S1AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_S1SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.S1SetupRequest;
+  /* mandatory */
+  ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
+  ie->id = S1AP_ProtocolIE_ID_id_Global_ENB_ID;
+  ie->criticality = S1AP_Criticality_reject;
+  ie->value.present = S1AP_S1SetupRequestIEs__value_PR_Global_ENB_ID;
+  MCC_MNC_TO_PLMNID(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[0]],
+                    instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[0]],
+                    instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[0]],
+                    &ie->value.choice.Global_ENB_ID.pLMNidentity);
+  ie->value.choice.Global_ENB_ID.eNB_ID.present = S1AP_ENB_ID_PR_macroENB_ID;
+  MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
+                             &ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID);
+  S1AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
+            ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0],
+            ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1],
+            ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional */
+  if (instance_p->eNB_name) {
+    ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
+    ie->id = S1AP_ProtocolIE_ID_id_eNBname;
+    ie->criticality = S1AP_Criticality_ignore;
+    ie->value.present = S1AP_S1SetupRequestIEs__value_PR_ENBname;
+    OCTET_STRING_fromBuf(&ie->value.choice.ENBname, instance_p->eNB_name,
+                         strlen(instance_p->eNB_name));
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */
+  ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
+  ie->id = S1AP_ProtocolIE_ID_id_SupportedTAs;
+  ie->criticality = S1AP_Criticality_reject;
+  ie->value.present = S1AP_S1SetupRequestIEs__value_PR_SupportedTAs;
+  {
+    ta = (S1AP_SupportedTAs_Item_t *)calloc(1, sizeof(S1AP_SupportedTAs_Item_t));
+    INT16_TO_OCTET_STRING(instance_p->tac, &ta->tAC);
+    {
+      for (int i = 0; i < s1ap_mme_data_p->broadcast_plmn_num; ++i) {
+        plmn = (S1AP_PLMNidentity_t *)calloc(1, sizeof(S1AP_PLMNidentity_t));
+        MCC_MNC_TO_TBCD(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[i]],
+                        instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[i]],
+                        instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[i]],
+                        plmn);
+        ASN_SEQUENCE_ADD(&ta->broadcastPLMNs.list, plmn);
+      }
+    }
+    ASN_SEQUENCE_ADD(&ie->value.choice.SupportedTAs.list, ta);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  /* mandatory */
+  ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
+  ie->id = S1AP_ProtocolIE_ID_id_DefaultPagingDRX;
+  ie->criticality = S1AP_Criticality_ignore;
+  ie->value.present = S1AP_S1SetupRequestIEs__value_PR_PagingDRX;
+  ie->value.choice.PagingDRX = instance_p->default_drx;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional */
+  if (0) {
+    ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
+    ie->id = S1AP_ProtocolIE_ID_id_CSG_IdList;
+    ie->criticality = S1AP_Criticality_reject;
+    ie->value.present = S1AP_S1SetupRequestIEs__value_PR_CSG_IdList;
+    // ie->value.choice.CSG_IdList = ;
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* optional */
+#if (S1AP_VERSION >= MAKE_VERSION(13, 0, 0))
+
+  if (0) {
+    ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
+    ie->id = S1AP_ProtocolIE_ID_id_UE_RetentionInformation;
+    ie->criticality = S1AP_Criticality_ignore;
+    ie->value.present = S1AP_S1SetupRequestIEs__value_PR_UE_RetentionInformation;
+    // ie->value.choice.UE_RetentionInformation = ;
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* optional */
+  if (0) {
+    ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
+    ie->id = S1AP_ProtocolIE_ID_id_NB_IoT_DefaultPagingDRX;
+    ie->criticality = S1AP_Criticality_ignore;
+    ie->value.present = S1AP_S1SetupRequestIEs__value_PR_NB_IoT_DefaultPagingDRX;
+    // ie->value.choice.NB_IoT_DefaultPagingDRX = ;
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+#endif /* #if (S1AP_VERSION >= MAKE_VERSION(14, 0, 0)) */
+
+  if (s1ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    S1AP_ERROR("Failed to encode S1 setup request\n");
+    return -1;
+  }
+
+  timer_kind = s1ap_mme_data_p->cnx_id;
+  timer_kind = timer_kind | S1AP_MMEIND;
+  timer_kind = timer_kind | S1_SETRSP_WAIT;
+  
+  if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT,
+    NULL, &s1ap_mme_data_p->timer_id) < 0 )
+  {
+    S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id);
+  }
+  s1ap_mme_data_p->s1_setupreq_cnt++;
+
+  /* Non UE-Associated signalling -> stream = 0 */
+  s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0);
+  return ret;
+}
diff --git a/openair3/S1AP/s1ap_eNB_management_procedures.c b/openair3/S1AP/s1ap_eNB_management_procedures.c
index fc7ae70e4902073e3a5ceb70ccd9b4b93b4be2a8..a870e975a2d0f5fb6f6ca91e9f56f5b273fedbf1 100644
--- a/openair3/S1AP/s1ap_eNB_management_procedures.c
+++ b/openair3/S1AP/s1ap_eNB_management_procedures.c
@@ -95,23 +95,43 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
 {
   struct s1ap_eNB_mme_data_s  temp;
   struct s1ap_eNB_mme_data_s *found;
+  struct s1ap_eNB_mme_data_s *mme_p;
 
   memset(&temp, 0, sizeof(struct s1ap_eNB_mme_data_s));
 
   temp.assoc_id = assoc_id;
   temp.cnx_id   = cnx_id;
 
-  if (instance_p == NULL) {
-    STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head,
-                   s1ap_eNB_entries) {
-      found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
+  if( cnx_id != 0 ) {
+    if (instance_p == NULL) {
+      STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head,
+                     s1ap_eNB_entries) {
+        found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
 
-      if (found != NULL) {
-        return found;
+        if (found != NULL) {
+          return found;
+        }
       }
+    } else {
+      return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
     }
   } else {
-    return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
+    if (instance_p == NULL) {
+      STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head,
+                     s1ap_eNB_entries) {
+        RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
+          if( mme_p->assoc_id == assoc_id ) {
+            return mme_p;
+          }
+        }
+      }
+    } else {
+      RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
+        if( mme_p->assoc_id == assoc_id ) {
+          return mme_p;
+        }
+      }
+    }
   }
 
   return NULL;
diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c
index 919989897afc52cf85b9b042835aaae5ec7c1a78..b55bc06e11a4842a4d607023cb85f05f75ac8e95 100644
--- a/openair3/S1AP/s1ap_eNB_nas_procedures.c
+++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c
@@ -138,8 +138,8 @@ int s1ap_eNB_handle_nas_first_req(
          * identity, selects the MME with the highest capacity.
          */
         mme_desc_p = s1ap_eNB_nnsf_select_mme(
-                         instance_p,
-                         s1ap_nas_first_req_p->establishment_cause);
+                       instance_p,
+                       s1ap_nas_first_req_p->establishment_cause);
 
         if (mme_desc_p) {
             S1AP_INFO("[eNB %ld] Chose MME '%s' (assoc_id %d) through highest relative capacity\n",
@@ -358,10 +358,18 @@ int s1ap_eNB_handle_nas_downlink(uint32_t         assoc_id,
     container = &pdu->choice.initiatingMessage.value.choice.DownlinkNASTransport;
     S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container,
                                S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true);
+    if(ie == NULL)
+    {
+      return -1;
+    }
     mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
 
     S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container,
                                S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true);
+    if(ie == NULL)
+    {
+      return -1;
+    }
     enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;
 
     if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance,
@@ -416,6 +424,10 @@ int s1ap_eNB_handle_nas_downlink(uint32_t         assoc_id,
 
     S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container,
                                S1AP_ProtocolIE_ID_id_NAS_PDU, true);
+    if(ie == NULL)
+    {
+      return -1;
+    }
     /* Forward the NAS PDU to RRC */
     s1ap_eNB_itti_send_nas_downlink_ind(s1ap_eNB_instance->instance,
                                         ue_desc_p->ue_initial_id,
@@ -494,9 +506,9 @@ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_
     ie->criticality = S1AP_Criticality_ignore;
     ie->value.present = S1AP_UplinkNASTransport_IEs__value_PR_EUTRAN_CGI;
     MCC_MNC_TO_PLMNID(
-        s1ap_eNB_instance_p->mcc[ue_context_p->selected_plmn_identity],
-        s1ap_eNB_instance_p->mnc[ue_context_p->selected_plmn_identity],
-        s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->selected_plmn_identity],
+        s1ap_eNB_instance_p->mcc[ue_context_p->mme_ref->broadcast_plmn_index[0]],
+        s1ap_eNB_instance_p->mnc[ue_context_p->mme_ref->broadcast_plmn_index[0]],
+        s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->mme_ref->broadcast_plmn_index[0]],
         &ie->value.choice.EUTRAN_CGI.pLMNidentity);
     //#warning "TODO get cell id from RRC"
     MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id,
diff --git a/openair3/S1AP/s1ap_eNB_nnsf.c b/openair3/S1AP/s1ap_eNB_nnsf.c
index 6319f6e054d878fb19087e0c3f3fa8e946a6d602..a5a4e747344a08d8ebf81dddcaca44c1cbdd73e6 100644
--- a/openair3/S1AP/s1ap_eNB_nnsf.c
+++ b/openair3/S1AP/s1ap_eNB_nnsf.c
@@ -36,15 +36,29 @@
 #include "s1ap_eNB_defs.h"
 #include "s1ap_eNB_nnsf.h"
 
+
+typedef struct MME_nnsf_inf {
+  struct s1ap_eNB_mme_data_s *mme_p;
+  uint64_t weight;
+} MME_nnsf_inf_t;
+
 struct s1ap_eNB_mme_data_s *
 s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t       *instance_p,
                          rrc_establishment_cause_t  cause)
 {
   struct s1ap_eNB_mme_data_s *mme_data_p = NULL;
   struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL;
-  uint8_t current_capacity = 0;
-
+  
+  uint16_t capacity_sum = 0;
+  MME_nnsf_inf_t mme_inf[10];
+  int       cnt;
+  int       nb_mme = 0;
+  uint64_t  weight = 0;
+  
+  memset(mme_inf, 0, sizeof(mme_inf));
+  
   RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
+    capacity_sum = capacity_sum + mme_data_p->relative_mme_capacity;
     if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) {
       /* The association between MME and eNB is not ready for the moment,
        * go to the next known MME.
@@ -69,7 +83,8 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t       *instance_p,
                 || (cause == RRC_CAUSE_HIGH_PRIO_ACCESS))) {
           continue;
         }
-
+        mme_inf[nb_mme].mme_p = mme_data_p;
+        nb_mme++;
         /* At this point, the RRC establishment can be handled by the MME
          * even if it is in overload state.
          */
@@ -78,14 +93,27 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t       *instance_p,
         continue;
       }
     }
-
-    if (current_capacity < mme_data_p->relative_mme_capacity) {
-      /* We find a better MME, keep a reference to it */
-      current_capacity = mme_data_p->relative_mme_capacity;
-      mme_highest_capacity_p = mme_data_p;
+  }
+  
+  if( nb_mme != 0 ) {
+    for( cnt = 0 ; cnt < nb_mme ; cnt++ ) {
+      mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity;
+      mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1);
+    }
+    mme_highest_capacity_p = mme_inf[0].mme_p;
+    weight = mme_inf[0].weight;
+    for( cnt = 1 ; cnt < nb_mme ; cnt++ ) {
+      if( weight > mme_inf[cnt].weight ) {
+        mme_highest_capacity_p = mme_inf[cnt].mme_p;
+        weight = mme_inf[cnt].weight;
+      }
     }
+  } else {
+    mme_highest_capacity_p = NULL;
+  }
+  if( mme_highest_capacity_p != NULL ) {
+    mme_highest_capacity_p->nb_calls++;
   }
-
   return mme_highest_capacity_p;
 }
 
@@ -96,8 +124,15 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t       *instance_p,
 {
   struct s1ap_eNB_mme_data_s *mme_data_p = NULL;
   struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL;
-  uint8_t current_capacity = 0;
-
+  
+  uint16_t capacity_sum = 0;
+  MME_nnsf_inf_t mme_inf[10];
+  int       cnt;
+  int       nb_mme = 0;
+  uint64_t  weight = 0;
+  
+  memset(mme_inf, 0, sizeof(mme_inf));
+  
   RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
     struct served_gummei_s *gummei_p = NULL;
     struct plmn_identity_s *served_plmn_p = NULL;
@@ -140,6 +175,8 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t       *instance_p,
       STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) {
         if ((served_plmn_p->mcc == instance_p->mcc[selected_plmn_identity]) &&
             (served_plmn_p->mnc == instance_p->mnc[selected_plmn_identity])) {
+          mme_inf[nb_mme].mme_p = mme_data_p;
+          nb_mme++;
           break;
         }
       }
@@ -148,14 +185,27 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t       *instance_p,
     }
     /* if we didn't find such a served PLMN, go on with the next MME */
     if (!served_plmn_p) continue;
+  }
 
-    if (current_capacity < mme_data_p->relative_mme_capacity) {
-      /* We find a better MME, keep a reference to it */
-      current_capacity = mme_data_p->relative_mme_capacity;
-      mme_highest_capacity_p = mme_data_p;
+  if( nb_mme != 0 ) {
+    for( cnt = 0 ; cnt < nb_mme ; cnt++ ) {
+      mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity;
+      mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1);
+    }
+    mme_highest_capacity_p = mme_inf[0].mme_p;
+    weight = mme_inf[0].weight;
+    for( cnt = 1 ; cnt < nb_mme ; cnt++ ) {
+      if( weight > mme_inf[cnt].weight ) {
+        mme_highest_capacity_p = mme_inf[cnt].mme_p;
+        weight = mme_inf[cnt].weight;
+      }
     }
+  } else {
+    mme_highest_capacity_p = NULL;
+  }
+  if( mme_highest_capacity_p != NULL ) {
+    mme_highest_capacity_p->nb_calls++;
   }
-
   return mme_highest_capacity_p;
 }
 
diff --git a/openair3/S1AP/s1ap_eNB_overload.c b/openair3/S1AP/s1ap_eNB_overload.c
index 9358ae62bdb6286873240f3194af9e609921172f..64d3fcdf65943c3b8f8d939f2072b943df3ef272 100644
--- a/openair3/S1AP/s1ap_eNB_overload.c
+++ b/openair3/S1AP/s1ap_eNB_overload.c
@@ -62,8 +62,16 @@ int s1ap_eNB_handle_overload_start(uint32_t         assoc_id,
                  S1AP_OverloadResponse_PR_overloadAction,
                  S1AP_OverloadResponse_PR_overloadAction, 0, 0);
     }
+    else
+    {
+        return -1;
+    }
     /* Non UE-associated signalling -> stream 0 */
-    DevCheck(stream == 0, stream, 0, 0);
+    if (stream != 0) {
+      S1AP_ERROR("[SCTP %d] Received s1 overload start on stream != 0 (%d)\n",
+                 assoc_id, stream);
+      return -1;
+    }
 
     if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
         /* No MME context associated */
@@ -93,7 +101,11 @@ int s1ap_eNB_handle_overload_stop(uint32_t         assoc_id,
     s1ap_eNB_mme_data_t *mme_desc_p;
 
     /* Non UE-associated signalling -> stream 0 */
-    DevCheck(stream == 0, stream, 0, 0);
+    if (stream != 0) {
+      S1AP_ERROR("[SCTP %d] Received s1 overload stop on stream != 0 (%d)\n",
+                 assoc_id, stream);
+      return -1;
+    }
 
     if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
         /* No MME context associated */
diff --git a/openair3/S1AP/s1ap_eNB_trace.c b/openair3/S1AP/s1ap_eNB_trace.c
index 19f50592386843fb774cf8bc3adbbd35b728cfb1..695eeb4ef836a340f4639153ba06699172596f0b 100644
--- a/openair3/S1AP/s1ap_eNB_trace.c
+++ b/openair3/S1AP/s1ap_eNB_trace.c
@@ -121,6 +121,10 @@ int s1ap_eNB_handle_trace_start(uint32_t         assoc_id,
   if (ie != NULL) {
     ue_desc_p = s1ap_eNB_get_ue_context(mme_ref_p->s1ap_eNB_instance,
                                         ie->value.choice.ENB_UE_S1AP_ID);
+  }
+  else
+  {
+    return -1;
   }
     if (ue_desc_p == NULL) {
         /* Could not find context associated with this eNB_ue_s1ap_id -> generate
diff --git a/openair3/SCTP/sctp_default_values.h b/openair3/SCTP/sctp_default_values.h
index 528ffb5a05114aea3c37ea584e8a55f871210ddc..0f8f94dca9b9e36be5b36379e67840b5bc53c900 100644
--- a/openair3/SCTP/sctp_default_values.h
+++ b/openair3/SCTP/sctp_default_values.h
@@ -24,8 +24,8 @@
 
 #define SCTP_OUT_STREAMS        (16)
 #define SCTP_IN_STREAMS         (16)
-#define SCTP_MAX_ATTEMPTS       (2)
-#define SCTP_TIMEOUT            (5)
+#define SCTP_MAX_ATTEMPTS       (8)
+#define SCTP_TIMEOUT            (60000)
 #define SCTP_RECV_BUFFER_SIZE   (8192)
 
 #endif /* SCTP_DEFAULT_VALUES_H_ */
diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c
index 2f732443bea0e9086fa79e2e8c61177dad9586ef..af49c5c350d9cde5d6db36ffb31c78cb9749ca48 100644
--- a/openair3/SCTP/sctp_eNB_task.c
+++ b/openair3/SCTP/sctp_eNB_task.c
@@ -270,7 +270,7 @@ sctp_handle_new_association_req_multi(
                            sctp_new_association_req_p->remote_address.ipv6_address);
                 //close(sd);
                 //return;
-                exit(1);
+                exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error");
             }
 
             SCTP_DEBUG("Converted ipv6 address %*s to network type\n",
@@ -290,7 +290,7 @@ sctp_handle_new_association_req_multi(
                            sctp_new_association_req_p->remote_address.ipv4_address);
                 //close(sd);
                 //return;
-                exit(1);
+                exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error");
             }
 
             SCTP_DEBUG("Converted ipv4 address %*s to network type\n",
@@ -329,7 +329,7 @@ sctp_handle_new_association_req_multi(
     if (ns == -1) {
       perror("sctp_peeloff");
       printf("sctp_peeloff: sd=%d assoc_id=%d\n", sd, assoc_id);
-      exit(1);
+      exit_fun("sctp_handle_new_association_req_multi fatal: sctp_peeloff error");
     }
 
     sctp_cnx = calloc(1, sizeof(*sctp_cnx));
@@ -943,10 +943,12 @@ sctp_eNB_read_from_socket(
                      &sinfo, &flags);
 
     if (n < 0) {
-        if (errno == ENOTCONN) {
+        if( (errno == ENOTCONN) || (errno == ECONNRESET) || (errno == ETIMEDOUT) || (errno == ECONNREFUSED) )
+        {
             itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd);
 
             SCTP_DEBUG("Received not connected for sd %d\n", sctp_cnx->sd);
+            SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno);
 
             sctp_itti_send_association_resp(
                 sctp_cnx->task_id, sctp_cnx->instance, -1,
@@ -969,7 +971,7 @@ sctp_eNB_read_from_socket(
 
     if (!(flags & MSG_EOR)) {
       SCTP_ERROR("fatal: partial SCTP messages are not handled\n");
-      exit(1);
+      exit_fun("fatal: partial SCTP messages are not handled" );
     }
 
     if (flags & MSG_NOTIFICATION) {
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index dd29d01fae751ebc527ea59dc1423ed29475150f..61a742af657e1023e59bd99bb3a6d60bbfe3a33f 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -1110,7 +1110,7 @@ extern "C" {
   
       case 46080000:
         //openair0_cfg[0].samples_per_packet    = 2048;
-        openair0_cfg[0].tx_sample_advance     = 15;
+        openair0_cfg[0].tx_sample_advance     = 65;
         openair0_cfg[0].tx_bw                 = 40e6;
         openair0_cfg[0].rx_bw                 = 40e6;
         break;
@@ -1125,7 +1125,7 @@ extern "C" {
   
       case 15360000:
         //openair0_cfg[0].samples_per_packet    = 2048;
-        openair0_cfg[0].tx_sample_advance     = 45;
+        openair0_cfg[0].tx_sample_advance     = 40;
         openair0_cfg[0].tx_bw                 = 10e6;
         openair0_cfg[0].rx_bw                 = 10e6;
         break;
diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c
index daf0133af20b1540c8c0786e499230f2333f7776..dcea69b9ddfe8c0f166423475a825edde3c8b6fe 100644
--- a/targets/ARCH/rfsimulator/stored_node.c
+++ b/targets/ARCH/rfsimulator/stored_node.c
@@ -200,7 +200,10 @@ int main(int argc, char *argv[]) {
   int bufSize=100000;
   void *buff=malloc(bufSize);
   uint64_t timestamp=0;
-  const int blockSize=1000;
+  const int blockSize=1920;
+
+  // If fileSize is not multiple of blockSize*4 then discard remaining samples
+  fileSize = (fileSize/(blockSize<<2))*(blockSize<<2);
 
   while (1) {
     //Rewind the file to loop on the samples
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf
index 9e13d493a8acc095e27d134e2b6d6e0dbaf0ca8b..32de0aa4f57d6ea6d05d8625fc93b547056db0dc 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf
@@ -225,14 +225,15 @@ MACRLCs = (
   num_cc = 1;
   tr_s_preference = "local_L1";
   tr_n_preference = "local_RRC";
-        }
+  }
 );
 
 L1s = (
-      {
+  {
   num_cc = 1;
   tr_n_preference = "local_mac";
-        }
+  pusch_proc_threads = 8;
+  }
 );
 
 RUs = (
@@ -246,8 +247,15 @@ RUs = (
          max_pdschReferenceSignalPower = -27;
          max_rxgain                    = 75;
          eNB_instances  = [0];
-         #beamforming 1x4 matrix:
-         bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
+         ##beamforming 1x2 matrix: 1 layer x 2 antennas
+         bf_weights = [0x00007fff, 0x0000];
+         ##beamforming 1x4 matrix: 1 layer x 4 antennas
+         #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
+         ## beamforming 2x2 matrix:
+         # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+         ## beamforming 4x4 matrix:
+         #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
+
          sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2";
          clock_src = "external";
          # if_freq = 3700000000L;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf
index 831f9c7978f738041d2e7242e04b63efd1cf4ac0..307cf52cb3074340a767a16c1e9aece217d3e6f1 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf
@@ -225,14 +225,15 @@ MACRLCs = (
   num_cc = 1;
   tr_s_preference = "local_L1";
   tr_n_preference = "local_RRC";
-        }
+  }
 );
 
 L1s = (
-      {
+  {
   num_cc = 1;
   tr_n_preference = "local_mac";
-        }
+  pusch_proc_threads = 8;
+  }
 );
 
 RUs = (
@@ -246,8 +247,15 @@ RUs = (
          max_pdschReferenceSignalPower = -27;
          max_rxgain                    = 114;
          eNB_instances  = [0];
-         #beamforming 1x4 matrix:
-         bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
+         ##beamforming 1x2 matrix: 1 layer x 2 antennas
+         bf_weights = [0x00007fff, 0x0000];
+         ##beamforming 1x4 matrix: 1 layer x 4 antennas
+         #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
+         ## beamforming 2x2 matrix:
+         # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+         ## beamforming 4x4 matrix:
+         #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
+
          sdr_addrs = "type=x300";
          clock_src = "external";
          # if_freq = 3700000000L;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf
new file mode 100644
index 0000000000000000000000000000000000000000..deed91c93cae122e5cc70a96e2c95fc148b1972e
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf
@@ -0,0 +1,331 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+   ////////// Identification parameters:
+   gNB_ID    =  0xe00;
+
+   cell_type =  "CELL_MACRO_GNB";
+
+   gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+   // Tracking area code, 0x0000 and 0xfffe are reserved values
+   tracking_area_code  =  1;
+
+   plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});
+
+   tr_s_preference     = "local_mac"
+
+   ////////// Physical parameters:
+
+   ssb_SubcarrierOffset                                           = 0;
+   pdsch_AntennaPorts                                             = 1;
+
+   servingCellConfigCommon = (
+   {
+     #spCellConfigCommon
+
+     physCellId                                                    = 0;
+
+     # downlinkConfigCommon
+     # frequencyInfoDL
+     # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
+     absoluteFrequencySSB                                          = 641032;
+     dl_frequencyBand                                              = 78;
+     # this is 3600 MHz
+     dl_absoluteFrequencyPointA                                    = 640000;
+     #scs-SpecificCarrierList
+     dl_offstToCarrier                                             = 0;
+     # subcarrierSpacing
+     # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+     dl_subcarrierSpacing                                          = 1;
+     dl_carrierBandwidth                                           = 106;
+     #initialDownlinkBWP
+     #genericParameters
+     # this is RBstart=0,L=50 (275*(L-1))+RBstart
+     initialDLBWPlocationAndBandwidth                              = 6366;
+     # subcarrierSpacing
+     # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+     initialDLBWPsubcarrierSpacing                                 = 1;
+     #pdcch-ConfigCommon
+     initialDLBWPcontrolResourceSetZero                            = 12;
+     initialDLBWPsearchSpaceZero                                   = 0;
+     #pdsch-ConfigCommon
+     #pdschTimeDomainAllocationList (up to 16 entries)
+     initialDLBWPk0_0                                              = 0;
+     #initialULBWPmappingType
+     #0=typeA,1=typeB
+     initialDLBWPmappingType_0                                     = 0;
+     #this is SS=1,L=13
+     initialDLBWPstartSymbolAndLength_0                            = 40;
+
+     initialDLBWPk0_1                                              = 0;
+     initialDLBWPmappingType_1                                     = 0;
+     #this is SS=2,L=12
+     initialDLBWPstartSymbolAndLength_1                            = 53;
+
+     initialDLBWPk0_2                                              = 0;
+     initialDLBWPmappingType_2                                     = 0;
+     #this is SS=1,L=12
+     initialDLBWPstartSymbolAndLength_2                            = 54;
+
+     initialDLBWPk0_3                                              = 0;
+     initialDLBWPmappingType_3                                     = 0;
+     #this is SS=1,L=4
+     initialDLBWPstartSymbolAndLength_3                            = 57;
+
+     #uplinkConfigCommon
+     #frequencyInfoUL
+     ul_frequencyBand                                              = 78;
+     #scs-SpecificCarrierList
+     ul_offstToCarrier                                             = 0;
+     # subcarrierSpacing
+     # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+     ul_subcarrierSpacing                                          = 1;
+     ul_carrierBandwidth                                           = 106;
+     pMax                                                          = 20;
+     #initialUplinkBWP
+     #genericParameters
+     initialULBWPlocationAndBandwidth                              = 6366;
+     # subcarrierSpacing
+     # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+     initialULBWPsubcarrierSpacing                                 = 1;
+     #rach-ConfigCommon
+     #rach-ConfigGeneric
+     prach_ConfigurationIndex                                      = 98;
+     #prach_msg1_FDM
+     #0 = one, 1=two, 2=four, 3=eight
+     prach_msg1_FDM                                                = 0;
+     prach_msg1_FrequencyStart                                     = 0;
+     zeroCorrelationZoneConfig                                     = 13;
+     preambleReceivedTargetPower                                   = -118;
+     #preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+     preambleTransMax                                              = 6;
+     #powerRampingStep
+     # 0=dB0,1=dB2,2=dB4,3=dB6
+     powerRampingStep                                              = 1;
+     #ra_ReponseWindow
+     #1,2,4,8,10,20,40,80
+     ra_ResponseWindow                                             = 4;
+     #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+     #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+     ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR                  = 4;
+     #oneHalf (0..15) 4,8,12,16,...60,64
+     ssb_perRACH_OccasionAndCB_PreamblesPerSSB                     = 15;
+     #ra_ContentionResolutionTimer
+     #(0..7) 8,16,24,32,40,48,56,64
+     ra_ContentionResolutionTimer                                  = 7;
+     rsrp_ThresholdSSB                                             = 19;
+     #prach-RootSequenceIndex_PR
+     #1 = 839, 2 = 139
+     prach_RootSequenceIndex_PR                                    = 2;
+     prach_RootSequenceIndex                                       = 1;
+     # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+     #
+     msg1_SubcarrierSpacing                                        = 1,
+     # restrictedSetConfig
+     # 0=unrestricted, 1=restricted type A, 2=restricted type B
+     restrictedSetConfig                                           = 0,
+
+     # pusch-ConfigCommon (up to 16 elements)
+     initialULBWPk2_0                                              = 6;
+     initialULBWPmappingType_0                                     = 1
+     # this is SS=0 L=11
+     initialULBWPstartSymbolAndLength_0                            = 55;
+
+     initialULBWPk2_1                                              = 6;
+     initialULBWPmappingType_1                                     = 1;
+     # this is SS=0 L=12
+     initialULBWPstartSymbolAndLength_1                            = 69;
+     initialULBWPk2_2                                              = 7;
+     initialULBWPmappingType_2                                     = 1;
+     # this is SS=10 L=4
+     initialULBWPstartSymbolAndLength_2                            = 52;
+
+     msg3_DeltaPreamble                                            = 1;
+     p0_NominalWithGrant                                           =-90;
+
+     # pucch-ConfigCommon setup :
+     # pucchGroupHopping
+     # 0 = neither, 1= group hopping, 2=sequence hopping
+     pucchGroupHopping                                             = 0;
+     hoppingId                                                     = 40;
+     p0_nominal                                                    = -90;
+     # ssb_PositionsInBurs_BitmapPR
+     # 1=short, 2=medium, 3=long
+     ssb_PositionsInBurst_PR                                       = 2;
+     ssb_PositionsInBurst_Bitmap                                   = 1;
+
+     # ssb_periodicityServingCell
+     # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
+     ssb_periodicityServingCell                                    = 2;
+
+     # dmrs_TypeA_position
+     # 0 = pos2, 1 = pos3
+     dmrs_TypeA_Position                                           = 0;
+
+     # subcarrierSpacing
+     # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+     subcarrierSpacing                                             = 1;
+
+
+      #tdd-UL-DL-ConfigurationCommon
+      # subcarrierSpacing
+      # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+      referenceSubcarrierSpacing                                    = 1;
+      # pattern1
+      # dl_UL_TransmissionPeriodicity
+      # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+      dl_UL_TransmissionPeriodicity                                 = 6;
+      nrofDownlinkSlots                                             = 7;
+      nrofDownlinkSymbols                                           = 6;
+      nrofUplinkSlots                                               = 2;
+      nrofUplinkSymbols                                             = 4;
+
+      ssPBCH_BlockPower                                             = 10;
+  }
+
+  );
+
+ # Dedicated Serving Cell Configuration
+  servingCellConfigDedicated = (
+  {
+    # DL PTRS related parameters.
+    # 3GPP TS 38.331 PTRS-DownlinkConfig
+
+    # frequencyDensity value range: 1-276
+    dl_ptrsFreqDensity0_0                                           = 25;
+    dl_ptrsFreqDensity1_0                                           = 75;
+
+    # timeDensity value range: 0-29
+    dl_ptrsTimeDensity0_0                                           =  2;
+    dl_ptrsTimeDensity1_0                                           =  4;
+    dl_ptrsTimeDensity2_0                                           = 10;
+
+    # epre_Ratio
+    # 0 = "00", 1 = "01" in TS 38.214, table 4.1-2
+    dl_ptrsEpreRatio_0                                              =  0;
+
+    # resourceElementOffset
+    # 0 = offset01 1 = offset02, 2 = offset02
+    # 3GPP TS 38.331 PTRS-DownlinkConfig; TS 38.211 sec. 7.4.1.2.2
+    dl_ptrsReOffset_0                                               =  0;
+
+    # UL PTRS related parameters.
+    # 3GPP TS 38.331 PTRS-UplinkConfig
+
+    # frequencyDensity value range: 1-276
+    ul_ptrsFreqDensity0_0                                           = 25;
+    ul_ptrsFreqDensity1_0                                           = 75;
+
+    # timeDensity value range: 0-29
+    ul_ptrsTimeDensity0_0                                           =  2;
+    ul_ptrsTimeDensity1_0                                           =  4;
+    ul_ptrsTimeDensity2_0                                           = 10;
+
+    # resourceElementOffset
+    # 0 = offset01 1 = offset02, 2 = offset02
+    # TS 38.331 PTRS-UplinkConfig; TS 38.211 sec. 6.4.1.2.2.1
+    ul_ptrsReOffset_0                                               =  0;
+
+    # maxNrofPorts
+    # 0 = n1, 1 = n2
+    ul_ptrsMaxPorts_0                                               =  0;
+
+    # ptrs-Power
+    # 0 = p00, 1 = p01, 2 = p10, 3 = p11
+    #ul_ptrsPower_0                                                 =  0;
+    }
+  );
+
+  # ------- SCTP definitions
+  SCTP :
+  {
+      # Number of streams to use in input/output
+      SCTP_INSTREAMS  = 2;
+      SCTP_OUTSTREAMS = 2;
+  };
+
+
+  ////////// MME parameters:
+  mme_ip_address      = ( { ipv4       = "192.168.12.26";
+                            ipv6       = "192:168:30::17";
+                            active     = "yes";
+                            preference = "ipv4";
+                          }
+                        );
+
+  NETWORK_INTERFACES :
+  {
+
+      GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+      GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
+      GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+      GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
+      GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+  };
+ }
+);
+
+MACRLCs = (
+ {
+  num_cc = 1;
+  tr_s_preference = "local_L1";
+  tr_n_preference = "local_RRC";
+  }
+);
+
+L1s = (
+ {
+   num_cc = 1;
+   tr_n_preference = "local_mac";
+ }
+);
+
+RUs = (
+ {
+   local_rf       = "yes"
+   nb_tx          = 1
+   nb_rx          = 1
+   att_tx         = 0
+   att_rx         = 0;
+   bands          = [7];
+   max_pdschReferenceSignalPower = -27;
+   max_rxgain                    = 114;
+   eNB_instances  = [0];
+   #beamforming 1x4 matrix:
+   bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
+   sdr_addrs = "type=x300";
+   clock_src = "external";
+  }
+);
+
+THREAD_STRUCT = (
+ {
+   #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+   parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+   #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+   worker_config      = "WORKER_ENABLE";
+ }
+);
+
+log_config :
+{
+  global_log_level                      ="info";
+  global_log_verbosity                  ="medium";
+  hw_log_level                          ="info";
+  hw_log_verbosity                      ="medium";
+  phy_log_level                         ="info";
+  phy_log_verbosity                     ="medium";
+  mac_log_level                         ="info";
+  mac_log_verbosity                     ="high";
+  rlc_log_level                         ="info";
+  rlc_log_verbosity                     ="medium";
+  pdcp_log_level                        ="info";
+  pdcp_log_verbosity                    ="medium";
+  rrc_log_level                         ="info";
+  rrc_log_verbosity                     ="medium";
+};
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
index 760689f653f19bb50f79afd99850d53a46784437..c77497dedd6406ac68d0251fbdf35b6055718ba1 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -226,15 +226,15 @@ MACRLCs = (
 	num_cc = 1;
 	tr_s_preference = "local_L1";
 	tr_n_preference = "local_RRC";
-        }  
+	}
 );
 
 L1s = (
-    	{
+	{
 	num_cc = 1;
 	tr_n_preference = "local_mac";
-  pusch_proc_threads = 8;
-        }  
+	pusch_proc_threads = 8;
+	}
 );
 
 RUs = (
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
index d38fff42419efb95e1f4ecdee4ce4bc0d66ab98a..b3fdd7947518d9eea2bb4fbfff9ccb22ed373736 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
@@ -23,7 +23,7 @@ gNBs =
 
     ssb_SubcarrierOffset                                      = 0;
     pdsch_AntennaPorts                                        = 1;
-	
+
     servingCellConfigCommon = (
     {
  #spCellConfigCommon
@@ -135,18 +135,17 @@ gNBs =
         initialULBWPmappingType_0             = 1
         # this is SS=0 L=11
         initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 6;
+
+        initialULBWPk2_1                      = 6;
         initialULBWPmappingType_1             = 1;
         # this is SS=0 L=12
         initialULBWPstartSymbolAndLength_1    = 69;
 
-	initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;
         initialULBWPmappingType_2             = 1;
         # this is SS=10 L=4
         initialULBWPstartSymbolAndLength_2    = 52;
 
-
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
 
@@ -227,14 +226,15 @@ MACRLCs = (
 	num_cc = 1;
 	tr_s_preference = "local_L1";
 	tr_n_preference = "local_RRC";
-        }  
+	}
 );
 
 L1s = (
-    	{
+	{
 	num_cc = 1;
 	tr_n_preference = "local_mac";
-        }  
+	pusch_proc_threads = 8;
+	}
 );
 
 RUs = (
@@ -248,8 +248,15 @@ RUs = (
          max_pdschReferenceSignalPower = -27;
          max_rxgain                    = 114;
          eNB_instances  = [0];
-         #beamforming 1x4 matrix:
-         bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
+         ##beamforming 1x2 matrix: 1 layer x 2 antennas
+         bf_weights = [0x00007fff, 0x0000];
+         ##beamforming 1x4 matrix: 1 layer x 4 antennas
+         #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
+         ## beamforming 2x2 matrix:
+         # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+         ## beamforming 4x4 matrix:
+         #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
+
          sdr_addrs = "type=x300";
          clock_src = "external";
     }
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf
new file mode 100644
index 0000000000000000000000000000000000000000..9f69849acec8eddbe9679c22641758f99917414f
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf
@@ -0,0 +1,292 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});	 
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    ssb_SubcarrierOffset                                      = 0;
+    pdsch_AntennaPorts                                        = 1;
+	
+    servingCellConfigCommon = (
+    {
+ #spCellConfigCommon
+
+      physCellId                                                    = 0;
+
+#  downlinkConfigCommon
+    #frequencyInfoDL
+      # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
+      absoluteFrequencySSB                                          = 640288;
+      dl_frequencyBand                                                 = 78;
+      # this is 3600 MHz
+      dl_absoluteFrequencyPointA                                       = 640000;
+      #scs-SpecificCarrierList
+        dl_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        dl_subcarrierSpacing                                           = 1;
+        dl_carrierBandwidth                                            = 24;
+     #initialDownlinkBWP
+      #genericParameters
+        # this is RBstart=41,L=24 (275*(L-1))+RBstart
+        initialDLBWPlocationAndBandwidth                                        = 6325;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialDLBWPsubcarrierSpacing                                           = 1;
+      #pdcch-ConfigCommon
+        initialDLBWPcontrolResourceSetZero                                      = 0;
+        initialDLBWPsearchSpaceZero                                             = 0;
+      #pdsch-ConfigCommon
+        #pdschTimeDomainAllocationList (up to 16 entries)
+             initialDLBWPk0_0                    = 0;
+             #initialULBWPmappingType
+	     #0=typeA,1=typeB
+             initialDLBWPmappingType_0           = 0;
+             #this is SS=1,L=13
+             initialDLBWPstartSymbolAndLength_0  = 40;
+
+             initialDLBWPk0_1                    = 0;
+             initialDLBWPmappingType_1           = 0;
+             #this is SS=2,L=12 
+             initialDLBWPstartSymbolAndLength_1  = 53;
+
+             initialDLBWPk0_2                    = 0;
+             initialDLBWPmappingType_2           = 0;
+             #this is SS=1,L=12 
+             initialDLBWPstartSymbolAndLength_2  = 54;
+
+             initialDLBWPk0_3                    = 0;
+             initialDLBWPmappingType_3           = 0;
+             #this is SS=1,L=5
+             initialDLBWPstartSymbolAndLength_3  = 57;
+
+  #uplinkConfigCommon 
+     #frequencyInfoUL
+      ul_frequencyBand                                                 = 78;
+      #scs-SpecificCarrierList
+      ul_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      ul_subcarrierSpacing                                           = 1;
+      ul_carrierBandwidth                                            = 24;
+      pMax                                                          = 20;
+     #initialUplinkBWP
+      #genericParameters
+        initialULBWPlocationAndBandwidth                                        = 6325;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialULBWPsubcarrierSpacing                                           = 1;
+      #rach-ConfigCommon
+        #rach-ConfigGeneric
+          prach_ConfigurationIndex                                  = 98;
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+          prach_msg1_FDM                                            = 0;
+          prach_msg1_FrequencyStart                                 = 0;
+          zeroCorrelationZoneConfig                                 = 13;
+          preambleReceivedTargetPower                               = -118;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+          preambleTransMax                                          = 6;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+        powerRampingStep                                            = 1;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+        ra_ResponseWindow                                           = 4;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR                = 4;
+#oneHalf (0..15) 4,8,12,16,...60,64
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB                   = 15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+        ra_ContentionResolutionTimer                                = 7;
+        rsrp_ThresholdSSB                                           = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+        prach_RootSequenceIndex_PR                                  = 2;
+        prach_RootSequenceIndex                                     = 1;
+        # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+        #  
+        msg1_SubcarrierSpacing                                      = 1,
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+        restrictedSetConfig                                         = 0,
+
+      # pusch-ConfigCommon (up to 16 elements)
+        initialULBWPk2_0                      = 6;
+        initialULBWPmappingType_0             = 1
+        # this is SS=0 L=11
+        initialULBWPstartSymbolAndLength_0    = 55;
+
+        initialULBWPk2_1                      = 6;
+        initialULBWPmappingType_1             = 1;
+        # this is SS=0 L=12
+        initialULBWPstartSymbolAndLength_1    = 69;
+
+        initialULBWPk2_2                      = 7;
+        initialULBWPmappingType_2             = 1;
+        # this is SS=10 L=4
+        initialULBWPstartSymbolAndLength_2    = 52;
+
+        msg3_DeltaPreamble                                          = 1;
+        p0_NominalWithGrant                                         =-90;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+        pucchGroupHopping                                           = 0;
+        hoppingId                                                   = 40;
+        p0_nominal                                                  = -90;
+# ssb_PositionsInBurs_BitmapPR
+# 1=short, 2=medium, 3=long
+      ssb_PositionsInBurst_PR                                       = 2;
+      ssb_PositionsInBurst_Bitmap                                   = 1;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 
+      ssb_periodicityServingCell                                    = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+      dmrs_TypeA_Position                                           = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      subcarrierSpacing                                             = 1;
+
+
+  #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      referenceSubcarrierSpacing                                    = 1;
+      # pattern1 
+      # dl_UL_TransmissionPeriodicity
+      # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+      dl_UL_TransmissionPeriodicity                                 = 6;
+      nrofDownlinkSlots                                             = 7;
+      nrofDownlinkSymbols                                           = 6;
+      nrofUplinkSlots                                               = 2;
+      nrofUplinkSymbols                                             = 4;
+
+  ssPBCH_BlockPower                                             = 10;
+  }
+
+  );
+
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.12.26";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
+        GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+	pusch_proc_threads = 8;
+        }  
+);
+
+RUs = (
+    {		  
+         local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 75;
+         eNB_instances  = [0];
+         ## beamforming 1x2 matrix: 1 layer x 2 antennas
+         bf_weights = [0x00007fff, 0x0000];
+         ## beamforming 1x4 matrix: 1 layer x 4 antennas
+         #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
+         ## beamforming 2x2 matrix:
+         #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+         ## beamforming 4x4 matrix:
+         #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
+         sdr_addrs = "type=b200";
+                    #"addr=192.168.18.207";
+                    #"addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2";
+         clock_src = "external";
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf
new file mode 100644
index 0000000000000000000000000000000000000000..56f07668d7744e909717d73963fd5fa02b8e981b
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf
@@ -0,0 +1,290 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});	 
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    ssb_SubcarrierOffset                                      = 0;
+    pdsch_AntennaPorts                                        = 1;
+	
+    servingCellConfigCommon = (
+    {
+ #spCellConfigCommon
+
+      physCellId                                                    = 0;
+
+#  downlinkConfigCommon
+    #frequencyInfoDL
+      # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
+      absoluteFrequencySSB                                          = 640288;
+      dl_frequencyBand                                                 = 78;
+      # this is 3600 MHz
+      dl_absoluteFrequencyPointA                                       = 640000;
+      #scs-SpecificCarrierList
+        dl_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        dl_subcarrierSpacing                                           = 1;
+        dl_carrierBandwidth                                            = 24;
+     #initialDownlinkBWP
+      #genericParameters
+        # this is RBstart=41,L=24 (275*(L-1))+RBstart
+        initialDLBWPlocationAndBandwidth                                        = 6325;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialDLBWPsubcarrierSpacing                                           = 1;
+      #pdcch-ConfigCommon
+        initialDLBWPcontrolResourceSetZero                                      = 0;
+        initialDLBWPsearchSpaceZero                                             = 0;
+      #pdsch-ConfigCommon
+        #pdschTimeDomainAllocationList (up to 16 entries)
+             initialDLBWPk0_0                    = 0;
+             #initialULBWPmappingType
+	     #0=typeA,1=typeB
+             initialDLBWPmappingType_0           = 0;
+             #this is SS=1,L=13
+             initialDLBWPstartSymbolAndLength_0  = 40;
+
+             initialDLBWPk0_1                    = 0;
+             initialDLBWPmappingType_1           = 0;
+             #this is SS=2,L=12 
+             initialDLBWPstartSymbolAndLength_1  = 53;
+
+             initialDLBWPk0_2                    = 0;
+             initialDLBWPmappingType_2           = 0;
+             #this is SS=1,L=12 
+             initialDLBWPstartSymbolAndLength_2  = 54;
+
+             initialDLBWPk0_3                    = 0;
+             initialDLBWPmappingType_3           = 0;
+             #this is SS=1,L=5
+             initialDLBWPstartSymbolAndLength_3  = 57;
+
+  #uplinkConfigCommon 
+     #frequencyInfoUL
+      ul_frequencyBand                                                 = 78;
+      #scs-SpecificCarrierList
+      ul_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      ul_subcarrierSpacing                                           = 1;
+      ul_carrierBandwidth                                            = 24;
+      pMax                                                          = 20;
+     #initialUplinkBWP
+      #genericParameters
+        initialULBWPlocationAndBandwidth                                        = 6325;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialULBWPsubcarrierSpacing                                           = 1;
+      #rach-ConfigCommon
+        #rach-ConfigGeneric
+          prach_ConfigurationIndex                                  = 98;
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+          prach_msg1_FDM                                            = 0;
+          prach_msg1_FrequencyStart                                 = 0;
+          zeroCorrelationZoneConfig                                 = 13;
+          preambleReceivedTargetPower                               = -118;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+          preambleTransMax                                          = 6;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+        powerRampingStep                                            = 1;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+        ra_ResponseWindow                                           = 4;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR                = 4;
+#oneHalf (0..15) 4,8,12,16,...60,64
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB                   = 15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+        ra_ContentionResolutionTimer                                = 7;
+        rsrp_ThresholdSSB                                           = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+        prach_RootSequenceIndex_PR                                  = 2;
+        prach_RootSequenceIndex                                     = 1;
+        # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+        #  
+        msg1_SubcarrierSpacing                                      = 1,
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+        restrictedSetConfig                                         = 0,
+
+      # pusch-ConfigCommon (up to 16 elements)
+        initialULBWPk2_0                      = 6;
+        initialULBWPmappingType_0             = 1
+        # this is SS=0 L=11
+        initialULBWPstartSymbolAndLength_0    = 55;
+
+        initialULBWPk2_1                      = 6;
+        initialULBWPmappingType_1             = 1;
+        # this is SS=0 L=12
+        initialULBWPstartSymbolAndLength_1    = 69;
+
+        initialULBWPk2_2                      = 7;
+        initialULBWPmappingType_2             = 1;
+        # this is SS=10 L=4
+        initialULBWPstartSymbolAndLength_2    = 52;
+
+        msg3_DeltaPreamble                                          = 1;
+        p0_NominalWithGrant                                         =-90;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+        pucchGroupHopping                                           = 0;
+        hoppingId                                                   = 40;
+        p0_nominal                                                  = -90;
+# ssb_PositionsInBurs_BitmapPR
+# 1=short, 2=medium, 3=long
+      ssb_PositionsInBurst_PR                                       = 2;
+      ssb_PositionsInBurst_Bitmap                                   = 1;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 
+      ssb_periodicityServingCell                                    = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+      dmrs_TypeA_Position                                           = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      subcarrierSpacing                                             = 1;
+
+
+  #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      referenceSubcarrierSpacing                                    = 1;
+      # pattern1 
+      # dl_UL_TransmissionPeriodicity
+      # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+      dl_UL_TransmissionPeriodicity                                 = 6;
+      nrofDownlinkSlots                                             = 7;
+      nrofDownlinkSymbols                                           = 6;
+      nrofUplinkSlots                                               = 2;
+      nrofUplinkSymbols                                             = 4;
+
+  ssPBCH_BlockPower                                             = 10;
+  }
+
+  );
+
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.12.26";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
+        GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+	pusch_proc_threads = 8;
+        }  
+);
+
+RUs = (
+    {		  
+         local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 75;
+         eNB_instances  = [0];
+         ## beamforming 1x2 matrix: 1 layer x 2 antennas
+         bf_weights = [0x00007fff, 0x0000];
+         ## beamforming 1x4 matrix: 1 layer x 4 antennas
+         #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
+         ## beamforming 2x2 matrix:
+         #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+         ## beamforming 4x4 matrix:
+         #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
+         sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2";
+         clock_src = "external";
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf
new file mode 100644
index 0000000000000000000000000000000000000000..687a188456b8b3451b0361b510c5d74f1396c8ea
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf
@@ -0,0 +1,290 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    ssb_SubcarrierOffset                                      = 0;
+    pdsch_AntennaPorts                                        = 1;
+
+    servingCellConfigCommon = (
+    {
+ #spCellConfigCommon
+
+      physCellId                                                    = 0;
+
+#  downlinkConfigCommon
+    #frequencyInfoDL
+      # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
+      absoluteFrequencySSB                                          = 640288;
+      dl_frequencyBand                                                 = 78;
+      # this is 3600 MHz
+      dl_absoluteFrequencyPointA                                       = 640000;
+      #scs-SpecificCarrierList
+        dl_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+        dl_subcarrierSpacing                                           = 1;
+        dl_carrierBandwidth                                            = 24;
+     #initialDownlinkBWP
+      #genericParameters
+        # this is RBstart=41,L=24 (275*(L-1))+RBstart
+        initialDLBWPlocationAndBandwidth                                        = 6325;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+        initialDLBWPsubcarrierSpacing                                           = 1;
+      #pdcch-ConfigCommon
+        initialDLBWPcontrolResourceSetZero                                      = 0;
+        initialDLBWPsearchSpaceZero                                             = 0;
+      #pdsch-ConfigCommon
+        #pdschTimeDomainAllocationList (up to 16 entries)
+             initialDLBWPk0_0                    = 0;
+             #initialULBWPmappingType
+	     #0=typeA,1=typeB
+             initialDLBWPmappingType_0           = 0;
+             #this is SS=1,L=13
+             initialDLBWPstartSymbolAndLength_0  = 40;
+
+             initialDLBWPk0_1                    = 0;
+             initialDLBWPmappingType_1           = 0;
+             #this is SS=2,L=12
+             initialDLBWPstartSymbolAndLength_1  = 53;
+
+             initialDLBWPk0_2                    = 0;
+             initialDLBWPmappingType_2           = 0;
+             #this is SS=1,L=12
+             initialDLBWPstartSymbolAndLength_2  = 54;
+
+             initialDLBWPk0_3                    = 0;
+             initialDLBWPmappingType_3           = 0;
+             #this is SS=1,L=5
+             initialDLBWPstartSymbolAndLength_3  = 57;
+
+  #uplinkConfigCommon
+     #frequencyInfoUL
+      ul_frequencyBand                                                 = 78;
+      #scs-SpecificCarrierList
+      ul_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+      ul_subcarrierSpacing                                           = 1;
+      ul_carrierBandwidth                                            = 24;
+      pMax                                                          = 20;
+     #initialUplinkBWP
+      #genericParameters
+        initialULBWPlocationAndBandwidth                                        = 6325;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+        initialULBWPsubcarrierSpacing                                           = 1;
+      #rach-ConfigCommon
+        #rach-ConfigGeneric
+          prach_ConfigurationIndex                                  = 98;
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+          prach_msg1_FDM                                            = 0;
+          prach_msg1_FrequencyStart                                 = 0;
+          zeroCorrelationZoneConfig                                 = 13;
+          preambleReceivedTargetPower                               = -118;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+          preambleTransMax                                          = 6;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+        powerRampingStep                                            = 1;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+        ra_ResponseWindow                                           = 4;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR                = 4;
+#oneHalf (0..15) 4,8,12,16,...60,64
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB                   = 15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+        ra_ContentionResolutionTimer                                = 7;
+        rsrp_ThresholdSSB                                           = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+        prach_RootSequenceIndex_PR                                  = 2;
+        prach_RootSequenceIndex                                     = 1;
+        # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+        #
+        msg1_SubcarrierSpacing                                      = 1,
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+        restrictedSetConfig                                         = 0,
+
+      # pusch-ConfigCommon (up to 16 elements)
+        initialULBWPk2_0                      = 6;
+        initialULBWPmappingType_0             = 1
+        # this is SS=0 L=11
+        initialULBWPstartSymbolAndLength_0    = 55;
+
+        initialULBWPk2_1                      = 6;
+        initialULBWPmappingType_1             = 1;
+        # this is SS=0 L=12
+        initialULBWPstartSymbolAndLength_1    = 69;
+
+        initialULBWPk2_2                      = 7;
+        initialULBWPmappingType_2             = 1;
+        # this is SS=10 L=4
+        initialULBWPstartSymbolAndLength_2    = 52;
+
+        msg3_DeltaPreamble                                          = 1;
+        p0_NominalWithGrant                                         =-90;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+        pucchGroupHopping                                           = 0;
+        hoppingId                                                   = 40;
+        p0_nominal                                                  = -90;
+# ssb_PositionsInBurs_BitmapPR
+# 1=short, 2=medium, 3=long
+      ssb_PositionsInBurst_PR                                       = 2;
+      ssb_PositionsInBurst_Bitmap                                   = 1;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
+      ssb_periodicityServingCell                                    = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+      dmrs_TypeA_Position                                           = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+      subcarrierSpacing                                             = 1;
+
+
+  #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+      referenceSubcarrierSpacing                                    = 1;
+      # pattern1
+      # dl_UL_TransmissionPeriodicity
+      # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+      dl_UL_TransmissionPeriodicity                                 = 6;
+      nrofDownlinkSlots                                             = 7;
+      nrofDownlinkSymbols                                           = 6;
+      nrofUplinkSlots                                               = 2;
+      nrofUplinkSymbols                                             = 4;
+
+  ssPBCH_BlockPower                                             = 10;
+  }
+
+  );
+
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.12.26";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
+        GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+  }
+);
+
+MACRLCs = (
+    {
+        num_cc = 1;
+        tr_s_preference = "local_L1";
+        tr_n_preference = "local_RRC";
+    }
+);
+
+L1s = (
+    {
+        num_cc = 1;
+        tr_n_preference = "local_mac";
+        pusch_proc_threads = 8;
+    }
+);
+
+RUs = (
+    {
+         local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 114;
+         eNB_instances  = [0];
+         ## beamforming 1x2 matrix: 1 layer x 2 antennas
+         bf_weights = [0x00007fff, 0x0000];
+         ## beamforming 1x4 matrix: 1 layer x 4 antennas
+         #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
+         ## beamforming 2x2 matrix:
+         #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+         ## beamforming 4x4 matrix:
+         #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
+         sdr_addrs = "type=x300";
+         clock_src = "external";
+    }
+);
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf
new file mode 100644
index 0000000000000000000000000000000000000000..12e45254544f43d810aa497722da74f0321360ec
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf
@@ -0,0 +1,306 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;});	 
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    ssb_SubcarrierOffset                                      = 31; //0;
+    pdsch_AntennaPorts                                        = 1;
+    pusch_TargetSNRx10                                        = 200;
+    pucch_TargetSNRx10                                        = 200;
+
+    servingCellConfigCommon = (
+    {
+ #spCellConfigCommon
+
+      physCellId                                                    = 0;
+
+#  downlinkConfigCommon
+    #frequencyInfoDL
+      # this is 3600 MHz + 12 PRBs@30kHz SCS 
+      absoluteFrequencySSB                                          = 640288;
+      dl_frequencyBand                                                 = 78;
+      # this is 3600 MHz
+      dl_absoluteFrequencyPointA                                       = 640000;
+      #scs-SpecificCarrierList
+        dl_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        dl_subcarrierSpacing                                           = 1;
+        dl_carrierBandwidth                                            = 24;
+     #initialDownlinkBWP
+      #genericParameters
+        # this is RBstart=0,L=24 (275*(L-1))+RBstart
+        initialDLBWPlocationAndBandwidth                                        = 6325; 
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialDLBWPsubcarrierSpacing                                           = 1;
+      #pdcch-ConfigCommon
+        initialDLBWPcontrolResourceSetZero                                      = 0;
+        initialDLBWPsearchSpaceZero                                             = 0;
+      #pdsch-ConfigCommon
+        #pdschTimeDomainAllocationList (up to 16 entries)
+             initialDLBWPk0_0                    = 0;
+             #initialULBWPmappingType
+	     #0=typeA,1=typeB
+             initialDLBWPmappingType_0           = 0;
+             #this is SS=1,L=13
+             initialDLBWPstartSymbolAndLength_0  = 40;
+
+             initialDLBWPk0_1                    = 0;
+             initialDLBWPmappingType_1           = 0;
+             #this is SS=2,L=12 
+             initialDLBWPstartSymbolAndLength_1  = 53;
+
+             initialDLBWPk0_2                    = 0;
+             initialDLBWPmappingType_2           = 0;
+             #this is SS=1,L=12 
+             initialDLBWPstartSymbolAndLength_2  = 54;
+
+             initialDLBWPk0_3                    = 0;
+             initialDLBWPmappingType_3           = 0;
+             #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57)
+             initialDLBWPstartSymbolAndLength_3  = 57; //43; //57;
+  #uplinkConfigCommon 
+     #frequencyInfoUL
+      ul_frequencyBand                                                 = 78;
+      #scs-SpecificCarrierList
+      ul_offstToCarrier                                              = 0;
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      ul_subcarrierSpacing                                           = 1;
+      ul_carrierBandwidth                                            = 24;
+      pMax                                                          = 20;
+     #initialUplinkBWP
+      #genericParameters
+        initialULBWPlocationAndBandwidth                                        = 6325; 
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+        initialULBWPsubcarrierSpacing                                           = 1;
+      #rach-ConfigCommon
+        #rach-ConfigGeneric
+          prach_ConfigurationIndex                                  = 98;
+#prach_msg1_FDM
+#0 = one, 1=two, 2=four, 3=eight
+          prach_msg1_FDM                                            = 0;
+          prach_msg1_FrequencyStart                                 = 0;
+          zeroCorrelationZoneConfig                                 = 13;
+          preambleReceivedTargetPower                               = -100;
+#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+          preambleTransMax                                          = 6;
+#powerRampingStep
+# 0=dB0,1=dB2,2=dB4,3=dB6
+        powerRampingStep                                            = 1;
+#ra_ReponseWindow
+#1,2,4,8,10,20,40,80
+        ra_ResponseWindow                                           = 5;
+#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR                = 4;
+#oneHalf (0..15) 4,8,12,16,...60,64
+        ssb_perRACH_OccasionAndCB_PreamblesPerSSB                   = 14; //15;
+#ra_ContentionResolutionTimer
+#(0..7) 8,16,24,32,40,48,56,64
+        ra_ContentionResolutionTimer                                = 7;
+        rsrp_ThresholdSSB                                           = 19;
+#prach-RootSequenceIndex_PR
+#1 = 839, 2 = 139
+        prach_RootSequenceIndex_PR                                  = 2;
+        prach_RootSequenceIndex                                     = 1;
+        # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+        #  
+        msg1_SubcarrierSpacing                                      = 1,
+
+# restrictedSetConfig
+# 0=unrestricted, 1=restricted type A, 2=restricted type B
+        restrictedSetConfig                                         = 0,
+      # pusch-ConfigCommon (up to 16 elements)
+        initialULBWPk2_0                      = 2;
+        initialULBWPmappingType_0             = 1
+        # this is SS=0 L=12
+        initialULBWPstartSymbolAndLength_0    = 55;
+ 	
+	initialULBWPk2_1                      = 2;
+        initialULBWPmappingType_1             = 1;
+        # this is SS=0 L=11
+        initialULBWPstartSymbolAndLength_1    = 69;
+
+        initialULBWPk2_2                      = 7;
+        initialULBWPmappingType_2             = 1;
+        # this is SS=10 L=4
+        initialULBWPstartSymbolAndLength_2    = 52;
+
+        msg3_DeltaPreamble                                          = 1;
+        p0_NominalWithGrant                                         =-90;
+
+# pucch-ConfigCommon setup :
+# pucchGroupHopping
+# 0 = neither, 1= group hopping, 2=sequence hopping
+        pucchGroupHopping                                           = 0;
+        hoppingId                                                   = 40;
+        p0_nominal                                                  = -90;
+# ssb_PositionsInBurs_BitmapPR
+# 1=short, 2=medium, 3=long
+      ssb_PositionsInBurst_PR                                       = 2;
+      ssb_PositionsInBurst_Bitmap                                   = 1; #0x80;
+
+# ssb_periodicityServingCell
+# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 
+      ssb_periodicityServingCell                                    = 2;
+
+# dmrs_TypeA_position
+# 0 = pos2, 1 = pos3
+      dmrs_TypeA_Position                                           = 0;
+
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      subcarrierSpacing                                             = 1;
+
+
+  #tdd-UL-DL-ConfigurationCommon
+# subcarrierSpacing
+# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
+      referenceSubcarrierSpacing                                    = 1;
+      # pattern1 
+      # dl_UL_TransmissionPeriodicity
+      # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+      dl_UL_TransmissionPeriodicity                                 = 6;
+      nrofDownlinkSlots                                             = 7; //8; //7;
+      nrofDownlinkSymbols                                           = 6; //0; //6;
+      nrofUplinkSlots                                               = 2;
+      nrofUplinkSymbols                                             = 4; //0; //4;
+
+  ssPBCH_BlockPower                                             = -25;
+  }
+
+  );
+
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.18.99";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    ///X2
+    enable_x2 = "yes";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_overall = 2000;      /* unit: millisecond */
+    t_dc_prep         = 1000;      /* unit: millisecond */
+    t_dc_overall      = 2000;      /* unit: millisecond */
+    target_enb_x2_ip_address      = (
+                                     { ipv4       = "192.168.18.199";
+                                       ipv6       = "192:168:30::17";
+                                       preference = "ipv4";
+                                     }
+                                    );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.18.198/24";
+        GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.18.198/24";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+        GNB_IPV4_ADDRESS_FOR_X2C                 = "192.168.18.198/24";
+        GNB_PORT_FOR_X2C                         = 36422; # Spec 36422
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+	pusch_proc_threads = 8;
+        }  
+);
+
+RUs = (
+    {		  
+         local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 114;
+         eNB_instances  = [0];
+         ## beamforming 1x2 matrix: 1 layer x 2 antennas
+         bf_weights = [0x00007fff, 0x0000];
+         ## beamforming 1x4 matrix: 1 layer x 4 antennas
+         #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000];
+         ## beamforming 2x2 matrix:
+         #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+         ## beamforming 4x4 matrix:
+         #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff];
+         clock_src = "external";
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    //parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
index 4373f38e7bdc833d47d472f4513465904e2a0c28..d28427dbf3615f8fedf243557d262590297317cb 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
@@ -75,17 +75,12 @@ gNBs =
              initialDLBWPk0_2                    = 0;
              initialDLBWPmappingType_2           = 0;
              #this is SS=1,L=12
-             initialDLBWPstartSymbolAndLength_2  = 95;
+             initialDLBWPstartSymbolAndLength_2  = 54;
 
              initialDLBWPk0_3                    = 0;
              initialDLBWPmappingType_3           = 0;
-             #this is SS=2,L=7
-             initialDLBWPstartSymbolAndLength_3  = 86;
-
-             initialDLBWPk0_4                    = 0;
-             initialDLBWPmappingType_4           = 0;
-             #this is SS=2,L=5
-             initialDLBWPstartSymbolAndLength_4  = 58;
+             #this is SS=1,L=5
+             initialDLBWPstartSymbolAndLength_3  = 57;
 
   #uplinkConfigCommon
      #frequencyInfoUL