diff --git a/README.txt b/README.txt
index 8204bb0cb517b66585adae09dde226f1031d677a..c65502325f89749a3f0caf84c41b3b6ecdf64ef4 100644
--- a/README.txt
+++ b/README.txt
@@ -43,17 +43,36 @@ openairinterface5g
 
 RELEASE NOTES:
 
-v0.1 -> Last stable commit on develop branch before enhancement-10-harmony
-v0.2 -> Merge of enhancement-10-harmony to include NGFI RRH + New Interface for RF/BBU
-v0.3 -> Last stable commit on develop branch before the merge of feature-131-new-license. This is the last commit with GPL License
-v0.4 -> Merge of feature-131-new-license. It closes issue#131 and changes the license to OAI Public License V1.0
-v0.5 -> Merge of enhancement-10-harmony-lts. It includes fixes for Ubuntu 16.04 support
-v0.5.1 -> Merge of bugfix-137-uplink-fixes. It includes stablity fixes for eNB
-v0.5.2 -> Last version with old code for oaisim (abstraction mode works)
-v0.6 -> RRH functionality, UE greatly improved, better TDD support,
-        a lot of bugs fixed. WARNING: oaisim in PHY abstraction mode does not
-        work, you need to use v0.5.2 for that.
-v0.6.1 -> Mostly bugfixes. This is the last version without NFAPI.
+v1.1.0 -> July 2019. This version adds the following implemented features:
+           * Experimental support of LTE-M
+             - Single LTE-M UE attachment, legacy-LTE UE attachment is disabled
+           * X2 interface and handover (also X2-U interface)
+             - In FDD and TDD
+           * CU/DU split (F1 interface)
+             - Tested only in FDD
+           * CDRX
+             - Tested only in FDD
+           * Experimental eMBMS support (only on UE side)
+           * Experimental multi-RRU support
+             - Tested only in TDD
+          This version has an improved code quality:
+           * Simplification of the Build System
+             - A single build includes all full-stack simulators, S1/noS1 modes and one HW platform (such as USRP, BladeRF, ...)
+           * TUN interface is now used as default for the data plane
+             - for UE, eNB-noS1 and UE-noS1
+           * Code Cleanup
+           * Better Static Code Analysis:
+             - Limited number of errors in cppcheck
+             - Important Decrease on high Impact errors in CoverityScan
+           * Better Test Coverage in Continuous Integration:
+             - TM2, CDRX, IF4.5, F1
+             - OAI UE is tested in S1 and noS1 modes with USRP board
+             - Multi-RRU TDD mode
+             - X2 Handover in FDD mode
+
+v1.0.3 -> June 2019: Bug fix for LimeSuite v19.04.0 API
+v1.0.2 -> February 2019: Full OAI support for 3.13.1 UHD
+v1.0.1 -> February 2019: Bug fix for the UE L1 simulator.
 v1.0.0 -> January 2019. This version first implements the architectural split described in doc/oai_lte_enb_func_split_arch.png picture.
             Only FAPI, nFAPI and IF4.5 interfaces are implemented.
             Repository tree structure prepares future integrations of features such as LTE-M, nbIOT or 5G-NR.
@@ -61,6 +80,15 @@ v1.0.0 -> January 2019. This version first implements the architectural split de
             S1-flex has been introduced.
             New tools: config library, telnet server, ...
             A lot of bugfixes and a proper automated Continuous Integration process validates contributions.
-v1.0.1 -> February 2019: Bug fix for the UE L1 simulator.
-v1.0.2 -> February 2019: Full OAI support for 3.13.1 UHD
-v1.0.3 -> June 2019: Bug fix for LimeSuite v19.04.0 API
+
+v0.6.1 -> Mostly bugfixes. This is the last version without NFAPI.
+v0.6 -> RRH functionality, UE greatly improved, better TDD support,
+        a lot of bugs fixed. WARNING: oaisim in PHY abstraction mode does not
+        work, you need to use v0.5.2 for that.
+v0.5.2 -> Last version with old code for oaisim (abstraction mode works)
+v0.5.1 -> Merge of bugfix-137-uplink-fixes. It includes stablity fixes for eNB
+v0.5 -> Merge of enhancement-10-harmony-lts. It includes fixes for Ubuntu 16.04 support
+v0.4 -> Merge of feature-131-new-license. It closes issue#131 and changes the license to OAI Public License V1.0
+v0.3 -> Last stable commit on develop branch before the merge of feature-131-new-license. This is the last commit with GPL License
+v0.2 -> Merge of enhancement-10-harmony to include NGFI RRH + New Interface for RF/BBU
+v0.1 -> Last stable commit on develop branch before enhancement-10-harmony
diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab
index 56624d32300372d6f6326e5d873c9c66fc2a4395..ed7489aa932d96a499083eecd9fe0fa2c59cf1db 100644
--- a/ci-scripts/Jenkinsfile-gitlab
+++ b/ci-scripts/Jenkinsfile-gitlab
@@ -44,7 +44,7 @@ pipeline {
         disableConcurrentBuilds()
         timestamps()
         gitLabConnection('OAI GitLab')
-        gitlabBuilds(builds: ["Build eNb-USRP", "Build basic-sim", "Build phy-sim", "Build eNb-ethernet", "Build UE-ethernet", "Analysis with cppcheck", "Test phy-sim", "Test basic-sim", "Test L2-sim", "Test-Mono-FDD-Band7", "Test-Mono-TDD-Band40", "Test-IF4p5-FDD-Band7", "Test-IF4p5-TDD-Band40", "Test-Mono-FDD-Band13"])
+        gitlabBuilds(builds: ["Build eNb-USRP", "Build basic-sim", "Build phy-sim", "Build eNb-ethernet", "Build UE-ethernet", "Analysis with cppcheck", "Test phy-sim", "Test basic-sim", "Test L2-sim", "Test-Mono-FDD-Band7", "Test-Mono-TDD-Band40", "Test-IF4p5-FDD-Band7", "Test-IF4p5-TDD-Band40", "Test-Mono-FDD-Band13", "Test-IF4p5-TDD-Band38-Multi-RRU" , "Test-Mono-FDD-Band13-X2-HO"])
         ansiColor('xterm')
     }
 
@@ -481,6 +481,45 @@ pipeline {
                         }
                     }
                 }
+                stage ("Test X2 Handover - FDD - Band 13 - B210") {
+                    steps {
+                        script {
+                            sh "sleep 60"
+                            triggerSlaveJob ('eNB-CI-MONO-FDD-Band13-X2HO-B210', 'Test-Mono-FDD-Band13-X2-HO')
+                        }
+                    }
+                    post {
+                        always {
+                            script {
+                                finalizeSlaveJob('eNB-CI-MONO-FDD-Band13-X2HO-B210')
+                            }
+                        }
+                        failure {
+                            script {
+                                currentBuild.result = 'FAILURE'
+                            }
+                        }
+                    }
+                }
+                stage ("Test IF4p5 - TDD - Band 38 - B210 - MultiRRU") {
+                    steps {
+                        script {
+                            triggerSlaveJob ('eNB-CI-IF4p5-TDD-Band38-MultiRRU-B210', 'Test-IF4p5-TDD-Band38-Multi-RRU')
+                        }
+                    }
+                    post {
+                        always {
+                            script {
+                                finalizeSlaveJob('eNB-CI-IF4p5-TDD-Band38-MultiRRU-B210')
+                            }
+                        }
+                        failure {
+                            script {
+                                currentBuild.result = 'FAILURE'
+                            }
+                        }
+                    }
+                }
                 stage ("Test IF4p5 - TDD - Band 40 - B210") {
                     steps {
                         script {
@@ -504,6 +543,7 @@ pipeline {
                 stage ("Test MONOLITHIC - FDD - Band 13 - B210") {
                     steps {
                         script {
+                            sh "sleep 60"
                             triggerSlaveJob ('eNB-CI-MONO-FDD-Band13-B210', 'Test-Mono-FDD-Band13')
                         }
                     }
diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb b/ci-scripts/Jenkinsfile-tmp-multi-enb
new file mode 100644
index 0000000000000000000000000000000000000000..c3b825ec0622c0faed979706840eb15a9a3a3687
--- /dev/null
+++ b/ci-scripts/Jenkinsfile-tmp-multi-enb
@@ -0,0 +1,282 @@
+#!/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 ciSmartPhoneResource = params.smartphonesResource
+
+// 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 = false
+def eNB_TargetBranch
+
+pipeline {
+    agent {
+        label pythonExecutor
+    }
+    options {
+        disableConcurrentBuilds()
+        ansiColor('xterm')
+        lock (ciSmartPhoneResource)
+    }
+    stages {
+        stage ("Verify Parameters") {
+            steps {
+                script {
+                    echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
+                    def allParametersPresent = true
+
+                    // It is already to late to check it
+                    if (params.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.smartphonesResource == 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_mergeRequest != null) {
+                        eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
+                        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/conf_files/enb.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf
new file mode 100644
index 0000000000000000000000000000000000000000..2a7783da08bfbab86560711358f8b652c6253cba
--- /dev/null
+++ b/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf
@@ -0,0 +1,271 @@
+Active_eNBs = ( "eNB-Eurecom-LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    ////////// Identification parameters:
+    eNB_ID    =  0xe01;
+
+    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 = 208; mnc = 93; mnc_length = 2; } );
+
+    nr_cellid = 98765L;
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "3GPP_eNODEB";
+      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              			      = 13;
+      downlink_frequency      			      = 751000000L;
+      uplink_frequency_offset 			      = 31000000;
+      Nid_cell					      = 1;
+      N_RB_DL                 			      = 25;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 1;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 110;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 0;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 0;
+      pdsch_referenceSignalPower 			      = -27;
+      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;
+
+      }
+    );
+
+
+    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";
+                            }
+                          );
+
+    ///X2
+    enable_x2 = "yes";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_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                 = "CI_ENB_IP_ADDR";
+        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     =  200;
+        puCch10xSnr     =  200;
+        }  
+);
+
+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                    = 125;
+         eNB_instances  = [0];
+
+    }
+);  
+
+NETWORK_CONTROLLER :
+{
+    FLEXRAN_ENABLED        = "no";
+    FLEXRAN_INTERFACE_NAME = "eth0";
+    FLEXRAN_IPV4_ADDRESS   = "CI_MME_IP_ADDR";
+    FLEXRAN_PORT           = 2210;
+    FLEXRAN_CACHE          = "/mnt/oai_agent_cache";
+    FLEXRAN_AWAIT_RECONF   = "no";
+};
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_SINGLE_THREAD";//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/enb.slave.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf
new file mode 100644
index 0000000000000000000000000000000000000000..c76a664c15648bf2951fd04e5b359fd577a6ede6
--- /dev/null
+++ b/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf
@@ -0,0 +1,276 @@
+Active_eNBs = ( "eNB-Eurecom-LTEBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    ////////// 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 = 208; mnc = 93; mnc_length = 2; } );
+
+    nr_cellid = 123456L;
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function             = "3GPP_eNODEB";
+      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              			      = 13;
+      downlink_frequency      			      = 751000000L;
+      uplink_frequency_offset 			      = 31000000;
+      Nid_cell					      = 0;
+      N_RB_DL                 			      = 25;
+      Nid_cell_mbsfn          			      = 0;
+      nb_antenna_ports                                = 1;
+      nb_antennas_tx          			      = 1;
+      nb_antennas_rx          			      = 1;
+      tx_gain                                            = 90;
+      rx_gain                                            = 110;
+      pbch_repetition                                 = "FALSE";
+      prach_root              			      = 0;
+      prach_config_index      			      = 0;
+      prach_high_speed        			      = "DISABLE";
+      prach_zero_correlation  			      = 1;
+      prach_freq_offset       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 0;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 0;
+      pdsch_referenceSignalPower 			      = -27;
+      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;
+
+      }
+    );
+
+
+    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";
+                            }
+                          );
+    ///X2
+    enable_x2 = "yes";
+    t_reloc_prep      = 1000;      /* unit: millisecond */
+    tx2_reloc_overall = 2000;      /* unit: millisecond */
+    target_enb_x2_ip_address      = (
+                                     { ipv4       = "CI_RCC_IP_ADDR";
+                                       ipv6       = "192:168:30::17";
+                                       preference = "ipv4";
+                                     }
+                                    );
+
+    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                 = "CI_ENB_IP_ADDR";
+        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     =  200;
+        puCch10xSnr     =  200;
+        }  
+);
+
+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                    = 125;
+         eNB_instances  = [0];
+
+    }
+);  
+
+NETWORK_CONTROLLER :
+{
+    FLEXRAN_ENABLED        = "no";
+    FLEXRAN_INTERFACE_NAME = "eth0";
+    FLEXRAN_IPV4_ADDRESS   = "CI_MME_IP_ADDR";
+    FLEXRAN_PORT           = 2210;
+    FLEXRAN_CACHE          = "/mnt/oai_agent_cache";
+    FLEXRAN_AWAIT_RECONF   = "no";
+};
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_SINGLE_THREAD";//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/rcc.band38.tm1.50PRB.multi.rru.conf b/ci-scripts/conf_files/rcc.band38.tm1.50PRB.multi.rru.conf
new file mode 100644
index 0000000000000000000000000000000000000000..b3899fdb6af99cac329720914e293cdbefc6e786
--- /dev/null
+++ b/ci-scripts/conf_files/rcc.band38.tm1.50PRB.multi.rru.conf
@@ -0,0 +1,242 @@
+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 = 208; mnc = 92; 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					      = "TDD";
+      tdd_config 					      = 1;
+      tdd_config_s            			      = 0;
+      prefix_type             			      = "NORMAL";
+      eutra_band              			      = 38;
+      downlink_frequency      			      = 2580000000L;
+      uplink_frequency_offset 			      = 0;
+      Nid_cell					      = 0;
+      N_RB_DL                 			      = 50; #25;
+      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       			      = 2;
+      pucch_delta_shift       			      = 1;
+      pucch_nRB_CQI           			      = 0;
+      pucch_nCS_AN            			      = 0;
+      pucch_n1_AN             			      = 32;
+      pdsch_referenceSignalPower 			      = -27;
+      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                                   = -104; #-96;
+      pusch_alpha                                        = "AL1";
+      pucch_p0_Nominal                                   = -96; #-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;
+      }
+    );
+
+
+    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";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "enp129s0f0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "CI_ENB_IP_ADDR";
+        ENB_INTERFACE_NAME_FOR_S1U               = "enp129s0f0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "CI_ENB_IP_ADDR"; #"127.0.0.4/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152\
+
+        ENB_IPV4_ADDRESS_FOR_X2C                 = "CI_ENB_IP_ADDR";
+        ENB_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";
+        }  
+);
+
+RUs = (
+    {		  
+      	local_if_name  = "enp129s0f0";			  
+      	local_address  = "CI_ENB_IP_ADDR";
+    	remote_address = "CI_RRU1_IP_ADDR";
+    	local_portc    = 50002;	
+    	remote_portc   = 50002;
+    	local_portd    = 50003;	
+    	remote_portd   = 50003;
+	local_rf       = "no"
+    	tr_preference  = "udp_if4p5"
+	nb_tx          = 1
+	nb_rx          = 1
+	att_tx         = 20
+	att_rx         = 20;
+	eNB_instances  = [0];
+	is_slave       = "no";
+	ota_sync_enabled = "yes";
+    },
+    {		  
+      	local_if_name  = "enp129s0f0";			  
+      	local_address  = "CI_ENB_IP_ADDR";
+    	remote_address = "CI_RRU2_IP_ADDR";
+    	local_portc    = 50010;	
+    	remote_portc   = 50010;
+    	local_portd    = 50011;	
+    	remote_portd   = 50011;
+	local_rf       = "no"
+    	tr_preference  = "udp_if4p5"
+	nb_tx          = 1
+	nb_rx          = 1
+	att_tx         = 20
+	att_rx         = 20;
+	eNB_instances  = [0];
+	is_slave       = "yes";
+	ota_sync_enabled = "yes";
+    }
+);  
+
+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/rcc.band7.tm1.nfapi.conf b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf
index 81fc7eedce43275998cfca24428ee77563e79452..28bfd91560d9085aa446f3e1267b6cf7853ea665 100644
--- a/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf
+++ b/ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf
@@ -218,7 +218,7 @@ MACRLCs = (
 THREAD_STRUCT = (
   {
     #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
-    parallel_config    = "PARALLEL_SINGLE_THREAD";
+    parallel_config    = "PARALLEL_RU_L1_SPLIT";
     #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
     worker_config      = "WORKER_ENABLE";
   }
diff --git a/ci-scripts/conf_files/rru.band38.tm1.master.conf b/ci-scripts/conf_files/rru.band38.tm1.master.conf
new file mode 100644
index 0000000000000000000000000000000000000000..101ce83892e66d3d52ef1a70b55be9c24ca384e4
--- /dev/null
+++ b/ci-scripts/conf_files/rru.band38.tm1.master.conf
@@ -0,0 +1,47 @@
+RUs = (
+    {		  
+      	local_if_name                    = "enp1s0";			  
+      	remote_address                   = "CI_RCC_IP_ADDR";
+    	local_address                    = "CI_ENB_IP_ADDR";
+    	local_portc                       = 50002;	     
+    	remote_portc                      = 50002;
+    	local_portd                       = 50003;	     
+    	remote_portd                      = 50003;
+	local_rf                         = "yes"
+    	tr_preference                    = "udp_if4p5";
+	nb_tx                            = 1;
+	nb_rx                            = 1;
+	max_pdschReferenceSignalPower    = -12;
+	max_rxgain                       = 100;
+	bands                            = [38];
+        is_slave			 = "no";
+        ota_sync_enabled		 = "yes";
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_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/rru.band38.tm1.slave.conf b/ci-scripts/conf_files/rru.band38.tm1.slave.conf
new file mode 100644
index 0000000000000000000000000000000000000000..d5efe6bd61ae925e9c08cf12350a6635abbcec27
--- /dev/null
+++ b/ci-scripts/conf_files/rru.band38.tm1.slave.conf
@@ -0,0 +1,47 @@
+RUs = (
+    {		  
+      	local_if_name                    = "enp1s0";			  
+      	remote_address                   = "CI_RCC_IP_ADDR";
+    	local_address                    = "CI_ENB_IP_ADDR";
+    	local_portc                       = 50010;	     
+    	remote_portc                      = 50010;
+    	local_portd                       = 50011;	     
+    	remote_portd                      = 50011;
+	local_rf                         = "yes"
+    	tr_preference                    = "udp_if4p5";
+	nb_tx                            = 1;
+	nb_rx                            = 1;
+	max_pdschReferenceSignalPower    = -12;
+	max_rxgain                       = 100;
+	bands                            = [38];
+	is_slave			 = "yes";
+	ota_sync_enabled		 = "yes";
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_SINGLE_THREAD";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_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/doGitLabMerge.sh b/ci-scripts/doGitLabMerge.sh
index dd93ff41b7443ac4f145ef02902a63b3e9a5ad86..c4aa9157de51e4f6691bfd9b31c2738d93ace45e 100755
--- a/ci-scripts/doGitLabMerge.sh
+++ b/ci-scripts/doGitLabMerge.sh
@@ -125,7 +125,16 @@ fi
 git config user.email "jenkins@openairinterface.org"
 git config user.name "OAI Jenkins"
 
-git checkout -f $SOURCE_COMMIT_ID
+git checkout -f $SOURCE_COMMIT_ID > checkout.txt 2>&1
+STATUS=`egrep -c "fatal: reference is not a tree" checkout.txt`
+rm -f checkout.txt
+if [ $STATUS -ne 0 ]
+then
+    echo "fatal: reference is not a tree --> $SOURCE_COMMIT_ID"
+    STATUS=-1
+    exit $STATUS
+fi
+
 git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG
 
 git merge --ff $TARGET_COMMIT_ID -m "Temporary merge for CI"
diff --git a/ci-scripts/main.py b/ci-scripts/main.py
index 23e8921a64dad06b284faf059eea6f44ae8ad779..8a0b10d2573b1d651d65eceed3e2077b336b1774 100644
--- a/ci-scripts/main.py
+++ b/ci-scripts/main.py
@@ -43,6 +43,7 @@ ENB_PROCESS_SEG_FAULT = -11
 ENB_PROCESS_ASSERTION = -12
 ENB_PROCESS_REALTIME_ISSUE = -13
 ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14
+ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15
 HSS_PROCESS_FAILED = -2
 HSS_PROCESS_OK = +2
 MME_PROCESS_FAILED = -3
@@ -57,6 +58,17 @@ OAI_UE_PROCESS_FAILED = -23
 OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24
 OAI_UE_PROCESS_OK = +6
 
+UE_STATUS_DETACHED = 0
+UE_STATUS_DETACHING = 1
+UE_STATUS_ATTACHING = 2
+UE_STATUS_ATTACHED = 3
+
+X2_HO_REQ_STATE__IDLE = 0
+X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1
+X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2
+X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3
+X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10
+
 #-----------------------------------------------------------
 # Import
 #-----------------------------------------------------------
@@ -81,18 +93,27 @@ logging.basicConfig(
 #-----------------------------------------------------------
 class SSHConnection():
 	def __init__(self):
+		self.prematureExit = False
+		self.ranRepository = ''
+		self.ranBranch = ''
+		self.ranAllowMerge = False
+		self.ranCommitID = ''
+		self.ranTargetBranch = ''
 		self.eNBIPAddress = ''
-		self.eNBRepository = ''
-		self.eNBBranch = ''
-		self.eNB_AllowMerge = False
-		self.eNBCommitID = ''
-		self.eNBTargetBranch = ''
 		self.eNBUserName = ''
 		self.eNBPassword = ''
 		self.eNBSourceCodePath = ''
 		self.EPCIPAddress = ''
 		self.EPCUserName = ''
 		self.EPCPassword = ''
+		self.eNB1IPAddress = ''
+		self.eNB1UserName = ''
+		self.eNB1Password = ''
+		self.eNB1SourceCodePath = ''
+		self.eNB2IPAddress = ''
+		self.eNB2UserName = ''
+		self.eNB2Password = ''
+		self.eNB2SourceCodePath = ''
 		self.EPCSourceCodePath = ''
 		self.EPCType = ''
 		self.EPC_PcapFileName = ''
@@ -104,12 +125,13 @@ class SSHConnection():
 		self.nbTestXMLfiles = 0
 		self.desc = ''
 		self.Build_eNB_args = ''
+		self.backgroundBuild = False
+		self.backgroundBuildTestId = ['', '', '']
 		self.Initialize_eNB_args = ''
-		self.eNBLogFile = ''
 		self.eNB_instance = ''
-		self.eNBOptions = ''
-		self.rruOptions = ''
-		self.rruLogFile = ''
+		self.eNB_serverId = ''
+		self.eNBLogFiles = ['', '', '']
+		self.eNBOptions = ['', '', '']
 		self.ping_args = ''
 		self.ping_packetloss_threshold = ''
 		self.iperf_args = ''
@@ -117,6 +139,7 @@ class SSHConnection():
 		self.iperf_profile = ''
 		self.nbMaxUEtoAttach = -1
 		self.UEDevices = []
+		self.UEDevicesStatus = []
 		self.CatMDevices = []
 		self.UEIPAddresses = []
 		self.htmlFile = ''
@@ -127,9 +150,14 @@ class SSHConnection():
 		self.htmlUEFailureMsg = ''
 		self.picocom_closure = False
 		self.idle_sleep_time = 0
+		self.x2_ho_options = 'network'
+		self.x2NbENBs = 0
+		self.x2ENBBsIds = []
+		self.x2ENBConnectedUEs = []
 		self.htmlTabRefs = []
 		self.htmlTabNames = []
 		self.htmlTabIcons = []
+		self.repeatCounts = []
 		self.finalStatus = False
 		self.OsVersion = ''
 		self.KernelVersion = ''
@@ -312,45 +340,168 @@ class SSHConnection():
 			sys.exit('SCP failed')
 
 	def BuildeNB(self):
-		if self.eNBIPAddress == '' or self.eNBRepository == '' or self.eNBBranch == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.eNBSourceCodePath == '':
+		if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
 			Usage()
 			sys.exit('Insufficient Parameter')
-		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
-		self.command('mkdir -p ' + self.eNBSourceCodePath, '\$', 5)
-		self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
-		self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.eNBRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600)
+		if self.eNB_serverId == '0':
+			lIpAddr = self.eNBIPAddress
+			lUserName = self.eNBUserName
+			lPassWord = self.eNBPassword
+			lSourcePath = self.eNBSourceCodePath
+		elif self.eNB_serverId == '1':
+			lIpAddr = self.eNB1IPAddress
+			lUserName = self.eNB1UserName
+			lPassWord = self.eNB1Password
+			lSourcePath = self.eNB1SourceCodePath
+		elif self.eNB_serverId == '2':
+			lIpAddr = self.eNB2IPAddress
+			lUserName = self.eNB2UserName
+			lPassWord = self.eNB2Password
+			lSourcePath = self.eNB2SourceCodePath
+		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
+			Usage()
+			sys.exit('Insufficient Parameter')
+		self.open(lIpAddr, lUserName, lPassWord)
+		self.command('mkdir -p ' + lSourcePath, '\$', 5)
+		self.command('cd ' + lSourcePath, '\$', 5)
+		self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600)
 		# Raphael: here add a check if git clone or git fetch went smoothly
 		self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5)
 		self.command('git config user.name "OAI Jenkins"', '\$', 5)
-		self.command('echo ' + self.eNBPassword + ' | sudo -S git clean -x -d -ff', '\$', 30)
+		# Checking the BUILD INFO file
+		if not self.backgroundBuild:
+			self.command('ls *.txt', '\$', 5)
+			result = re.search('LAST_BUILD_INFO', str(self.ssh.before))
+			if result is not None:
+				mismatch = False
+				self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2)
+				result = re.search(self.ranCommitID, str(self.ssh.before))
+				if result is None:
+					mismatch = True
+				self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2)
+				if (self.ranAllowMerge):
+					result = re.search('YES', str(self.ssh.before))
+					if result is None:
+						mismatch = True
+					self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2)
+					if self.ranTargetBranch == '':
+						result = re.search('develop', str(self.ssh.before))
+					else:
+						result = re.search(self.ranTargetBranch, str(self.ssh.before))
+					if result is None:
+						mismatch = True
+				else:
+					result = re.search('NO', str(self.ssh.before))
+					if result is None:
+						mismatch = True
+				if not mismatch:
+					self.close()
+					self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
+					return
+				
+		self.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30)
 		# if the commit ID is provided use it to point to it
-		if self.eNBCommitID != '':
-			self.command('git checkout -f ' + self.eNBCommitID, '\$', 5)
+		if self.ranCommitID != '':
+			self.command('git checkout -f ' + self.ranCommitID, '\$', 5)
 		# 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
-		if (self.eNB_AllowMerge):
-			if self.eNBTargetBranch == '':
-				if (self.eNBBranch != 'develop') and (self.eNBBranch != 'origin/develop'):
+		if (self.ranAllowMerge):
+			if self.ranTargetBranch == '':
+				if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'):
 					self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5)
 			else:
-				logging.debug('Merging with the target branch: ' + self.eNBTargetBranch)
-				self.command('git merge --ff origin/' + self.eNBTargetBranch + ' -m "Temporary merge for CI"', '\$', 5)
+				logging.debug('Merging with the target branch: ' + self.ranTargetBranch)
+				self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5)
 		self.command('source oaienv', '\$', 5)
 		self.command('cd cmake_targets', '\$', 5)
 		self.command('mkdir -p log', '\$', 5)
 		self.command('chmod 777 log', '\$', 5)
 		# no need to remove in log (git clean did the trick)
-		self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 600)
+		if self.backgroundBuild:
+			self.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5)
+			self.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5)
+			self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5)
+			self.close()
+			self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
+			self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id
+			return
+		self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500)
+		self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id)
+
+	def WaitBuildeNBisFinished(self):
+		if self.eNB_serverId == '0':
+			lIpAddr = self.eNBIPAddress
+			lUserName = self.eNBUserName
+			lPassWord = self.eNBPassword
+			lSourcePath = self.eNBSourceCodePath
+		elif self.eNB_serverId == '1':
+			lIpAddr = self.eNB1IPAddress
+			lUserName = self.eNB1UserName
+			lPassWord = self.eNB1Password
+			lSourcePath = self.eNB1SourceCodePath
+		elif self.eNB_serverId == '2':
+			lIpAddr = self.eNB2IPAddress
+			lUserName = self.eNB2UserName
+			lPassWord = self.eNB2Password
+			lSourcePath = self.eNB2SourceCodePath
+		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
+			Usage()
+			sys.exit('Insufficient Parameter')
+		self.open(lIpAddr, lUserName, lPassWord)
+		count = 40
+		buildOAIprocess = True
+		while (count > 0) and buildOAIprocess:
+			self.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3)
+			result = re.search('build_oai', str(self.ssh.before))
+			if result is None:
+				buildOAIprocess = False
+			else:
+				count -= 1
+				time.sleep(30)
+		self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)])
+
+	def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId):
+		self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3)
 		self.command('ls lte_build_oai/build', '\$', 3)
 		self.command('ls lte_build_oai/build', '\$', 3)
 		buildStatus = True
 		result = re.search('lte-softmodem', str(self.ssh.before))
 		if result is None:
 			buildStatus = False
-		self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5)
-		self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5)
-		self.command('mv compile_oai_enb.log ' + 'build_log_' + self.testCase_id, '\$', 5)
-		self.close()
+		else:
+			# Generating a BUILD INFO file
+			self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2)
+			self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2)
+			if (self.ranAllowMerge):
+				self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2)
+				if self.ranTargetBranch == '':
+					self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2)
+				else:
+					self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2)
+			else:
+				self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2)
+		self.command('mkdir -p build_log_' + testcaseId, '\$', 5)
+		self.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5)
+		self.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5)
+		if self.eNB_serverId != '0':
+			self.command('cd cmake_targets', '\$', 5)
+			self.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5)
+			self.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5)
+			self.close()
+			if (os.path.isfile('./tmp_build' + testcaseId + '.zip')):
+				os.remove('./tmp_build' + testcaseId + '.zip')
+			self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.')
+			if (os.path.isfile('./tmp_build' + testcaseId + '.zip')):
+				self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.')
+				os.remove('./tmp_build' + testcaseId + '.zip')
+				self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
+				self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5)
+				self.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5)
+				self.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5)
+				self.close()
+		else:
+			self.close()
+
 		if buildStatus:
 			self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
 		else:
@@ -360,29 +511,29 @@ class SSHConnection():
 			sys.exit(1)
 
 	def BuildOAIUE(self):
-		if self.UEIPAddress == '' or self.eNBRepository == '' or self.eNBBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
+		if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
 			Usage()
 			sys.exit('Insufficient Parameter')
 		self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
 		self.command('mkdir -p ' + self.UESourceCodePath, '\$', 5)
 		self.command('cd ' + self.UESourceCodePath, '\$', 5)
-		self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.eNBRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600)
+		self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600)
 		# here add a check if git clone or git fetch went smoothly
 		self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5)
 		self.command('git config user.name "OAI Jenkins"', '\$', 5)
 		self.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30)
 		# if the commit ID is provided use it to point to it
-		if self.eNBCommitID != '':
-			self.command('git checkout -f ' + self.eNBCommitID, '\$', 5)
+		if self.ranCommitID != '':
+			self.command('git checkout -f ' + self.ranCommitID, '\$', 5)
 		# 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
-		if (self.eNB_AllowMerge):
-			if self.eNBTargetBranch == '':
-				if (self.eNBBranch != 'develop') and (self.eNBBranch != 'origin/develop'):
+		if (self.ranAllowMerge):
+			if self.ranTargetBranch == '':
+				if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'):
 					self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5)
 			else:
-				logging.debug('Merging with the target branch: ' + self.eNBTargetBranch)
-				self.command('git merge --ff origin/' + self.eNBTargetBranch + ' -m "Temporary merge for CI"', '\$', 5)
+				logging.debug('Merging with the target branch: ' + self.ranTargetBranch)
+				self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5)
 		self.command('source oaienv', '\$', 5)
 		self.command('cd cmake_targets', '\$', 5)
 		self.command('mkdir -p log', '\$', 5)
@@ -498,7 +649,22 @@ class SSHConnection():
 		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
 	def InitializeeNB(self):
-		if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.eNBSourceCodePath == '':
+		if self.eNB_serverId == '0':
+			lIpAddr = self.eNBIPAddress
+			lUserName = self.eNBUserName
+			lPassWord = self.eNBPassword
+			lSourcePath = self.eNBSourceCodePath
+		elif self.eNB_serverId == '1':
+			lIpAddr = self.eNB1IPAddress
+			lUserName = self.eNB1UserName
+			lPassWord = self.eNB1Password
+			lSourcePath = self.eNB1SourceCodePath
+		elif self.eNB_serverId == '2':
+			lIpAddr = self.eNB2IPAddress
+			lUserName = self.eNB2UserName
+			lPassWord = self.eNB2Password
+			lSourcePath = self.eNB2SourceCodePath
+		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
 			Usage()
 			sys.exit('Insufficient Parameter')
 		check_eNB = False
@@ -519,10 +685,10 @@ class SSHConnection():
 				logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m')
 				self.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap'
 				self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + self.EPC_PcapFileName, '\$', 5)
-				self.command('echo $USER; nohup sudo tshark -f "host ' + self.eNBIPAddress +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5)
+				self.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5)
 			self.close()
-		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
-		self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
+		self.open(lIpAddr, lUserName, lPassWord)
+		self.command('cd ' + lSourcePath, '\$', 5)
 		# Initialize_eNB_args usually start with -O and followed by the location in repository
 		full_config_file = self.Initialize_eNB_args.replace('-O ','')
 		extra_options = ''
@@ -535,31 +701,34 @@ class SSHConnection():
 				logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m')
 				self.command('cd common/utils/T/tracer', '\$', 5)
 				self.command('make', '\$', 10)
-				self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', self.eNBUserName, 5)
-				self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
+				self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5)
+				self.command('cd ' + lSourcePath, '\$', 5)
 			full_config_file = full_config_file[:extIdx + 5]
 			config_path, config_file = os.path.split(full_config_file)
 		else:
 			sys.exit('Insufficient Parameter')
 		ci_full_config_file = config_path + '/ci-' + config_file
 		rruCheck = False
-		result = re.search('rru|du.band', str(config_file))
+		result = re.search('^rru|^rcc|^du.band', str(config_file))
 		if result is not None:
 			rruCheck = True
 		# do not reset board twice in IF4.5 case
-		result = re.search('rru|enb|du.band', str(config_file))
+		result = re.search('^rru|^enb|^du.band', str(config_file))
 		if result is not None:
-			self.command('echo ' + self.eNBPassword + ' | sudo -S uhd_find_devices', '\$', 10)
+			self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 10)
 			result = re.search('type: b200', str(self.ssh.before))
 			if result is not None:
 				logging.debug('Found a B2xx device --> resetting it')
-				self.command('echo ' + self.eNBPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10)
+				self.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10)
 				# Reloading FGPA bin firmware
-				self.command('echo ' + self.eNBPassword + ' | sudo -S uhd_find_devices', '\$', 15)
+				self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 15)
 		# Make a copy and adapt to EPC / eNB IP addresses
 		self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5)
 		self.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2);
-		self.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2);
+		self.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2);
+		self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2);
+		self.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2);
+		self.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2);
 		if self.flexranCtrlInstalled and self.flexranCtrlStarted:
 			self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED        = "yes";/\' ' + ci_full_config_file, '\$', 2);
 		else:
@@ -567,18 +736,13 @@ class SSHConnection():
 		# Launch eNB with the modified config file
 		self.command('source oaienv', '\$', 5)
 		self.command('cd cmake_targets', '\$', 5)
-		self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + self.eNBSourceCodePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
+		self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
 		self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
-		self.command('echo ' + self.eNBPassword + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5)
-		self.command('echo ' + self.eNBPassword + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + self.eNBSourceCodePath + '/cmake_targets -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
-		result = re.search('rcc|enb|cu.band', str(config_file))
-		if result is not None:
-			self.eNBLogFile = 'enb_' + self.testCase_id + '.log'
-			if extra_options != '':
-				self.eNBOptions = extra_options
-		result = re.search('rru|du.band', str(config_file))
-		if result is not None:
-			self.rruLogFile = 'enb_' + self.testCase_id + '.log'
+		self.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5)
+		self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
+		self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log'
+		if extra_options != '':
+			self.eNBOptions[int(self.eNB_instance)] = extra_options
 		time.sleep(6)
 		doLoop = True
 		loopCounter = 10
@@ -593,7 +757,6 @@ class SSHConnection():
 				doLoop = False
 				logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m')
 				self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK)
-				self.CreateHtmlTabFooter(False)
 				# In case of T tracer recording, we need to kill tshark on EPC side
 				result = re.search('T_stdout', str(self.Initialize_eNB_args))
 				if result is not None:
@@ -608,8 +771,9 @@ class SSHConnection():
 					if self.EPC_PcapFileName != '':
 						copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.')
 						if (copyin_res == 0):
-							self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.EPC_PcapFileName, self.eNBSourceCodePath + '/cmake_targets/.')
-				sys.exit(1)
+							self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.')
+				self.prematureExit = True
+				return
 			else:
 				self.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4)
 				if rruCheck:
@@ -620,8 +784,6 @@ class SSHConnection():
 					time.sleep(6)
 				else:
 					doLoop = False
-					if rruCheck and extra_options != '':
-						self.rruOptions = extra_options
 					self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK)
 					logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m')
 					time.sleep(10)
@@ -640,7 +802,10 @@ class SSHConnection():
 			# self.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60)
 			# a dedicated script has to be installed inside the UE
 			# airplane mode on means call /data/local/tmp/off
-			self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
+			if device_id == '84B7N16418004022':
+				self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60)
+			else:
+				self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
 			#airplane mode off means call /data/local/tmp/on
 			logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m')
 			self.close()
@@ -788,8 +953,6 @@ class SSHConnection():
 			self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE')
 			logging.error('\033[91mInitialize OAI UE Failed! \033[0m')
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
 
 	def checkDevTTYisUnlocked(self):
 		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
@@ -940,8 +1103,8 @@ class SSHConnection():
 		pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE)
 		if (pStatus < 0):
 			self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
+			self.prematureExit = True
+			return
 		try:
 			statusQueue = SimpleQueue()
 			lock = Lock()
@@ -1023,15 +1186,16 @@ class SSHConnection():
 			else:
 				self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue)
 				self.AutoTerminateUEandeNB()
-				self.CreateHtmlTabFooter(False)
-				sys.exit(1)
 		except:
 			os.kill(os.getppid(),signal.SIGUSR1)
 
 	def AttachUE_common(self, device_id, statusQueue, lock):
 		try:
 			self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
-			self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60)
+			if device_id == '84B7N16418004022':
+				self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60)
+			else:
+				self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60)
 			time.sleep(2)
 			max_count = 45
 			count = max_count
@@ -1058,9 +1222,15 @@ class SSHConnection():
 				count = count - 1
 				if count == 15 or count == 30:
 					logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m')
-					self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
+					if device_id == '84B7N16418004022':
+						self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60)
+					else:
+						self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
 					time.sleep(0.5)
-					self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60)
+					if device_id == '84B7N16418004022':
+						self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60)
+					else:
+						self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60)
 					time.sleep(0.5)
 				logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m')
 				time.sleep(1)
@@ -1085,14 +1255,14 @@ class SSHConnection():
 		if (pStatus < 0):
 			self.CreateHtmlTestRow('N/A', 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
+			return
 		multi_jobs = []
 		status_queue = SimpleQueue()
 		lock = Lock()
 		nb_ue_to_connect = 0
 		for device_id in self.UEDevices:
 			if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach):
+				self.UEDevicesStatus[nb_ue_to_connect] = UE_STATUS_ATTACHING
 				p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,))
 				p.daemon = True
 				p.start()
@@ -1103,9 +1273,8 @@ class SSHConnection():
 
 		if (status_queue.empty()):
 			self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK)
-			self.CreateHtmlTabFooter(False)
 			self.AutoTerminateUEandeNB()
-			sys.exit(1)
+			return
 		else:
 			attach_status = True
 			html_queue = SimpleQueue()
@@ -1121,6 +1290,11 @@ class SSHConnection():
 					html_cell = '<pre style="background-color:white">UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds</pre>'
 				html_queue.put(html_cell)
 			if (attach_status):
+				cnt = 0
+				while cnt < len(self.UEDevices):
+					if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING:
+						self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED
+					cnt += 1
 				self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
 				result = re.search('T_stdout', str(self.Initialize_eNB_args))
 				if result is not None:
@@ -1129,13 +1303,14 @@ class SSHConnection():
 			else:
 				self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue)
 				self.AutoTerminateUEandeNB()
-				self.CreateHtmlTabFooter(False)
-				sys.exit(1)
 
 	def DetachUE_common(self, device_id):
 		try:
 			self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
-			self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
+			if device_id == '84B7N16418004022':
+				self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60)
+			else:
+				self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60)
 			logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m')
 			self.close()
 		except:
@@ -1151,14 +1326,16 @@ class SSHConnection():
 		if (pStatus < 0):
 			self.CreateHtmlTestRow('N/A', 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
+			return
 		multi_jobs = []
+		cnt = 0
 		for device_id in self.UEDevices:
+			self.UEDevicesStatus[cnt] = UE_STATUS_DETACHING
 			p = Process(target = self.DetachUE_common, args = (device_id,))
 			p.daemon = True
 			p.start()
 			multi_jobs.append(p)
+			cnt += 1
 		for job in multi_jobs:
 			job.join()
 		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
@@ -1166,6 +1343,10 @@ class SSHConnection():
 		if result is not None:
 			logging.debug('Waiting 5 seconds to fill up record file')
 			time.sleep(5)
+		cnt = 0
+		while cnt < len(self.UEDevices):
+			self.UEDevicesStatus[cnt] = UE_STATUS_DETACHED
+			cnt += 1
 
 	def RebootUE_common(self, device_id):
 		try:
@@ -1286,6 +1467,11 @@ class SSHConnection():
 			if len(self.UEDevices) == 0:
 				logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m')
 				sys.exit(1)
+		if len(self.UEDevicesStatus) == 0:
+			cnt = 0
+			while cnt < len(self.UEDevices):
+				self.UEDevicesStatus.append(UE_STATUS_DETACHED)
+				cnt += 1
 		self.close()
 
 	def GetAllCatMDevices(self, terminate_ue_flag):
@@ -1392,8 +1578,6 @@ class SSHConnection():
 		if (status_queue.empty()):
 			self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
 		else:
 			check_status = True
 			html_queue = SimpleQueue()
@@ -1410,8 +1594,6 @@ class SSHConnection():
 			else:
 				self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue)
 				self.AutoTerminateUEandeNB()
-				self.CreateHtmlTabFooter(False)
-				sys.exit(1)
 
 	def GetAllUEIPAddresses(self):
 		if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '':
@@ -1436,7 +1618,11 @@ class SSHConnection():
 			self.close()
 			return ue_ip_status
 		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
+		idx = 0
 		for device_id in self.UEDevices:
+			if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED:
+				idx += 1
+				continue
 			count = 0
 			while count < 4:
 				self.command('stdbuf -o0 adb -s ' + device_id + ' shell ip addr show | grep rmnet', '\$', 15)
@@ -1458,6 +1644,7 @@ class SSHConnection():
 					ue_ip_status -= 1
 					continue
 			self.UEIPAddresses.append(UE_IPAddress)
+			idx += 1
 		self.close()
 		return ue_ip_status
 
@@ -1552,8 +1739,7 @@ class SSHConnection():
 		if (pStatus < 0):
 			self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
+			return
 		ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args))
 		if ping_from_eNB is not None:
 			if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '':
@@ -1656,14 +1842,12 @@ class SSHConnection():
 		if (pStatus < 0):
 			self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
+			return
 		ueIpStatus = self.GetAllUEIPAddresses()
 		if (ueIpStatus < 0):
 			self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
+			return
 		multi_jobs = []
 		i = 0
 		lock = Lock()
@@ -1681,8 +1865,6 @@ class SSHConnection():
 		if (status_queue.empty()):
 			self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
 		else:
 			ping_status = True
 			html_queue = SimpleQueue()
@@ -1700,8 +1882,6 @@ class SSHConnection():
 			else:
 				self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue)
 				self.AutoTerminateUEandeNB()
-				self.CreateHtmlTabFooter(False)
-				sys.exit(1)
 
 	def Iperf_ComputeTime(self):
 		result = re.search('-t (?P<iperf_time>\d+)', str(self.iperf_args))
@@ -2179,8 +2359,6 @@ class SSHConnection():
 		if (pStatus < 0):
 			self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
 		if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '':
 			Usage()
 			sys.exit('Insufficient Parameter')
@@ -2270,8 +2448,6 @@ class SSHConnection():
 		else:
 			self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
 
 	def Iperf(self):
 		result = re.search('noS1', str(self.Initialize_eNB_args))
@@ -2290,14 +2466,12 @@ class SSHConnection():
 		if (pStatus < 0):
 			self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
+			return
 		ueIpStatus = self.GetAllUEIPAddresses()
 		if (ueIpStatus < 0):
 			self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
+			return
 		multi_jobs = []
 		i = 0
 		ue_num = len(self.UEIPAddresses)
@@ -2316,8 +2490,6 @@ class SSHConnection():
 		if (status_queue.empty()):
 			self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK)
 			self.AutoTerminateUEandeNB()
-			self.CreateHtmlTabFooter(False)
-			sys.exit(1)
 		else:
 			iperf_status = True
 			iperf_noperf = False
@@ -2340,8 +2512,6 @@ class SSHConnection():
 			else:
 				self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue)
 				self.AutoTerminateUEandeNB()
-				self.CreateHtmlTabFooter(False)
-				sys.exit(1)
 
 	def CheckProcessExist(self, check_eNB, check_OAI_UE):
 		multi_jobs = []
@@ -2386,13 +2556,13 @@ class SSHConnection():
 				if (status < 0):
 					result = status
 			if result == ENB_PROCESS_FAILED:
-				fileCheck = re.search('enb_', str(self.eNBLogFile))
+				fileCheck = re.search('enb_', str(self.eNBLogFiles[0]))
 				if fileCheck is not None:
-					self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFile, '.')
-					logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFile)
+					self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFiles[0], '.')
+					logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFiles[0])
 					if logStatus < 0:
 						result = logStatus
-					self.eNBLogFile = ''
+					self.eNBLogFiles[0] = ''
 				if self.flexranCtrlInstalled and self.flexranCtrlStarted:
 					self.TerminateFlexranCtrl()
 			return result
@@ -2530,17 +2700,49 @@ class SSHConnection():
 		cdrxActivationMessageCount = 0
 		dropNotEnoughRBs = 0
 		self.htmleNBFailureMsg = ''
+		isRRU = False
+		isSlave = False
+		slaveReceivesFrameResyncCmd = False
+		X2HO_state = X2_HO_REQ_STATE__IDLE
+		X2HO_inNbProcedures = 0
+		X2HO_outNbProcedures = 0
 		for line in enb_log_file.readlines():
-			if self.rruOptions != '':
-				res1 = re.search('max_rxgain (?P<requested_option>[0-9]+)', self.rruOptions)
+			if X2HO_state == X2_HO_REQ_STATE__IDLE:
+				result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ
+				result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK
+			if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ:
+				result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE
+			if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE:
+				result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ
+			if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ:
+				result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__IDLE
+					X2HO_inNbProcedures += 1
+			if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK:
+				result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line))
+				if result is not None:
+					X2HO_state = X2_HO_REQ_STATE__IDLE
+					X2HO_outNbProcedures += 1
+
+			if self.eNBOptions[int(self.eNB_instance)] != '':
+				res1 = re.search('max_rxgain (?P<requested_option>[0-9]+)', self.eNBOptions[int(self.eNB_instance)])
 				res2 = re.search('max_rxgain (?P<applied_option>[0-9]+)',  str(line))
 				if res1 is not None and res2 is not None:
 					requested_option = int(res1.group('requested_option'))
 					applied_option = int(res2.group('applied_option'))
 					if requested_option == applied_option:
-						self.htmleNBFailureMsg += '<span class="glyphicon glyphicon-ok-circle"></span> Command line option(s) correctly applied <span class="glyphicon glyphicon-arrow-right"></span> ' + self.rruOptions + '\n\n'
+						self.htmleNBFailureMsg += '<span class="glyphicon glyphicon-ok-circle"></span> Command line option(s) correctly applied <span class="glyphicon glyphicon-arrow-right"></span> ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n'
 					else:
-						self.htmleNBFailureMsg += '<span class="glyphicon glyphicon-ban-circle"></span> Command line option(s) NOT applied <span class="glyphicon glyphicon-arrow-right"></span> ' + self.rruOptions + '\n\n'
+						self.htmleNBFailureMsg += '<span class="glyphicon glyphicon-ban-circle"></span> Command line option(s) NOT applied <span class="glyphicon glyphicon-arrow-right"></span> ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n'
 			result = re.search('Exiting OAI softmodem', str(line))
 			if result is not None:
 				exitSignalReceived = True
@@ -2562,6 +2764,17 @@ class SSHConnection():
 			if foundAssertion and (msgLine < 3):
 				msgLine += 1
 				msgAssertion += str(line)
+			result = re.search('Setting function for RU', str(line))
+			if result is not None:
+				isRRU = True
+			if isRRU:
+				result = re.search('RU 0 is_slave=yes', str(line))
+				if result is not None:
+					isSlave = True
+				if isSlave:
+					result = re.search('Received RRU_frame_resynch command', str(line))
+					if result is not None:
+						slaveReceivesFrameResyncCmd = True
 			result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line))
 			if result is not None:
 				rrcSetupComplete += 1
@@ -2647,14 +2860,41 @@ class SSHConnection():
 			rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected'
 			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
 			self.htmleNBFailureMsg += rrcMsg + '\n'
-		if cdrxActivationMessageCount > 0:
-			rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)'
+		if X2HO_inNbProcedures > 0:
+			rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)'
+			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
+			self.htmleNBFailureMsg += rrcMsg + '\n'
+		if X2HO_outNbProcedures > 0:
+			rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)'
 			logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
 			self.htmleNBFailureMsg += rrcMsg + '\n'
+		if self.eNBOptions[int(self.eNB_instance)] != '':
+			res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)])
+			if res1 is not None:
+				if cdrxActivationMessageCount > 0:
+					rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)'
+					logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m')
+					self.htmleNBFailureMsg += rrcMsg + '\n'
+				else:
+					rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration'
+					logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m')
+					self.htmleNBFailureMsg += rrcMsg + '\n'
 		if rachCanceledProcedure > 0:
 			rachMsg = 'eNB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)'
 			logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m')
 			self.htmleNBFailureMsg += rachMsg + '\n'
+		if isRRU:
+			if isSlave:
+				if slaveReceivesFrameResyncCmd:
+					rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU'
+					logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m')
+					self.htmleNBFailureMsg += rruMsg + '\n'
+				else:
+					rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU'
+					logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m')
+					self.htmleNBFailureMsg += rruMsg + '\n'
+					self.prematureExit = True
+					return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED
 		if foundSegFault:
 			logging.debug('\u001B[1;37;41m eNB ended with a Segmentation Fault! \u001B[0m')
 			return ENB_PROCESS_SEG_FAULT
@@ -2842,18 +3082,36 @@ class SSHConnection():
 		return 0
 
 	def TerminateeNB(self):
-		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
-		self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5)
+		if self.eNB_serverId == '0':
+			lIpAddr = self.eNBIPAddress
+			lUserName = self.eNBUserName
+			lPassWord = self.eNBPassword
+			lSourcePath = self.eNBSourceCodePath
+		elif self.eNB_serverId == '1':
+			lIpAddr = self.eNB1IPAddress
+			lUserName = self.eNB1UserName
+			lPassWord = self.eNB1Password
+			lSourcePath = self.eNB1SourceCodePath
+		elif self.eNB_serverId == '2':
+			lIpAddr = self.eNB2IPAddress
+			lUserName = self.eNB2UserName
+			lPassWord = self.eNB2Password
+			lSourcePath = self.eNB2SourceCodePath
+		if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '':
+			Usage()
+			sys.exit('Insufficient Parameter')
+		self.open(lIpAddr, lUserName, lPassWord)
+		self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5)
 		self.command('stdbuf -o0  ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5)
 		result = re.search('lte-softmodem', str(self.ssh.before))
 		if result is not None:
-			self.command('echo ' + self.eNBPassword + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5)
-			self.command('echo ' + self.eNBPassword + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5)
+			self.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5)
+			self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5)
 			time.sleep(5)
 			self.command('stdbuf -o0  ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5)
 			result = re.search('lte-softmodem', str(self.ssh.before))
 			if result is not None:
-				self.command('echo ' + self.eNBPassword + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5)
+				self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5)
 				time.sleep(2)
 		self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
 		self.close()
@@ -2867,50 +3125,46 @@ class SSHConnection():
 			if self.EPC_PcapFileName != '':
 				self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5)
 				self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.')
-				self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.EPC_PcapFileName, self.eNBSourceCodePath + '/cmake_targets/.')
+				self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.')
 			self.close()
 			logging.debug('\u001B[1m Replaying RAW record file\u001B[0m')
-			self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
-			self.command('cd ' + self.eNBSourceCodePath + '/common/utils/T/tracer/', '\$', 5)
-			raw_record_file = self.eNBLogFile.replace('.log', '_record.raw')
-			replay_log_file = self.eNBLogFile.replace('.log', '_replay.log')
-			extracted_txt_file = self.eNBLogFile.replace('.log', '_extracted_messages.txt')
-			extracted_log_file = self.eNBLogFile.replace('.log', '_extracted_messages.log')
-			self.command('./extract_config -i ' + self.eNBSourceCodePath + '/cmake_targets/' + raw_record_file + ' > ' + self.eNBSourceCodePath + '/cmake_targets/' + extracted_txt_file, '\$', 5)
-			self.command('echo $USER; nohup ./replay -i ' + self.eNBSourceCodePath + '/cmake_targets/' + raw_record_file + ' > ' + self.eNBSourceCodePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', self.eNBUserName, 5)
-			self.command('./textlog -d ' +  self.eNBSourceCodePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + self.eNBSourceCodePath + '/cmake_targets/' + extracted_log_file, '\$', 5)
+			self.open(lIpAddr, lUserName, lPassWord)
+			self.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5)
+			enbLogFile = self.eNBLogFiles[int(self.eNB_instance)]
+			raw_record_file = enbLogFile.replace('.log', '_record.raw')
+			replay_log_file = enbLogFile.replace('.log', '_replay.log')
+			extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt')
+			extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log')
+			self.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5)
+			self.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5)
+			self.command('./textlog -d ' +  lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5)
 			self.close()
-			self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + extracted_log_file, '.')
+			self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.')
 			logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m')
 			logStatus = self.AnalyzeLogFile_eNB(extracted_log_file)
 			self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
-			self.eNBLogFile = ''
+			self.eNBLogFiles[int(self.eNB_instance)] = ''
 		else:
-			result = re.search('enb_', str(self.eNBLogFile))
 			analyzeFile = False
-			if result is not None:
+			if self.eNBLogFiles[int(self.eNB_instance)] != '':
 				analyzeFile = True
-				fileToAnalyze = str(self.eNBLogFile)
-				self.eNBLogFile = ''
-			else:
-				result = re.search('enb_', str(self.rruLogFile))
-				if result is not None:
-					analyzeFile = True
-					fileToAnalyze = str(self.rruLogFile)
-					self.rruLogFile = ''
+				fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)]
+				self.eNBLogFiles[int(self.eNB_instance)] = ''
 			if analyzeFile:
-				copyin_res = self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + fileToAnalyze, '.')
+				copyin_res = self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.')
 				if (copyin_res == -1):
 					logging.debug('\u001B[1;37;41m Could not copy eNB logfile to analyze it! \u001B[0m')
 					self.htmleNBFailureMsg = 'Could not copy eNB logfile to analyze it!'
 					self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE)
 					return
+				if self.eNB_serverId != '0':
+					self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/')
 				logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m ' + fileToAnalyze)
 				logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze)
 				if (logStatus < 0):
 					self.CreateHtmlTestRow('N/A', 'KO', logStatus)
-					self.CreateHtmlTabFooter(False)
-					sys.exit(1)
+					self.preamtureExit = True
+					return
 				else:
 					self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 			else:
@@ -3049,8 +3303,6 @@ class SSHConnection():
 				if (logStatus != OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'):
 					self.Initialize_OAI_UE_args = ''
 					self.AutoTerminateUEandeNB()
-					self.CreateHtmlTabFooter(False)
-					sys.exit(1)
 			else:
 				logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m')
 				self.htmlUEFailureMsg = '<b>' + ueAction + ' Completed</b>\n' + self.htmlUEFailureMsg
@@ -3076,11 +3328,122 @@ class SSHConnection():
 			self.ShowTestID()
 			self.eNB_instance = '0'
 			self.TerminateeNB()
+		self.prematureExit = True
 
 	def IdleSleep(self):
 		time.sleep(self.idle_sleep_time)
 		self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK)
 
+	def X2_Status(self, idx, fileName):
+		cmd = "curl --silent http://" + self.EPCIPAddress + ":9999/stats | jq '.' > " + fileName
+		message = cmd + '\n'
+		logging.debug(cmd)
+		subprocess.run(cmd, shell=True)
+		if idx == 0:
+			cmd = "jq '.mac_stats | length' " + fileName
+			strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True)
+			self.x2NbENBs = int(strNbEnbs.strip())
+		cnt = 0
+		while cnt < self.x2NbENBs:
+			cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName
+			bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True)
+			self.x2ENBBsIds[idx].append(bs_id.strip())
+			cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName
+			stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True)
+			nbUEs = int(stNbUEs.strip())
+			ueIdx = 0
+			self.x2ENBConnectedUEs[idx].append([])
+			while ueIdx < nbUEs:
+				cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName
+				rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True)
+				self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip())
+				ueIdx += 1
+			cnt += 1
+
+		msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)"
+		logging.debug(msg)
+		message += msg + '\n'
+		cnt = 0
+		while cnt < self.x2NbENBs:
+			msg = "   -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][cnt])) + " UE(s)"
+			logging.debug(msg)
+			message += msg + '\n'
+			ueIdx = 0
+			while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]):
+				msg = "      -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx])
+				logging.debug(msg)
+				message += msg + '\n'
+				ueIdx += 1
+			cnt += 1
+		return message
+
+	def Perform_X2_Handover(self):
+		html_queue = SimpleQueue()
+		fullMessage = '<pre style="background-color:white">'
+		msg = 'Doing X2 Handover w/ option ' + self.x2_ho_options
+		logging.debug(msg)
+		fullMessage += msg + '\n'
+		if self.x2_ho_options == 'network':
+			if self.flexranCtrlInstalled and self.flexranCtrlStarted:
+				self.x2ENBBsIds = []
+				self.x2ENBConnectedUEs = []
+				self.x2ENBBsIds.append([])
+				self.x2ENBBsIds.append([])
+				self.x2ENBConnectedUEs.append([])
+				self.x2ENBConnectedUEs.append([])
+				fullMessage += self.X2_Status(0, self.testCase_id + '_pre_ho.json') 
+
+				msg = "Activating the X2 Net control on each eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				eNB_cnt = self.x2NbENBs
+				cnt = 0
+				while cnt < eNB_cnt:
+					cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1"
+					logging.debug(cmd)
+					fullMessage += cmd + '\n'
+					subprocess.run(cmd, shell=True)
+					cnt += 1
+				# Waiting for the activation to be active
+				time.sleep(10)
+				msg = "Switching UE(s) from eNB to eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				cnt = 0
+				while cnt < eNB_cnt:
+					ueIdx = 0
+					while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]):
+						cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1])
+						logging.debug(cmd)
+						fullMessage += cmd + '\n'
+						subprocess.run(cmd, shell=True)
+						ueIdx += 1
+					cnt += 1
+				time.sleep(10)
+				# check
+				logging.debug("Checking the Status after X2 Handover")
+				fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') 
+				cnt = 0
+				x2Status = True
+				while cnt < eNB_cnt:
+					if len(self.x2ENBConnectedUEs[0][cnt]) == len(self.x2ENBConnectedUEs[1][cnt]):
+						x2Status = False
+					cnt += 1
+				if x2Status:
+					msg = "X2 Handover was successful"
+					logging.debug(msg)
+					fullMessage += msg + '</pre>'
+					html_queue.put(fullMessage)
+					self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
+				else:
+					msg = "X2 Handover FAILED"
+					logging.error(msg)
+					fullMessage += msg + '</pre>'
+					html_queue.put(fullMessage)
+					self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue)
+			else:
+				self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK)
+
 	def LogCollectBuild(self):
 		if (self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != ''):
 			IPAddress = self.eNBIPAddress
@@ -3099,7 +3462,6 @@ class SSHConnection():
 		self.command('cd cmake_targets', '\$', 5)
 		self.command('rm -f build.log.zip', '\$', 5)
 		self.command('zip build.log.zip build_log_*/*', '\$', 60)
-		self.command('echo ' + Password + ' | sudo -S rm -rf build_log_*', '\$', 5)
 		self.close()
 
 	def LogCollecteNB(self):
@@ -3276,46 +3638,46 @@ class SSHConnection():
 			self.htmlFile.write('     </tr>\n')
 			self.htmlFile.write('     <tr>\n')
 			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-cloud-upload"></span> GIT Repository </td>\n')
-			self.htmlFile.write('       <td><a href="' + self.eNBRepository + '">' + self.eNBRepository + '</a></td>\n')
+			self.htmlFile.write('       <td><a href="' + self.ranRepository + '">' + self.ranRepository + '</a></td>\n')
 			self.htmlFile.write('     </tr>\n')
 			self.htmlFile.write('     <tr>\n')
 			self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-wrench"></span> Job Trigger </td>\n')
-			if (self.eNB_AllowMerge):
+			if (self.ranAllowMerge):
 				self.htmlFile.write('       <td>Merge-Request</td>\n')
 			else:
 				self.htmlFile.write('       <td>Push to Branch</td>\n')
 			self.htmlFile.write('     </tr>\n')
 			self.htmlFile.write('     <tr>\n')
-			if (self.eNB_AllowMerge):
+			if (self.ranAllowMerge):
 				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-out"></span> Source Branch </td>\n')
 			else:
 				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tree-deciduous"></span> Branch</td>\n')
-			self.htmlFile.write('       <td>' + self.eNBBranch + '</td>\n')
+			self.htmlFile.write('       <td>' + self.ranBranch + '</td>\n')
 			self.htmlFile.write('     </tr>\n')
 			self.htmlFile.write('     <tr>\n')
-			if (self.eNB_AllowMerge):
+			if (self.ranAllowMerge):
 				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Source Commit ID </td>\n')
 			else:
 				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-tag"></span> Commit ID </td>\n')
-			self.htmlFile.write('       <td>' + self.eNBCommitID + '</td>\n')
+			self.htmlFile.write('       <td>' + self.ranCommitID + '</td>\n')
 			self.htmlFile.write('     </tr>\n')
-			if self.eNB_AllowMerge != '':
-				commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.eNBCommitID, shell=True, universal_newlines=True)
+			if self.ranAllowMerge != '':
+				commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True)
 				commit_message = commit_message.strip()
 				self.htmlFile.write('     <tr>\n')
-				if (self.eNB_AllowMerge):
+				if (self.ranAllowMerge):
 					self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Source Commit Message </td>\n')
 				else:
 					self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-comment"></span> Commit Message </td>\n')
 				self.htmlFile.write('       <td>' + commit_message + '</td>\n')
 				self.htmlFile.write('     </tr>\n')
-			if (self.eNB_AllowMerge):
+			if (self.ranAllowMerge):
 				self.htmlFile.write('     <tr>\n')
 				self.htmlFile.write('       <td bgcolor = "lightcyan" > <span class="glyphicon glyphicon-log-in"></span> Target Branch </td>\n')
-				if (self.eNBTargetBranch == ''):
+				if (self.ranTargetBranch == ''):
 					self.htmlFile.write('       <td>develop</td>\n')
 				else:
-					self.htmlFile.write('       <td>' + self.eNBTargetBranch + '</td>\n')
+					self.htmlFile.write('       <td>' + self.ranTargetBranch + '</td>\n')
 				self.htmlFile.write('     </tr>\n')
 			self.htmlFile.write('  </table>\n')
 
@@ -3337,6 +3699,7 @@ class SSHConnection():
 				pillMsg = '    <li><a data-toggle="pill" href="#'
 				pillMsg += self.htmlTabRefs[count]
 				pillMsg += '">'
+				pillMsg += '__STATE_' + self.htmlTabNames[count] + '__'
 				pillMsg += self.htmlTabNames[count]
 				pillMsg += ' <span class="glyphicon glyphicon-'
 				pillMsg += self.htmlTabIcons[count]
@@ -3390,6 +3753,14 @@ class SSHConnection():
 			self.htmlFile.write('      </tr>\n')
 			self.htmlFile.write('  </table>\n')
 			self.htmlFile.write('  </div>\n')
+			self.htmlFile.close()
+			time.sleep(1)
+			if passStatus:
+				cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html"
+				subprocess.run(cmd, shell=True)
+			else:
+				cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<span class=\"glyphicon glyphicon-remove\"><\/span>/' test_results.html"
+				subprocess.run(cmd, shell=True)
 		self.htmlFooterCreated = False
 
 	def CreateHtmlFooter(self, passStatus):
@@ -3468,6 +3839,8 @@ class SSHConnection():
 					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process faced Real Time issue(s)</td>\n')
 				elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE):
 					self.htmlFile.write('        <td bgcolor = "orange" >OK?</td>\n')
+				elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' Slave RRU could not synch</td>\n')
 				elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC):
 					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - UE could not sync</td>\n')
 				elif (processesStatus == HSS_PROCESS_FAILED):
@@ -3563,12 +3936,12 @@ def Usage():
 	print('      InitiateHtml, FinalizeHtml')
 	print('      TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW')
 	print('      LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf')
+	print('  --eNBRepository=[eNB\'s Repository URL]                             or --ranRepository=[OAI RAN Repository URL]')
+	print('  --eNBBranch=[eNB\'s Branch Name]                                    or --ranBranch=[OAI RAN Repository Branch')
+	print('  --eNBCommitID=[eNB\'s Commit Number]                                or --ranCommitID=[OAI RAN Repository Commit SHA-1')
+	print('  --eNB_AllowMerge=[eNB\'s Allow Merge Request (with target branch)]  or --ranAllowMerge=true/false')
+	print('  --eNBTargetBranch=[eNB\'s Target Branch in case of a Merge Request] or --ranTargetBranch=[Target Branch]')
 	print('  --eNBIPAddress=[eNB\'s IP Address]')
-	print('  --eNBRepository=[eNB\'s Repository URL]')
-	print('  --eNBBranch=[eNB\'s Branch Name]')
-	print('  --eNBCommitID=[eNB\'s Commit Number]')
-	print('  --eNB_AllowMerge=[eNB\'s Allow Merge Request (with target branch)]')
-	print('  --eNBTargetBranch=[eNB\'s Target Branch in case of a Merge Request]')
 	print('  --eNBUserName=[eNB\'s Login User Name]')
 	print('  --eNBPassword=[eNB\'s Login Password]')
 	print('  --eNBSourceCodePath=[eNB\'s Source Code Path]')
@@ -3584,7 +3957,7 @@ def Usage():
 	print('------------------------------------------------------------')
 
 def CheckClassValidity(action,id):
-	if action != 'Build_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep':
+	if action != 'Build_eNB' and action != 'WaitEndBuild_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover':
 		logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action)
 		return False
 	return True
@@ -3592,17 +3965,46 @@ def CheckClassValidity(action,id):
 def GetParametersFromXML(action):
 	if action == 'Build_eNB':
 		SSH.Build_eNB_args = test.findtext('Build_eNB_args')
+		SSH.eNB_instance = test.findtext('eNB_instance')
+		if (SSH.eNB_instance is None):
+			SSH.eNB_instance = '0'
+		SSH.eNB_serverId = test.findtext('eNB_serverId')
+		if (SSH.eNB_serverId is None):
+			SSH.eNB_serverId = '0'
+		xmlBgBuildField = test.findtext('backgroundBuild')
+		if (xmlBgBuildField is None):
+			SSH.backgroundBuild = False
+		else:
+			if re.match('true', xmlBgBuildField, re.IGNORECASE):
+				SSH.backgroundBuild = True
+			else:
+				SSH.backgroundBuild = False
+
+	if action == 'WaitEndBuild_eNB':
+		SSH.Build_eNB_args = test.findtext('Build_eNB_args')
+		SSH.eNB_instance = test.findtext('eNB_instance')
+		if (SSH.eNB_instance is None):
+			SSH.eNB_instance = '0'
+		SSH.eNB_serverId = test.findtext('eNB_serverId')
+		if (SSH.eNB_serverId is None):
+			SSH.eNB_serverId = '0'
 
 	if action == 'Initialize_eNB':
 		SSH.Initialize_eNB_args = test.findtext('Initialize_eNB_args')
 		SSH.eNB_instance = test.findtext('eNB_instance')
 		if (SSH.eNB_instance is None):
 			SSH.eNB_instance = '0'
+		SSH.eNB_serverId = test.findtext('eNB_serverId')
+		if (SSH.eNB_serverId is None):
+			SSH.eNB_serverId = '0'
 
 	if action == 'Terminate_eNB':
 		SSH.eNB_instance = test.findtext('eNB_instance')
 		if (SSH.eNB_instance is None):
 			SSH.eNB_instance = '0'
+		SSH.eNB_serverId = test.findtext('eNB_serverId')
+		if (SSH.eNB_serverId is None):
+			SSH.eNB_serverId = '0'
 
 	if action == 'Attach_UE':
 		nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach')
@@ -3654,6 +4056,18 @@ def GetParametersFromXML(action):
 		else:
 			SSH.idle_sleep_time = int(string_field)
 
+	if action == 'Perform_X2_Handover':
+		string_field = test.findtext('x2_ho_options')
+		if (string_field is None):
+			SSH.x2_ho_options = 'network'
+		else:
+			if string_field != 'network':
+				logging.error('ERROR: test-case has wrong option ' + string_field)
+				SSH.x2_ho_options = 'network'
+			else:
+				SSH.x2_ho_options = string_field
+
+
 #check if given test is in list
 #it is in list if one of the strings in 'list' is at the beginning of 'test'
 def test_in_list(test, list):
@@ -3684,35 +4098,78 @@ while len(argvs) > 1:
 	elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE):
 		matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE)
 		mode = matchReg.group(1)
-	elif re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE):
-		matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE)
-		SSH.eNBIPAddress = matchReg.group(1)
-	elif re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE):
-		matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE)
-		SSH.eNBRepository = matchReg.group(1)
-	elif re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE):
-		matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE)
+	elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE):
+		if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE)
+		else:
+			matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE)
+		SSH.ranRepository = matchReg.group(1)
+	elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE):
+		if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE)
+		else:
+			matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE)
 		doMerge = matchReg.group(1)
 		if ((doMerge == 'true') or (doMerge == 'True')):
-			SSH.eNB_AllowMerge = True
-	elif re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE):
-		matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE)
-		SSH.eNBBranch = matchReg.group(1)
-	elif re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE):
-		matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE)
-		SSH.eNBCommitID = matchReg.group(1)
-	elif re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE):
-		matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE)
-		SSH.eNBTargetBranch = matchReg.group(1)
-	elif re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE):
-		matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE)
-		SSH.eNBUserName = matchReg.group(1)
-	elif re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE):
-		matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE)
-		SSH.eNBPassword = matchReg.group(1)
-	elif re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE):
-		matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
-		SSH.eNBSourceCodePath = matchReg.group(1)
+			SSH.ranAllowMerge = True
+	elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE):
+		if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE)
+		else:
+			matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE)
+		SSH.ranBranch = matchReg.group(1)
+	elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE):
+		if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE)
+		else:
+			matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE)
+		SSH.ranCommitID = matchReg.group(1)
+	elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE):
+		if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE)
+		else:
+			matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE)
+		SSH.ranTargetBranch = matchReg.group(1)
+	elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE):
+		if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNBIPAddress = matchReg.group(1)
+		elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNB1IPAddress = matchReg.group(1)
+		elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNB2IPAddress = matchReg.group(1)
+	elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE):
+		if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNBUserName = matchReg.group(1)
+		elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNB1UserName = matchReg.group(1)
+		elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNB2UserName = matchReg.group(1)
+	elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE):
+		if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNBPassword = matchReg.group(1)
+		elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNB1Password = matchReg.group(1)
+		elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNB2Password = matchReg.group(1)
+	elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
+		if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNBSourceCodePath = matchReg.group(1)
+		elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNB1SourceCodePath = matchReg.group(1)
+		elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
+			matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE)
+			SSH.eNB2SourceCodePath = matchReg.group(1)
 	elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE):
 		matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE)
 		SSH.EPCIPAddress = matchReg.group(1)
@@ -3772,6 +4229,9 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE):
 	if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '':
 		Usage()
 		sys.exit('Insufficient Parameter')
+	SSH.eNB_serverId = '0'
+	SSH.eNB_instance = '0'
+	SSH.eNBSourceCodePath = '/tmp/'
 	SSH.TerminateeNB()
 elif re.match('^TerminateUE$', mode, re.IGNORECASE):
 	if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''):
@@ -3864,15 +4324,15 @@ elif re.match('^FinalizeHtml$', mode, re.IGNORECASE):
 	SSH.CreateHtmlFooter(SSH.finalStatus)
 elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE):
 	if re.match('^TesteNB$', mode, re.IGNORECASE):
-		if SSH.eNBIPAddress == '' or SSH.eNBRepository == '' or SSH.eNBBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '':
+		if SSH.eNBIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '':
 			Usage()
 			sys.exit('Insufficient Parameter')
 
-		if (SSH.EPCIPAddress != ''):
+		if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'):
 			SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp")
 			SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp")
 	else:
-		if SSH.UEIPAddress == '' or SSH.eNBRepository == '' or SSH.eNBBranch == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '':
+		if SSH.UEIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '':
 			Usage()
 			sys.exit('UE: Insufficient Parameter')
 
@@ -3890,6 +4350,9 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
 	requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='')
 	if (SSH.nbTestXMLfiles == 1):
 		SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0'))
+		SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0'))
+		repeatCount = xmlRoot.findtext('repeatCount',default='1')
+		SSH.repeatCounts.append(int(repeatCount))
 	all_tests=xmlRoot.findall('testCase')
 
 	exclusion_tests=exclusion_tests.split()
@@ -3915,7 +4378,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
 		else:
 			logging.debug('ERROR: requested test is invalidly formatted: ' + test)
 			sys.exit(1)
-	SSH.CheckFlexranCtrlInstallation()
+	if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'):
+		SSH.CheckFlexranCtrlInstallation()
 
 	#get the list of tests to be done
 	todo_tests=[]
@@ -3930,86 +4394,104 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re
 
 	SSH.CreateHtmlTabHeader()
 
-	for test_case_id in todo_tests:
-		for test in all_tests:
-			id = test.get('id')
-			if test_case_id != id:
-				continue
-			SSH.testCase_id = id
-			SSH.desc = test.findtext('desc')
-			action = test.findtext('class')
-			if (CheckClassValidity(action, id) == False):
-				continue
-			SSH.ShowTestID()
-			GetParametersFromXML(action)
-			if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE':
-				if (SSH.ADBIPAddress != 'none'):
-					terminate_ue_flag = False
-					SSH.GetAllUEDevices(terminate_ue_flag)
-			if action == 'Build_eNB':
-				SSH.BuildeNB()
-			elif action == 'Initialize_eNB':
-				SSH.InitializeeNB()
-			elif action == 'Terminate_eNB':
-				SSH.TerminateeNB()
-			elif action == 'Initialize_UE':
-				SSH.InitializeUE()
-			elif action == 'Terminate_UE':
-				SSH.TerminateUE()
-			elif action == 'Attach_UE':
-				SSH.AttachUE()
-			elif action == 'Detach_UE':
-				SSH.DetachUE()
-			elif action == 'DataDisable_UE':
-				SSH.DataDisableUE()
-			elif action == 'DataEnable_UE':
-				SSH.DataEnableUE()
-			elif action == 'CheckStatusUE':
-				SSH.CheckStatusUE()
-			elif action == 'Build_OAI_UE':
-				SSH.BuildOAIUE()
-			elif action == 'Initialize_OAI_UE':
-				SSH.InitializeOAIUE()
-			elif action == 'Terminate_OAI_UE':
-				SSH.TerminateOAIUE()
-			elif action == 'Initialize_CatM_module':
-				SSH.InitializeCatM()
-			elif action == 'Terminate_CatM_module':
-				SSH.TerminateCatM()
-			elif action == 'Attach_CatM_module':
-				SSH.AttachCatM()
-			elif action == 'Detach_CatM_module':
-				SSH.TerminateCatM()
-			elif action == 'Ping_CatM_module':
-				SSH.PingCatM()
-			elif action == 'Ping':
-				SSH.Ping()
-			elif action == 'Iperf':
-				SSH.Iperf()
-			elif action == 'Reboot_UE':
-				SSH.RebootUE()
-			elif action == 'Initialize_HSS':
-				SSH.InitializeHSS()
-			elif action == 'Terminate_HSS':
-				SSH.TerminateHSS()
-			elif action == 'Initialize_MME':
-				SSH.InitializeMME()
-			elif action == 'Terminate_MME':
-				SSH.TerminateMME()
-			elif action == 'Initialize_SPGW':
-				SSH.InitializeSPGW()
-			elif action == 'Terminate_SPGW':
-				SSH.TerminateSPGW()
-			elif action == 'Initialize_FlexranCtrl':
-				SSH.InitializeFlexranCtrl()
-			elif action == 'Terminate_FlexranCtrl':
-				SSH.TerminateFlexranCtrl()
-			elif action == 'IdleSleep':
-				SSH.IdleSleep()
-			else:
-				sys.exit('Invalid action')
-
-	SSH.CreateHtmlTabFooter(True)
+	cnt = 0
+	SSH.prematureExit = True
+	while cnt < SSH.repeatCounts[0] and SSH.prematureExit:
+		SSH.prematureExit = False
+		for test_case_id in todo_tests:
+			for test in all_tests:
+				id = test.get('id')
+				if test_case_id != id:
+					continue
+				SSH.testCase_id = id
+				SSH.desc = test.findtext('desc')
+				action = test.findtext('class')
+				if (CheckClassValidity(action, id) == False):
+					continue
+				SSH.ShowTestID()
+				GetParametersFromXML(action)
+				if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE':
+					if (SSH.ADBIPAddress != 'none'):
+						terminate_ue_flag = False
+						SSH.GetAllUEDevices(terminate_ue_flag)
+				if action == 'Build_eNB':
+					SSH.BuildeNB()
+				elif action == 'WaitEndBuild_eNB':
+					SSH.WaitBuildeNBisFinished()
+				elif action == 'Initialize_eNB':
+					SSH.InitializeeNB()
+				elif action == 'Terminate_eNB':
+					SSH.TerminateeNB()
+				elif action == 'Initialize_UE':
+					SSH.InitializeUE()
+				elif action == 'Terminate_UE':
+					SSH.TerminateUE()
+				elif action == 'Attach_UE':
+					SSH.AttachUE()
+				elif action == 'Detach_UE':
+					SSH.DetachUE()
+				elif action == 'DataDisable_UE':
+					SSH.DataDisableUE()
+				elif action == 'DataEnable_UE':
+					SSH.DataEnableUE()
+				elif action == 'CheckStatusUE':
+					SSH.CheckStatusUE()
+				elif action == 'Build_OAI_UE':
+					SSH.BuildOAIUE()
+				elif action == 'Initialize_OAI_UE':
+					SSH.InitializeOAIUE()
+				elif action == 'Terminate_OAI_UE':
+					SSH.TerminateOAIUE()
+				elif action == 'Initialize_CatM_module':
+					SSH.InitializeCatM()
+				elif action == 'Terminate_CatM_module':
+					SSH.TerminateCatM()
+				elif action == 'Attach_CatM_module':
+					SSH.AttachCatM()
+				elif action == 'Detach_CatM_module':
+					SSH.TerminateCatM()
+				elif action == 'Ping_CatM_module':
+					SSH.PingCatM()
+				elif action == 'Ping':
+					SSH.Ping()
+				elif action == 'Iperf':
+					SSH.Iperf()
+				elif action == 'Reboot_UE':
+					SSH.RebootUE()
+				elif action == 'Initialize_HSS':
+					SSH.InitializeHSS()
+				elif action == 'Terminate_HSS':
+					SSH.TerminateHSS()
+				elif action == 'Initialize_MME':
+					SSH.InitializeMME()
+				elif action == 'Terminate_MME':
+					SSH.TerminateMME()
+				elif action == 'Initialize_SPGW':
+					SSH.InitializeSPGW()
+				elif action == 'Terminate_SPGW':
+					SSH.TerminateSPGW()
+				elif action == 'Initialize_FlexranCtrl':
+					SSH.InitializeFlexranCtrl()
+				elif action == 'Terminate_FlexranCtrl':
+					SSH.TerminateFlexranCtrl()
+				elif action == 'IdleSleep':
+					SSH.IdleSleep()
+				elif action == 'Perform_X2_Handover':
+					SSH.Perform_X2_Handover()
+				else:
+					sys.exit('Invalid action')
+				if SSH.prematureExit:
+					break
+			if SSH.prematureExit:
+				break
+		cnt += 1
+	if cnt == SSH.repeatCounts[0] and SSH.prematureExit:
+		logging.debug('Testsuite failed ' + str(cnt) + ' time(s)')
+		SSH.CreateHtmlTabFooter(False)
+		sys.exit('Failed Scenario')
+	else:
+		logging.info('Testsuite passed after ' + str(cnt) + ' time(s)')
+		SSH.CreateHtmlTabFooter(True)
 else:
 	Usage()
 	sys.exit('Invalid mode')
diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh
index 06b56458d0434125f55547dcbacc11b6a8800460..f2df1f7be046e584041dc4109780aeb0fd909b07 100755
--- a/ci-scripts/runTestOnVM.sh
+++ b/ci-scripts/runTestOnVM.sh
@@ -1843,7 +1843,7 @@ function run_test_on_vm {
                     fi
                 fi
 
-                if [ $S1_NOS1_CFG -eq 0 ]
+                if [ $S1_NOS1_CFG -eq 2 ]
                 then
                     get_enb_noS1_ip_addr $ENB_VM_CMDS $ENB_VM_IP_ADDR
                     echo "############################################################"
diff --git a/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1.xml
index 29c9a29c2d2f9eeae14cc68dea9c59f5a52a8fd2..a2e74c6de9329c1f0a1215d62592388b9ef18afd 100644
--- a/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1.xml
+++ b/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1.xml
@@ -24,6 +24,7 @@
 	<htmlTabRef>test-05-tm1-nos1-tunnel</htmlTabRef>
 	<htmlTabName>Test-05MHz-TM1-noS1-tunnel</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>2</repeatCount>
 	<TestCaseRequestedList>
  030201 090109
  030101 000001 090101 000002 040501 040502 000001 040601 040602 040641 040642 000001 090109 030201
diff --git a/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_s1.xml b/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_s1.xml
index 2e6b9a0dc6c25f7ef8d2ff45780b3074b6be6aa9..9f7546cab347cbfed1513460c2b0158402a55c0b 100644
--- a/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_s1.xml
+++ b/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_s1.xml
@@ -24,6 +24,7 @@
 	<htmlTabRef>test-05-tm1-tunnel</htmlTabRef>
 	<htmlTabName>Test-05MHz-TM1-tunnel</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>2</repeatCount>
 	<TestCaseRequestedList>
  030201 090109
  030102 000001 090102 000002 040503 000001 040603 040604 040643 040644 000001 090109 030201
diff --git a/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml
index a3f88307ec0057a0ca0c2ee94b483266eb741038..9c98ba4a8eb33677e1c7bf6c7093e47136e0ed59 100644
--- a/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml
+++ b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml
@@ -25,6 +25,7 @@
 	<htmlTabRef>test-05-tm2</htmlTabRef>
 	<htmlTabName>Test-05MHz-TM2</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>2</repeatCount>
         <TestCaseRequestedList>
  030201
  040101
diff --git a/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
index fd6aabcbbc82b4aefe9def99120c4680d37d61c5..1ee223d1c7cceca179be0f1bafc5a29519dafca1 100644
--- a/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
+++ b/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1.xml
@@ -34,7 +34,7 @@
 	<testCase id="030111">
 		<class>Initialize_eNB</class>
 		<desc>Initialize eNB (FDD/Band7/10MHz)</desc>
-		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf</Initialize_eNB_args>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf --eNBs.[0].component_carriers.[0].drx_Config_present prRelease</Initialize_eNB_args>
 	</testCase>
 
 	<testCase id="030201">
diff --git a/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1_cdrx.xml b/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1_cdrx.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f62c31dd5a4be1718f09af57cb6475f3f743b935
--- /dev/null
+++ b/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1_cdrx.xml
@@ -0,0 +1,90 @@
+<!--
+
+ 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-10-cdrx-tm1</htmlTabRef>
+	<htmlTabName>Test-10MHz-CDRX-TM1</htmlTabName>
+	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>4</repeatCount>
+	<TestCaseRequestedList>
+ 030201
+ 040101
+ 030112 040302 040512 040612 040650 040401 040201 030201
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="030112">
+		<class>Initialize_eNB</class>
+		<desc>Initialize eNB (FDD/Band7/10MHz) with CDRX</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf  --eNBs.[0].component_carriers.[0].drx_Config_present prSetup</Initialize_eNB_args>
+	</testCase>
+
+	<testCase id="030201">
+		<class>Terminate_eNB</class>
+		<desc>Terminate eNB</desc>
+	</testCase>
+
+	<testCase id="040101">
+		<class>Initialize_UE</class>
+		<desc>Initialize UE</desc>
+	</testCase>
+
+	<testCase id="040201">
+		<class>Terminate_UE</class>
+		<desc>Terminate UE</desc>
+	</testCase>
+
+	<testCase id="040302">
+		<class>Attach_UE</class>
+		<desc>Attach UE</desc>
+		<nbMaxUEtoAttach>1</nbMaxUEtoAttach>
+	</testCase>
+
+	<testCase id="040401">
+		<class>Detach_UE</class>
+		<desc>Detach UE</desc>
+	</testCase>
+
+	<testCase id="040512">
+		<class>Ping</class>
+		<desc>ping (10MHz - 20 sec)</desc>
+		<ping_args>-c 20</ping_args>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
+	</testCase>
+
+	<testCase id="040612">
+		<class>Iperf</class>
+		<desc>iperf (10MHz - DL/30Mbps/UDP)(30 sec)(balanced profile)</desc>
+		<iperf_args>-u -b 30M -t 30 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>balanced</iperf_profile>
+	</testCase>
+
+	<testCase id="040650">
+		<class>Iperf</class>
+		<desc>iperf (10MHz - UL/20Mbps/UDP)(30 sec)(balanced profile)</desc>
+		<iperf_args>-u -b 20M -t 30 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>balanced</iperf_profile>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/f1_usrp210_band7_test_05mhz.xml b/ci-scripts/xml_files/f1_usrp210_band7_test_05mhz.xml
index 4dadbbdcba3cc51f1e79640f9c86464db660da1c..c2a48037baf5c2e6b151059d3806d15e4d07e2f9 100644
--- a/ci-scripts/xml_files/f1_usrp210_band7_test_05mhz.xml
+++ b/ci-scripts/xml_files/f1_usrp210_band7_test_05mhz.xml
@@ -22,8 +22,9 @@
 -->
 <testCaseList>
 	<htmlTabRef>test-f1-05</htmlTabRef>
-	<htmlTabName>Test-F1-CU/DU-05MHz</htmlTabName>
+	<htmlTabName>Test-F1-CU-DU-05MHz</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>2</repeatCount>
 	<TestCaseRequestedList>
  030201
  040101
diff --git a/ci-scripts/xml_files/f1_usrp210_band7_test_10mhz.xml b/ci-scripts/xml_files/f1_usrp210_band7_test_10mhz.xml
index 115f3c648a3e9b90ed5c3d106b47ea5106a9795b..8d028df433a9d0ec2a972f2b16f6c64e36441ce9 100644
--- a/ci-scripts/xml_files/f1_usrp210_band7_test_10mhz.xml
+++ b/ci-scripts/xml_files/f1_usrp210_band7_test_10mhz.xml
@@ -22,8 +22,9 @@
 -->
 <testCaseList>
 	<htmlTabRef>test-f1-10</htmlTabRef>
-	<htmlTabName>Test-F1-CU/DU-10MHz</htmlTabName>
+	<htmlTabName>Test-F1-CU-DU-10MHz</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>4</repeatCount>
 	<TestCaseRequestedList>
  030201
  040101
diff --git a/ci-scripts/xml_files/f1_usrp210_band7_test_20mhz.xml b/ci-scripts/xml_files/f1_usrp210_band7_test_20mhz.xml
index 790afe2a7166b885ea8656864828e6a677bae58a..061b87294bfe6e328d3433faf420436d508c55f8 100644
--- a/ci-scripts/xml_files/f1_usrp210_band7_test_20mhz.xml
+++ b/ci-scripts/xml_files/f1_usrp210_band7_test_20mhz.xml
@@ -22,8 +22,9 @@
 -->
 <testCaseList>
 	<htmlTabRef>test-f1-20</htmlTabRef>
-	<htmlTabName>Test-F1-CU/DU-20MHz</htmlTabName>
+	<htmlTabName>Test-F1-CU-DU-20MHz</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>4</repeatCount>
 	<TestCaseRequestedList>
  030201
  040101
diff --git a/ci-scripts/xml_files/if4p5_usrp210_band40_test_20mhz.xml b/ci-scripts/xml_files/if4p5_usrp210_band40_test_20mhz.xml
index 17ede3f8305ec26db5e8204c3080717c48811f7c..15d641efeb431917f96d24568558447d68d64080 100644
--- a/ci-scripts/xml_files/if4p5_usrp210_band40_test_20mhz.xml
+++ b/ci-scripts/xml_files/if4p5_usrp210_band40_test_20mhz.xml
@@ -24,6 +24,7 @@
 	<htmlTabRef>test-20</htmlTabRef>
 	<htmlTabName>Test-20MHz</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>2</repeatCount>
 	<TestCaseRequestedList>
  030201
  040101
diff --git a/ci-scripts/xml_files/multi_rru_band38_build.xml b/ci-scripts/xml_files/multi_rru_band38_build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..614ef394f3307d89cee917d7f78c2fd9fc790835
--- /dev/null
+++ b/ci-scripts/xml_files/multi_rru_band38_build.xml
@@ -0,0 +1,84 @@
+<!--
+
+ Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The OpenAirInterface Software Alliance licenses this file to You under
+ the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.openairinterface.org/?page_id=698
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ For more information about the OpenAirInterface (OAI) Software Alliance:
+      contact@openairinterface.org
+
+-->
+<testCaseList>
+	<htmlTabRef>build-tab</htmlTabRef>
+	<htmlTabName>Build</htmlTabName>
+	<htmlTabIcon>wrench</htmlTabIcon>
+	<TestCaseRequestedList>
+ 010101 010102 010103
+ 000101 000102 000103
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="010101">
+		<class>Build_eNB</class>
+		<desc>Build RCC</desc>
+		<Build_eNB_args>-w USRP -c --eNB</Build_eNB_args>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+		<backgroundBuild>True</backgroundBuild>
+	</testCase>
+
+	<testCase id="000101">
+		<class>WaitEndBuild_eNB</class>
+		<desc>Wait for end of Build RCC</desc>
+		<Build_eNB_args>-w USRP -c --eNB</Build_eNB_args>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="010102">
+		<class>Build_eNB</class>
+		<desc>Build Master RRU</desc>
+		<Build_eNB_args>-w USRP -c --eNB</Build_eNB_args>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+		<backgroundBuild>True</backgroundBuild>
+	</testCase>
+
+	<testCase id="000102">
+		<class>WaitEndBuild_eNB</class>
+		<desc>Wait for end of Build Master RRU</desc>
+		<Build_eNB_args>-w USRP -c --eNB</Build_eNB_args>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+	<testCase id="010103">
+		<class>Build_eNB</class>
+		<desc>Build Slave RRU</desc>
+		<Build_eNB_args>-w USRP -c --eNB</Build_eNB_args>
+		<eNB_instance>2</eNB_instance>
+		<eNB_serverId>2</eNB_serverId>
+		<backgroundBuild>True</backgroundBuild>
+	</testCase>
+
+	<testCase id="000103">
+		<class>WaitEndBuild_eNB</class>
+		<desc>Wait for end of Build Slave RRU</desc>
+		<Build_eNB_args>-w USRP -c --eNB</Build_eNB_args>
+		<eNB_instance>2</eNB_instance>
+		<eNB_serverId>2</eNB_serverId>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/multi_rru_band38_full_termination.xml b/ci-scripts/xml_files/multi_rru_band38_full_termination.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d63c73aec55342220a43486dc2180924baeef882
--- /dev/null
+++ b/ci-scripts/xml_files/multi_rru_band38_full_termination.xml
@@ -0,0 +1,53 @@
+<!--
+
+ 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-full-termintation</htmlTabRef>
+	<htmlTabName>Test-RCC-RRUs-Termination</htmlTabName>
+	<htmlTabIcon>off</htmlTabIcon>
+	<TestCaseRequestedList>
+ 030211 030212 030213
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="030211">
+		<class>Terminate_eNB</class>
+		<desc>Terminate RCC</desc>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="030212">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Master RRU</desc>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+	<testCase id="030213">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Slave RRU</desc>
+		<eNB_instance>2</eNB_instance>
+		<eNB_serverId>2</eNB_serverId>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/multi_rru_band38_test_10mhz_tm1.xml b/ci-scripts/xml_files/multi_rru_band38_test_10mhz_tm1.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7658f8a0e5069a975d3477184eaabd9ee6646210
--- /dev/null
+++ b/ci-scripts/xml_files/multi_rru_band38_test_10mhz_tm1.xml
@@ -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
+
+-->
+<testCaseList>
+	<htmlTabRef>test-multi-rru-10</htmlTabRef>
+	<htmlTabName>Test-Multi-RRU-10MHz</htmlTabName>
+	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>4</repeatCount>
+	<TestCaseRequestedList>
+ 030211 030212 030213
+ 030111 030112 030113
+ 000001
+ 030211 030212 030213
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="000001">
+		<class>IdleSleep</class>
+		<desc>Sleep</desc>
+		<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="030111">
+		<class>Initialize_eNB</class>
+		<desc>Initialize RCC (TDD/Band38/10MHz)</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/rcc.band38.tm1.50PRB.multi.rru.conf --noS1</Initialize_eNB_args>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="030112">
+		<class>Initialize_eNB</class>
+		<desc>Initialize Master RRU (TDD/Band38/10MHz)</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/rru.band38.tm1.master.conf --noS1</Initialize_eNB_args>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+	<testCase id="030113">
+		<class>Initialize_eNB</class>
+		<desc>Initialize Slave RRU (TDD/Band38/10MHz)</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/rru.band38.tm1.slave.conf --noS1</Initialize_eNB_args>
+		<eNB_instance>2</eNB_instance>
+		<eNB_serverId>2</eNB_serverId>
+	</testCase>
+
+	<testCase id="030211">
+		<class>Terminate_eNB</class>
+		<desc>Terminate RCC</desc>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="030212">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Master RRU</desc>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+	<testCase id="030213">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Slave RRU</desc>
+		<eNB_instance>2</eNB_instance>
+		<eNB_serverId>2</eNB_serverId>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/ue_band20_test_10mhz_orange.xml b/ci-scripts/xml_files/ue_band20_test_10mhz_orange.xml
index 19d08d511968868d0751770ca44a8e2469f7c083..d3e36f603eb10deac64f57a72f26d93f13bad480 100644
--- a/ci-scripts/xml_files/ue_band20_test_10mhz_orange.xml
+++ b/ci-scripts/xml_files/ue_band20_test_10mhz_orange.xml
@@ -24,6 +24,7 @@
 	<htmlTabRef>test-10mhz-orange</htmlTabRef>
 	<htmlTabName>Test-10Mhz-Orange</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>	
+	<repeatCount>4</repeatCount>	
 	<TestCaseRequestedList>
  090109
  090110 000001 090109
diff --git a/ci-scripts/xml_files/ue_band20_test_10mhz_sfr.xml b/ci-scripts/xml_files/ue_band20_test_10mhz_sfr.xml
index 50912d3458108830b0db16229ba17d7dc9e457e5..3f6441e06ea8de2379e808f1ee35743379038413 100644
--- a/ci-scripts/xml_files/ue_band20_test_10mhz_sfr.xml
+++ b/ci-scripts/xml_files/ue_band20_test_10mhz_sfr.xml
@@ -24,6 +24,7 @@
 	<htmlTabRef>test-10mHz-sfr</htmlTabRef>
 	<htmlTabName>Test-10MHz-SFR</htmlTabName>
 	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>4</repeatCount>
 	<TestCaseRequestedList>
  090109
  090111 000001 090109
diff --git a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_build.xml b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d2a122537d2caf3344e0dc43fc236bdaa7233d2
--- /dev/null
+++ b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_build.xml
@@ -0,0 +1,66 @@
+<!--
+
+ Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The OpenAirInterface Software Alliance licenses this file to You under
+ the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.openairinterface.org/?page_id=698
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ For more information about the OpenAirInterface (OAI) Software Alliance:
+      contact@openairinterface.org
+
+-->
+<testCaseList>
+	<htmlTabRef>build-tab</htmlTabRef>
+	<htmlTabName>Build</htmlTabName>
+	<htmlTabIcon>wrench</htmlTabIcon>
+	<TestCaseRequestedList>
+ 010101
+ 010102
+ 050101 060101 070101
+	</TestCaseRequestedList>
+	<TestCaseExclusionList>
+	</TestCaseExclusionList>
+
+	<testCase id="010101">
+		<class>Build_eNB</class>
+		<desc>Build Master eNB (USRP)</desc>
+		<Build_eNB_args>-w USRP -c --eNB</Build_eNB_args>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="010102">
+		<class>Build_eNB</class>
+		<desc>Build Slave eNB (USRP)</desc>
+		<Build_eNB_args>-w USRP -c --eNB</Build_eNB_args>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+	<testCase id="050101">
+		<class>Initialize_HSS</class>
+		<desc>Initialize HSS</desc>
+	</testCase>
+
+	<testCase id="060101">
+		<class>Initialize_MME</class>
+		<desc>Initialize MME</desc>
+	</testCase>
+
+	<testCase id="070101">
+		<class>Initialize_SPGW</class>
+		<desc>Initialize SPGW</desc>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_epc_closure.xml b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_epc_closure.xml
new file mode 100644
index 0000000000000000000000000000000000000000..07fb6951f8e99a35cabd2ee4e48232d2bd035f41
--- /dev/null
+++ b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_epc_closure.xml
@@ -0,0 +1,47 @@
+<!--
+
+ 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>epc-closure</htmlTabRef>
+	<htmlTabName>EPC-Closure</htmlTabName>
+	<htmlTabIcon>log-out</htmlTabIcon>
+	<TestCaseRequestedList>
+ 050201 060201 070201
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="050201">
+		<class>Terminate_HSS</class>
+		<desc>Terminate HSS</desc>
+	</testCase>
+
+	<testCase id="060201">
+		<class>Terminate_MME</class>
+		<desc>Terminate MME</desc>
+	</testCase>
+
+	<testCase id="070201">
+		<class>Terminate_SPGW</class>
+		<desc>Terminate SPGW</desc>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_full_terminate.xml b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_full_terminate.xml
new file mode 100644
index 0000000000000000000000000000000000000000..91280462b70b1b31887ce17edf0bb9a92be9a932
--- /dev/null
+++ b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_full_terminate.xml
@@ -0,0 +1,46 @@
+<!--
+
+ 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-x2-ho-full-end</htmlTabRef>
+	<htmlTabName>Test-X2-HO-Full-Terminate</htmlTabName>
+	<htmlTabIcon>tasks</htmlTabIcon>
+	<TestCaseRequestedList>
+ 030201 030202
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="030201">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Master eNB</desc>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="030202">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Slave eNB</desc>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_test_05mhz_tm1.xml b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_test_05mhz_tm1.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c43be75a8721feda87fbfeba9e29d932d96154ac
--- /dev/null
+++ b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_test_05mhz_tm1.xml
@@ -0,0 +1,191 @@
+<!--
+
+ 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
+
+ 030101 000002 030102 040301 040501 040601 040641 050401 000002 040502 040602 040642 050402 000002 040503 040603 040643 040401 040201 030201 030202
+-->
+<testCaseList>
+	<htmlTabRef>test-x2-ho-05-tm1</htmlTabRef>
+	<htmlTabName>Test-X2-HO-FDD-05MHz-TM1</htmlTabName>
+	<htmlTabIcon>tasks</htmlTabIcon>
+	<repeatCount>2</repeatCount>
+	<TestCaseRequestedList>
+ 030201 030202
+ 040101
+ 050102
+ 030101 000002 030102 040301 040501 050401 000002 040502 050402 000002 040503 040401 040201 030201 030202
+ 050202
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="000001">
+		<class>IdleSleep</class>
+		<desc>Waiting for 60 seconds</desc>
+		<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="000002">
+		<class>IdleSleep</class>
+		<desc>Waiting for 10 seconds</desc>
+		<idle_sleep_time_in_sec>10</idle_sleep_time_in_sec>
+	</testCase>
+
+	<testCase id="050102">
+		<class>Initialize_FlexranCtrl</class>
+		<desc>Starting Flexran Controller</desc>
+	</testCase>
+
+	<testCase id="050202">
+		<class>Terminate_FlexranCtrl</class>
+		<desc>Stopping Flexran Controller</desc>
+	</testCase>
+
+	<testCase id="030101">
+		<class>Initialize_eNB</class>
+		<desc>Initialize Master eNB (FDD/Band7/5MHz)</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf</Initialize_eNB_args>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="030102">
+		<class>Initialize_eNB</class>
+		<desc>Initialize Slave eNB (FDD/Band7/5MHz)</desc>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf</Initialize_eNB_args>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+	<testCase id="030201">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Master eNB</desc>
+		<eNB_instance>0</eNB_instance>
+		<eNB_serverId>0</eNB_serverId>
+	</testCase>
+
+	<testCase id="030202">
+		<class>Terminate_eNB</class>
+		<desc>Terminate Slave eNB</desc>
+		<eNB_instance>1</eNB_instance>
+		<eNB_serverId>1</eNB_serverId>
+	</testCase>
+
+	<testCase id="040101">
+		<class>Initialize_UE</class>
+		<desc>Initialize UE</desc>
+	</testCase>
+
+	<testCase id="040201">
+		<class>Terminate_UE</class>
+		<desc>Terminate UE</desc>
+	</testCase>
+
+	<testCase id="040301">
+		<class>Attach_UE</class>
+		<desc>Attach UE</desc>
+	</testCase>
+
+	<testCase id="040401">
+		<class>Detach_UE</class>
+		<desc>Detach UE</desc>
+	</testCase>
+
+	<testCase id="040501">
+		<class>Ping</class>
+		<desc>ping (5MHz - 20 sec)</desc>
+		<ping_args>-c 20</ping_args>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
+	</testCase>
+
+	<testCase id="040502">
+		<class>Ping</class>
+		<desc>ping (5MHz - 20 sec)</desc>
+		<ping_args>-c 20</ping_args>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
+	</testCase>
+
+	<testCase id="040503">
+		<class>Ping</class>
+		<desc>ping (5MHz - 20 sec)</desc>
+		<ping_args>-c 20</ping_args>
+		<ping_packetloss_threshold>5</ping_packetloss_threshold>
+	</testCase>
+
+	<testCase id="040601">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - DL/8Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 8M -t 30 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040602">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - DL/8Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 8M -t 30 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040603">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - DL/8Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 8M -t 30 -i 1</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040641">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - UL/5Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 5M -t 30 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040642">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - UL/5Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 5M -t 30 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="040643">
+		<class>Iperf</class>
+		<desc>iperf (5MHz - UL/5Mbps/UDP)(30 sec)</desc>
+		<iperf_args>-u -b 5M -t 30 -i 1 -R</iperf_args>
+		<iperf_packetloss_threshold>50</iperf_packetloss_threshold>
+		<iperf_profile>single-ue</iperf_profile>
+	</testCase>
+
+	<testCase id="050401">
+		<class>Perform_X2_Handover</class>
+		<desc>Doing a Flexran-Controlled X2 Handover</desc>
+		<x2_ho_options>network</x2_ho_options>
+	</testCase>
+
+	<testCase id="050402">
+		<class>Perform_X2_Handover</class>
+		<desc>Doing a Flexran-Controlled X2 Handover</desc>
+		<x2_ho_options>network</x2_ho_options>
+	</testCase>
+
+</testCaseList>
diff --git a/cmake_targets/build_ue b/cmake_targets/build_ue
deleted file mode 100755
index 9d9ca839d10c0164f038a8b6eb4a79f772e01d70..0000000000000000000000000000000000000000
--- a/cmake_targets/build_ue
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-#sudo ./build_oai -c -C -I --install-optional-packages --install-system-files --UE -w USRP -V 
-#sudo ./build_oai -c -C -I --install-optional-packages --UE -w USRP -V 
-#sudo ./build_oai -c -C --UE -w USRP -V
-sudo ./build_oai -c -C --UE -w USRP
-#sudo ./build_oai -c -C --UE -w USRP --build-eclipse
diff --git a/cmake_targets/lte_noS1_build_oai/CMakeLists.template b/cmake_targets/lte_noS1_build_oai/CMakeLists.template
deleted file mode 100644
index 95216b139e9fe7635d6d95c0c232f10d5713ad9e..0000000000000000000000000000000000000000
--- a/cmake_targets/lte_noS1_build_oai/CMakeLists.template
+++ /dev/null
@@ -1,10 +0,0 @@
-set(ENABLE_ITTI True)
-set(ENABLE_USE_MME False)
-set(PDCP_USE_NETLINK True)
-set(LINK_ENB_PDCP_TO_IP_DRIVER True)
-set(LINK_ENB_PDCP_TO_GTPV1U False)
-set(PDCP_USE_NETLINK_QUEUES False)
-set(LINUX True)
-set(SECU False)
-set(NAS_UE False)
-
diff --git a/cmake_targets/oaisim_build_oai/CMakeLists.template b/cmake_targets/oaisim_build_oai/CMakeLists.template
deleted file mode 100644
index cffbddc93c5b5170dcb83896f2af5c90c5ef311a..0000000000000000000000000000000000000000
--- a/cmake_targets/oaisim_build_oai/CMakeLists.template
+++ /dev/null
@@ -1,59 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-set (  CMAKE_BUILD_TYPE "RelWithDebInfo" )
-set (  DEBUG_OMG False )
-set (  DISABLE_XER_PRINT False )
-set (  DRIVER2013 True )
-set (  ENABLE_ITTI True )
-set (  ENABLE_NAS_UE_LOGGING True )
-set (  ENABLE_NEW_MULTICAST True )
-set (  ENABLE_RAL False )
-set (  ENABLE_STANDALONE_EPC False)
-set (  ENABLE_USE_CPU_EXECUTION_TIME True )
-set (  ENABLE_USE_MME True )
-set (  ENABLE_USE_RAW_SOCKET_FOR_SGI True)
-set (  ENABLE_VCD_FIFO False )
-set (  ENB_MODE True )
-set (  EXMIMO_IOT True )
-set (  JUMBO_FRAME True )
-set (  LARGE_SCALE False )
-set (  LINK_ENB_PDCP_TO_GTPV1U True)
-set (  LINUX_LIST False )
-set (  LINUX True )
-set (  LOCALIZATION False )
-set (  LOG_NO_THREAD True )
-set (  DEADLINE_SCHEDULER False )
-set (  MAC_CONTEXT 1 )
-set (  MAX_NUM_CCs 1 )
-set (  MESSAGE_CHART_GENERATOR False)
-set (  MSG_PRINT False )
-set (  MU_RECEIVER False )
-set (  NAS_ADDRESS_FIX False )
-set (  NAS_BUILT_IN_UE True)
-set (  NAS_MME False )
-set (  NAS_UE True )
-set (  NB_ANTENNAS_RX "2" )
-set (  NB_ANTENNAS_TX "2" )
-set (  NO_RRM True )
-set (  OAISIM True )
-set (  OAI_NW_DRIVER_TYPE_ETHERNET False )
-set (  OAI_NW_DRIVER_USE_NETLINK True )
-set (  OPENAIR2 True )
-set (  OPENAIR_LTE True )
-set (  PACKAGE_NAME "oaisim" )
-set (  PDCP_USE_NETLINK True )
-set (  PDCP_MSG_PRINT False )
-set (  PHY_CONTEXT False )
-set (  PHY_EMUL False )
-set (  PHYSIM True )
-set (  RF_BOARD "False" )
-set (  RLC_STOP_ON_LOST_PDU False )
-set (  RRC_ASN1_VERSION "Rel10" )
-set (  RRC_DEFAULT_RAB_IS_AM True)
-set (  RRC_MSG_PRINT False )
-set (  SECU False )
-set (  SMBV False )
-set (  TEST_OMG False )
-set (  USE_3GPP_ADDR_AS_LINK_ADDR False )
-set (  USE_MME "R10" )
-set (  XER_PRINT False )
diff --git a/cmake_targets/oaisim_mme_build_oai/CMakeLists.template b/cmake_targets/oaisim_mme_build_oai/CMakeLists.template
deleted file mode 100644
index eac29006da6ad83a48c6b3256fbe564fba59ade4..0000000000000000000000000000000000000000
--- a/cmake_targets/oaisim_mme_build_oai/CMakeLists.template
+++ /dev/null
@@ -1,61 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-set (  CMAKE_BUILD_TYPE "RelWithDebInfo" )
-set (  DEBUG_OMG False )
-set (  DISABLE_XER_PRINT False )
-set (  DRIVER2013 False )
-set (  ENABLE_ITTI True )
-set (  ENABLE_NAS_UE_LOGGING False )
-set (  ENABLE_NEW_MULTICAST False )
-set (  ENABLE_RAL False )
-set (  ENABLE_STANDALONE_EPC False )
-set (  ENABLE_USE_CPU_EXECUTION_TIME False )
-set (  ENABLE_USE_MME False )
-set (  ENABLE_USE_RAW_SOCKET_FOR_SGI True)
-set (  ENABLE_VCD_FIFO False )
-set (  ENB_MODE False )
-set (  EPC_BUILD True )
-set (  EXMIMO_IOT False )
-set (  JUMBO_FRAME False )
-set (  LARGE_SCALE False )
-set (  LINK_ENB_PDCP_TO_GTPV1U True)
-set (  LINUX_LIST False )
-set (  LINUX False )
-set (  LOCALIZATION False )
-set (  LOG_NO_THREAD False )
-set (  DEADLINE_SCHEDULER False )
-set (  MAC_CONTEXT 1 )
-set (  MAX_NUM_CCs 1 )
-set (  MSG_PRINT False )
-set (  MU_RECEIVER False )
-set (  NAS_ADDRESS_FIX False )
-set (  NAS_BUILT_IN_EPC True )
-set (  NAS_MME True )
-set (  NAS_NETLINK False )
-set (  NAS_UE False )
-set (  NB_ANTENNAS_RX "2" )
-set (  NB_ANTENNAS_TX "2" )
-set (  NO_RRM False )
-set (  OAISIM False )
-set (  OAI_NW_DRIVER_TYPE_ETHERNET False )
-set (  OAI_NW_DRIVER_USE_NETLINK False )
-set (  OPENAIR2 False )
-set (  OPENAIR_LTE False )
-set (  PACKAGE_NAME "EPC" )
-set (  PDCP_MSG_PRINT False )
-set (  PHY_CONTEXT False )
-set (  PHY_EMUL False )
-set (  PHYSIM False )
-set (  RF_BOARD "False" )
-set (  RRC_ASN1_VERSION "Rel10" )
-set (  RLC_STOP_ON_LOST_PDU False )
-set (  RRC_MSG_PRINT False )
-set (  SECU False )
-set (  SMBV False )
-set (  TEST_OMG False )
-set (  UPDATE_RELEASE_9 True)
-set (  UPDATE_RELEASE_10 True)
-set (  USE_3GPP_ADDR_AS_LINK_ADDR False )
-set (  USE_MME "R10" )
-set (  XER_PRINT False )
-set (  XFORMS False )
diff --git a/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template b/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
deleted file mode 100644
index 343e9280902b4074740fbea0d0fb3b1427394e17..0000000000000000000000000000000000000000
--- a/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
+++ /dev/null
@@ -1,62 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-set (  DEBUG_OMG False )
-set (  DISABLE_XER_PRINT False )
-set (  DRIVER2013 True )
-set (  ENABLE_ITTI True )
-set (  ENABLE_NAS_UE_LOGGING False )
-set (  ENABLE_NEW_MULTICAST True )
-set (  ENABLE_RAL False )
-set (  ENABLE_STANDALONE_EPC False)
-set (  ENABLE_USE_CPU_EXECUTION_TIME True )
-set (  ENABLE_USE_MME False )
-set (  ENABLE_USE_RAW_SOCKET_FOR_SGI False)
-set (  ENABLE_VCD_FIFO False )
-set (  ENB_MODE True )
-set (  EXMIMO_IOT True )
-set (  JUMBO_FRAME True )
-set (  LARGE_SCALE False )
-set (  LINK_ENB_PDCP_TO_GTPV1U False)
-set (  LINUX_LIST False )
-set (  LINUX True )
-set (  LOCALIZATION False )
-set (  LOG_NO_THREAD 1 )
-set (  DEADLINE_SCHEDULER False )
-set (  MAC_CONTEXT 1 )
-set (  MAX_NUM_CCs 1 )
-set (  MESSAGE_CHART_GENERATOR         False )
-set (  MESSAGE_CHART_GENERATOR_RLC_MAC False )
-set (  MESSAGE_CHART_GENERATOR_PHY     False )
-set (  MSG_PRINT False )
-set (  MU_RECEIVER False )
-set (  NAS_ADDRESS_FIX False )
-set (  NAS_BUILT_IN_UE False)
-set (  NAS_MME False )
-set (  NAS_UE False )
-set (  NB_ANTENNAS_RX "2" )
-set (  NB_ANTENNAS_TX "2" )
-set (  NO_RRM True )
-set (  OAISIM True )
-set (  OAI_NW_DRIVER_TYPE_ETHERNET False )
-set (  OAI_NW_DRIVER_USE_NETLINK True )
-set (  OPENAIR2 True )
-set (  OPENAIR_LTE True )
-set (  PACKAGE_NAME "oaisim" )
-set (  PDCP_USE_NETLINK True )
-set (  PDCP_MSG_PRINT False )
-set (  PHY_CONTEXT False )
-set (  PHY_EMUL False )
-set (  PHYSIM True )
-set (  RF_BOARD "False" )
-set (  RRC_ASN1_VERSION "Rel10" )
-set (  RLC_STOP_ON_LOST_PDU False )
-set (  RRC_MSG_PRINT False )
-set (  SECU False )
-set (  SMBV False )
-set (  TEST_OMG False )
-set (  USE_3GPP_ADDR_AS_LINK_ADDR False )
-set (  USE_MME "R10" )
-set (  XER_PRINT False )
-set (  DEBUG_PHY False )
-set (  DEBUG_PHY_PROC False)
-set (  DEBUG_DLSCH False)
diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c
index 87150650db697c5f3c6e2127c125039f6a0e3269..857a83deab80c3b9027d62e64c5d4ea8b0d113d4 100644
--- a/common/utils/LOG/log.c
+++ b/common/utils/LOG/log.c
@@ -45,7 +45,19 @@
 #include "common/config/config_userapi.h"
 // main log variables
 
-
+log_mem_cnt_t log_mem_d[2];
+int log_mem_flag=0;
+int log_mem_multi=1;
+volatile int log_mem_side=0;
+pthread_mutex_t log_mem_lock;
+pthread_cond_t log_mem_notify;
+pthread_t log_mem_thread;
+int log_mem_file_cnt=0;
+volatile int log_mem_write_flag=0;
+volatile int log_mem_write_side=0;
+char __log_mem_filename[1024]={0};
+char * log_mem_filename = &__log_mem_filename[0];
+char logmem_filename[1024] = {0};
 
 
 mapping log_level_names[] = {
@@ -456,15 +468,23 @@ void logRecord_mt(const char *file, const char *func, int line, int comp, int le
   char log_buffer[MAX_LOG_TOTAL];
   va_list args;
   va_start(args, format);
+  if (log_mem_flag == 1) {
+    log_output_memory(file,func,line,comp,level, format,args);
+  } else {
   log_header(log_buffer,MAX_LOG_TOTAL,comp, level,format);
   g_log->log_component[comp].vprint(g_log->log_component[comp].stream,log_buffer, args);
+  }
   va_end(args);
 }
 
 void vlogRecord_mt(const char *file, const char *func, int line, int comp, int level, const char *format, va_list args ) {
   char log_buffer[MAX_LOG_TOTAL];
+  if (log_mem_flag == 1) {
+    log_output_memory(file,func,line,comp,level, format,args);
+  } else {
   log_header(log_buffer,MAX_LOG_TOTAL,comp, level,format);
   g_log->log_component[comp].vprint(g_log->log_component[comp].stream,log_buffer, args);
+  }
 }
 
 void log_dump(int component, void *buffer, int buffsize,int datatype, const char *format, ... ) {
@@ -646,6 +666,265 @@ void logClean (void) {
   }
 }
 
+extern int oai_exit;
+void flush_mem_to_file(void)
+{
+  int fp;
+  char f_name[1024];
+  struct timespec slp_tm;
+  slp_tm.tv_sec = 0;
+  slp_tm.tv_nsec = 10000;
+  
+  pthread_setname_np( pthread_self(), "flush_mem_to_file");
+
+  while (!oai_exit) {
+    pthread_mutex_lock(&log_mem_lock);
+    log_mem_write_flag=0;
+    pthread_cond_wait(&log_mem_notify, &log_mem_lock);
+    log_mem_write_flag=1;
+    pthread_mutex_unlock(&log_mem_lock);
+    // write!
+    if(log_mem_d[log_mem_write_side].enable_flag==0){
+      if(log_mem_file_cnt>5){
+        log_mem_file_cnt=5;
+        printf("log over write!!!\n");
+      }
+      snprintf(f_name,1024, "%s_%d.log",log_mem_filename,log_mem_file_cnt);
+      fp=open(f_name, O_WRONLY | O_CREAT, 0666);
+      int ret = write(fp, log_mem_d[log_mem_write_side].buf_p, log_mem_d[log_mem_write_side].buf_index);
+      if ( ret < 0) {
+          fprintf(stderr,"{LOG} %s %d Couldn't write in %s \n",__FILE__,__LINE__,f_name);
+          exit(EXIT_FAILURE);
+      }
+      close(fp);
+      log_mem_file_cnt++;
+      log_mem_d[log_mem_write_side].buf_index=0;
+      log_mem_d[log_mem_write_side].enable_flag=1;
+    }else{
+      printf("If you'd like to write log, you should set enable flag to 0!!!\n");
+      nanosleep(&slp_tm,NULL);
+    }
+  }
+}
+
+char logmem_log_level[NUM_LOG_LEVEL]={'E','W','I','D','T'};
+
+void log_output_memory(const char *file, const char *func, int line, int comp, int level, const char* format,va_list args)
+{
+  //logRecord_mt(file,func,line, pthread_self(), comp, level, format, ##args)
+  int len = 0;
+  log_component_t *c;
+  char *log_start;
+  char *log_end;
+  /* The main difference with the version above is the use of this local log_buffer.
+   * The other difference is the return value of snprintf which was not used
+   * correctly. It was not a big problem because in practice MAX_LOG_TOTAL is
+   * big enough so that the buffer is never full.
+   */
+  char log_buffer[MAX_LOG_TOTAL];
+
+  /* for no gcc warnings */
+  (void)log_start;
+  (void)log_end;
+
+
+  c = &g_log->log_component[comp];
+
+  //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD, VCD_FUNCTION_IN);
+
+  // make sure that for log trace the extra info is only printed once, reset when the level changes
+  if (level == OAILOG_TRACE) {
+    log_start = log_buffer;
+    len = vsnprintf(log_buffer, MAX_LOG_TOTAL, format, args);
+    if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+    log_end = log_buffer + len;
+  } else {
+    if ( (g_log->flag & 0x001) || (c->flag & 0x001) ) {
+      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "%s",
+                      log_level_highlight_start[level]);
+      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+    }
+
+    log_start = log_buffer + len;
+
+//    if ( (g_log->flag & 0x004) || (c->flag & 0x004) ) {
+      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]",
+                      g_log->log_component[comp].name);
+      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+//    }
+
+    if ( (level >= OAILOG_ERR) && (level <= OAILOG_TRACE) ) {
+      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%c]",
+                      logmem_log_level[level]);
+      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+    }
+
+    if ( (g_log->flag & FLAG_THREAD) || (c->flag & FLAG_THREAD) ) {
+#     define THREAD_NAME_LEN 128
+      char threadname[THREAD_NAME_LEN];
+      if (pthread_getname_np(pthread_self(), threadname, THREAD_NAME_LEN) != 0)
+      {
+        perror("pthread_getname_np : ");
+      } else {
+        len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]", threadname);
+        if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+      }
+#     undef THREAD_NAME_LEN
+    }
+
+    if ( (g_log->flag & FLAG_FUNCT) || (c->flag & FLAG_FUNCT) ) {
+      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s] ",
+                      func);
+      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+    }
+
+    if ( (g_log->flag & FLAG_FILE_LINE) || (c->flag & FLAG_FILE_LINE) ) {
+      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s:%d]",
+                      file, line);
+      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+    }
+
+/*    len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%08lx]", thread_id);
+    if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+
+    struct timeval gettime;
+    gettimeofday(&gettime,NULL);
+    len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%ld.%06ld]", gettime.tv_sec, gettime.tv_usec);
+    if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+*/
+    if ( (g_log->flag & FLAG_NOCOLOR) || (c->flag & FLAG_NOCOLOR) ) {
+      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "%s",
+          log_level_highlight_end[level]);
+      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+    }
+
+    len += vsnprintf(&log_buffer[len], MAX_LOG_TOTAL - len, format, args);
+    if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
+    log_end = log_buffer + len;
+  }
+
+  //va_end(args);
+
+  // OAI printf compatibility
+    if(log_mem_flag==1){
+      if(log_mem_d[log_mem_side].enable_flag==1){
+        int temp_index;
+        temp_index=log_mem_d[log_mem_side].buf_index;
+        if(temp_index+len+1 < LOG_MEM_SIZE){
+          log_mem_d[log_mem_side].buf_index+=len;
+          memcpy(&log_mem_d[log_mem_side].buf_p[temp_index],log_buffer,len);
+        }else{
+          log_mem_d[log_mem_side].enable_flag=0;
+          if(log_mem_d[1-log_mem_side].enable_flag==1){
+            temp_index=log_mem_d[1-log_mem_side].buf_index;
+            if(temp_index+len+1 < LOG_MEM_SIZE){
+              log_mem_d[1-log_mem_side].buf_index+=len;
+              log_mem_side=1-log_mem_side;
+              memcpy(&log_mem_d[log_mem_side].buf_p[temp_index],log_buffer,len);
+              /* write down !*/
+              if (pthread_mutex_lock(&log_mem_lock) != 0) {
+                return;
+              }
+              if(log_mem_write_flag==0){
+                log_mem_write_side=1-log_mem_side;
+                if(pthread_cond_signal(&log_mem_notify) != 0) {
+                }
+              }
+              if(pthread_mutex_unlock(&log_mem_lock) != 0) {
+                return;
+              }
+            }else{
+              log_mem_d[1-log_mem_side].enable_flag=0;
+            }
+          }
+        }
+      }
+    }else{
+      fwrite(log_buffer, len, 1, stdout);
+    }
+}
+
+int logInit_log_mem (void)
+{
+  if(log_mem_flag==1){
+    if(log_mem_multi==1){
+      printf("log-mem multi!!!\n");
+      log_mem_d[0].buf_p = malloc(LOG_MEM_SIZE);
+      log_mem_d[0].buf_index=0;
+      log_mem_d[0].enable_flag=1;
+      log_mem_d[1].buf_p = malloc(LOG_MEM_SIZE);
+      log_mem_d[1].buf_index=0;
+      log_mem_d[1].enable_flag=1;
+      log_mem_side=0;
+      if ((pthread_mutex_init (&log_mem_lock, NULL) != 0)
+          || (pthread_cond_init (&log_mem_notify, NULL) != 0)) {
+        log_mem_d[1].enable_flag=0;
+        return -1;
+      }
+      pthread_create(&log_mem_thread, NULL, (void *(*)(void *))flush_mem_to_file, (void*)NULL);
+    }else{
+      printf("log-mem single!!!\n");
+      log_mem_d[0].buf_p = malloc(LOG_MEM_SIZE);
+      log_mem_d[0].buf_index=0;
+      log_mem_d[0].enable_flag=1;
+      log_mem_d[1].enable_flag=0;
+      log_mem_side=0;
+    }
+  }else{
+    log_mem_d[0].buf_p=NULL;
+    log_mem_d[1].buf_p=NULL;
+    log_mem_d[0].enable_flag=0;
+    log_mem_d[1].enable_flag=0;
+  }
+
+  printf("log init done\n");
+  
+  return 0;
+}
+
+void close_log_mem(void){
+  int fp;
+  char f_name[1024];
+
+  if(log_mem_flag==1){
+    log_mem_d[0].enable_flag=0;
+    log_mem_d[1].enable_flag=0;
+    usleep(10); // wait for log writing
+    while(log_mem_write_flag==1){
+      usleep(100);
+    }
+    if(log_mem_multi==1){
+      snprintf(f_name,1024, "%s_%d.log",log_mem_filename,log_mem_file_cnt);
+      fp=open(f_name, O_WRONLY | O_CREAT, 0666);
+      int ret = write(fp, log_mem_d[0].buf_p, log_mem_d[0].buf_index);
+      if ( ret < 0) {
+          fprintf(stderr,"{LOG} %s %d Couldn't write in %s \n",__FILE__,__LINE__,f_name);
+          exit(EXIT_FAILURE);
+      }
+      close(fp);
+      free(log_mem_d[0].buf_p);
+      
+      snprintf(f_name,1024, "%s_%d.log",log_mem_filename,log_mem_file_cnt);
+      fp=open(f_name, O_WRONLY | O_CREAT, 0666);
+      ret = write(fp, log_mem_d[1].buf_p, log_mem_d[1].buf_index);
+      if ( ret < 0) {
+          fprintf(stderr,"{LOG} %s %d Couldn't write in %s \n",__FILE__,__LINE__,f_name);
+          exit(EXIT_FAILURE);
+      }
+      close(fp);
+      free(log_mem_d[1].buf_p);
+    }else{
+      fp=open(log_mem_filename, O_WRONLY | O_CREAT, 0666);
+      int ret = write(fp, log_mem_d[0].buf_p, log_mem_d[0].buf_index);
+      if ( ret < 0) {
+          fprintf(stderr,"{LOG} %s %d Couldn't write in %s \n",__FILE__,__LINE__,log_mem_filename);
+          exit(EXIT_FAILURE);
+       }
+      close(fp);
+      free(log_mem_d[0].buf_p);
+    }
+  }
+ }
 
 #ifdef LOG_TEST
 
diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h
index 1c413d580e202e8b7a302a066a7b289357dd26e8..be7db5470e4eeb4e9fe1e483254cd5763af9de4d 100644
--- a/common/utils/LOG/log.h
+++ b/common/utils/LOG/log.h
@@ -118,6 +118,8 @@ extern "C" {
 #define FLAG_NOCOLOR     0x0001  /*!< \brief use colors in log messages, depending on level */
 #define FLAG_THREAD      0x0008  /*!< \brief display thread name in log messages */
 #define FLAG_LEVEL       0x0010  /*!< \brief display log level in log messages */
+#define FLAG_FUNCT       0x0020
+#define FLAG_FILE_LINE   0x0040
 #define FLAG_TIME        0x0100
 #define FLAG_INITIALIZED 0x8000
 
@@ -307,6 +309,19 @@ int  is_newline( char *str, int size);
 
 int register_log_component(char *name, char *fext, int compidx);
 
+#define LOG_MEM_SIZE 100*1024*1024
+#define LOG_MEM_FILE "./logmem.log"
+void flush_mem_to_file(void);
+void log_output_memory(const char *file, const char *func, int line, int comp, int level, const char* format,va_list args);
+int logInit_log_mem(void);
+void close_log_mem(void);
+  
+typedef struct {
+  char* buf_p;
+  int buf_index;
+  int enable_flag;
+} log_mem_cnt_t;
+
 /* @}*/
 
 /*!\fn int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format);
diff --git a/common/utils/LOG/log_extern.h b/common/utils/LOG/log_extern.h
index 3c93d517ca76456f57927b34cfb915482b8b87c2..f6205889dc1477f2bc1bc86115ed89ff9ecaed72 100644
--- a/common/utils/LOG/log_extern.h
+++ b/common/utils/LOG/log_extern.h
@@ -27,4 +27,6 @@ extern log_t *g_log;
 extern mapping log_level_names[];
 extern mapping log_options[];
 extern mapping log_maskmap[];
-
+extern int log_mem_flag;
+extern char * log_mem_filename;
+extern char logmem_filename[1024];
diff --git a/common/utils/T/tracer/macpdu2wireshark.c b/common/utils/T/tracer/macpdu2wireshark.c
index 8720efd8c0834e0a75b5452b12030420f7da082c..c391a9978679731c013d132849bbd13f24fe1bb0 100644
--- a/common/utils/T/tracer/macpdu2wireshark.c
+++ b/common/utils/T/tracer/macpdu2wireshark.c
@@ -52,6 +52,7 @@ typedef struct {
   int max_mib;
   int max_sib;
   int live;
+  int no_bind;
   /* runtime vars */
   int cur_mib;
   int cur_sib;
@@ -264,9 +265,11 @@ void *receiver(void *_d) {
     abort();
   }
 
-  if (bind(s, (struct sockaddr *)&d->to, sizeof(struct sockaddr_in)) == -1) {
-    perror("bind");
-    abort();
+  if (d->no_bind == 0) {
+    if (bind(s, (struct sockaddr *)&d->to, sizeof(struct sockaddr_in)) == -1) {
+      perror("bind");
+      abort();
+    }
   }
 
   while (1) {
@@ -290,6 +293,7 @@ void usage(void) {
     "    -live                     run live\n"
     "    -live-ip <IP address>     tracee's IP address (default %s)\n"
     "    -live-port <port>         tracee's port (default %d)\n"
+    "    -no-bind                  don't bind to IP address (for remote logging)\n"
     "-i and -live are mutually exclusive options. One of them must be provided\n"
     "but not both.\n",
     DEFAULT_IP,
@@ -318,78 +322,18 @@ int main(int n, char **v) {
 
   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;
-    }
-
-    if (!strcmp(v[i], "-i")) {
-      if (i > n-2) usage();
-
-      input_filename = v[++i];
-      continue;
-    }
-
-    if (!strcmp(v[i], "-ip")) {
-      if (i > n-2) usage();
-
-      ip = v[++i];
-      continue;
-    }
-
-    if (!strcmp(v[i], "-p")) {
-      if(i>n-2)usage();
-
-      port=atoi(v[++i]);
-      continue;
-    }
-
-    if (!strcmp(v[i], "-no-mib")) {
-      d.no_mib = 1;
-      continue;
-    }
-
-    if (!strcmp(v[i], "-no-sib")) {
-      d.no_sib = 1;
-      continue;
-    }
-
-    if (!strcmp(v[i], "-max-mib")) {
-      if (i > n-2) usage();
-
-      d.max_mib = atoi(v[++i]);
-      continue;
-    }
-
-    if (!strcmp(v[i], "-max-sib")) {
-      if (i > n-2) usage();
-
-      d.max_sib = atoi(v[++i]);
-      continue;
-    }
-
-    if (!strcmp(v[i], "-live")) {
-      live = 1;
-      continue;
-    }
-
-    if (!strcmp(v[i], "-live-ip")) {
-      if (i > n-2) usage();
-
-      live_ip = v[++i];
-      continue;
-    }
-
-    if (!strcmp(v[i], "-live-port")) {
-      if (i > n-2) usage();
-
-      live_port = atoi(v[++i]);
-      continue;
-    }
-
+    if (!strcmp(v[i], "-d"))         { if(i>n-2)usage(); database_filename = v[++i]; continue; }
+    if (!strcmp(v[i], "-i"))         { if(i>n-2)usage(); input_filename = v[++i];    continue; }
+    if (!strcmp(v[i], "-ip"))        { if(i>n-2)usage(); ip = v[++i];                continue; }
+    if (!strcmp(v[i], "-p"))         { if(i>n-2)usage(); port = atoi(v[++i]);        continue; }
+    if (!strcmp(v[i], "-no-mib"))    {                   d.no_mib = 1;               continue; }
+    if (!strcmp(v[i], "-no-sib"))    {                   d.no_sib = 1;               continue; }
+    if (!strcmp(v[i], "-max-mib"))   { if(i>n-2)usage(); d.max_mib = atoi(v[++i]);   continue; }
+    if (!strcmp(v[i], "-max-sib"))   { if(i>n-2)usage(); d.max_sib = atoi(v[++i]);   continue; }
+    if (!strcmp(v[i], "-live"))      {                   live = 1;                   continue; }
+    if (!strcmp(v[i], "-live-ip"))   { if(i>n-2)usage(); live_ip = v[++i];           continue; }
+    if (!strcmp(v[i], "-live-port")) { if(i>n-2)usage(); live_port = atoi(v[++i]);   continue; }
+    if (!strcmp(v[i], "-no-bind"))   {                   d.no_bind = 1;              continue; }
     usage();
   }
 
diff --git a/common/utils/itti_analyzer/filters.xml b/common/utils/itti_analyzer/filters.xml
index e4a0e627d56f2297ec6b667bb115a2984704210f..7305a2294cd8e035f4ec4c8391e2cfb8af9e95a1 100644
--- a/common/utils/itti_analyzer/filters.xml
+++ b/common/utils/itti_analyzer/filters.xml
@@ -91,6 +91,8 @@
     <TASK_MAC_ENB enabled="1"/>
     <TASK_RLC_ENB enabled="1"/>
     <TASK_PDCP_ENB enabled="1"/>
+    <TASK_DATA_FORWARDING enabled="1"/>
+    <TASK_END_MARKER enabled="1"/>
     <TASK_RRC_ENB enabled="1"/>
     <TASK_RAL_ENB enabled="1"/>
     <TASK_S1AP enabled="1"/>
@@ -114,6 +116,8 @@
     <TASK_MAC_ENB enabled="1"/>
     <TASK_RLC_ENB enabled="1"/>
     <TASK_PDCP_ENB enabled="1"/>
+    <TASK_DATA_FORWARDING enabled="1"/>
+    <TASK_END_MARKER enabled="1"/>
     <TASK_RRC_ENB enabled="1"/>
     <TASK_RAL_ENB enabled="1"/>
     <TASK_S1AP enabled="1"/>
diff --git a/common/utils/itti_analyzer/filters_ue_enb.xml b/common/utils/itti_analyzer/filters_ue_enb.xml
index 38ed00ceae6d1fd7ae200c0e1f51d180dff1a89e..77859d20b694414a9d03a7c98b1d5bbcf8f74f31 100644
--- a/common/utils/itti_analyzer/filters_ue_enb.xml
+++ b/common/utils/itti_analyzer/filters_ue_enb.xml
@@ -130,6 +130,8 @@
     <TASK_MAC_ENB enabled="1"/>
     <TASK_RLC_ENB enabled="1"/>
     <TASK_PDCP_ENB enabled="1"/>
+    <TASK_DATA_FORWARDING enabled="1"/>
+    <TASK_END_MARKER enabled="1"/>
     <TASK_RRC_ENB enabled="1"/>
     <TASK_RAL_ENB enabled="1"/>
     <TASK_S1AP enabled="1"/>
@@ -153,6 +155,8 @@
     <TASK_MAC_ENB enabled="1"/>
     <TASK_RLC_ENB enabled="1"/>
     <TASK_PDCP_ENB enabled="1"/>
+    <TASK_DATA_FORWARDING enabled="1"/>
+    <TASK_END_MARKER enabled="1"/>
     <TASK_RRC_ENB enabled="1"/>
     <TASK_RAL_ENB enabled="1"/>
     <TASK_S1AP enabled="1"/>
diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h
index 159265c6a8241762078665537dd726483afe141a..956d90072dd3afcad2f2bea57751828736300d19 100644
--- a/common/utils/ocp_itti/intertask_interface.h
+++ b/common/utils/ocp_itti/intertask_interface.h
@@ -283,6 +283,8 @@ typedef struct {
   TASK_DEF(TASK_RLC_ENB,  TASK_PRIORITY_MED, 200, NULL, NULL)   \
   TASK_DEF(TASK_RRC_ENB_NB_IoT,  TASK_PRIORITY_MED, 200, NULL, NULL) \
   TASK_DEF(TASK_PDCP_ENB, TASK_PRIORITY_MED, 200, NULL, NULL)   \
+  TASK_DEF(TASK_DATA_FORWARDING, TASK_PRIORITY_MED, 200, NULL, NULL)   \
+  TASK_DEF(TASK_END_MARKER, TASK_PRIORITY_MED, 200, NULL, NULL)   \
   TASK_DEF(TASK_RRC_ENB,  TASK_PRIORITY_MED,  200, NULL,NULL)\
   TASK_DEF(TASK_RAL_ENB,  TASK_PRIORITY_MED,  200, NULL, NULL)  \
   TASK_DEF(TASK_S1AP,     TASK_PRIORITY_MED,  200, NULL, NULL)  \
diff --git a/common/utils/system.c b/common/utils/system.c
index dcec681e2dcf2596b78352560672439e7bba58ee..31c1035129998da9a8340b1b80895e0dd4d44120 100644
--- a/common/utils/system.c
+++ b/common/utils/system.c
@@ -28,13 +28,23 @@
  * separate process solves this problem.
  */
 
+#define _GNU_SOURCE
 #include "system.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <pthread.h>
 #include <string.h>
-
+#include <stdint.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+#include <common/utils/assertions.h>
+#include <common/utils/LOG/log.h>
 #define MAX_COMMAND 4096
 
 static int command_pipe_read;
@@ -50,37 +60,37 @@ static int module_initialized = 0;
 /* util functions                                                   */
 /********************************************************************/
 
-static void lock_system(void)
-{
+static void lock_system(void) {
   if (pthread_mutex_lock(&lock) != 0) {
     printf("pthread_mutex_lock fails\n");
     abort();
   }
 }
 
-static void unlock_system(void)
-{
+static void unlock_system(void) {
   if (pthread_mutex_unlock(&lock) != 0) {
     printf("pthread_mutex_unlock fails\n");
     abort();
   }
 }
 
-static void write_pipe(int p, char *b, int size)
-{
+static void write_pipe(int p, char *b, int size) {
   while (size) {
     int ret = write(p, b, size);
+
     if (ret <= 0) exit(0);
+
     b += ret;
     size -= ret;
   }
 }
 
-static void read_pipe(int p, char *b, int size)
-{
+static void read_pipe(int p, char *b, int size) {
   while (size) {
     int ret = read(p, b, size);
+
     if (ret <= 0) exit(0);
+
     b += ret;
     size -= ret;
   }
@@ -95,14 +105,13 @@ static void read_pipe(int p, char *b, int size)
  * when the main process exits, because then a "read" on the pipe
  * will return 0, in which case "read_pipe" exits.
  */
-static void background_system_process(void)
-{
+static void background_system_process(void) {
   int len;
   int ret;
   char command[MAX_COMMAND+1];
 
   while (1) {
-    read_pipe(command_pipe_read, (char*)&len, sizeof(int));
+    read_pipe(command_pipe_read, (char *)&len, sizeof(int));
     read_pipe(command_pipe_read, command, len);
     ret = system(command);
     write_pipe(result_pipe_write, (char *)&ret, sizeof(int));
@@ -114,8 +123,7 @@ static void background_system_process(void)
 /*     return -1 on error, 0 on success                             */
 /********************************************************************/
 
-int background_system(char *command)
-{
+int background_system(char *command) {
   int res;
   int len;
 
@@ -125,18 +133,22 @@ int background_system(char *command)
   }
 
   len = strlen(command)+1;
+
   if (len > MAX_COMMAND) {
     printf("FATAL: command too long. Increase MAX_COMMAND (%d).\n", MAX_COMMAND);
     printf("command was: '%s'\n", command);
     abort();
   }
+
   /* only one command can run at a time, so let's lock/unlock */
   lock_system();
-  write_pipe(command_pipe_write, (char*)&len, sizeof(int));
+  write_pipe(command_pipe_write, (char *)&len, sizeof(int));
   write_pipe(command_pipe_write, command, len);
-  read_pipe(result_pipe_read, (char*)&res, sizeof(int));
+  read_pipe(result_pipe_read, (char *)&res, sizeof(int));
   unlock_system();
+
   if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != 0) return -1;
+
   return 0;
 }
 
@@ -146,17 +158,16 @@ int background_system(char *command)
 /*     to be called very early by the main processing               */
 /********************************************************************/
 
-void start_background_system(void)
-{
+void start_background_system(void) {
   int p[2];
   pid_t son;
-
   module_initialized = 1;
 
   if (pipe(p) == -1) {
     perror("pipe");
     exit(1);
   }
+
   command_pipe_read  = p[0];
   command_pipe_write = p[1];
 
@@ -164,10 +175,11 @@ void start_background_system(void)
     perror("pipe");
     exit(1);
   }
+
   result_pipe_read  = p[0];
   result_pipe_write = p[1];
-
   son = fork();
+
   if (son == -1) {
     perror("fork");
     exit(1);
@@ -181,6 +193,56 @@ void start_background_system(void)
 
   close(result_pipe_read);
   close(command_pipe_write);
-
   background_system_process();
 }
+
+
+void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, int affinity, int priority){
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+  pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+  pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+  struct sched_param sparam={0};
+  sparam.sched_priority = priority;
+  pthread_attr_setschedparam(&attr, &sparam);
+
+  pthread_create(t, &attr, func, param);
+
+  pthread_setname_np(*t, name);
+  if (affinity != -1 ) {
+    cpu_set_t cpuset;
+    CPU_ZERO(&cpuset);
+    CPU_SET(affinity, &cpuset);
+    AssertFatal( pthread_setaffinity_np(*t, sizeof(cpu_set_t), &cpuset) == 0, "Error setting processor affinity");
+  }
+
+  pthread_attr_destroy(&attr);
+}
+
+// Block CPU C-states deep sleep
+void configure_linux(void) {
+  int ret;
+  static int latency_target_fd=-1;
+  uint32_t latency_target_value=10; // in microseconds
+  if (latency_target_fd == -1) {
+    if ( (latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR)) != -1 ) {
+      ret = write(latency_target_fd, &latency_target_value, sizeof(latency_target_value));
+      if (ret == 0) {
+	printf("# error setting cpu_dma_latency to %d!: %s\n", latency_target_value, strerror(errno));
+	close(latency_target_fd);
+	latency_target_fd=-1;
+	return;
+      }
+    }
+  }
+  if (latency_target_fd != -1) 
+    LOG_I(HW,"# /dev/cpu_dma_latency set to %dus\n", latency_target_value);
+  else
+    LOG_E(HW,"Can't set /dev/cpu_dma_latency to %dus\n", latency_target_value);
+
+  // Set CPU frequency to it's maximum
+  if ( 0 != system("for d in /sys/devices/system/cpu/cpu[0-9]*; do cat $d/cpufreq/cpuinfo_max_freq > $d/cpufreq/scaling_min_freq; done"))
+	  LOG_W(HW,"Can't set cpu frequency\n");
+  
+}
diff --git a/common/utils/system.h b/common/utils/system.h
index 658c17adc1a476ce68c03d1510623c87c382ab29..a89a6c5b1729f0b968fbfd4baed9cfd3cce85b10 100644
--- a/common/utils/system.h
+++ b/common/utils/system.h
@@ -21,6 +21,12 @@
 
 #ifndef _SYSTEM_H_OAI_
 #define _SYSTEM_H_OAI_
+#include <stdint.h>
+#include <pthread.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 
 /****************************************************
  * send a command to the background process
@@ -36,4 +42,23 @@ int background_system(char *command);
 
 void start_background_system(void);
 
+void set_latency_target(void);
+void configure_linux(void);
+
+void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, int affinity, int priority);
+#define OAI_PRIORITY_RT_LOW sched_get_priority_min(SCHED_FIFO)
+#define OAI_PRIORITY_RT sched_get_priority_max(SCHED_FIFO)-10
+#define OAI_PRIORITY_RT_MAX sched_get_priority_max(SCHED_FIFO)
+
+void thread_top_init(char *thread_name,
+                     int affinity,
+                     uint64_t runtime,
+                     uint64_t deadline,
+                     uint64_t period);
+
+#ifdef __cplusplus
+}
+#endif
+
+
 #endif /* _SYSTEM_H_OAI_ */
diff --git a/common/utils/telnetsrv/telnetsrv_ltemeasur_def.h b/common/utils/telnetsrv/telnetsrv_ltemeasur_def.h
index 2f479d8ee6f9e5f59b06720e751df617d871e3bb..160111f15e8bca2abd60af3f63ef4d487ed6a2a6 100644
--- a/common/utils/telnetsrv/telnetsrv_ltemeasur_def.h
+++ b/common/utils/telnetsrv/telnetsrv_ltemeasur_def.h
@@ -81,8 +81,8 @@
   {"total_num_pdus",	   &(macuestatptr->total_num_pdus),TELNET_VARTYPE_INT32,0},\
   {"overhead_bytes",	   &(macuestatptr->overhead_bytes),TELNET_VARTYPE_INT64,0},\
   {"crnti",	           &(macuestatptr->crnti),TELNET_VARTYPE_INT16,0},\
-  {"normalized_rx_power",  &(macuestatptr->normalized_rx_power),TELNET_VARTYPE_INT32,0},\
-  {"target_rx_power",	   &(macuestatptr->target_rx_power),TELNET_VARTYPE_INT32,0},\
+  {"snr",                  &(macuestatptr->snr),TELNET_VARTYPE_INT32,0},\
+  {"target_snr ",          &(macuestatptr->target_snr),TELNET_VARTYPE_INT32,0},\
   {"ulsch_mcs1",	   &(macuestatptr->ulsch_mcs1),TELNET_VARTYPE_INT8,0},\
   {"ulsch_mcs2",	   &(macuestatptr->ulsch_mcs2),TELNET_VARTYPE_INT8,0},\
   {"rbs_used_rx",	   &(macuestatptr->rbs_used_rx),TELNET_VARTYPE_INT32,0},\
diff --git a/doc/BASIC_SIM.md b/doc/BASIC_SIM.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab4c3489d9a3562cbb20acc59e0e101e84d922f6
--- /dev/null
+++ b/doc/BASIC_SIM.md
@@ -0,0 +1,191 @@
+<table style="border-collapse: collapse; border: none;">
+  <tr style="border-collapse: collapse; border: none;">
+    <td style="border-collapse: collapse; border: none;">
+      <a href="http://www.openairinterface.org/">
+         <img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
+         </img>
+      </a>
+    </td>
+    <td style="border-collapse: collapse; border: none; vertical-align: center;">
+      <b><font size = "5">Running OAI Basic Simulator</font></b>
+    </td>
+  </tr>
+</table>
+
+This page is valid on the following branches:
+
+- `master` starting from tag `v1.1.0`
+- `develop` starting from tag `2019.w11`
+
+# 1. Building the basic-simulator.
+
+After the build simplification, the basic simulator is available directly from the standard build.
+
+```bash
+$ source oaienv
+$ cd cmake_targets
+$ ./build_oai --eNB --UE
+```
+
+Both eNB (lte-softmodem) and UE (lte-uesoftmodem) are present on `cmake_targets/lte_build_oai/build` folder.
+
+More details are available on the [build page](BUILD.md).
+
+# 2. Running the basic simulator.
+
+The basic simulator is a oai device replacing the radio heads (for example the USRP device). It allows connecting the oai UE and the oai eNodeB through a network interface carrying the time-domain samples, getting rid of over the air unpredictable perturbations.
+
+This is the ideal tool to check signal processing algorithms and protocols implementation and having debug sessions without any HW radio equipment.
+
+The main limitations are:
+
+- A single OAI UE will connect to the OAI eNB
+- No channel noise
+
+## 2.1. Starting eNB
+
+The basic simulator is able to run with a connected EPC or without any (the so-called "noS1" mode).
+
+Example 1: running in FDD mode with EPC.
+
+```bash
+$ source oaienv
+$ cd cmake_targets/lte_build_oai/build
+$ ENODEB=1 sudo -E ./lte-softmodem -O $OPENAIR_HOME/ci-scripts/conf_files/lte-fdd-basic-sim.conf --basicsim
+```
+
+Edit previously the `ci-scripts/conf_files/lte-fdd-basic-sim.conf` file to modify:
+
+- `N_RB_DL` field to change the Bandwidth (25, 50, 100)
+- `CI_MME_IP_ADDR` with the EPC IP address
+- `CI_ENB_IP_ADDR` with the container (physical server, virtual machine, ...) on which you are executing the eNB soft-modem
+
+Example 2: running in TDD mode without any EPC.
+
+```bash
+$ source oaienv
+$ cd cmake_targets/lte_build_oai/build
+$ ENODEB=1 sudo -E ./lte-softmodem -O $OPENAIR_HOME/ci-scripts/conf_files/lte-tdd-basic-sim.conf --basicsim --noS1
+```
+
+## 2.2. Starting UE
+
+Before starting the UE, you may need to edit the SIM parameters to adapt to your eNB configuration and HSS database.
+
+The <conf> file to use for conf2uedate is `openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf`
+
+You need to set the correct OPC, USIM_API_K, MSIN (this is the end par of the IMSI), HPLMN (the front part of IMSI) to match values from HSS.
+
+```bash
+$ source oaienv
+# Edit openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf
+$ cd cmake_targets/lte_build_oai/build
+$ ../../nas_sim_tools/build/conf2uedata -c $OPENAIR_HOME/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o .
+$ sudo -E ./lte-uesoftmodem -C 2625000000 -r 25 --ue-rxgain 140 --basicsim [--noS1]
+```
+
+The `-r 25` is to use if in the conf file of the eNB you use N_RB_DL=25. Use 50 if you have N_RB_DL=50 and 100 if you have N_RB_DL=100.
+
+The `-C 2625000000` is the downlink frequency. Use the same value as `downlink_frequency` in the eNB configuration file.
+
+The `--noS1` is mandatory if you started the eNB in that mode.
+
+# 3. Testing the data plane
+
+# 3.1. In S1 mode
+
+First we need to retrieve the IP address allocated to the OAI UE.
+
+On the server that runs the UE:
+
+```bash
+$ ifconfig oaitun_ue1
+oaitun_ue1 Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
+            inet addr:192.172.0.2  P-t-P:192.172.0.2  Mask:255.255.255.0
+...
+```
+
+`192.172.0.2` is the IP address that has been allocated by the SPGW in the EPC.
+
+On the server that runs the EPC:
+
+```bash
+$ ping -c 20 192.172.0.2
+  --- 192.172.0.2 ping statistics ---
+  20 packets transmitted, 20 received, 0% packet loss, time 19020ms
+  rtt min/avg/max/mdev = 13.241/18.999/24.208/2.840 ms
+```
+
+You can ping the EPC from the UE:
+
+```bash
+$ ping -I oaitun_ue1 -c 20 192.172.0.1
+  --- 192.172.0.1 ping statistics ---
+...
+  20 packets transmitted, 20 received, 0% packet loss, time 19019ms
+  rtt min/avg/max/mdev = 13.015/18.674/23.738/2.917 ms
+```
+
+For DL iperf testing:
+
+On the server that runs the UE.
+
+```bash
+$  iperf -B 192.172.0.2 -u -s -i 1 -fm -p 5001
+```
+
+On the server that runs the EPC.
+
+```bash
+$  iperf -c 192.172.0.2 -u -t 30 -b 10M -i 1 -fm -B 192.172.0.1 -p 5001
+```
+
+For UL iperf testing:
+
+On the server that runs the EPC.
+
+```bash
+$  iperf -B 192.172.0.1 -u -s -i 1 -fm -p 5001
+```
+
+On the server that runs the UE.
+
+```bash
+$  iperf -c 192.172.0.1 -u -t 30 -b 2M -i 1 -fm -B 192.172.0.2 -p 5001
+```
+
+# 3.2. In noS1 mode
+
+The IP addresses are fixed. But we can still retrieve them programmatically.
+
+For the UE it is quite the same:
+
+```bash
+$ ifconfig oaitun_ue1
+oaitun_ue1 Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
+            inet addr:10.0.1.2  P-t-P:10.0.1.2  Mask:255.255.255.0
+...
+```
+
+For the eNB:
+
+```bash
+$ ifconfig oaitun_enb1
+oaitun_enb1 Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
+            inet addr:10.0.1.1  P-t-P:10.0.1.1  Mask:255.255.255.0
+...
+```
+
+Pinging like this:
+
+```bash
+$ ping -I oaitun_ue1 -c 20 10.0.1.1
+$ ping -I oaitun_enb1 -c 20 10.0.1.2
+```
+
+And the same for iperf:
+
+```bash
+$ iperf -B 10.0.1.2 -u -s -i 1 -fm
+$ iperf -c 10.0.1.2 -u -b 1.00M -t 30 -i 1 -fm -B 10.0.1.1
+```
diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md
index 49c3c93dd63c2ebac60950d85e61ba0167a21551..9c9e72862b97ad893ab5dc9b1d45d397d6b6311d 100644
--- a/doc/FEATURE_SET.md
+++ b/doc/FEATURE_SET.md
@@ -33,10 +33,12 @@ The Physical layer implements **3GPP 36.211**, **36.212**, **36.213** and provid
 - Max number of antennas: 2
 - CQI/PMI reporting: aperiodic, feedback mode 3 - 0 and 3 - 1
 - PRACH preamble format 0
-- All downlink (DL) channels are supported: PSS, SSS, PBCH, PCFICH, PHICH, PDCCH, PDSCH, PMCH
-- All uplink (UL) channels are supported: PRACH, PUSCH, PUCCH (format 1/1a/1b), SRS, DRS
+- Downlink (DL) channels are supported: PSS, SSS, PBCH, PCFICH, PHICH, PDCCH, PDSCH, PMCH, MPDCCH
+- Uplink (UL) channels are supported: PRACH, PUSCH, PUCCH (format 1/1a/1b), SRS, DRS
 - HARQ support (UL and DL)
 - Highly optimized base band processing (including turbo decoder)
+- Multi-RRU support: over the air synchro b/ multi RRU in TDD mode
+- Support for CE-modeA for LTE-M. Limited support for repeatition, single-LTE-M connection, legacy-LTE UE attach is disabled.
 
 ### Performances ###
 
@@ -136,6 +138,7 @@ The X2AP layer is based on **3GPP 36.423** v14.6.0 and implements the following
  - UE Context Release
  - X2 timers (t_reloc_prep, tx2_reloc_overall)
  - Handover Cancel
+ - X2-U interface implemented
 
 ## eNB Advanced Features ##
 
diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md
index 314c2cc78bd7de484f3df3c68d5f39c7cc2683fb..bb89407f70bb0b4460bab65861cd207e0635757e 100644
--- a/doc/RUNMODEM.md
+++ b/doc/RUNMODEM.md
@@ -14,6 +14,10 @@
 
 After you have [built the softmodem executables](BUILD.md) you can set your default directory  to the build directory `cmake_targets/lte_build_oai/build/` and start testing some use cases. Below, the description of the different oai functionalities should help you choose the oai configuration that suits your need. 
 
+# Basic Simulator
+
+See the [dedicated page](BASIC_SIM.md).
+
 # RF Simulator
 
 The rf simulator is a oai device replacing the radio heads (for example the USRP device). It allows connecting the oai UE and the oai eNodeB through a network interface carrying the time-domain samples, getting rid of over the air unpredictable perturbations. This is the ideal tool to check signal processing algorithms and protocols implementation.
diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c
index c835f38e115a449b6ede31168954873b52219288..f07fb1ad23f13aadeeabfe0b2178655bb4c2722e 100644
--- a/nfapi/oai_integration/nfapi_pnf.c
+++ b/nfapi/oai_integration/nfapi_pnf.c
@@ -83,7 +83,7 @@ nfapi_tx_request_pdu_t *tx_request_pdu[1023][10][10]; // [frame][subframe][max_n
 
 uint8_t tx_pdus[32][8][4096];
 
-
+nfapi_ue_release_request_body_t release_rntis;
 uint16_t phy_antenna_capability_values[] = { 1, 2, 4, 8, 16 };
 
 nfapi_pnf_param_response_t g_pnf_param_resp;
@@ -197,19 +197,19 @@ static pthread_t pnf_start_pthread;
 int nfapitooai_level(int nfapi_level) {
   switch(nfapi_level) {
     case NFAPI_TRACE_ERROR:
-      return LOG_ERR;
+      return OAILOG_ERR;
 
     case NFAPI_TRACE_WARN:
-      return LOG_WARNING;
+      return OAILOG_WARNING;
 
     case NFAPI_TRACE_NOTE:
-      return LOG_INFO;
+      return OAILOG_INFO;
 
     case NFAPI_TRACE_INFO:
-      return LOG_DEBUG;
+      return OAILOG_DEBUG;
   }
 
-  return LOG_ERR;
+  return OAILOG_ERR;
 }
 
 void pnf_nfapi_trace(nfapi_trace_level_t nfapi_level, const char *message, ...) {
@@ -540,7 +540,6 @@ int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfap
   }
 
   if(req->nfapi_config.earfcn.tl.tag == NFAPI_NFAPI_EARFCN_TAG) {
-    fp->eutra_band = 0;
     fp->dl_CarrierFreq = from_earfcn(fp->eutra_band, req->nfapi_config.earfcn.value);
     fp->ul_CarrierFreq = fp->dl_CarrierFreq - (get_uldl_offset(fp->eutra_band) * 1e5);
     num_tlv++;
@@ -896,6 +895,15 @@ int pnf_phy_lbt_dl_config_req(nfapi_pnf_p7_config_t *config, nfapi_lbt_dl_config
   return 0;
 }
 
+int pnf_phy_ue_release_req(nfapi_pnf_p7_config_t* config, nfapi_ue_release_request_t* req) {
+  if (req->ue_release_request_body.number_of_TLVs==0)
+    return -1;
+
+  release_rntis.number_of_TLVs = req->ue_release_request_body.number_of_TLVs;
+  memcpy(&release_rntis.ue_release_request_TLVs_list, req->ue_release_request_body.ue_release_request_TLVs_list, sizeof(nfapi_ue_release_request_TLVs_t)*req->ue_release_request_body.number_of_TLVs);
+  return 0;
+}
+
 int pnf_phy_vendor_ext(nfapi_pnf_p7_config_t *config, nfapi_p7_message_header_t *msg) {
   if(msg->message_id == P7_VENDOR_EXT_REQ) {
     //vendor_ext_p7_req* req = (vendor_ext_p7_req*)msg;
@@ -1024,7 +1032,7 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi
   p7_config->hi_dci0_req = &pnf_phy_hi_dci0_req;
   p7_config->tx_req = &pnf_phy_tx_req;
   p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req;
-
+  p7_config->ue_release_req = &pnf_phy_ue_release_req;
   if (NFAPI_MODE==NFAPI_UE_STUB_PNF) {
     p7_config->dl_config_req = &memcpy_dl_config_req;
     p7_config->ul_config_req = &memcpy_ul_config_req;
@@ -1367,7 +1375,7 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr,
   printf("%s() PNF\n\n\n\n\n\n", __FUNCTION__);
 
   if(NFAPI_MODE!=NFAPI_UE_STUB_PNF) {
-    nfapi_setmode(NFAPI_PNF);  // PNF!
+    nfapi_setmode(NFAPI_MODE_PNF);  // PNF!
   }
 
   nfapi_pnf_config_t *config = nfapi_pnf_config_create();
diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c
index 2752df3435d37090e4ddc3f2347e8a45896869ba..6b68a2965885dc02fd6d394eae28ef5372116810 100644
--- a/nfapi/oai_integration/nfapi_vnf.c
+++ b/nfapi/oai_integration/nfapi_vnf.c
@@ -42,6 +42,7 @@
 
 #include "common/ran_context.h"
 extern RAN_CONTEXT_t RC;
+extern UL_RCC_IND_t  UL_RCC_INFO;
 
 typedef struct {
   uint8_t enabled;
@@ -424,6 +425,40 @@ int phy_rach_indication(struct nfapi_vnf_p7_config *config, nfapi_rach_indicatio
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   printf("[VNF] RACH_IND eNB:%p sfn_sf:%d number_of_preambles:%d\n", eNB, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->rach_indication_body.number_of_preambles);
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.rach_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_rach_indication : num of rach reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.rach_ind[index] = *ind;
+
+    if (ind->rach_indication_body.number_of_preambles > 0)
+      UL_RCC_INFO.rach_ind[index].rach_indication_body.preamble_list = malloc(sizeof(nfapi_preamble_pdu_t)*ind->rach_indication_body.number_of_preambles );
+
+    for (int i=0; i<ind->rach_indication_body.number_of_preambles; i++) {
+      if (ind->rach_indication_body.preamble_list[i].preamble_rel8.tl.tag == NFAPI_PREAMBLE_REL8_TAG) {
+
+        printf("preamble[%d]: rnti:%02x preamble:%d timing_advance:%d\n",
+              i,
+              ind->rach_indication_body.preamble_list[i].preamble_rel8.rnti,
+              ind->rach_indication_body.preamble_list[i].preamble_rel8.preamble,
+              ind->rach_indication_body.preamble_list[i].preamble_rel8.timing_advance
+              );
+      }
+      if(ind->rach_indication_body.preamble_list[i].preamble_rel13.tl.tag == NFAPI_PREAMBLE_REL13_TAG) {
+        printf("RACH PREAMBLE REL13 present\n");
+      }
+
+      UL_RCC_INFO.rach_ind[index].rach_indication_body.preamble_list[i] = ind->rach_indication_body.preamble_list[i];
+    }
+  }else{
   eNB->UL_INFO.rach_ind = *ind;
   eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = eNB->preamble_list;
 
@@ -443,7 +478,7 @@ int phy_rach_indication(struct nfapi_vnf_p7_config *config, nfapi_rach_indicatio
 
     eNB->preamble_list[i] = ind->rach_indication_body.preamble_list[i];
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_rach_ind(p7_vnf->mac, ind);
@@ -454,13 +489,33 @@ int phy_harq_indication(struct nfapi_vnf_p7_config *config, nfapi_harq_indicatio
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   LOG_D(MAC, "%s() NFAPI SFN/SF:%d number_of_harqs:%u\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->harq_indication_body.number_of_harqs);
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.harq_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_harq_indication : num of harq reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.harq_ind[index] = *ind;
+
+    if (ind->harq_indication_body.number_of_harqs > 0)
+      UL_RCC_INFO.harq_ind[index].harq_indication_body.harq_pdu_list = malloc(sizeof(nfapi_harq_indication_pdu_t)*ind->harq_indication_body.number_of_harqs );
+    for (int i=0; i<ind->harq_indication_body.number_of_harqs; i++) {
+        memcpy(&UL_RCC_INFO.harq_ind[index].harq_indication_body.harq_pdu_list[i], &ind->harq_indication_body.harq_pdu_list[i], sizeof(nfapi_harq_indication_pdu_t));
+    }
+  }else{
   eNB->UL_INFO.harq_ind = *ind;
   eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list;
 
   for (int i=0; i<ind->harq_indication_body.number_of_harqs; i++) {
     memcpy(&eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list[i], &ind->harq_indication_body.harq_pdu_list[i], sizeof(eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list[i]));
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_harq_ind(p7_vnf->mac, ind);
@@ -470,6 +525,37 @@ int phy_harq_indication(struct nfapi_vnf_p7_config *config, nfapi_harq_indicatio
 int phy_crc_indication(struct nfapi_vnf_p7_config *config, nfapi_crc_indication_t *ind) {
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.crc_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+      }
+      if(UL_RCC_INFO.rx_ind[i].sfn_sf == ind->sfn_sf){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_crc_indication : num of crc reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.crc_ind[index] = *ind;
+
+    if (ind->crc_indication_body.number_of_crcs > 0)
+      UL_RCC_INFO.crc_ind[index].crc_indication_body.crc_pdu_list = malloc(sizeof(nfapi_crc_indication_pdu_t)*ind->crc_indication_body.number_of_crcs );
+
+    for (int i=0; i<ind->crc_indication_body.number_of_crcs; i++) {
+      memcpy(&UL_RCC_INFO.crc_ind[index].crc_indication_body.crc_pdu_list[i], &ind->crc_indication_body.crc_pdu_list[i], sizeof(ind->crc_indication_body.crc_pdu_list[0]));
+
+      LOG_D(MAC, "%s() NFAPI SFN/SF:%d CRC_IND:number_of_crcs:%u UL_INFO:crcs:%d PDU[%d] rnti:%04x UL_INFO:rnti:%04x\n",
+          __FUNCTION__,
+          NFAPI_SFNSF2DEC(ind->sfn_sf), ind->crc_indication_body.number_of_crcs, UL_RCC_INFO.crc_ind[index].crc_indication_body.number_of_crcs,
+          i,
+          ind->crc_indication_body.crc_pdu_list[i].rx_ue_information.rnti,
+          UL_RCC_INFO.crc_ind[index].crc_indication_body.crc_pdu_list[i].rx_ue_information.rnti);
+    }
+  }else{
   eNB->UL_INFO.crc_ind = *ind;
   nfapi_crc_indication_t *dest_ind = &eNB->UL_INFO.crc_ind;
   nfapi_crc_indication_pdu_t *dest_pdu_list = eNB->crc_pdu_list;
@@ -489,7 +575,7 @@ int phy_crc_indication(struct nfapi_vnf_p7_config *config, nfapi_crc_indication_
           ind->crc_indication_body.crc_pdu_list[i].rx_ue_information.rnti,
           eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list[i].rx_ue_information.rnti);
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_crc_ind(p7_vnf->mac, ind);
@@ -504,6 +590,52 @@ int phy_rx_indication(struct nfapi_vnf_p7_config *config, nfapi_rx_indication_t
   }
 
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.rx_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+      }
+      if(UL_RCC_INFO.crc_ind[i].sfn_sf == ind->sfn_sf){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_rx_indication : num of rx reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.rx_ind[index] = *ind;
+
+    if (ind->rx_indication_body.number_of_pdus > 0)
+      UL_RCC_INFO.rx_ind[index].rx_indication_body.rx_pdu_list = malloc(sizeof(nfapi_rx_indication_pdu_t)*ind->rx_indication_body.number_of_pdus );
+
+    for (int i=0; i<ind->rx_indication_body.number_of_pdus; i++) {
+      nfapi_rx_indication_pdu_t *dest_pdu = &UL_RCC_INFO.rx_ind[index].rx_indication_body.rx_pdu_list[i];
+      nfapi_rx_indication_pdu_t *src_pdu = &ind->rx_indication_body.rx_pdu_list[i];
+
+      memcpy(dest_pdu, src_pdu, sizeof(*src_pdu));
+      // DJP - TODO FIXME - intentional memory leak
+      if(dest_pdu->rx_indication_rel8.length > 0){
+        dest_pdu->data = malloc(dest_pdu->rx_indication_rel8.length);
+        memcpy(dest_pdu->data, src_pdu->data, dest_pdu->rx_indication_rel8.length);
+      }else{
+        dest_pdu->data = NULL;
+      }
+
+      LOG_D(PHY, "%s() NFAPI SFN/SF:%d PDUs:%d [PDU:%d] handle:%d rnti:%04x length:%d offset:%d ul_cqi:%d ta:%d data:%p\n",
+          __FUNCTION__,
+          NFAPI_SFNSF2DEC(ind->sfn_sf), ind->rx_indication_body.number_of_pdus, i,
+          dest_pdu->rx_ue_information.handle,
+          dest_pdu->rx_ue_information.rnti,
+          dest_pdu->rx_indication_rel8.length,
+          dest_pdu->rx_indication_rel8.offset,
+          dest_pdu->rx_indication_rel8.ul_cqi,
+          dest_pdu->rx_indication_rel8.timing_advance,
+          dest_pdu->data
+          );
+    }
+  }else{
   nfapi_rx_indication_t *dest_ind = &eNB->UL_INFO.rx_ind;
   nfapi_rx_indication_pdu_t *dest_pdu_list = eNB->rx_pdu_list;
   *dest_ind = *ind;
@@ -528,7 +660,7 @@ int phy_rx_indication(struct nfapi_vnf_p7_config *config, nfapi_rx_indication_t
           dest_pdu->data
          );
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_rx_ind(p7_vnf->mac, ind);
@@ -544,6 +676,32 @@ int phy_sr_indication(struct nfapi_vnf_p7_config *config, nfapi_sr_indication_t
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   LOG_D(MAC, "%s() NFAPI SFN/SF:%d srs:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->sr_indication_body.number_of_srs);
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.sr_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_sr_indication : num of sr reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.sr_ind[index] = *ind;
+    LOG_D(MAC,"%s() UL_INFO[%d].sr_ind.sr_indication_body.number_of_srs:%d\n", __FUNCTION__, index, eNB->UL_INFO.sr_ind.sr_indication_body.number_of_srs);
+    if (ind->sr_indication_body.number_of_srs > 0)
+      UL_RCC_INFO.sr_ind[index].sr_indication_body.sr_pdu_list = malloc(sizeof(nfapi_sr_indication_pdu_t)*ind->sr_indication_body.number_of_srs );
+
+    for (int i=0; i<ind->sr_indication_body.number_of_srs; i++) {
+        nfapi_sr_indication_pdu_t *dest_pdu = &UL_RCC_INFO.sr_ind[index].sr_indication_body.sr_pdu_list[i];
+        nfapi_sr_indication_pdu_t *src_pdu = &ind->sr_indication_body.sr_pdu_list[i];
+
+        LOG_D(MAC, "SR_IND[PDU:%d %d][rnti:%x cqi:%d channel:%d]\n", index, i, src_pdu->rx_ue_information.rnti, src_pdu->ul_cqi_information.ul_cqi, src_pdu->ul_cqi_information.channel);
+
+        memcpy(dest_pdu, src_pdu, sizeof(*src_pdu));
+    }
+  }else{
   nfapi_sr_indication_t *dest_ind = &eNB->UL_INFO.sr_ind;
   nfapi_sr_indication_pdu_t *dest_pdu_list = eNB->sr_pdu_list;
   *dest_ind = *ind;
@@ -556,7 +714,7 @@ int phy_sr_indication(struct nfapi_vnf_p7_config *config, nfapi_sr_indication_t
     LOG_D(MAC, "SR_IND[PDU:%d][rnti:%x cqi:%d channel:%d]\n", i, src_pdu->rx_ue_information.rnti, src_pdu->ul_cqi_information.ul_cqi, src_pdu->ul_cqi_information.channel);
     memcpy(dest_pdu, src_pdu, sizeof(*src_pdu));
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_sr_ind(p7_vnf->mac, ind);
@@ -569,7 +727,48 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   LOG_D(MAC, "%s() NFAPI SFN/SF:%d number_of_cqis:%u\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->cqi_indication_body.number_of_cqis);
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
-  eNB->UL_INFO.cqi_ind = ind->cqi_indication_body;
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.cqi_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_cqi_indication : num of cqi reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.cqi_ind[index] = *ind;
+    if (ind->cqi_indication_body.number_of_cqis > 0){
+      UL_RCC_INFO.cqi_ind[index].cqi_indication_body.cqi_pdu_list = malloc(sizeof(nfapi_cqi_indication_pdu_t)*ind->cqi_indication_body.number_of_cqis );
+      UL_RCC_INFO.cqi_ind[index].cqi_indication_body.cqi_raw_pdu_list = malloc(sizeof(nfapi_cqi_indication_raw_pdu_t)*ind->cqi_indication_body.number_of_cqis );
+    }
+    for (int i=0; i<ind->cqi_indication_body.number_of_cqis; i++) {
+        nfapi_cqi_indication_pdu_t *src_pdu = &ind->cqi_indication_body.cqi_pdu_list[i];
+        LOG_D(MAC, "SR_IND[PDU:%d][rnti:%x cqi:%d channel:%d]\n", i, src_pdu->rx_ue_information.rnti,
+                    src_pdu->ul_cqi_information.ul_cqi, src_pdu->ul_cqi_information.channel);
+        memcpy(&UL_RCC_INFO.cqi_ind[index].cqi_indication_body.cqi_pdu_list[i],
+               src_pdu, sizeof(nfapi_cqi_indication_pdu_t));
+
+        memcpy(&UL_RCC_INFO.cqi_ind[index].cqi_indication_body.cqi_raw_pdu_list[i],
+               &ind->cqi_indication_body.cqi_raw_pdu_list[i], sizeof(nfapi_cqi_indication_raw_pdu_t));
+    }
+  }else{
+  nfapi_cqi_indication_t *dest_ind = &eNB->UL_INFO.cqi_ind;
+  *dest_ind = *ind;
+  dest_ind->cqi_indication_body.cqi_pdu_list = ind->cqi_indication_body.cqi_pdu_list;
+  dest_ind->cqi_indication_body.cqi_raw_pdu_list = ind->cqi_indication_body.cqi_raw_pdu_list;
+  for(int i=0; i<ind->cqi_indication_body.number_of_cqis; i++) {
+    nfapi_cqi_indication_pdu_t *src_pdu = &ind->cqi_indication_body.cqi_pdu_list[i];
+    LOG_D(MAC, "SR_IND[PDU:%d][rnti:%x cqi:%d channel:%d]\n", i, src_pdu->rx_ue_information.rnti,
+                src_pdu->ul_cqi_information.ul_cqi, src_pdu->ul_cqi_information.channel);
+    memcpy(&dest_ind->cqi_indication_body.cqi_pdu_list[i],
+           src_pdu, sizeof(nfapi_cqi_indication_pdu_t));
+    memcpy(&dest_ind->cqi_indication_body.cqi_raw_pdu_list[i],
+           &ind->cqi_indication_body.cqi_raw_pdu_list[i], sizeof(nfapi_cqi_indication_raw_pdu_t));
+  }
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   return 1;
 }
@@ -947,6 +1146,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) {
   config->deallocate_p4_p5_vendor_ext = &vnf_deallocate_p4_p5_vendor_ext;
   config->codec_config.allocate = &vnf_allocate;
   config->codec_config.deallocate = &vnf_deallocate;
+  memset(&UL_RCC_INFO,0,sizeof(UL_RCC_IND_t));
   NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__);
   pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_start_thread, config);
   NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__);
@@ -1021,3 +1221,21 @@ int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) {
 
   return retval;
 }
+
+int oai_nfapi_ue_release_req(nfapi_ue_release_request_t *release_req){
+    if(release_req->ue_release_request_body.number_of_TLVs <= 0)
+        return 0;
+    nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
+
+    release_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
+    release_req->header.message_id = NFAPI_UE_RELEASE_REQUEST;
+    release_req->ue_release_request_body.tl.tag = NFAPI_UE_RELEASE_BODY_TAG;
+
+    int retval = nfapi_vnf_p7_ue_release_req(p7_config, release_req);
+    if (retval!=0) {
+      LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval);
+    } else {
+        release_req->ue_release_request_body.number_of_TLVs = 0;
+    }
+    return retval;
+}
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
index 6a70e1f10afae444929d0ec07807318ee9f8f261..a1a0b6e7245ff7fc22963f6c9804a9a62716ee69 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h
@@ -146,6 +146,8 @@ typedef enum {
 	NFAPI_LBT_DL_INDICATION,
 	NFAPI_NB_HARQ_INDICATION,
 	NFAPI_NRACH_INDICATION,
+	NFAPI_UE_RELEASE_REQUEST,
+	NFAPI_UE_RELEASE_RESPONSE,
 
 	NFAPI_PNF_PARAM_REQUEST = 0x0100,
 	NFAPI_PNF_PARAM_RESPONSE,
@@ -2392,6 +2394,19 @@ typedef struct {
 } nfapi_tx_request_body_t;
 #define NFAPI_TX_REQUEST_BODY_TAG 0x2022
 
+#define  NFAPI_RELEASE_MAX_RNTI  256
+typedef struct {
+    uint32_t handle;
+    uint16_t rnti;
+} nfapi_ue_release_request_TLVs_t;
+
+typedef struct {
+    nfapi_tl_t tl;
+    uint16_t number_of_TLVs;
+    nfapi_ue_release_request_TLVs_t ue_release_request_TLVs_list[NFAPI_RELEASE_MAX_RNTI];
+} nfapi_ue_release_request_body_t;
+#define NFAPI_UE_RELEASE_BODY_TAG 0x2068
+
 // P7 Message Structures
 typedef struct {
 	nfapi_p7_message_header_t header;
@@ -3418,6 +3433,19 @@ typedef struct {
 	nfapi_vendor_extension_tlv_t vendor_extension;
 } nfapi_error_indication_t;
 
+typedef struct {
+    nfapi_p7_message_header_t header;
+    uint16_t sfn_sf;
+    nfapi_ue_release_request_body_t ue_release_request_body;
+    nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_ue_release_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_ue_release_response_t;
+
 // 
 // P4 Messages
 // 
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
old mode 100644
new mode 100755
index 2daf1450c852c9bbb7b5ff1003e308903b494ba4..be9205d035ea075803e8e548925f1c8f3a9f1e8c
--- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
@@ -81,13 +81,19 @@ void* nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t* config)
 	if(size == 0)
 		return 0;
 
+       void* buffer_p = NULL;
 	if(config && config->allocate)
 	{
-		return (config->allocate)(size);
+               buffer_p = (config->allocate)(size);
+               if(buffer_p != NULL){
+               memset(buffer_p,0,size);
+               }
+               return buffer_p;
 	}
 	else
 	{
-		return calloc(1, size);
+               buffer_p = calloc(1, size);
+               return buffer_p;
 	}
 }
 
@@ -1577,7 +1583,43 @@ static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e
 
         return x && y && z;
 }
-
+
+static uint8_t pack_release_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
+{
+  nfapi_ue_release_request_body_t* value = (nfapi_ue_release_request_body_t*)tlv;
+  if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0){
+    return 0;
+  }
+
+  uint8_t j;
+  uint16_t num = value->number_of_TLVs;
+  for(j = 0; j < num; ++j){
+    if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0){
+      return 0;
+    }
+  }
+  return 1;
+}
+
+static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+  nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg;
+  int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end);
+  int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value);
+  int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+  return x && y && z;
+}
+
+static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
+{
+
+	nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg;
+
+	int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end);
+	int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config);
+	return x && z;
+}
+
 static uint8_t pack_rx_ue_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end)
 {
 	nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv;
@@ -2665,7 +2707,15 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu
                         //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__);
 			result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
-
+
+		case NFAPI_UE_RELEASE_REQUEST:
+			result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
+		case NFAPI_UE_RELEASE_RESPONSE:
+			result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config);
+			break;
+
 		case NFAPI_HARQ_INDICATION:
 			result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config);
 			break;
@@ -4479,7 +4529,55 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
 
 	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;
+    nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg;
+
+    if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0)
+        return 0;
+
+    while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed)
+    {
+        nfapi_tl_t generic_tl;
+        if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0)
+            return 0;
+
+        switch(generic_tl.tag)
+        {
+            case NFAPI_UE_RELEASE_BODY_TAG:
+            {
+                pNfapiMsg->ue_release_request_body.tl = generic_tl;
+                if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0)
+                    return 0;
+
+                if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI)
+                {
+                    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI);
+                    return 0;
+                } else {
+                    uint8_t j;
+                    uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs;
+                    for(j = 0; j < num; ++j){
+                    		if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0){
+                    				return 0;
+                    		}
+                    }
+                }
+            }
+            break;
+            default:
+            {
+              NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag );
+            }
+            break;
+        };
+    }
+
+    return 1;
+}
+
 static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end)
 {
 	nfapi_harq_indication_tdd_harq_data_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_bundling_t*)tlv;
@@ -5727,7 +5825,18 @@ static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPa
 			pull8(ppReadPackedMsg, &value->nrach_ce_level, end));
 }
 
-
+static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config)
+{
+	nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg;
+	if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0){
+		return 0;
+	}
+	else{
+		NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code);
+	}
+	return 1;
+}
+
 static uint8_t unpack_nrach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config)
 {
 	nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv;
@@ -5940,7 +6049,17 @@ static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen
 			if (unpackedBufLen >= sizeof(nfapi_timing_info_t))
 				retLen = sizeof(nfapi_timing_info_t);
 			break;
-
+
+		case NFAPI_UE_RELEASE_REQUEST:
+			if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t))
+				retLen = sizeof(nfapi_ue_release_request_t);
+			break;
+
+		case NFAPI_UE_RELEASE_RESPONSE:
+			if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t))
+				retLen = sizeof(nfapi_ue_release_response_t);
+			break;
+
 		default:
 			NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId);
 			break;
@@ -6060,7 +6179,14 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn
 			else
 				return -1;
 			break;
-
+
+		case NFAPI_UE_RELEASE_REQUEST:
+			if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen))
+				result = unpack_ue_release_request(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
 		case NFAPI_HARQ_INDICATION:
 			if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen))
 				result = unpack_harq_indication(&pReadPackedMessage,  end, pMessageHeader, config);
@@ -6158,7 +6284,14 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn
 			else
 				return -1;
 			break;
-
+
+		case NFAPI_UE_RELEASE_RESPONSE:
+			if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen))
+				result = unpack_ue_release_resp(&pReadPackedMessage,  end, pMessageHeader, config);
+			else
+				return -1;
+			break;
+
 		default:
 
 			if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && 
diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h
index b25caf28760ff6e06ef4607b2d49f7e1a46e1de5..8d17416a418a98a822494726b1f1261aa1f66e54 100644
--- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h
+++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h
@@ -546,7 +546,7 @@ typedef struct
 	nfapi_hi_dci0_request_t* hi_dci0_req;
 	nfapi_tx_request_t* tx_req;
 	nfapi_lbt_dl_config_request_t* lbt_dl_config_req;
-
+	nfapi_ue_release_request_t* ue_release_req;
 } nfapi_pnf_p7_subframe_buffer_t;
 
 typedef struct nfapi_pnf_p7_config nfapi_pnf_p7_config_t;
@@ -652,6 +652,17 @@ typedef struct nfapi_pnf_p7_config
 	 * \return not currently used
 	 */
 	int (*lbt_dl_config_req)(nfapi_pnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req);
+
+    /*! A callback for the UE_RELEASE_REQ.request
+     * \param config A poiner to the PNF P7 config
+     * \param req A pointer to the release rnti request message structure
+     * \return not currently used
+     *
+     * The release request contains pointers to the release rnti to be sent. In the case that the FAPI interface
+     * will 'keep' the pointers until they are transmitted the callee should set the pointers in the req to 0
+     * and then use the p7 codec config free function to release the rnti when appropriate.
+     */
+    int (*ue_release_req)(nfapi_pnf_p7_config_t* config, nfapi_ue_release_request_t* req);
 	
 	/*! A callback for vendor extension messages
 	 * \param config A poiner to the PNF P7 config
@@ -796,6 +807,7 @@ int nfapi_pnf_p7_nrach_ind(nfapi_pnf_p7_config_t* config, nfapi_nrach_indication
  */
 int nfapi_pnf_p7_vendor_extension(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg);
 
+int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_response_t* resp);
 #if defined(__cplusplus)
 }
 #endif
diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c
index 81abed81a95b27935df7b19bb21ddb8b5c25f97d..944673037500c6f8478b3352f0998f28e840cc07 100644
--- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c
+++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c
@@ -36,7 +36,7 @@ extern uint16_t sf_ahead;
 
 void add_sf(uint16_t *frameP, uint16_t *subframeP, int offset)
 {
-    *frameP    = *frameP + ((*subframeP + offset) / 10);
+    *frameP    = (*frameP + ((*subframeP + offset) / 10))%1024;
 
     *subframeP = ((*subframeP + offset) % 10);
 }
@@ -241,6 +241,16 @@ void deallocate_nfapi_lbt_dl_config_request(nfapi_lbt_dl_config_request_t* req,
 	pnf_p7_free(pnf_p7, req);
 }
 
+nfapi_ue_release_request_t* allocate_nfapi_ue_release_request(pnf_p7_t* pnf_p7)
+{
+    return pnf_p7_malloc(pnf_p7, sizeof(nfapi_ue_release_request_t));
+}
+
+void deallocate_nfapi_ue_release_request(nfapi_ue_release_request_t* req, pnf_p7_t* pnf_p7)
+{
+	pnf_p7_free(pnf_p7, req);
+}
+
 pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len)
 {
 	pnf_p7_rx_message_t* msg = 0;
@@ -720,6 +730,21 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf)
 				}
 			}
 
+			if(tx_subframe_buffer->ue_release_req != 0)
+			{
+				if(pnf_p7->_public.ue_release_req)
+					(pnf_p7->_public.ue_release_req)(&(pnf_p7->_public), tx_subframe_buffer->ue_release_req);
+			}
+			else
+			{
+				//send dummy
+				if(pnf_p7->_public.ue_release_req && pnf_p7->_public.dummy_subframe.ue_release_req)
+				{
+					pnf_p7->_public.dummy_subframe.ue_release_req->sfn_sf = sfn_sf_tx;
+					(pnf_p7->_public.ue_release_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.ue_release_req);
+				}
+			}
+
                         if(tx_subframe_buffer->dl_config_req != 0)
                         {
                           deallocate_nfapi_dl_config_request(tx_subframe_buffer->dl_config_req, pnf_p7);
@@ -735,6 +760,10 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf)
                           deallocate_nfapi_hi_dci0_request(tx_subframe_buffer->hi_dci0_req, pnf_p7);
                           tx_subframe_buffer->hi_dci0_req = 0;
                         }
+                        if(tx_subframe_buffer->ue_release_req != 0){
+                            deallocate_nfapi_ue_release_request(tx_subframe_buffer->ue_release_req, pnf_p7);
+                            tx_subframe_buffer->ue_release_req = 0;
+                        }
                 }
 		else
 		{
@@ -799,7 +828,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf)
                         }
                 } // sfn_sf match
 
-                if (subframe_buffer->dl_config_req == 0 && subframe_buffer->tx_req == 0 && subframe_buffer->ul_config_req == 0 && subframe_buffer->lbt_dl_config_req == 0)
+                if (subframe_buffer->dl_config_req == 0 && subframe_buffer->tx_req == 0 && subframe_buffer->ul_config_req == 0 && subframe_buffer->lbt_dl_config_req == 0 && subframe_buffer->ue_release_req == 0)
                 {
                   memset(&(pnf_p7->subframe_buffer[buffer_index]), 0, sizeof(nfapi_pnf_p7_subframe_buffer_t));
                   pnf_p7->subframe_buffer[buffer_index].sfn_sf = -1;
@@ -1310,6 +1339,80 @@ void pnf_handle_p7_vendor_extension(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pn
 	
 }
 
+void pnf_handle_ue_release_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7)
+{
+    nfapi_ue_release_request_t* req = allocate_nfapi_ue_release_request(pnf_p7);
+    if(req == NULL)
+    {
+        NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to alloced nfapi_ue_release_request structure\n");
+        return;
+    }
+
+    int unpack_result = nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_ue_release_request_t), &pnf_p7->_public.codec_config);
+    if(unpack_result == 0)
+    {
+        if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0)
+        {
+            NFAPI_TRACE(NFAPI_TRACE_ERROR, "failed to lock mutex\n");
+            return;
+        }
+
+        if(is_p7_request_in_window(req->sfn_sf, "ue_release_request", pnf_p7))
+        {
+            uint32_t sfn_sf_dec = NFAPI_SFNSF2DEC(req->sfn_sf);
+            uint8_t buffer_index = sfn_sf_dec % pnf_p7->_public.subframe_buffer_size;
+
+            struct timespec t;
+            clock_gettime(CLOCK_MONOTONIC, &t);
+
+            NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UE_RELEASE_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_sf_dec, buffer_index);
+
+            if (0 && NFAPI_SFNSF2DEC(req->sfn_sf)%100==0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() UE_RELEASE_REQ.req sfn_sf:%d rntis:%d - UE_RELEASE_REQ is within window\n",
+                            __FUNCTION__,
+                            NFAPI_SFNSF2DEC(req->sfn_sf),
+                            req->ue_release_request_body.number_of_TLVs);
+
+            if(pnf_p7->subframe_buffer[buffer_index].ue_release_req != 0)
+            {
+                deallocate_nfapi_ue_release_request(pnf_p7->subframe_buffer[buffer_index].ue_release_req, pnf_p7);
+            }
+
+            pnf_p7->subframe_buffer[buffer_index].sfn_sf = req->sfn_sf;
+            pnf_p7->subframe_buffer[buffer_index].ue_release_req = req;
+
+            pnf_p7->stats.tx_ontime++;
+        }
+        else
+        {
+            NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() UE_RELEASE_REQUEST Request is outside of window REQ:SFN_SF:%d CURR:SFN_SF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), NFAPI_SFNSF2DEC(pnf_p7->sfn_sf));
+
+            deallocate_nfapi_ue_release_request(req, pnf_p7);
+            if(pnf_p7->_public.timing_info_mode_aperiodic)
+            {
+                pnf_p7->timing_info_aperiodic_send = 1;
+            }
+
+            pnf_p7->stats.tx_late++;
+        }
+        nfapi_ue_release_response_t resp;
+        memset(&resp, 0, sizeof(resp));
+        resp.header.message_id = NFAPI_UE_RELEASE_RESPONSE;
+        resp.header.phy_id = req->header.phy_id;
+        resp.error_code = NFAPI_MSG_OK;
+        nfapi_pnf_ue_release_resp(&(pnf_p7->_public), &resp);
+        NFAPI_TRACE(NFAPI_TRACE_INFO, "do ue_release_response\n");
+
+        if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0)
+        {
+            NFAPI_TRACE(NFAPI_TRACE_ERROR, "failed to unlock mutex\n");
+            return;
+        }
+    }
+    else
+    {
+        deallocate_nfapi_ue_release_request(req, pnf_p7);
+    }
+}
 
 uint32_t calculate_t2(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_time_hr)
 {
@@ -1445,7 +1548,11 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7,
 		case NFAPI_LBT_DL_CONFIG_REQUEST:
 			pnf_handle_lbt_dl_config_request(pRecvMsg, recvMsgLen, pnf_p7);
 			break;
-		
+
+		case NFAPI_UE_RELEASE_REQUEST:
+			pnf_handle_ue_release_request(pRecvMsg, recvMsgLen, pnf_p7);
+			break;
+
 		default:
 			{
 				if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
@@ -1536,7 +1643,7 @@ void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7,  ui
 					NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length);
 					return;
 				}
-
+                                memset(pnf_p7->reassemby_buffer, 0, length);
 				pnf_p7->reassemby_buffer_size = length;
 			}
 			
diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c
index 74de5e5d785e5d251dfcc65133fd2154219b7641..24e73ae9b3c6fb54efd362b6ed855a941b6cb932 100644
--- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c
+++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c
@@ -223,3 +223,15 @@ int nfapi_pnf_p7_vendor_extension(nfapi_pnf_p7_config_t* config, nfapi_p7_messag
 	return pnf_p7_pack_and_send_p7_message(_this, msg, 0);
 }
 
+int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_response_t* resp)
+{
+	if (config == NULL || resp == NULL)
+	{
+		NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__);
+		return -1;
+	}
+
+	pnf_p7_t* _this = (pnf_p7_t*)(config);
+
+	return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t));
+}
diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h
index 462901391a8cd63bfc9b25a239f8600870fdad52..ed8f6ba9688939bf953fc0f52729ba7877a86659 100644
--- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h
+++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h
@@ -988,6 +988,15 @@ int nfapi_vnf_p7_lbt_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_lbt_dl_c
  */
 int nfapi_vnf_p7_vendor_extension(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* msg);
 
+/*! Send the RELEASE_RNTI.request
+ *  \param config A pointer to the vnf p7 configuration
+ *  \param req A data structure for the decoded RELEASE_RNTI.request.
+ *  \return A status value. 0 equal success, -1 indicates failure
+ *
+ *  The caller is responsiable for memory management of any pointers set in the req, which
+ *  may be released after this function call has returned or at a later pointer
+ */
+int nfapi_vnf_p7_ue_release_req(nfapi_vnf_p7_config_t* config, nfapi_ue_release_request_t* req);
 #if defined(__cplusplus)
 }
 #endif
diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c
index 4b7acabec3637af74e3d95f8d9d805ea3337b118..985a6f830a6835db67f38ff587c6e0d86f5a99b4 100644
--- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c
+++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c
@@ -822,6 +822,28 @@ void vnf_handle_nrach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p
 	}
 }
 
+void vnf_handle_ue_release_resp(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_ue_release_response_t resp;
+
+		if(nfapi_p7_message_unpack(pRecvMsg, recvMsgLen, &resp, sizeof(resp), &vnf_p7->_public.codec_config) < 0)
+		{
+			NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__);
+		}
+
+
+		vnf_p7_codec_free(vnf_p7, resp.vendor_extension);
+	}
+}
+
 void vnf_handle_p7_vendor_extension(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7, uint16_t message_id)
 {
 	if (pRecvMsg == NULL || vnf_p7 == NULL)
@@ -1334,6 +1356,10 @@ void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
 			vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7);
 			break;			
 
+		case NFAPI_UE_RELEASE_RESPONSE:
+			vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7);
+			break;
+
 		default:
 			{
 				if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN &&
@@ -1430,7 +1456,7 @@ void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7)
 						NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate VNF_P7 reassemby buffer len:%d\n", length);
 						return;
 					}
-
+                                       memset(phy->reassembly_buffer, 0, length);
 					phy->reassembly_buffer_size = length;
 				}
 
diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c
index 4a85f7e4b3b9b245f5f5660e6c1a3a0dc8ce80eb..0444dca71d0f7d2d5973a123458be8b22df60a20 100644
--- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c
+++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c
@@ -523,6 +523,14 @@ int nfapi_vnf_p7_vendor_extension(nfapi_vnf_p7_config_t* config, nfapi_p7_messag
 	return vnf_p7_pack_and_send_p7_msg(vnf_p7, header);
 }
 
+int nfapi_vnf_p7_ue_release_req(nfapi_vnf_p7_config_t* config, nfapi_ue_release_request_t* req)
+{
+    if(config == 0 || req == 0)
+        return -1;
+
+    vnf_p7_t* vnf_p7 = (vnf_p7_t*)config;
+    return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header);
+}
 
 int nfapi_vnf_p7_release_msg(nfapi_vnf_p7_config_t* config, nfapi_p7_message_header_t* header)
 {
diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c
index fad4311714bfdb11bd2703e409c4c4629118dc77..61a58c1b1932aff02e5d0fe4d7ba9ad79adfe340 100644
--- a/openair1/PHY/INIT/lte_init.c
+++ b/openair1/PHY/INIT/lte_init.c
@@ -34,6 +34,7 @@
 #include "common/utils/LOG/vcd_signal_dumper.h"
 #include "assertions.h"
 #include <math.h>
+#include "nfapi/oai_integration/vendor_ext.h"
 
 extern uint32_t from_earfcn(int eutra_bandP,uint32_t dl_earfcn);
 extern int32_t get_uldl_offset(int eutra_bandP);
@@ -408,6 +409,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
 
 
     
+  if (NFAPI_MODE!=NFAPI_MODE_VNF){
   common_vars->rxdata  = (int32_t **)NULL;
   common_vars->txdataF = (int32_t **)malloc16(NB_ANTENNA_PORTS_ENB*sizeof(int32_t*));
   common_vars->rxdataF = (int32_t **)malloc16(64*sizeof(int32_t*));
@@ -511,6 +513,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
 
   for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++)
     eNB->UE_stats_ptr[UE_id] = &eNB->UE_stats[UE_id];
+  }
 
   eNB->pdsch_config_dedicated->p_a = dB0;       //defaul value until overwritten by RRCConnectionReconfiguration
 
diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c
index b4b253a297648df6e0dbaa4ae91a358f7e4f9575..1913afab2df61d0dca23cb3d510a66b3eb643c00 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci.c
@@ -291,24 +291,8 @@ uint8_t generate_dci_top(uint8_t num_pdcch_symbols,
   y[0] = &yseq0[0];
   y[1] = &yseq1[0];
 
-  if (IS_SOFTMODEM_BASICSIM) {
-    /* this should be the normal case
-     * but it has to be validated for all the various cases
-     * so let's just do it for the basic simulator
-     */
-    //  memset(e, 2, DCI_BITS_MAX);
-  } else {
-    // reset all bits to <NIL>, here we set <NIL> elements as 2
-    // memset(e, 2, DCI_BITS_MAX);
-    // here we interpret NIL as a random QPSK sequence. That makes power estimation easier.
-    for (i=0; i<DCI_BITS_MAX; i++)
-      e[i]=taus()&1;
-
-    /* clear all bits, the above code may generate too much false detections
-     * (not sure about this, to be checked somehow)
-     */
-    //memset(e, 0, DCI_BITS_MAX);
-  }/* BASIC_SIMULATOR */
+  /* reset all bits to <NIL>, here we set <NIL> elements as 2 */
+  memset(e, 2, DCI_BITS_MAX);
 
   e_ptr = e;
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DCI0,1);
diff --git a/openair1/PHY/LTE_TRANSPORT/dci.h b/openair1/PHY/LTE_TRANSPORT/dci.h
index c5654aa7428203ca04b4c709eaedae3612adf84d..cd76f209197f3854948cb14854fb7985a56fef9b 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci.h
+++ b/openair1/PHY/LTE_TRANSPORT/dci.h
@@ -38,7 +38,7 @@
 #define CCEBITS 72
 #define CCEPERSYMBOL 33  // This is for 1200 RE
 #define CCEPERSYMBOL0 22  // This is for 1200 RE
-#define DCI_BITS_MAX ((2*CCEPERSYMBOL+CCEPERSYMBOL0)*CCEBITS)
+#define DCI_BITS_MAX ((2*CCEPERSYMBOL+CCEPERSYMBOL0)*CCEBITS + 64)
 
 //#define Mquad (Msymb/4)
 
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
index b44a04eb742488b2dc599ba83997619987630d41..327b0cf57cd4223094a9ffea3ffbd9ace07d4d3d 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
@@ -384,9 +384,8 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
   unsigned int G;
   unsigned int crc=1;
   unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe];
-
-  if(harq_pid >= dlsch->Mdlharq) {
-    LOG_E(PHY,"dlsch_encoding_2threads illegal harq_pid %d\n", harq_pid);
+  if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) {
+    LOG_E(PHY,"dlsch_encoding_2threads illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
     return(-1);
   }
 
@@ -569,7 +568,12 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB,
                        time_stats_t *i_stats) {
   int encoding_return = 0;
   unsigned int L,C,B;
-  B = dlsch->harq_processes[dlsch->harq_ids[frame%2][subframe]]->B;
+  uint8_t harq_pid = dlsch->harq_ids[frame%2][subframe];
+  if(harq_pid >= dlsch->Mdlharq) {
+    LOG_E(PHY,"dlsch_encoding_all illegal harq_pid %d\n", harq_pid);
+    return(-1);
+  }
+  B = dlsch->harq_processes[harq_pid]->B;
 
   LOG_D(PHY,"B %d, harq_pid %d\n",B,dlsch->harq_ids[frame%2][subframe]);
 
@@ -676,9 +680,8 @@ int dlsch_encoding(PHY_VARS_eNB *eNB,
   unsigned int crc=1;
   LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
   unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe];
-
-  if(harq_pid >= dlsch->Mdlharq) {
-    LOG_E(PHY,"dlsch_encoding illegal harq_pid %d\n", harq_pid);
+  if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) {
+    LOG_E(PHY,"dlsch_encoding illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
     return(-1);
   }
 
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
index e8b56f3bdfe99292b3a5db85d91b5d99f1fba697..8a3649cf8727d5ad00ec73ae3a754593406afef2 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c
@@ -2257,8 +2257,8 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
   if ((dlsch0 != NULL) && (dlsch1 != NULL)){
 
     harq_pid = dlsch0->harq_ids[frame%2][subframe_offset];
-    if(harq_pid >= dlsch0->Mdlharq) {
-      LOG_E(PHY,"illegal harq_pid %d\n", harq_pid);
+    if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
+      LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
       return(-1);
     }
     dlsch0_harq = dlsch0->harq_processes[harq_pid];
@@ -2278,8 +2278,8 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
   }else if ((dlsch0 != NULL) && (dlsch1 == NULL)){
 
     harq_pid = dlsch0->harq_ids[frame%2][subframe_offset];
-    if(harq_pid >= dlsch0->Mdlharq) {
-      LOG_E(PHY,"illegal harq_pid %d\n", harq_pid);
+    if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
+      LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
       return(-1);
     }
     dlsch0_harq = dlsch0->harq_processes[harq_pid];
@@ -2299,8 +2299,8 @@ int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
   }else if ((dlsch0 == NULL) && (dlsch1 != NULL)){
 
     harq_pid = dlsch1->harq_ids[frame%2][subframe_offset];
-    if(harq_pid >= dlsch1->Mdlharq) {
-      LOG_E(PHY,"illegal harq_pid %d\n", harq_pid);
+    if((harq_pid < 0) || (harq_pid >= dlsch1->Mdlharq)) {
+      LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
       return(-1);
     }
     dlsch1_harq = dlsch1->harq_processes[harq_pid];
diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c
index 676d753ab5d61bcf7c42f19200a5e9a57f728d05..72be96c95bfb4509bc821d8ad75346077798af02 100644
--- a/openair1/PHY/LTE_TRANSPORT/pucch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pucch.c
@@ -1063,7 +1063,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
 #endif
           }
 
-          for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) {
+          for (l2=0,l=(nsymb>>1); l < nsymb; l++,l2++) {
             stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15)     - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15))/nsymb;
             stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15))/nsymb;
             off+=2;
@@ -1092,7 +1092,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
 
 //    stat_max *= nsymb;  // normalize to energy per symbol
 //    stat_max /= (frame_parms->N_RB_UL*12); //
-    stat_max /= (nsymb*12);
+    stat_max /= 12;
     
 #ifdef DEBUG_PUCCH_RX
     printf("[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max);
@@ -1181,7 +1181,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
           stat_ref_re=0;
           stat_ref_im=0;
 
-          for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) {
+          for (l2=0,l=(nsymb>>1); l< nsymb; l++,l2++) {
             if ((l2<2) || ((l2>(nsymb>>1) - 3)) ) {  // data symbols
               stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15)     - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15);
               stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15);
diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h
index 6c1f6747886ad9225482c5764c42a317147a01b6..9e8685732f9ce36cd4ca515c673251a77ac9b786 100644
--- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h
+++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h
@@ -329,6 +329,8 @@ typedef struct {
   uint8_t     subframe;
   /// corresponding UE RNTI
   uint16_t    rnti;
+  /// UE ID from Layer2
+  uint16_t    ue_id;
   /// Type (SR, HARQ, CQI, HARQ_SR, HARQ_CQI, SR_CQI, HARQ_SR_CQI)
   UCI_type_t  type;
   /// SRS active flag
diff --git a/openair1/PHY/LTE_TRANSPORT/uci_tools.c b/openair1/PHY/LTE_TRANSPORT/uci_tools.c
index 88c652133b783bb627f708985c08c0d4004ca707..c301c8510f03f4ab7d22b50496cdf507435336de 100644
--- a/openair1/PHY/LTE_TRANSPORT/uci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/uci_tools.c
@@ -41,7 +41,7 @@ int16_t find_uci(uint16_t rnti, int frame, int subframe, PHY_VARS_eNB *eNB,find_
   uint16_t i;
   int16_t first_free_index=-1;
   AssertFatal(eNB!=NULL,"eNB is null\n");
-  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
+  for (i=0; i<NUMBER_OF_UCI_VARS_MAX; i++) {
     if ((eNB->uci_vars[i].active >0) &&
 	(eNB->uci_vars[i].rnti==rnti) &&
 	(eNB->uci_vars[i].frame==frame) &&
diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h
index f7123d6b43b72b06ce88fbd317a70174a0691162..6036928a9078fb400c0720c31b285d30b8d490d5 100644
--- a/openair1/PHY/defs_eNB.h
+++ b/openair1/PHY/defs_eNB.h
@@ -339,6 +339,8 @@ typedef struct RU_t_s{
   int north_out_cnt;
   /// flag to indicate the RU is a slave to another source
   int is_slave;
+  /// flag to indicate if the RU has to perform OTA sync
+  int ota_sync_enable;
   /// flag to indicate that the RU should generate the DMRS sequence in slot 2 (subframe 1) for OTA synchronization and calibration
   int generate_dmrs_sync;
   /// flag to indicate if the RU has a control channel
@@ -1049,7 +1051,7 @@ typedef struct PHY_VARS_eNB_s {
   LTE_eNB_PRACH        prach_vars_br;
 #endif
   LTE_eNB_COMMON       common_vars;
-  LTE_eNB_UCI          uci_vars[NUMBER_OF_UE_MAX];
+  LTE_eNB_UCI          uci_vars[NUMBER_OF_UCI_VARS_MAX];
   LTE_eNB_SRS          srs_vars[NUMBER_OF_UE_MAX];
   LTE_eNB_PBCH         pbch;
   LTE_eNB_PUSCH       *pusch_vars[NUMBER_OF_UE_MAX];
diff --git a/openair1/PHY/phy_vars.h b/openair1/PHY/phy_vars.h
index ea7d2e5033f2d87504b1dbac7aa497e5f9d85542..272ca0a9ff73928c141d565fc0d3256bb3882e08 100644
--- a/openair1/PHY/phy_vars.h
+++ b/openair1/PHY/phy_vars.h
@@ -45,6 +45,7 @@ int16_t *primary_synch2_time;
 #ifndef OCP_FRAMEWORK
 PHY_VARS_UE ***PHY_vars_UE_g;
 RAN_CONTEXT_t RC;
+UL_RCC_IND_t  UL_RCC_INFO;
 
 //PHY_VARS_eNB ***PHY_vars_eNB_g;
 //PHY_VARS_RN **PHY_vars_RN_g;
diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c
index b311149532432a4e0f1d6e09923929eedc897a05..5f8b4ec3db810495192e35e18b601322fa92db17 100644
--- a/openair1/SCHED/fapi_l1.c
+++ b/openair1/SCHED/fapi_l1.c
@@ -42,7 +42,7 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req);
 int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req);
 int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req);
 
-
+int oai_nfapi_ue_release_req(nfapi_ue_release_request_t *release_req);
 void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB *eNB,
                              int frame, int subframe,
                              L1_rxtx_proc_t *proc,
@@ -186,21 +186,11 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro
 
 #endif
   harq_pid        = dlsch0->harq_ids[proc->frame_tx%2][proc->subframe_tx];
-  AssertFatal((harq_pid>=0) && (harq_pid<8),"harq_pid %d not in 0...7 frame:%d subframe:%d subframe(TX):%d rnti:%x UE_id:%d dlsch0[harq_ids:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d]\n",
-              harq_pid,
-              frame,subframe,
-              proc->subframe_tx,rel8->rnti,UE_id,
-              dlsch0->harq_ids[proc->frame_tx%2][0],
-              dlsch0->harq_ids[proc->frame_tx%2][1],
-              dlsch0->harq_ids[proc->frame_tx%2][2],
-              dlsch0->harq_ids[proc->frame_tx%2][3],
-              dlsch0->harq_ids[proc->frame_tx%2][4],
-              dlsch0->harq_ids[proc->frame_tx%2][5],
-              dlsch0->harq_ids[proc->frame_tx%2][6],
-              dlsch0->harq_ids[proc->frame_tx%2][7],
-              dlsch0->harq_ids[proc->frame_tx%2][8],
-              dlsch0->harq_ids[proc->frame_tx%2][9]
-             );
+  if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
+    LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
+    return;
+  }
+
   dlsch0_harq     = dlsch0->harq_processes[harq_pid];
   dlsch1_harq     = dlsch1->harq_processes[harq_pid];
   AssertFatal(dlsch0_harq!=NULL,"dlsch_harq is null\n");
@@ -588,6 +578,7 @@ void handle_uci_sr_pdu(PHY_VARS_eNB *eNB,
   uci->frame               = frame;
   uci->subframe            = subframe;
   uci->rnti                = ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti;
+  uci->ue_id               = find_dlsch(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE);
   uci->type                = SR;
   uci->pucch_fmt           = pucch_format1;
   uci->num_antenna_ports   = 1;
@@ -615,6 +606,7 @@ void handle_uci_sr_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_
   uci->frame               = frame;
   uci->subframe            = subframe;
   uci->rnti                = ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti;
+  uci->ue_id               = find_dlsch(ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE);
   uci->type                = HARQ_SR;
   uci->num_antenna_ports   = 1;
   uci->num_pucch_resources = 1;
@@ -638,6 +630,7 @@ void handle_uci_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu
   uci->frame             = frame;
   uci->subframe          = subframe;
   uci->rnti              = ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti;
+  uci->ue_id             = find_dlsch(ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE);
   uci->type              = HARQ;
   uci->srs_active        = srs_active;
   uci->num_antenna_ports = ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel11.num_ant_ports;
@@ -809,7 +802,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
     harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
 
     // clear DCI allocation maps for new subframe
-
+    if (NFAPI_MODE!=NFAPI_MODE_VNF)
     for (i=0; i<NUMBER_OF_UE_MAX; i++) {
       if (eNB->ulsch[i]) {
         ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid];
@@ -825,7 +818,8 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
     //LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_config_pdu->pdu_type);
     switch (dl_config_pdu->pdu_type) {
       case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE:
-        handle_nfapi_dci_dl_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu);
+        if (NFAPI_MODE!=NFAPI_MODE_VNF)
+          handle_nfapi_dci_dl_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu);
         eNB->pdcch_vars[NFAPI_SFNSF2SF(DL_req->sfn_sf)&1].num_dci++;
         //LOG_E(PHY,"Incremented num_dci:%d but already set??? dl_config:num_dci:%d\n", eNB->pdcch_vars[subframe&1].num_dci, number_dci);
         do_oai=1;
@@ -840,7 +834,8 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
         do_oai=1;
         //LOG_D(PHY,"%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE TX:%d/%d RX:%d/%d TXREQ:%d/%d\n",
         //__FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->frame_rx, proc->subframe_rx, NFAPI_SFNSF2SFN(TX_req->sfn_sf), NFAPI_SFNSF2SF(TX_req->sfn_sf));
-        handle_nfapi_bch_pdu(eNB,proc,dl_config_pdu,
+        if (NFAPI_MODE!=NFAPI_MODE_VNF)
+          handle_nfapi_bch_pdu(eNB,proc,dl_config_pdu,
                              TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index].segments[0].segment_data);
         break;
 
@@ -872,7 +867,8 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
                     dlsch_pdu_rel8->transport_blocks);
 
         if (1) { //sdu != NULL)
-          handle_nfapi_dlsch_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu, dlsch_pdu_rel8->transport_blocks-1, sdu);
+            if (NFAPI_MODE!=NFAPI_MODE_VNF)
+              handle_nfapi_dlsch_pdu(eNB,NFAPI_SFNSF2SFN(DL_req->sfn_sf),NFAPI_SFNSF2SF(DL_req->sfn_sf),proc,dl_config_pdu, dlsch_pdu_rel8->transport_blocks-1, sdu);
         } else {
           dont_send=1;
           LOG_E(MAC,"%s() NFAPI_DL_CONFIG_DLSCH_PDU_TYPE sdu is NULL DL_CFG:SFN/SF:%d:pdu_index:%d TX_REQ:SFN/SF:%d:pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(DL_req->sfn_sf), pdu_index,
@@ -913,7 +909,8 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
 #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
 
       case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE:
-        handle_nfapi_mpdcch_pdu(eNB,proc,dl_config_pdu);
+        if (NFAPI_MODE!=NFAPI_MODE_VNF)
+          handle_nfapi_mpdcch_pdu(eNB,proc,dl_config_pdu);
         eNB->mpdcch_vars[subframe&1].num_dci++;
         break;
 #endif
@@ -921,16 +918,24 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
   }
 
   if ((NFAPI_MODE!=NFAPI_MONOLITHIC) && do_oai && !dont_send) {
-    oai_nfapi_tx_req(Sched_INFO->TX_req);
+    if(Sched_INFO->TX_req->tx_request_body.number_of_pdus > 0){
+      Sched_INFO->TX_req->sfn_sf = frame << 4 | subframe;
+      oai_nfapi_tx_req(Sched_INFO->TX_req);
+    }
+    Sched_INFO->DL_req->sfn_sf = frame << 4 | subframe;
     oai_nfapi_dl_config_req(Sched_INFO->DL_req); // DJP - .dl_config_request_body.dl_config_pdu_list[0]); // DJP - FIXME TODO - yuk - only copes with 1 pdu
+    Sched_INFO->UE_release_req->sfn_sf = frame << 4 | subframe;
+    oai_nfapi_ue_release_req(Sched_INFO->UE_release_req);
   }
 
   if ((NFAPI_MODE!=NFAPI_MONOLITHIC) && number_hi_dci0_pdu!=0) {
+    HI_DCI0_req->sfn_sf = frame << 4 | subframe;
     oai_nfapi_hi_dci0_req(HI_DCI0_req);
     eNB->pdcch_vars[NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf)&1].num_dci=0;
     eNB->pdcch_vars[NFAPI_SFNSF2SF(HI_DCI0_req->sfn_sf)&1].num_pdcch_symbols=0;
   }
 
+if (NFAPI_MODE!=NFAPI_MODE_VNF)
   for (i=0; i<number_hi_dci0_pdu; i++) {
     hi_dci0_req_pdu = &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[i];
     LOG_D(PHY,"NFAPI: hi_dci0_pdu %d : type %d\n",i,hi_dci0_req_pdu->pdu_type);
@@ -955,6 +960,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
   if (NFAPI_MODE!=NFAPI_MONOLITHIC) {
     if (number_ul_pdu>0) {
       //LOG_D(PHY, "UL_CONFIG to send to PNF\n");
+      UL_req->sfn_sf = frame << 4 | subframe;
       oai_nfapi_ul_config_req(UL_req);
       UL_req->ul_config_request_body.number_of_pdus=0;
       number_ul_pdu=0;
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 28dd38b65a1c2a9d803d1fae7813f109c409aa5a..f5a724e39c8e7bc5621f457ac0c116332140d958 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -47,8 +47,7 @@
 
 #include "intertask_interface.h"
 
-
-
+nfapi_ue_release_request_body_t release_rntis;
 
 int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t UE_id,uint8_t harq_pid, uint8_t bw_factor) {
   uint32_t Nre,sumKr,MPR_x100,Kr,r;
@@ -230,13 +229,11 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
 
 
 
-void pdsch_procedures(PHY_VARS_eNB *eNB,
+bool dlsch_procedures(PHY_VARS_eNB *eNB,
                       L1_rxtx_proc_t *proc,
                       int harq_pid,
                       LTE_eNB_DLSCH_t *dlsch,
-                      LTE_eNB_DLSCH_t *dlsch1,
-                      LTE_eNB_UE_stats *ue_stats,
-                      int ra_flag) {
+                      LTE_eNB_UE_stats *ue_stats) {
   int frame=proc->frame_tx;
   int subframe=proc->subframe_tx;
   LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
@@ -265,27 +262,6 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,
           dlsch_harq->round);
   }
 
-  MSC_LOG_TX_MESSAGE(
-    MSC_PHY_ENB,MSC_PHY_UE,
-    NULL,0,
-    "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", TBS %"PRIu16", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")",
-    frame, subframe,
-    dlsch_harq->TBS/8,
-    get_G(fp,
-          dlsch_harq->nb_rb,
-          dlsch_harq->rb_alloc,
-          dlsch_harq->Qm,
-          dlsch_harq->Nl,
-          dlsch_harq->pdsch_start,
-          frame,
-          subframe,
-          dlsch_harq->mimo_mode==TM7?7:0),
-    dlsch_harq->nb_rb,
-    dlsch_harq->TBS,
-    pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
-    dlsch_harq->rvidx,
-    dlsch_harq->round);
-
   if (ue_stats) ue_stats->dlsch_sliding_cnt++;
 
   if (dlsch_harq->round == 0) {
@@ -300,15 +276,17 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,
 #endif
   }
 
-  if (dlsch->rnti!=0xffff) LOG_D(PHY,"Generating DLSCH/PDSCH pdu:%p pdsch_start:%d frame:%d subframe:%d nb_rb:%d rb_alloc:%d Qm:%d Nl:%d round:%d\n",
-                                   dlsch_harq->pdu,dlsch_harq->pdsch_start,frame,subframe,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0],dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round);
+  if (dlsch->rnti!=0xffff)
+    LOG_D(PHY,"Generating DLSCH/PDSCH pdu:%p pdsch_start:%d frame:%d subframe:%d nb_rb:%d rb_alloc:%d Qm:%d Nl:%d round:%d\n",
+	  dlsch_harq->pdu,dlsch_harq->pdsch_start,frame,subframe,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0],
+	  dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round);
 
   // 36-212
   if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // monolthic OR PNF - do not need turbo encoding on VNF
     if (dlsch_harq->pdu==NULL) {
       LOG_E(PHY,"dlsch_harq->pdu == NULL SFN/SF:%04d%d dlsch[rnti:%x] dlsch_harq[pdu:%p pdsch_start:%d Qm:%d Nl:%d round:%d nb_rb:%d rb_alloc[0]:%d]\n", frame,subframe,dlsch->rnti, dlsch_harq->pdu,
             dlsch_harq->pdsch_start,dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0]);
-      return;
+      return false;
     }
 
     start_meas(&eNB->dlsch_encoding_stats);
@@ -330,44 +308,57 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,
     if(eNB->dlsch_encoding_stats.p_time>500*3000 && opp_enabled == 1) {
       print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr);
     }
-
-    // 36-211
-    start_meas(&eNB->dlsch_scrambling_stats);
-    dlsch_scrambling(fp,
-                     0,
-                     dlsch,
-                     harq_pid,
-                     get_G(fp,
-                           dlsch_harq->nb_rb,
-                           dlsch_harq->rb_alloc,
-                           dlsch_harq->Qm,
-                           dlsch_harq->Nl,
-                           dlsch_harq->pdsch_start,
-                           frame,subframe,
-                           0),
-                     0,
-                     frame,
-                     subframe<<1);
-    stop_meas(&eNB->dlsch_scrambling_stats);
-    start_meas(&eNB->dlsch_modulation_stats);
-    dlsch_modulation(eNB,
-                     eNB->common_vars.txdataF,
-                     AMP,
-                     frame,
-                     subframe,
-                     dlsch_harq->pdsch_start,
-                     dlsch,
-                     dlsch->ue_type==0 ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL);
-    stop_meas(&eNB->dlsch_modulation_stats);
-  }
-
 #ifdef PHY_TX_THREAD
-  dlsch->active[subframe] = 0;
+    dlsch->active[subframe] = 0;
 #else
-  dlsch->active = 0;
+    dlsch->active = 0;
 #endif
-  dlsch_harq->round++;
-  LOG_D(PHY,"Generating DLSCH/PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
+    dlsch_harq->round++;
+    LOG_D(PHY,"Generated DLSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
+    return true;
+  }
+  return false;
+}
+
+void pdsch_procedures(PHY_VARS_eNB *eNB,
+                      L1_rxtx_proc_t *proc,
+                      int harq_pid,
+                      LTE_eNB_DLSCH_t *dlsch,
+                      LTE_eNB_DLSCH_t *dlsch1) {
+  int frame=proc->frame_tx;
+  int subframe=proc->subframe_tx;
+  LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
+  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
+  // 36-211
+  start_meas(&eNB->dlsch_scrambling_stats);
+  dlsch_scrambling(fp,
+		   0,
+		   dlsch,
+		   harq_pid,
+		   get_G(fp,
+			 dlsch_harq->nb_rb,
+			 dlsch_harq->rb_alloc,
+			 dlsch_harq->Qm,
+			 dlsch_harq->Nl,
+			 dlsch_harq->pdsch_start,
+			 frame,subframe,
+			 0),
+		   0,
+		   frame,
+		   subframe<<1);
+  stop_meas(&eNB->dlsch_scrambling_stats);
+  start_meas(&eNB->dlsch_modulation_stats);
+  dlsch_modulation(eNB,
+		   eNB->common_vars.txdataF,
+		   AMP,
+		   frame,
+		   subframe,
+		   dlsch_harq->pdsch_start,
+		   dlsch,
+		   dlsch->ue_type==0 ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL);
+  stop_meas(&eNB->dlsch_modulation_stats);
+
+  LOG_D(PHY,"Generated PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
 }
 
 
@@ -467,6 +458,11 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols);
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME (VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO, (frame * 10) + subframe);
 
+  if (num_pdcch_symbols == 0){
+    LOG_E(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %"PRIu8") num_pdcch_symbols:%d\n",eNB->Mod_id,frame, subframe, num_dci, num_pdcch_symbols);
+    return;
+  }
+
   if (num_dci > 0)
     LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %"PRIu8") num_pdcch_symbols:%d\n",eNB->Mod_id,frame, subframe, num_dci, num_pdcch_symbols);
 
@@ -514,9 +510,9 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
        ) {
       // get harq_pid
       harq_pid = dlsch0->harq_ids[frame%2][subframe];
-      AssertFatal(harq_pid>=0,"harq_pid is negative\n");
+	//AssertFatal(harq_pid>=0,"harq_pid is negative\n");
 
-      if (harq_pid>=8) {
+        if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
 #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
 
         if (dlsch0->ue_type==0)
@@ -531,14 +527,18 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
                 dlsch0->harq_ids[frame%2][6],
                 dlsch0->harq_ids[frame%2][7]);
       } else {
-        // generate pdsch
-        pdsch_procedures(eNB,
+	if (dlsch_procedures(eNB,
                          proc,
                          harq_pid,
                          dlsch0,
-                         dlsch1,
-                         &eNB->UE_stats[(uint32_t)UE_id],
-                         0);
+                         &eNB->UE_stats[(uint32_t)UE_id])) {
+	  // if we generate dlsch, we must generate pdsch
+	  pdsch_procedures(eNB,
+			   proc,
+			   harq_pid,
+			   dlsch0,
+			   dlsch1);
+	}
       }
     } else if ((dlsch0)&&(dlsch0->rnti>0)&&
 #ifdef PHY_TX_THREAD
@@ -601,7 +601,7 @@ void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,u
   //  pdu->rx_ue_information.handle                       = handle;
   pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
   pdu->rx_ue_information.rnti                         = rnti;
-  int SNRtimes10 = dB_fixed_times10(stat) - 300;//(10*eNB->measurements.n0_power_dB[0]);
+  int SNRtimes10 = dB_fixed_times10(stat) - 10 * eNB->measurements.n0_subband_power_dB[0][0];
   pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
 
   if      (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0;
@@ -634,7 +634,7 @@ uci_procedures(PHY_VARS_eNB *eNB,
   LTE_eNB_UCI *uci = NULL;
   LTE_DL_FRAME_PARMS *fp = &(eNB->frame_parms);
 
-  for (int i = 0; i < NUMBER_OF_UE_MAX; i++) {
+  for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) {
     uci = &(eNB->uci_vars[i]);
 
     if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) {
@@ -682,7 +682,7 @@ uci_procedures(PHY_VARS_eNB *eNB,
           int pucch1_thres = (uci->ue_type == 0) ? eNB->pucch1_DTX_threshold : eNB->pucch1_DTX_threshold_emtc[0];
           metric_SR = rx_pucch(eNB,
                                uci->pucch_fmt,
-                               i,
+                               uci->ue_id,
                                uci->n_pucch_1_0_sr[0],
                                0, // n2_pucch
                                uci->srs_active, // shortened format
@@ -724,7 +724,7 @@ uci_procedures(PHY_VARS_eNB *eNB,
                   SR_payload);
             metric[0] = rx_pucch(eNB,
                                  uci->pucch_fmt,
-                                 i,
+                                 uci->ue_id,
                                  uci->n_pucch_1[0][0],
                                  0, //n2_pucch
                                  uci->srs_active, // shortened format
@@ -748,7 +748,7 @@ uci_procedures(PHY_VARS_eNB *eNB,
               SR_payload = 1;
               metric[0]=rx_pucch(eNB,
                                  uci->pucch_fmt,
-                                 i,
+                                 uci->ue_id,
                                  uci->n_pucch_1_0_sr[0],
                                  0, //n2_pucch
                                  uci->srs_active, // shortened format
@@ -778,7 +778,7 @@ uci_procedures(PHY_VARS_eNB *eNB,
 #if 1
             metric[0] = rx_pucch(eNB,
                                  uci->pucch_fmt,
-                                 i,
+                                 uci->ue_id,
                                  uci->n_pucch_1[0][0],
                                  0, //n2_pucch
                                  uci->srs_active, // shortened format
@@ -798,7 +798,7 @@ uci_procedures(PHY_VARS_eNB *eNB,
               SR_payload = 1;
               metric[0] = rx_pucch(eNB,
                                    pucch_format1b,
-                                   i,
+                                   uci->ue_id,
                                    uci->n_pucch_1_0_sr[0],
                                    0, //n2_pucch
                                    uci->srs_active, // shortened format
@@ -1136,11 +1136,11 @@ uci_procedures(PHY_VARS_eNB *eNB,
           if (SR_payload == 1) {
             LOG_D (PHY, "[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n", eNB->Mod_id, uci->rnti, frame, subframe);
 
-            if (eNB->first_sr[i] == 1) {    // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
-              eNB->first_sr[i] = 0;
-              eNB->dlsch[i][0]->harq_processes[0]->round = 0;
-              eNB->dlsch[i][0]->harq_processes[0]->status = SCH_IDLE;
-              LOG_D (PHY, "[eNB %d][SR %x] Frame %d subframe %d First SR\n", eNB->Mod_id, eNB->ulsch[i]->rnti, frame, subframe);
+            if (eNB->first_sr[uci->ue_id] == 1) {    // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
+              eNB->first_sr[uci->ue_id] = 0;
+              eNB->dlsch[uci->ue_id][0]->harq_processes[0]->round = 0;
+              eNB->dlsch[uci->ue_id][0]->harq_processes[0]->status = SCH_IDLE;
+              LOG_D (PHY, "[eNB %d][SR %x] Frame %d subframe %d First SR\n", eNB->Mod_id, eNB->ulsch[uci->ue_id]->rnti, frame, subframe);
             }
           }
       }
@@ -1463,7 +1463,7 @@ void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe) {
 
   pdu->rx_indication_rel8.timing_advance = timing_advance_update;
   // estimate UL_CQI for MAC (from antenna port 0 only)
-  int SNRtimes10 = dB_fixed_times10(eNB->pusch_vars[UE_id]->ulsch_power[0]) - 300;//(10*eNB->measurements.n0_power_dB[0]);
+  int SNRtimes10 = dB_fixed_times10(eNB->pusch_vars[UE_id]->ulsch_power[0]) - 10 * eNB->measurements.n0_subband_power_dB[0][0];
 
   if (SNRtimes10 < -640)
     pdu->rx_indication_rel8.ul_cqi = 0;
@@ -1516,8 +1516,10 @@ static void do_release_harq(PHY_VARS_eNB *eNB,
 
     harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];
 
-    AssertFatal((harq_pid >= 0) && (harq_pid < 8),"harq_pid %d not in 0...7\n", harq_pid);
-
+    if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
+      LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
+      return;
+    }
     dlsch0_harq = dlsch0->harq_processes[harq_pid];
     dlsch1_harq = dlsch1->harq_processes[harq_pid];
     
@@ -1566,37 +1568,39 @@ static void do_release_harq(PHY_VARS_eNB *eNB,
       if (((1 << m) & mask) > 0) {
         harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];
 
-        if ((harq_pid >= 0) && (harq_pid < dlsch0->Mdlharq)) {
-          dlsch0_harq = dlsch0->harq_processes[harq_pid];
-          dlsch1_harq = dlsch1->harq_processes[harq_pid];
+        if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
+          LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
+          return;
+        }
+        dlsch0_harq = dlsch0->harq_processes[harq_pid];
+        dlsch1_harq = dlsch1->harq_processes[harq_pid];
 
-          AssertFatal(dlsch0_harq != NULL, "Dlsch0_harq is null\n");
+        AssertFatal(dlsch0_harq != NULL, "Dlsch0_harq is null\n");
 
 #if T_TRACER
-          if (after_rounds != -1) {
-            T(T_ENB_PHY_DLSCH_UE_NACK,
-              T_INT(0),
-              T_INT(frame),
-              T_INT(subframe),
-              T_INT(dlsch0->rnti),
-              T_INT(harq_pid));
-          } else {
-            T(T_ENB_PHY_DLSCH_UE_ACK,
-              T_INT(0),
-              T_INT(frame),
-              T_INT(subframe),
-              T_INT(dlsch0->rnti),
-              T_INT(harq_pid));
-          }
+        if (after_rounds != -1) {
+          T(T_ENB_PHY_DLSCH_UE_NACK,
+            T_INT(0),
+            T_INT(frame),
+            T_INT(subframe),
+            T_INT(dlsch0->rnti),
+            T_INT(harq_pid));
+        } else {
+          T(T_ENB_PHY_DLSCH_UE_ACK,
+            T_INT(0),
+            T_INT(frame),
+            T_INT(subframe),
+            T_INT(dlsch0->rnti),
+            T_INT(harq_pid));
+        }
 #endif
-          if (dlsch0_harq->round >= after_rounds) {
-            dlsch0_harq->status = SCH_IDLE;
+        if (dlsch0_harq->round >= after_rounds) {
+          dlsch0_harq->status = SCH_IDLE;
 
-            if ((dlsch1_harq == NULL) || ((dlsch1_harq != NULL) && (dlsch1_harq->status == SCH_IDLE))) {
-              dlsch0->harq_mask &= ~(1 << harq_pid);
-            }
+          if ((dlsch1_harq == NULL) || ((dlsch1_harq != NULL) && (dlsch1_harq->status == SCH_IDLE))) {
+            dlsch0->harq_mask &= ~(1 << harq_pid);
           }
-	    } // end if ((harq_pid >= 0) && (harq_pid < dlsch0->Mdlharq))
+        }
       } // end if (((1 << m) & mask) > 0)
     } // end for (int m=0; m < M; m++)
   } // end if TDD
@@ -1635,7 +1639,7 @@ int getM(PHY_VARS_eNB *eNB,int frame,int subframe) {
 
     harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];
 
-    if (harq_pid>=0 && harq_pid<10) {
+    if (harq_pid>=0 && harq_pid<dlsch0->Mdlharq) {
       dlsch0_harq     = dlsch0->harq_processes[harq_pid];
       dlsch1_harq     = dlsch1->harq_processes[harq_pid];
       AssertFatal(dlsch0_harq!=NULL,"dlsch0_harq is null\n");
@@ -1651,8 +1655,9 @@ int getM(PHY_VARS_eNB *eNB,int frame,int subframe) {
 
 void fill_ulsch_cqi_indication (PHY_VARS_eNB *eNB, uint16_t frame, uint8_t subframe, LTE_UL_eNB_HARQ_t *ulsch_harq, uint16_t rnti) {
   pthread_mutex_lock (&eNB->UL_INFO_mutex);
-  nfapi_cqi_indication_pdu_t *pdu = &eNB->UL_INFO.cqi_ind.cqi_pdu_list[eNB->UL_INFO.cqi_ind.number_of_cqis];
-  nfapi_cqi_indication_raw_pdu_t *raw_pdu = &eNB->UL_INFO.cqi_ind.cqi_raw_pdu_list[eNB->UL_INFO.cqi_ind.number_of_cqis];
+  nfapi_cqi_indication_pdu_t *pdu         = &eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_pdu_list[eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis];
+  nfapi_cqi_indication_raw_pdu_t *raw_pdu = &eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_raw_pdu_list[eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis];
+  pdu->instance_length = 0;
   pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
   pdu->rx_ue_information.rnti = rnti;
 
@@ -1678,9 +1683,11 @@ void fill_ulsch_cqi_indication (PHY_VARS_eNB *eNB, uint16_t frame, uint8_t subfr
 
   pdu->cqi_indication_rel9.number_of_cc_reported = 1;
   pdu->ul_cqi_information.channel = 1;  // PUSCH
+  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
   memcpy ((void *) raw_pdu->pdu, ulsch_harq->o, pdu->cqi_indication_rel9.length);
-  eNB->UL_INFO.cqi_ind.number_of_cqis++;
-  LOG_D(PHY,"eNB->UL_INFO.cqi_ind.number_of_cqis:%d\n", eNB->UL_INFO.cqi_ind.number_of_cqis);
+  eNB->UL_INFO.cqi_ind.cqi_indication_body.tl.tag = NFAPI_CQI_INDICATION_BODY_TAG;
+  eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis++;
+  LOG_D(PHY,"eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis:%d\n", eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis);
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
 }
 
@@ -1769,7 +1776,7 @@ void fill_uci_harq_indication (PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, i
   pdu->rx_ue_information.rnti                         = uci->rnti;
   // estimate UL_CQI for MAC (from antenna port 0 only)
   pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
-  int SNRtimes10 = dB_fixed_times10(uci->stat) - 300;//(10*eNB->measurements.n0_power_dB[0]);
+  int SNRtimes10 = dB_fixed_times10(uci->stat) - 10 * eNB->measurements.n0_subband_power_dB[0][0];
 
   if (SNRtimes10 < -100)
     LOG_I (PHY, "uci->stat %d \n", uci->stat);
@@ -1997,3 +2004,44 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 );
 }
+
+void release_rnti_of_phy(module_id_t mod_id){
+    int i,j;
+    int CC_id;
+    rnti_t rnti;
+    PHY_VARS_eNB *eNB_PHY = NULL;
+    LTE_eNB_ULSCH_t *ulsch = NULL;
+    LTE_eNB_DLSCH_t *dlsch = NULL;
+    for(i = 0; i< release_rntis.number_of_TLVs;i++){
+        for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
+          eNB_PHY = RC.eNB[mod_id][CC_id];
+          rnti = release_rntis.ue_release_request_TLVs_list[i].rnti;
+          for (j=0; j<NUMBER_OF_UE_MAX; j++) {
+              ulsch = eNB_PHY->ulsch[j];
+              if((ulsch != NULL) && (ulsch->rnti == rnti)){
+                LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti);
+                clean_eNb_ulsch(ulsch);
+              }
+
+              dlsch = eNB_PHY->dlsch[j][0];
+              if((dlsch != NULL) && (dlsch->rnti == rnti)){
+                LOG_I(PHY, "clean_eNb_dlsch dlsch[%d] UE %x \n", j, rnti);
+                clean_eNb_dlsch(dlsch);
+              }
+          }
+          ulsch = eNB_PHY->ulsch[j];
+          if((ulsch != NULL) && (ulsch->rnti == rnti)){
+            LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti);
+            clean_eNb_ulsch(ulsch);
+          }
+          for(j=0; j<NUMBER_OF_UCI_VARS_MAX; j++) {
+              if(eNB_PHY->uci_vars[j].rnti == rnti){
+                LOG_I(PHY, "clean eNb uci_vars[%d] UE %x \n",j, rnti);
+                memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI));
+              }
+
+          }
+        }
+    }
+    memset(&release_rntis, 0, sizeof(nfapi_ue_release_request_body_t));
+}
diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c
index 928b272edd6e6f43e98d1315f562531dc30c9d2f..1f1a36b238eb8a09d847a0eaf009155575e9e18d 100644
--- a/openair1/SCHED/ru_procedures.c
+++ b/openair1/SCHED/ru_procedures.c
@@ -100,7 +100,7 @@ void feptx0(RU_t *ru,int slot) {
 */
       int num_symb = 7;
 
-      if (subframe_select(fp,subframe) == SF_S) num_symb=fp->dl_symbols_in_S_subframe;
+      if (subframe_select(fp,subframe) == SF_S) num_symb=fp->dl_symbols_in_S_subframe+1;
    
       if (ru->generate_dmrs_sync == 1 && slot == 0 && subframe == 1 && aa==0) {
 	//int32_t dmrs[ru->frame_parms.ofdm_symbol_size*14] __attribute__((aligned(32)));
diff --git a/openair1/SCHED/sched_eNB.h b/openair1/SCHED/sched_eNB.h
index dccfbf7c388ac204771e391eaa1044cffea9e4cd..7fcabdc5ddf8163b063edc655cdca442a0f0617c 100644
--- a/openair1/SCHED/sched_eNB.h
+++ b/openair1/SCHED/sched_eNB.h
@@ -219,6 +219,7 @@ int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subf
 
 void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset);
 
+void release_rnti_of_phy(module_id_t mod_id);
 /*@}*/
 
 
diff --git a/openair1/SIMULATION/LTE_PHY/dummy_functions.c b/openair1/SIMULATION/LTE_PHY/dummy_functions.c
index 7f5fa1fb75f42609e973948fb4805d122acbdf75..d3c6381d72ff863c25b5c8cee01d71db5af8a16c 100644
--- a/openair1/SIMULATION/LTE_PHY/dummy_functions.c
+++ b/openair1/SIMULATION/LTE_PHY/dummy_functions.c
@@ -91,5 +91,5 @@ int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { return(0);}
 int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { return(0); }
 
 int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); }
-
+int oai_nfapi_ue_release_req(nfapi_ue_release_request_t *release_req){ return(0); }
 int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); }
diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c
index df6781cea24d1dec9dced771a23ead9b958b5629..a90d1995261e13f7d5e71695cd441ba7859ea354 100644
--- a/openair1/SIMULATION/LTE_PHY/ulsim.c
+++ b/openair1/SIMULATION/LTE_PHY/ulsim.c
@@ -618,8 +618,8 @@ int main(int argc, char **argv) {
   eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = eNB->crc_pdu_list;
   eNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = eNB->sr_pdu_list;
   eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list;
-  eNB->UL_INFO.cqi_ind.cqi_pdu_list = eNB->cqi_pdu_list;
-  eNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list;
+  eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_pdu_list = eNB->cqi_pdu_list;
+  eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list;
   printf("lte_param_init done\n");
   // for a call to phy_reset_ue later we need PHY_vars_UE_g allocated and pointing to UE
   PHY_vars_UE_g = (PHY_VARS_UE ** *)malloc(sizeof(PHY_VARS_UE **));
diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c
index 8341c574da2968b8a361cdc82c3801bf8a91b998..f056d51b5d3c49a55a71e058ec2b061f2f911022 100644
--- a/openair1/SIMULATION/TOOLS/random_channel.c
+++ b/openair1/SIMULATION/TOOLS/random_channel.c
@@ -1204,6 +1204,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
   return(chan_desc);
 }
 
+void free_channel_desc_scm(channel_desc_t * ch) {
+	// Must be made cleanly, a lot of leaks...
+	free(ch);
+}
 
 int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
 
diff --git a/openair2/COMMON/gtpv1_u_messages_def.h b/openair2/COMMON/gtpv1_u_messages_def.h
index 27723eec15937c7ce204bc4f4e6e9190b7505bfb..1948f1596addcac0e9a3a865791b4f67362a60a1 100644
--- a/openair2/COMMON/gtpv1_u_messages_def.h
+++ b/openair2/COMMON/gtpv1_u_messages_def.h
@@ -25,4 +25,8 @@ MESSAGE_DEF(GTPV1U_ENB_DELETE_TUNNEL_REQ,   MESSAGE_PRIORITY_MED, gtpv1u_enb_del
 MESSAGE_DEF(GTPV1U_ENB_DELETE_TUNNEL_RESP,  MESSAGE_PRIORITY_MED, gtpv1u_enb_delete_tunnel_resp_t, Gtpv1uDeleteTunnelResp)
 MESSAGE_DEF(GTPV1U_ENB_TUNNEL_DATA_IND,     MESSAGE_PRIORITY_MED, gtpv1u_enb_tunnel_data_ind_t,    Gtpv1uTunnelDataInd)
 MESSAGE_DEF(GTPV1U_ENB_TUNNEL_DATA_REQ,     MESSAGE_PRIORITY_MED, gtpv1u_enb_tunnel_data_req_t,    Gtpv1uTunnelDataReq)
+MESSAGE_DEF(GTPV1U_ENB_DATA_FORWARDING_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_data_forwarding_req_t,Gtpv1uDataForwardingReq)
+MESSAGE_DEF(GTPV1U_ENB_DATA_FORWARDING_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_data_forwarding_ind_t,Gtpv1uDataForwardingInd)
+MESSAGE_DEF(GTPV1U_ENB_END_MARKER_REQ,      MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_req_t,    Gtpv1uEndMarkerReq)
+MESSAGE_DEF(GTPV1U_ENB_END_MARKER_IND,      MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_ind_t,    Gtpv1uEndMarkerInd)
 MESSAGE_DEF(GTPV1U_ENB_S1_REQ,        MESSAGE_PRIORITY_MED, Gtpv1uS1Req,    gtpv1uS1Req)
diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h
index c398b55e3ef2fc40d2bb21946c0d9fb68ff2751b..4f81c22fb0bee322e307222890e6ff51c456ddb8 100644
--- a/openair2/COMMON/gtpv1_u_messages_types.h
+++ b/openair2/COMMON/gtpv1_u_messages_types.h
@@ -33,10 +33,33 @@
 #define GTPV1U_ENB_DELETE_TUNNEL_RESP(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uDeleteTunnelResp
 #define GTPV1U_ENB_TUNNEL_DATA_IND(mSGpTR)    (mSGpTR)->ittiMsg.Gtpv1uTunnelDataInd
 #define GTPV1U_ENB_TUNNEL_DATA_REQ(mSGpTR)    (mSGpTR)->ittiMsg.Gtpv1uTunnelDataReq
+#define GTPV1U_ENB_DATA_FORWARDING_REQ(mSGpTR)    (mSGpTR)->ittiMsg.Gtpv1uDataForwardingReq
+#define GTPV1U_ENB_DATA_FORWARDING_IND(mSGpTR)    (mSGpTR)->ittiMsg.Gtpv1uDataForwardingInd
+#define GTPV1U_ENB_END_MARKER_REQ(mSGpTR)     (mSGpTR)->ittiMsg.Gtpv1uEndMarkerReq
+#define GTPV1U_ENB_END_MARKER_IND(mSGpTR)     (mSGpTR)->ittiMsg.Gtpv1uEndMarkerInd
+
 #define GTPV1U_ENB_S1_REQ(mSGpTR)    (mSGpTR)->ittiMsg.gtpv1uS1Req
 
 #define GTPV1U_ALL_TUNNELS_TEID (teid_t)0xFFFFFFFF
 
+typedef struct gtpv1u_enb_create_x2u_tunnel_req_s {
+  rnti_t                 rnti;
+  int                    num_tunnels;
+  teid_t                 tenb_X2u_teid[GTPV1U_MAX_BEARERS_PER_UE];  ///< Tunnel Endpoint Identifier
+  ebi_t                  eps_bearer_id[GTPV1U_MAX_BEARERS_PER_UE];
+  transport_layer_addr_t enb_addr[GTPV1U_MAX_BEARERS_PER_UE];
+} gtpv1u_enb_create_x2u_tunnel_req_t;
+
+typedef struct gtpv1u_enb_create_x2u_tunnel_resp_s {
+  uint8_t                status;               ///< Status of S1U endpoint creation (Failed = 0xFF or Success = 0x0)
+  rnti_t                 rnti;
+  int                    num_tunnels;
+  teid_t                 enb_X2u_teid[GTPV1U_MAX_BEARERS_PER_UE];  ///< Tunnel Endpoint Identifier
+  ebi_t                  eps_bearer_id[GTPV1U_MAX_BEARERS_PER_UE];
+  transport_layer_addr_t enb_addr;
+} gtpv1u_enb_create_x2u_tunnel_resp_t;
+
+
 typedef struct gtpv1u_enb_create_tunnel_req_s {
   rnti_t                 rnti;
   int                    num_tunnels;
@@ -99,6 +122,50 @@ typedef struct gtpv1u_enb_tunnel_data_req_s {
   rb_id_t                rab_id;
 } gtpv1u_enb_tunnel_data_req_t;
 
+typedef struct gtpv1u_enb_data_forwarding_req_s {
+  uint8_t               *buffer;
+  uint32_t               length;
+  uint32_t               offset;               ///< start of message offset in buffer
+  rnti_t                 rnti;
+  rb_id_t                rab_id;
+} gtpv1u_enb_data_forwarding_req_t;
+
+typedef struct gtpv1u_enb_data_forwarding_ind_s {
+  uint32_t 				 frame;
+  uint8_t 				 enb_flag;
+  uint32_t 				 rb_id;
+  uint32_t 				 muip;
+  uint32_t 				 confirmp;
+  uint32_t 				 sdu_size;
+  uint8_t 				 *sdu_p;
+  uint8_t 				 mode;
+  uint16_t     			 rnti;
+  uint8_t      			 module_id;
+  uint8_t 				 eNB_index;
+} gtpv1u_enb_data_forwarding_ind_t;
+
+typedef struct gtpv1u_enb_end_marker_req_s {
+	  uint8_t               *buffer;
+	  uint32_t               length;
+	  uint32_t               offset;               ///< start of message offset in buffer
+	  rnti_t                 rnti;
+	  rb_id_t                rab_id;
+} gtpv1u_enb_end_marker_req_t;
+
+typedef struct gtpv1u_enb_end_marker_ind_s {
+  uint32_t 			 frame;
+  uint8_t 			 enb_flag;
+  uint32_t 			 rb_id;
+  uint32_t 			 muip;
+  uint32_t 			 confirmp;
+  uint32_t 			 sdu_size;
+  uint8_t 			 *sdu_p;
+  uint8_t 			 mode;
+  uint16_t     			 rnti;
+  uint8_t      			 module_id;
+  uint8_t 			 eNB_index;
+} gtpv1u_enb_end_marker_ind_t;
+
 typedef struct {
   in_addr_t             enb_ip_address_for_S1u_S12_S4_up;
   tcp_udp_port_t        enb_port_for_S1u_S12_S4_up;
diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h
index d284f4d0b9d8b566511c835e3bcc6645d5f5284d..5f2a95f576611df8596103ee9652e94127cb08a7 100644
--- a/openair2/COMMON/x2ap_messages_types.h
+++ b/openair2/COMMON/x2ap_messages_types.h
@@ -107,6 +107,8 @@ typedef struct x2ap_register_enb_req_s {
   lte_frame_type_t        frame_type[MAX_NUM_CCs];
   uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
   uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  uint32_t                subframeAssignment[MAX_NUM_CCs];
+  uint32_t                specialSubframe[MAX_NUM_CCs];
   int                     num_cc;
 
   /* To be considered for TDD */
@@ -205,7 +207,7 @@ typedef struct x2ap_handover_req_s {
 
   x2ap_lastvisitedcell_info_t lastvisitedcell_info;
 
-  uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
+  uint8_t rrc_buffer[8192 /* arbitrary, big enough */];
   int rrc_buffer_size;
 
   int target_assoc_id;
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 290b1c8cdf29a08cdec061d502393971f27af3e2..a957e11bcda914c7af0f860c271bfcce73f9972c 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -160,7 +160,7 @@ void RCconfig_L1(void) {
         LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_inst=1 this is because phy_init_RU() uses that to index and not RC.num_eNB - why the 2 similar variables?\n", __FUNCTION__);
         LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_CC[0]=%d for init_eNB_afterRU()\n", __FUNCTION__, RC.nb_CC[0]);
         LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_macrlc_inst:%d because used by mac_top_init_eNB()\n", __FUNCTION__, RC.nb_macrlc_inst);
-        //mac_top_init_eNB();
+        mac_top_init_eNB();
         configure_nfapi_pnf(RC.eNB[j][0]->eth_params_n.remote_addr, RC.eNB[j][0]->eth_params_n.remote_portc, RC.eNB[j][0]->eth_params_n.my_addr, RC.eNB[j][0]->eth_params_n.my_portd,
                             RC.eNB[j][0]->eth_params_n     .remote_portd);
       } else { // other midhaul
@@ -2509,6 +2509,8 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
                   X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = FDD;
                 } else  if (strcmp(ccparams_lte.frame_type, "TDD") == 0) {
                   X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD;
+                  X2AP_REGISTER_ENB_REQ (msg_p).subframeAssignment[J] = ccparams_lte.tdd_config;
+                  X2AP_REGISTER_ENB_REQ (msg_p).specialSubframe[J] = ccparams_lte.tdd_config_s;
                 } else {
                   AssertFatal (0,
                                "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n",
diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h
index 63aeee09e45afa8a0b00a4b58204d4ad1a6c734c..2caba47e2b6d77592e8ffe8cc7b79ff36fae647f 100644
--- a/openair2/ENB_APP/enb_paramdef.h
+++ b/openair2/ENB_APP/enb_paramdef.h
@@ -104,6 +104,7 @@ typedef enum {
 #define CONFIG_STRING_RU_SDR_CLK_SRC              "clock_src"
 #define CONFIG_STRING_RU_SF_EXTENSION             "sf_extension"
 #define CONFIG_STRING_RU_END_OF_BURST_DELAY       "end_of_burst_delay"
+#define CONFIG_STRING_RU_OTA_SYNC_ENABLE          "ota_sync_enabled"
 
 #define RU_LOCAL_IF_NAME_IDX          0
 #define RU_LOCAL_ADDRESS_IDX          1
@@ -128,6 +129,7 @@ typedef enum {
 #define RU_SDR_CLK_SRC                20
 #define RU_SF_EXTENSION_IDX           21
 #define RU_END_OF_BURST_DELAY_IDX     22
+#define RU_OTA_SYNC_ENABLE_IDX        23
 
 
 
@@ -153,12 +155,13 @@ typedef enum {
 {CONFIG_STRING_RU_ENB_LIST,                 	 NULL,       0,       uptr:NULL,       defintarrayval:DEFENBS,  TYPE_INTARRAY,    1}, \
 {CONFIG_STRING_RU_ATT_TX,                   	 NULL,       0,       uptr:NULL,       defintval:0,		TYPE_UINT,	  0}, \
 {CONFIG_STRING_RU_ATT_RX,                   	 NULL,       0,       uptr:NULL,       defintval:0,		TYPE_UINT,	  0}, \
-{CONFIG_STRING_RU_IS_SLAVE,                      NULL,       0,       strptr:NULL,     defstrval:"no",         TYPE_STRING,      0}, \
+{CONFIG_STRING_RU_IS_SLAVE,                      NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
 {CONFIG_STRING_RU_NBIOTRRC_LIST,                 NULL,       0,       uptr:NULL,       defintarrayval:DEFENBS,  TYPE_INTARRAY,    1}, \
 {CONFIG_STRING_RU_SDR_ADDRS,                 	 NULL,       0,       strptr:NULL,     defstrval:"type=b200",   TYPE_STRING,      0}, \
 {CONFIG_STRING_RU_SDR_CLK_SRC,               	 NULL,       0,       strptr:NULL,     defstrval:"internal",    TYPE_STRING,      0}, \
 {CONFIG_STRING_RU_SF_EXTENSION,                  NULL,       0,       uptr:NULL,       defuintval:312,          TYPE_UINT,        0}, \
 {CONFIG_STRING_RU_END_OF_BURST_DELAY,            NULL,       0,       uptr:NULL,       defuintval:400,          TYPE_UINT,        0}, \
+{CONFIG_STRING_RU_OTA_SYNC_ENABLE,               NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
 }
 
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c
index cc6751ddb13aaa6108461dc766662c36814febb4..ec2497d6ad4ffba3ea201669e375e2092cb3c854 100644
--- a/openair2/LAYER2/MAC/config.c
+++ b/openair2/LAYER2/MAC/config.c
@@ -113,22 +113,22 @@ static const eutra_bandentry_t eutra_bandtable[] = {
   {30, 23050, 23250, 23500, 23600, 97700},
   {31, 45250, 34900, 46250, 35900, 98700},
   {32, 0, 0, 14520, 14960, 99200},
-  {33, 19000, 19200, 19000, 19200, 36000},
-  {34, 20100, 20250, 20100, 20250, 36200},
-  {35, 18500, 19100, 18500, 19100, 36350},
-  {36, 19300, 19900, 19300, 19900, 36950},
-  {37, 19100, 19300, 19100, 19300, 37550},
-  {38, 25700, 26200, 25700, 26300, 37750},
-  {39, 18800, 19200, 18800, 19200, 38250},
-  {40, 23000, 24000, 23000, 24000, 38650},
-  {41, 24960, 26900, 24960, 26900, 39650},
-  {42, 34000, 36000, 34000, 36000, 41590},
-  {43, 36000, 38000, 36000, 38000, 43590},
-  {44, 7030, 8030, 7030, 8030, 45590},
-  {45, 14470, 14670, 14470, 14670, 46590},
-  {46, 51500, 59250, 51500, 59250, 46790},
-  {65, 19200, 20100, 21100, 22000, 65536},
-  {66, 17100, 18000, 21100, 22000, 66436},
+  {33, 19000, 19200, 19000, 19200, 360000},
+  {34, 20100, 20250, 20100, 20250, 362000},
+  {35, 18500, 19100, 18500, 19100, 363500},
+  {36, 19300, 19900, 19300, 19900, 369500},
+  {37, 19100, 19300, 19100, 19300, 375500},
+  {38, 25700, 26200, 25700, 26300, 377500},
+  {39, 18800, 19200, 18800, 19200, 382500},
+  {40, 23000, 24000, 23000, 24000, 386500},
+  {41, 24960, 26900, 24960, 26900, 396500},
+  {42, 34000, 36000, 34000, 36000, 415900},
+  {43, 36000, 38000, 36000, 38000, 435900},
+  {44, 7030, 8030, 7030, 8030, 455900},
+  {45, 14470, 14670, 14470, 14670, 465900},
+  {46, 51500, 59250, 51500, 59250, 467900},
+  {65, 19200, 20100, 21100, 22000, 655360},
+  {66, 17100, 18000, 21100, 22000, 664360},
   {67, 0, 0, 7380, 7580, 67336},
   {68, 6980, 7280, 7530, 7830, 67536}
 };
diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h
index 4e781e5b3f33f6873ee159b163aa8dd62dc6844f..45b46aae549a2b737b1f83dba3009dd5e4006535 100644
--- a/openair2/LAYER2/MAC/defs.h
+++ b/openair2/LAYER2/MAC/defs.h
@@ -600,10 +600,10 @@ typedef struct {
   uint32_t rbs_used_retx_rx;
   ///  total rb used for a new uplink transmission
   uint32_t total_rbs_used_rx;
-  /// normalized rx power
-  int32_t      normalized_rx_power;
-   /// target rx power
-  int32_t    target_rx_power;
+  /// snr
+  int32_t      snr;
+   /// target snr
+  int32_t    target_snr;
 
   /// num rx pdu
   uint32_t num_pdu_rx[NB_RB_MAX];
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index c6200dc74d8fd114722ba340c7c4a60aa767cf2c..3a809c4327aa4dc6d13d992db87c8ed2c0453b94 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -126,9 +126,11 @@ void schedule_SRS(module_id_t module_idP,
             continue;
           }
 
-          AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL,
-                      "physicalConfigDedicated is null for UE %d\n",
-                      UE_id);
+	      if(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) {
+	        LOG_E(MAC,"physicalConfigDedicated is null for UE %d\n",UE_id);
+	        printf("physicalConfigDedicated is null for UE %d\n",UE_id);
+	        return;
+	      }
 
           /* CDRX condition on Active Time and SRS type-0 report (36.321 5.7) */
           UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]);
@@ -462,6 +464,7 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id,
       DL_req[CC_id].dl_config_request_body.number_dci++;
       DL_req[CC_id].dl_config_request_body.number_pdu++;
       DL_req[CC_id].dl_config_request_body.tl.tag                      = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
+      DL_req[CC_id].sfn_sf = frameP<<4 | subframeP;
       LOG_D(MAC,
             "UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n",
             UE_id, rnti,
@@ -506,6 +509,13 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id,
       UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync   = 1;
     }
   }       // ul_failure_timer>0
+  
+  UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer++;
+  if((U_PLANE_INACTIVITY_VALUE != 0) && (UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer > (U_PLANE_INACTIVITY_VALUE * 10))){
+     LOG_D(MAC,"UE %d rnti %x: U-Plane Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti); 
+     mac_eNB_rrc_uplane_failure(module_idP,CC_id,frameP,subframeP,rnti);
+     UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer  = 0;
+  }// time > 60s
 }
 
 void
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
index f7b11511fc59a0afe6ff7e7e861ae6d3595b1cb2..9a908313ba243247c1b9c770089d3117cc64149e 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c
@@ -868,8 +868,10 @@ generate_Msg4(module_id_t module_idP,
       ul_config_pdu = &ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus];
       ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE;
       ul_config_pdu->pdu_size = (uint8_t) (2 + sizeof (nfapi_ul_config_uci_harq_pdu));
+      ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
       ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.handle = 0;      // don't know how to use this
       ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti = ra->rnti;
+      ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG;
       ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.ue_type = (ra->rach_resource_type < 3) ? 1 : 2;
       ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.empty_symbols = 0;
       ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.total_number_of_repetitions = pucchreps[ra->rach_resource_type - 1];
@@ -957,9 +959,12 @@ generate_Msg4(module_id_t module_idP,
                              1, // tpc, none
                              getRIV(N_RB_DL, first_rb, 4),  // resource_block_coding
                              ra->msg4_mcs,  // mcs
-                             1, // ndi
+				 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid],
                              0, // rv
                              0);  // vrb_flag
+    	
+    	UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid] = 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid];
+
         LOG_D(MAC,
               "Frame %d, subframe %d: Msg4 DCI pdu_num %d (rnti %x,rnti_type %d,harq_pid %d, resource_block_coding (%p) %d\n",
               frameP, subframeP, dl_req_body->number_pdu,
@@ -1049,7 +1054,7 @@ generate_Msg4(module_id_t module_idP,
           mac->TX_req[CC_idP].sfn_sf =
             fill_nfapi_tx_req(&mac->TX_req[CC_idP].tx_request_body,
                               (frameP * 10) + subframeP,
-                              rrc_sdu_length,
+				      rrc_sdu_length+offset,
                               mac->pdu_index[CC_idP],
                               mac->UE_list.
                               DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0]);
@@ -1194,7 +1199,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP,
                              1, // tpc, none
                              getRIV(N_RB_DL, first_rb, 4),  // resource_block_coding
                              ra->msg4_mcs,  // mcs
-                             1, // ndi
+				     UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid],
                              round & 3, // rv
                              0);  // vrb_flag
 
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
index fb80c9e1d6058a9c50b33c869063c4cb6da40929..d523fb4e17b6f7aa031b6b7849a4a9b51430f756 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c
@@ -1158,6 +1158,7 @@ schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 		    LOG_D(MAC, "Frame %d: Subframe %d : Adding common DCI for S_RNTI\n", frameP, subframeP);
 		    dl_req->number_dci++;
 		    dl_req->number_pdu++;
+                    dl_req->tl.tag   = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
 		    dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
 		    memset((void *) dl_config_pdu, 0,
 			   sizeof(nfapi_dl_config_request_pdu_t));
@@ -1188,6 +1189,7 @@ schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
 		    dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector                          = 1;
 		    //    dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector                    = ; 
 		    dl_req->number_pdu++;
+		    dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
 
                     // Rel10 fields
                     dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.tl.tag                                = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
index ddbda5b2a0e49cfa178b856a1fbe7e0dea4fa3c5..134089dbf4da98ef21e5d604ff6c67a2bfc2f516 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
@@ -488,7 +488,7 @@ schedule_ue_spec(module_id_t module_idP,
   COMMON_channels_t *cc = eNB->common_channels;
   UE_list_t *UE_list = &eNB->UE_list;
   int continue_flag = 0;
-  int32_t normalized_rx_power, target_rx_power;
+  int32_t snr, target_snr;
   int tpc = 1;
   UE_sched_ctrl_t *ue_sched_ctrl;
   int mcs;
@@ -717,9 +717,12 @@ schedule_ue_spec(module_id_t module_idP,
       eNB_UE_stats->harq_pid = harq_pid;
       eNB_UE_stats->harq_round = round_DL;
 
+      if (eNB_UE_stats->rrc_status < RRC_RECONFIGURED) {
+        ue_sched_ctrl->uplane_inactivity_timer = 0;
+      }
+
       if (eNB_UE_stats->rrc_status < RRC_CONNECTED) {
-        LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n",
-              UE_id);
+        LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n", UE_id);
         continue;
       }
 
@@ -733,7 +736,7 @@ schedule_ue_spec(module_id_t module_idP,
                 eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE);
       */
       if (NFAPI_MODE != NFAPI_MONOLITHIC) {
-        eNB_UE_stats->dlsch_mcs1 = 10; // cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]];
+        eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]];
       } else { // this operation is also done in the preprocessor
         eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1,
                                         eNB->slice_info.dl[slice_idxP].maxmcs);  // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
@@ -1006,9 +1009,11 @@ schedule_ue_spec(module_id_t module_idP,
                                               , 0
 #endif
                                              );
-            pthread_mutex_lock(&rrc_release_freelist);
 
             if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) {
+              while(pthread_mutex_trylock(&rrc_release_freelist)){
+                /* spin... */
+              }
               uint16_t release_total = 0;
 
               for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0];
@@ -1055,9 +1060,9 @@ schedule_ue_spec(module_id_t module_idP,
                 if(release_total >= rrc_release_info.num_UEs)
                   break;
               }
+              pthread_mutex_unlock(&rrc_release_freelist);
             }
 
-            pthread_mutex_unlock(&rrc_release_freelist);
 
             for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) {
               if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) {
@@ -1477,11 +1482,11 @@ schedule_ue_spec(module_id_t module_idP,
           }
 
           // do PUCCH power control
-          // this is the normalized RX power
+          // this is the snr
           // unit is not dBm, it's special from nfapi
-          // converting to dBm: ToDo: Noise power hard coded to 30
-          normalized_rx_power = (((5 * ue_sched_ctrl->pucch1_snr[CC_id]) - 640) / 10) + 30;
-          target_rx_power= (eNB->puCch10xSnr / 10) + 30;
+          // converting to dBm
+          snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10;
+          target_snr = eNB->puCch10xSnr / 10;
           // this assumes accumulated tpc
           // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
           int32_t framex10psubframe = ue_template->pucch_tpc_tx_frame * 10 + ue_template->pucch_tpc_tx_subframe;
@@ -1493,22 +1498,22 @@ schedule_ue_spec(module_id_t module_idP,
               ue_template->pucch_tpc_tx_frame = frameP;
               ue_template->pucch_tpc_tx_subframe = subframeP;
 
-              if (normalized_rx_power > (target_rx_power + 4)) {
+              if (snr > target_snr + 4) {
                 tpc = 0;  //-1
-              } else if (normalized_rx_power < (target_rx_power - 4)) {
+              } else if (snr < target_snr - 4) {
                 tpc = 2;  //+1
               } else {
                 tpc = 1;  //0
               }
 
-              LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, normalized/target rx power %d/%d\n",
+              LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d\n",
                     module_idP,
                     frameP,
                     subframeP,
                     harq_pid,
                     tpc,
-                    normalized_rx_power,
-                    target_rx_power);
+                    snr,
+                    target_snr);
             } // Po_PUCCH has been updated
             else {
               tpc = 1;  //0
@@ -1889,8 +1894,8 @@ schedule_ue_spec_br(module_id_t module_idP,
   int round_DL = 0;
   int ta_update = 0;
   int32_t tpc = 1;
-  int32_t normalized_rx_power = 0;
-  int32_t target_rx_power = 0;
+  int32_t snr = 0;
+  int32_t target_snr = 0;
   uint16_t TBS = 0;
   uint16_t j = 0;
   uint16_t sdu_lengths[NB_RB_MAX];
@@ -2368,10 +2373,10 @@ schedule_ue_spec_br(module_id_t module_idP,
             T_INT(harq_pid),
             T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS));
           /* Do PUCCH power control */
-          /* This is the normalized RX power */
-          /* TODO: fix how we deal with power, unit is not dBm, it's special from nfapi */
-          normalized_rx_power = (5 * ue_sched_ctl->pucch1_snr[CC_id]-640) / 10 + 30;
-          target_rx_power = mac->puCch10xSnr / 10 + 30;
+          /* This is the snr */
+          /* unit is not dBm, it's special from nfapi, convert to dBm */
+          snr = (5 * ue_sched_ctl->pucch1_snr[CC_id] - 640) / 10;
+          target_snr = mac->puCch10xSnr / 10;
           /* This assumes accumulated tpc */
           /* Make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out */
           int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame * 10 + UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe;
@@ -2384,22 +2389,22 @@ schedule_ue_spec_br(module_id_t module_idP,
               UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frameP;
               UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframeP;
 
-              if (normalized_rx_power > (target_rx_power + 4)) {
+              if (snr > target_snr + 4) {
                 tpc = 0; //-1
-              } else if (normalized_rx_power<(target_rx_power - 4)) {
+              } else if (snr < target_snr - 4) {
                 tpc = 2; //+1
               } else {
                 tpc = 1; //0
               }
 
-              LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, normalized/target rx power %d/%d\n",
+              LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d\n",
                     module_idP,
                     frameP,
                     subframeP,
                     harq_pid,
                     tpc,
-                    normalized_rx_power,
-                    target_rx_power);
+                    snr,
+                    target_snr);
             } else { // Po_PUCCH has been updated
               tpc = 1; // 0
             }
@@ -3084,11 +3089,9 @@ schedule_PCH(module_id_t module_idP,
         dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                  = NFAPI_DL_DCI_FORMAT_1A;
         dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process                = 0;
         dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc                         = 1; // no TPC
-        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1        = 1;
-        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1        = 1;
-        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding       = getRIV(n_rb_dl,
-            first_rb,
-            4);
+	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1        = 0;
+	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1        = 0;
+        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(n_rb_dl, first_rb, 4);
         dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0;
 #endif
         dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level           = 4;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
index 697c738b807b2d37668ec79177b99b2c10246d18..c071c1f505d7aad17b990ff33b0b9a9b0e51e906 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c
@@ -585,6 +585,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t   Mod_id,
   //  uint16_t r1=0;
   uint8_t CC_id;
   UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
+  int N_RB_DL;
   UE_sched_ctrl_t *ue_sched_ctl;
   //  int rrc_status           = RRC_IDLE;
   COMMON_channels_t *cc;
@@ -600,6 +601,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t   Mod_id,
 #endif
   memset(rballoc_sub[0],0,(MAX_NUM_CCs)*(N_RBG_MAX)*sizeof(unsigned char));
   memset(min_rb_unit,0,sizeof(min_rb_unit));
+  memset(MIMO_mode_indicator[0], 0, MAX_NUM_CCs*N_RBG_MAX*sizeof(unsigned char));
 
   for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     if (mbsfn_flag[CC_id] > 0)  // If this CC is allocated for MBSFN skip it here
@@ -640,7 +642,18 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t   Mod_id,
     average_rbs_per_user[CC_id] = 0;
     cc = &RC.mac[Mod_id]->common_channels[CC_id];
     // Get total available RBS count and total UE count
-    temp_total_rbs_count = RC.mac[Mod_id]->eNB_stats[CC_id].available_prbs;
+    N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
+    temp_total_rbs_count = 0;
+    for(uint8_t rbg_i = 0;rbg_i < N_RBG[CC_id];rbg_i++ ){
+      if(rballoc_sub[CC_id][rbg_i] == 0){
+        if((rbg_i == N_RBG[CC_id] -1) &&
+           ((N_RB_DL == 25) || (N_RB_DL == 50))){
+          temp_total_rbs_count += (min_rb_unit[CC_id] -1);
+        }else{
+          temp_total_rbs_count += min_rb_unit[CC_id];
+        }
+      }
+    }
     temp_total_ue_count = dlsch_ue_select[CC_id].ue_num;
 
     for (i = 0; i < dlsch_ue_select[CC_id].ue_num; i++) {
@@ -825,7 +838,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
   COMMON_channels_t *cc = eNB->common_channels;
   UE_list_t *UE_list = &eNB->UE_list;
   // int continue_flag = 0;
-  int32_t normalized_rx_power, target_rx_power;
+  int32_t snr, target_snr;
   int32_t tpc = 1;
   static int32_t tpc_accumulated = 0;
   UE_sched_ctrl_t *ue_sched_ctl;
@@ -1001,6 +1014,10 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
       UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid;
       UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
 
+      if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_RECONFIGURED) {
+        UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
+      }
+
       if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status <
           RRC_CONNECTED)
         continue;
@@ -1013,7 +1030,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
          eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE);
        */
       if (NFAPI_MODE != NFAPI_MONOLITHIC) {
-        eNB_UE_stats->dlsch_mcs1 = 10;//cqi_to_mcs[ue_sched_ctl->dl_cqi[CC_id]];
+        eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctl->dl_cqi[CC_id]];
       } else {
         eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctl->dl_cqi[CC_id]];
       }
@@ -1287,9 +1304,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
                                               ,0, 0
 #endif
                                              );
-            pthread_mutex_lock(&rrc_release_freelist);
 
-            if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) {
+            if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)){
+              while(pthread_mutex_trylock(&rrc_release_freelist)) {
+                /* spin... */
+              }
               uint16_t release_total = 0;
 
               for(uint16_t release_num = 0; release_num < NUMBER_OF_UE_MAX; release_num++) {
@@ -1326,9 +1345,9 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
                 if(release_total >= rrc_release_info.num_UEs)
                   break;
               }
+              pthread_mutex_unlock(&rrc_release_freelist);
             }
 
-            pthread_mutex_unlock(&rrc_release_freelist);
             RA_t *ra = &eNB->common_channels[CC_id].ra[0];
 
             for (uint8_t ra_ii = 0; ra_ii < NB_RA_PROC_MAX; ra_ii++) {
@@ -1720,11 +1739,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
           }
 
           // do PUCCH power control
-          // this is the normalized RX power
+          // this is the snr
           eNB_UE_stats =  &UE_list->eNB_UE_stats[CC_id][UE_id];
           /* Unit is not dBm, it's special from nfapi */
-          normalized_rx_power = (5*ue_sched_ctl->pucch1_snr[CC_id]-640)/10+30;//(+eNB->measurements.n0_power_dB[0])
-          target_rx_power= eNB->puCch10xSnr/10 + 30;//(+eNB->measurements.n0_power_dB[0])
+          snr = (5 * ue_sched_ctl->pucch1_snr[CC_id] - 640) / 10;
+          target_snr = eNB->puCch10xSnr / 10;
           // this assumes accumulated tpc
           // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
           int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe;
@@ -1736,19 +1755,19 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
               UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP;
               UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP;
 
-              if (normalized_rx_power>(target_rx_power+4)) {
+              if (snr > target_snr + 4) {
                 tpc = 0; //-1
                 tpc_accumulated--;
-              } else if (normalized_rx_power<(target_rx_power-4)) {
+              } else if (snr < target_snr - 4) {
                 tpc = 2; //+1
                 tpc_accumulated++;
               } else {
                 tpc = 1; //0
               }
 
-              LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
+              LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n",
                     module_idP,frameP, subframeP,harq_pid,tpc,
-                    tpc_accumulated,normalized_rx_power,target_rx_power);
+                    tpc_accumulated,snr,target_snr);
             } // Po_PUCCH has been updated
             else {
               tpc = 1; //0
@@ -1763,6 +1782,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
           dl_config_pdu->pdu_size                                               = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
           dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                  = NFAPI_DL_DCI_FORMAT_1;
           dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level           = get_aggregation(get_bw_index(module_idP,CC_id),ue_sched_ctl->dl_cqi[CC_id],format1);
+          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag                      = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
           dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                        = rnti;
           dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type                   = 1;    // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications
           dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power          = 6000; // equal to RS power
@@ -1972,7 +1992,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
   uint8_t cc_id_flag[MAX_NUM_CCs];
   uint8_t harq_pid = 0,round = 0;
   UE_list_t *UE_list= &eNB->UE_list;
-  uint8_t                        aggregation = 2;
+  uint8_t                        aggregation;
   int                            format_flag;
   nfapi_hi_dci0_request_body_t   *HI_DCI0_req;
   nfapi_hi_dci0_request_pdu_t    *hi_dci0_pdu;
@@ -2031,7 +2051,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
     if ( round > 0 ) {
       hi_dci0_pdu   = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
       format_flag = 2;
-
+      aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0);
       if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
         cc_id_flag[CC_id] = 1;
         continue;
@@ -2110,7 +2130,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
       hi_dci0_pdu   = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
       format_flag = 2;
       rnti = UE_RNTI(module_idP,first_ue_id[CC_id][temp]);
-
+      aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[first_ue_id[CC_id][temp]].dl_cqi[CC_id],format0); 
       if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
         cc_id_flag[CC_id] = 1;
         break;
@@ -2182,7 +2202,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
          ((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED)) ) {
       hi_dci0_pdu   = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
       format_flag = 2;
-
+      aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0);
       if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
         cc_id_flag[CC_id] = 1;
         continue;
@@ -2235,7 +2255,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
       hi_dci0_pdu   = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi];
       format_flag = 2;
       rnti = UE_RNTI(module_idP,ul_inactivity_id[CC_id][temp]);
-
+      aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[ul_inactivity_id[CC_id][temp]].dl_cqi[CC_id],format0);
       if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) {
         cc_id_flag[CC_id] = 1;
         continue;
@@ -2402,8 +2422,8 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP,
             while ( (tbs < bytes_to_schedule) && (rb_table[rb_table_index]<(frame_parms->N_RB_UL-num_pucch_rb-first_rb[CC_id])) &&
                     ((UE_template->phr_info - tx_power) > 0) && (rb_table_index < 32 )) {
               rb_table_index++;
-              tbs = get_TBS_UL(mcs,rb_table[rb_table_index])<<3;
-              tx_power= estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0);
+              tbs = get_TBS_UL(mcs,rb_table[rb_table_index]);
+              tx_power= estimate_ue_tx_power(tbs*8,rb_table[rb_table_index],0,frame_parms->Ncp,0);
             }
 
             if ( rb_table[rb_table_index]<3 ) {
@@ -2434,12 +2454,20 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP,
               UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs;
             }
           } else {
-            // assigne RBS( 3 RBs)
-            first_rb[CC_id] = first_rb[CC_id] + 3;
-            UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3;
-            UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2;
-            UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10;
-          }
+            if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED){
+              // assigne RBS( 6 RBs)
+              first_rb[CC_id] = first_rb[CC_id] + 6;
+              UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 6;
+              UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 5;
+              UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10;
+            }else{
+              // assigne RBS( 3 RBs)
+              first_rb[CC_id] = first_rb[CC_id] + 3;
+              UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3;
+              UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2;
+              UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10;
+            }
+           }
         } else if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority  == SCH_UL_INACTIVE ) {
           // assigne RBS( 3 RBs)
           first_rb[CC_id] = first_rb[CC_id] + 3;
@@ -2609,7 +2637,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
                                 unsigned char sched_subframeP,
                                 ULSCH_UE_SELECT  ulsch_ue_select[MAX_NUM_CCs]) {
   int16_t           UE_id;
-  uint8_t           aggregation    = 2;
+  uint8_t           aggregation;
   uint16_t          first_rb[MAX_NUM_CCs];
   uint8_t           ULSCH_first_end;
   rnti_t            rnti           = -1;
@@ -2618,8 +2646,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
   uint8_t           status         = 0;
   uint8_t           rb_table_index = -1;
   uint32_t          cqi_req,cshift,ndi,tpc;
-  int32_t           normalized_rx_power;
-  int32_t           target_rx_power=-90;
+  int32_t           snr;
+  int32_t           target_snr=0;
   static int32_t    tpc_accumulated=0;
   int               CC_id,ulsch_ue_num;
   int               N_RB_UL;
@@ -2738,6 +2766,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
       UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
       harq_pid      = subframe2harqpid(cc,sched_frame,sched_subframeP);
       rnti = UE_RNTI(CC_id,UE_id);
+      aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); 
       LOG_D(MAC,"[eNB %d] frame %d subframe %d,Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n",
             module_idP,frameP,subframeP,harq_pid,UE_id,rnti,CC_id, aggregation,N_RB_UL);
       int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes;
@@ -2757,12 +2786,12 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
         if (cc->tdd_Config) {
           switch (cc->tdd_Config->subframeAssignment) {
             case 1:
-              if( subframeP == 1 || subframeP == 6 ) cqi_req=0;
+              if( sched_subframeP == 1 || sched_subframeP == 6 ) cqi_req=0;
 
               break;
 
             case 3:
-              if( subframeP == 1 ) cqi_req=0;
+              if( sched_subframeP == 1 ) cqi_req=0;
 
               break;
 
@@ -2782,8 +2811,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
       //power control
       //compute the expected ULSCH RX power (for the stats)
       // this is the normalized RX power and this should be constant (regardless of mcs
-      normalized_rx_power = (5*UE_sched_ctrl->pusch_snr[CC_id]-640)/10+30; //(+eNB->measurements.n0_power_dB[0])
-      target_rx_power= eNB->puSch10xSnr/10 + 30; //(+eNB->measurements.n0_power_dB[0])
+      snr = (5 * UE_sched_ctrl->pusch_snr[CC_id] - 640) / 10;
+      target_snr = eNB->puSch10xSnr / 10;
       // this assumes accumulated tpc
       // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
       int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame*10+UE_template->pusch_tpc_tx_subframe;
@@ -2793,10 +2822,10 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
         UE_template->pusch_tpc_tx_frame=frameP;
         UE_template->pusch_tpc_tx_subframe=subframeP;
 
-        if (normalized_rx_power>(target_rx_power+4)) {
+        if (snr > target_snr + 4) {
           tpc = 0; //-1
           tpc_accumulated--;
-        } else if (normalized_rx_power<(target_rx_power-4)) {
+        } else if (snr < target_snr - 4) {
           tpc = 2; //+1
           tpc_accumulated++;
         } else {
@@ -2807,9 +2836,9 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
       }
 
       if (tpc!=1) {
-        LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
+        LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n",
               module_idP,frameP,subframeP,harq_pid,tpc,
-              tpc_accumulated,normalized_rx_power,target_rx_power);
+              tpc_accumulated,snr,target_snr);
       }
 
       // new transmission
@@ -2822,8 +2851,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
               UE_sched_ctrl->cqi_req_timer);
         ndi = 1-UE_template->oldNDI_UL[harq_pid];
         UE_template->oldNDI_UL[harq_pid]=ndi;
-        UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
-        UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
+        UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr;
+        UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr;
         UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul;
         UE_template->mcs_UL[harq_pid] = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
 
@@ -2872,6 +2901,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
         memset((void *)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t));
         hi_dci0_pdu->pdu_type                                               = NFAPI_HI_DCI0_DCI_PDU_TYPE;
         hi_dci0_pdu->pdu_size                                               = 2+sizeof(nfapi_hi_dci0_dci_pdu);
+        hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag                            = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG;
         hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format                        = NFAPI_UL_DCI_FORMAT_0;
         hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level                 = aggregation;
         hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti                              = rnti;
@@ -2998,8 +3028,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
         T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
           T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb), T_INT(ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb),
           T_INT(round));
-        UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
-        UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
+        UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr;
+        UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr;
         uint8_t mcs_rv = 0;
 
         if(rvidx_tab[round&3]==1) {
@@ -3029,6 +3059,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t   module_idP,
         memset((void *)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t));
         hi_dci0_pdu->pdu_type                                               = NFAPI_HI_DCI0_DCI_PDU_TYPE;
         hi_dci0_pdu->pdu_size                                               = 2+sizeof(nfapi_hi_dci0_dci_pdu);
+        hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag                            = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG;
         hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format                        = NFAPI_UL_DCI_FORMAT_0;
         hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level                 = aggregation;
         hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti                              = rnti;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c
index 4f74ab0d09a908a0f139cc0c705ef90a8e442935..18f35d4fe3ad8303ded74420dcd2085ff177b774 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c
@@ -199,8 +199,8 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s
   uint8_t           mcs            = 20;
   uint8_t           harq_pid       = 0;
   uint32_t          cqi_req = 0,cshift,ndi,tpc = 1;
-  int32_t           normalized_rx_power;
-  int32_t           target_rx_power= 178;
+  int32_t           snr;
+  int32_t           target_snr = 10; /* TODO: target_rx_power was 178, what to put? is it meaningful? */
   int               CC_id = 0;
   int               nb_rb = 24;
   int               N_RB_UL;
@@ -258,15 +258,15 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s
       //power control
       //compute the expected ULSCH RX power (for the stats)
 	  
-      // this is the normalized RX power and this should be constant (regardless of mcs
-      normalized_rx_power = (5*UE_sched_ctrl->pusch_snr[CC_id]-640)/10+30;
+      // this is the snr and this should be constant (regardless of mcs)
+      snr = (5 * UE_sched_ctrl->pusch_snr[CC_id] - 640) / 10;
 	  
       // new transmission
 	  
       ndi = 1-UE_template->oldNDI_UL[harq_pid];
       UE_template->oldNDI_UL[harq_pid]=ndi;
-	  UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
-	  UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
+	  UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr;
+	  UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr;
 	  UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = mcs;
       UE_template->mcs_UL[harq_pid] = mcs;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
       UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = mcs;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
index 856045166f7b3f3b277e3d23947948b0527b8438..63f838f652daa216fa49b6d02c7b8c8848de23ce 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
@@ -2193,8 +2193,8 @@ add_new_ue(module_id_t mod_idP,
     UE_list->UE_sched_ctrl[UE_id].ta_update = 31;
 
     for (j = 0; j < 8; j++) {
-      UE_list->UE_template[cc_idP][UE_id].oldNDI[j] = (j == 0) ? 1 : 0; // 1 because first transmission is with format1A (Msg4) for harq_pid 0
-      UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = (j == harq_pidP) ? 0 : 1;  // 1st transmission is with Msg3;
+      UE_list->UE_template[cc_idP][UE_id].oldNDI[j] = 0;
+      UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = 0;
       UE_list->UE_sched_ctrl[UE_id].round[cc_idP][j] = 8;
       UE_list->UE_sched_ctrl[UE_id].round_UL[cc_idP][j] = 0;
     }
@@ -2319,9 +2319,10 @@ rrc_mac_remove_ue(module_id_t mod_idP,
                    rntiP);
   }
 
-  pthread_mutex_lock(&rrc_release_freelist);
-
-  if (rrc_release_info.num_UEs > 0) {
+  if(rrc_release_info.num_UEs > 0){
+    while(pthread_mutex_trylock(&rrc_release_freelist)) {
+      /* spin... */
+    }
     uint16_t release_total = 0;
 
     for (uint16_t release_num = 0; release_num < NUMBER_OF_UE_MAX; release_num++) {
@@ -2341,6 +2342,7 @@ rrc_mac_remove_ue(module_id_t mod_idP,
         break;
       }
     }
+    pthread_mutex_unlock(&rrc_release_freelist);
   }
 
   pthread_mutex_unlock(&rrc_release_freelist);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
index dd228c4250eca1fb13b85294e7ff199765981d46..be1f838aaadaba7db8841bdb61d81b9649565714 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
@@ -460,7 +460,7 @@ rx_sdu(const module_id_t enb_mod_idP,
 
             if (RA_id != -1) {
               RA_t *ra = &(mac->common_channels[CC_idP].ra[RA_id]);
-              mac_rrc_data_ind(enb_mod_idP,
+              int8_t ret = mac_rrc_data_ind(enb_mod_idP,
                                CC_idP,
                                frameP, subframeP,
                                UE_id,
@@ -474,6 +474,7 @@ rx_sdu(const module_id_t enb_mod_idP,
 #endif
                               );
               /* Received a new rnti */
+              if (ret == 0) {
               ra->state = MSGCRNTI;
               LOG_I(MAC, "[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) Received rnti(Msg4)\n",
                     enb_mod_idP,
@@ -502,6 +503,9 @@ rx_sdu(const module_id_t enb_mod_idP,
               }
               UE_template_ptr->ul_SR = 1;
               UE_scheduling_control->crnti_reconfigurationcomplete_flag = 1;
+              } else {
+                cancel_ra_proc(enb_mod_idP, CC_idP, frameP, current_rnti);
+              }
               // break;
             }
           }
@@ -797,6 +801,10 @@ rx_sdu(const module_id_t enb_mod_idP,
           mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL);  //(unsigned int*)crc_status);
           UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1;
           UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i];
+        
+          if (mac_eNB_get_rrc_status(enb_mod_idP, current_rnti) < RRC_RECONFIGURED) {
+            UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
+          }
         }
 
         break;
@@ -1329,8 +1337,8 @@ schedule_ulsch_rnti(module_id_t   module_idP,
   uint32_t cshift = 0;
   uint32_t ndi = 0;
   uint32_t tpc = 0;
-  int32_t normalized_rx_power = 0;
-  int32_t target_rx_power = 0;
+  int32_t snr = 0;
+  int32_t target_snr = 0;
   int32_t framex10psubframe = 0;
   static int32_t tpc_accumulated = 0;
   int sched_frame = 0;
@@ -1555,13 +1563,12 @@ schedule_ulsch_rnti(module_id_t   module_idP,
 
           /* Power control */
           /*
-           * Compute the expected ULSCH RX power (for the stats)
-           * This is the normalized RX power and this should be constant (regardless of mcs)
+           * Compute the expected ULSCH RX snr (for the stats)
+           * This is the normalized RX snr and this should be constant (regardless of mcs)
            * Is not in dBm, unit from nfapi, converting to dBm
-           * ToDo: Noise power hard coded to 30
            */
-          normalized_rx_power = ((5 * UE_sched_ctrl_ptr->pusch_snr[CC_id] - 640) / 10) + 30;
-          target_rx_power = (mac->puSch10xSnr / 10) + 30;
+          snr = (5 * UE_sched_ctrl_ptr->pusch_snr[CC_id] - 640) / 10;
+          target_snr = mac->puSch10xSnr / 10;
 
           /*
            * This assumes accumulated tpc
@@ -1575,10 +1582,10 @@ schedule_ulsch_rnti(module_id_t   module_idP,
             UE_template_ptr->pusch_tpc_tx_frame = frameP;
             UE_template_ptr->pusch_tpc_tx_subframe = subframeP;
 
-            if (normalized_rx_power > (target_rx_power + 4)) {
+            if (snr > target_snr + 4) {
               tpc = 0; // -1
               tpc_accumulated--;
-            } else if (normalized_rx_power < (target_rx_power - 4)) {
+            } else if (snr < target_snr - 4) {
               tpc = 2; // +1
               tpc_accumulated++;
             } else {
@@ -1589,21 +1596,21 @@ schedule_ulsch_rnti(module_id_t   module_idP,
           }
 
           if (tpc != 1) {
-            LOG_D(MAC, "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
+            LOG_D(MAC, "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n",
               module_idP,
               frameP,
               subframeP,
               harq_pid,
               tpc,
               tpc_accumulated,
-              normalized_rx_power,
-              target_rx_power);
+              snr,
+              target_snr);
           }
 
           ndi = 1 - UE_template_ptr->oldNDI_UL[harq_pid]; // NDI: new data indicator
           UE_template_ptr->oldNDI_UL[harq_pid] = ndi;
-          UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power = normalized_rx_power;
-          UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power = target_rx_power;
+          UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr;
+          UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr;
           UE_template_ptr->mcs_UL[harq_pid] = cmin(UE_template_ptr->pre_assigned_mcs_ul, sli->ul[slice_idx].maxmcs);
           UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1= UE_template_ptr->mcs_UL[harq_pid];
 
@@ -1941,8 +1948,8 @@ void schedule_ulsch_rnti_emtc(module_id_t   module_idP,
   uint8_t           status         = 0;
   uint32_t          cshift         = 0;
   uint32_t          ndi            = 0;
-  int32_t           normalized_rx_power = 0;
-  int32_t           target_rx_power = -90;
+  int32_t           snr = 0;
+  int32_t           target_snr = 0;
   int               n       = 0;
   int               CC_id = 0;
   int               N_RB_UL = 0;
@@ -2050,10 +2057,10 @@ void schedule_ulsch_rnti_emtc(module_id_t   module_idP,
         UE_template->ul_SR = 0;
         status = mac_eNB_get_rrc_status(module_idP,rnti);
         cqi_req = 0;
-        /* Power control: compute the expected ULSCH RX power (for the stats) */
-        /* This is the normalized RX power and this should be constant (regardless of mcs) */
-        normalized_rx_power = UE_sched_ctrl->pusch_snr[CC_id];
-        target_rx_power = 178;
+        /* Power control: compute the expected ULSCH RX snr (for the stats) */
+        /* This is the normalized snr and this should be constant (regardless of mcs) */
+        snr = (5 * UE_sched_ctrl->pusch_snr[CC_id] - 640) / 10;
+        target_snr = eNB->puSch10xSnr / 10; /* TODO: target_rx_power was 178, what to put? */
         /* This assumes accumulated tpc */
         /* Make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out */
         int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame * 10 + UE_template->pusch_tpc_tx_subframe;
@@ -2063,10 +2070,10 @@ void schedule_ulsch_rnti_emtc(module_id_t   module_idP,
           UE_template->pusch_tpc_tx_frame = frameP;
           UE_template->pusch_tpc_tx_subframe = subframeP;
 
-          if (normalized_rx_power > (target_rx_power + 4)) {
+          if (snr > target_snr + 4) {
             tpc = 0; //-1
             UE_sched_ctrl->tpc_accumulated[CC_id]--;
-          } else if (normalized_rx_power < (target_rx_power - 4)) {
+          } else if (snr < target_snr - 4) {
             tpc = 2; //+1
             UE_sched_ctrl->tpc_accumulated[CC_id]++;
           } else {
@@ -2077,15 +2084,15 @@ void schedule_ulsch_rnti_emtc(module_id_t   module_idP,
         }
 
         if (tpc != 1) {
-          LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
+          LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n",
                 module_idP,
                 frameP,
                 subframeP,
                 harq_pid,
                 tpc,
                 UE_sched_ctrl->tpc_accumulated[CC_id],
-                normalized_rx_power,
-                target_rx_power);
+                snr,
+                target_snr);
         }
 
         /* New transmission */
@@ -2094,8 +2101,8 @@ void schedule_ulsch_rnti_emtc(module_id_t   module_idP,
           UE_template->oldNDI_UL[harq_pid] = ndi;
           UE_template->mcs_UL[harq_pid] = 4;
           UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid], 6);
-          UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power = normalized_rx_power;
-          UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power = target_rx_power;
+          UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr;
+          UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr;
           UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = 4;
           UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template->mcs_UL[harq_pid];
           UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += 6;
diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h
index 276f1e4e6f25af1a85c256d0eda2a48a10d553a7..1760355f6152f12640c1916f84f6d3458032d567 100644
--- a/openair2/LAYER2/MAC/mac.h
+++ b/openair2/LAYER2/MAC/mac.h
@@ -169,7 +169,7 @@
 #define MAX_NUM_SLICES 10
 
 
-#define U_PLANE_INACTIVITY_VALUE 6000
+#define U_PLANE_INACTIVITY_VALUE 0   /* defined 10ms order (zero means infinity) */
 
 /*
  * eNB part
@@ -754,10 +754,10 @@ typedef struct {
     uint32_t rbs_used_retx_rx;
     ///  total rb used for a new uplink transmission
     uint32_t total_rbs_used_rx;
-    /// normalized rx power
-    int32_t normalized_rx_power;
-    /// target rx power
-    int32_t target_rx_power;
+    /// snr
+    int32_t snr;
+    /// target snr
+    int32_t target_snr;
 
     /// num rx pdu
     uint32_t num_pdu_rx[NB_RB_MAX];
@@ -1438,6 +1438,8 @@ typedef struct eNB_MAC_INST_s {
   tx_request_pdu[NFAPI_CC_MAX][MAX_NUM_TX_REQUEST_PDU];
   /// NFAPI DL PDU structure
   nfapi_tx_request_t TX_req[NFAPI_CC_MAX];
+  /// NFAPI UE_release_req structure
+  nfapi_ue_release_request_t UE_release_req;
   /// UL handle
   uint32_t ul_handle;
   UE_list_t UE_list;
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c
index 2f001bdcfd82eef375e29051555a352289bbbe1f..4d34338ea98097d1229d9ee26e79624ff17a951a 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c
@@ -806,6 +806,7 @@ mem_block_t * rlc_am_get_pdu_to_retransmit(
 	  rlc_sn_t             sn          = rlc_pP->vt_a;
 	  rlc_sn_t             sn_end      = rlc_pP->vt_s;
 	  mem_block_t*         pdu_p        = NULL;
+	  mem_block_t*         mb_p         = NULL;
 	  rlc_am_tx_data_pdu_management_t* tx_data_pdu_management;
 //Assertion(eNB)_PRAN_DesignDocument_annex No.769
       if((rlc_pP->retrans_num_pdus <= 0) || (rlc_pP->vt_a ==  rlc_pP->vt_s))
@@ -884,6 +885,18 @@ mem_block_t * rlc_am_get_pdu_to_retransmit(
 					                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
 									tx_data_pdu_management->retx_count_next,
 					                sn);
+					  mb_p = rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE].mem_block;
+					  if(mb_p != NULL){
+					    free_mem_block(mb_p, __func__);
+					    tx_data_pdu_management->mem_block = NULL;
+					    tx_data_pdu_management->flags.retransmit = 0;
+					    tx_data_pdu_management->flags.ack = 1;
+					    tx_data_pdu_management->flags.transmitted = 0;
+					    rlc_pP->retrans_num_bytes_to_retransmit -= tx_data_pdu_management->retx_payload_size;
+					    tx_data_pdu_management->retx_payload_size = 0;
+					    tx_data_pdu_management->num_holes = 0;
+					    rlc_pP->retrans_num_pdus --;
+					  }
 				  }
 			  }
 			  else if (rlc_pP->nb_bytes_requested_by_mac >= 5)
@@ -938,6 +951,18 @@ mem_block_t * rlc_am_get_pdu_to_retransmit(
 					  					                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
 					  									tx_data_pdu_management->retx_count_next,
 					  					                sn);
+					  mb_p = rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE].mem_block;
+					  if(mb_p != NULL){
+					    free_mem_block(mb_p, __func__);
+					    tx_data_pdu_management->mem_block = NULL;
+					    tx_data_pdu_management->flags.retransmit = 0;
+					    tx_data_pdu_management->flags.ack = 1;
+					    tx_data_pdu_management->flags.transmitted = 0;
+					    rlc_pP->retrans_num_bytes_to_retransmit -= tx_data_pdu_management->retx_payload_size;
+					    tx_data_pdu_management->retx_payload_size = 0;
+					    tx_data_pdu_management->num_holes = 0;
+					    rlc_pP->retrans_num_pdus --;
+					  }
 				  }
 			  }
 
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c
index 9d69882923d84e02d97cde5047c4cb50f00a85af..4a065539013f323cb16a146cf2dd07b975ff7a6d 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c
@@ -938,7 +938,7 @@ rlc_am_rx_check_all_byte_segments(
   rlc_am_pdu_info_t  *pdu_info_p        = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
   mem_block_t        *cursor_p        = NULL;
   mem_block_t        *first_cursor_p  = NULL;
-  rlc_sn_t            sn              = pdu_info_p->sn;
+  rlc_usn_t            sn              = pdu_info_p->sn;
   sdu_size_t          next_waited_so;
   sdu_size_t          last_end_so;
 
@@ -969,6 +969,9 @@ rlc_am_rx_check_all_byte_segments(
   // the so field of the first PDU should be 0
   //cursor_p = list.head;
   //we start from the first stored PDU segment of this SN
+  if(cursor_p->data == NULL){
+    return;
+  }
   pdu_info_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
 
   // if the first segment does not have SO = 0 then no need to continue
@@ -985,6 +988,9 @@ rlc_am_rx_check_all_byte_segments(
   while (cursor_p->next != NULL) {
     //msg("rlc_am_rx_check_all_byte_segments(%d) @4\n",sn);
     cursor_p = cursor_p->next;
+  if(cursor_p->data == NULL){
+    return;
+  }
     pdu_info_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
 
     if (pdu_info_p->sn == sn) {
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c
index 40bab6ff0b0b9f4021e7204fd3ab4e8b5fdf0e19..dbe55c483da8322bb1e1e76a76faca01630ee795 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c
@@ -358,8 +358,6 @@ void rlc_am_segment_10 (
               PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
               pdu_remaining_size);
         //msg ("[FRAME %05d][%s][RLC_AM][MOD %u/%u][RB %u][SEGMENT] pdu_mem_p %p pdu_p %p pdu_p->data %p data %p data_sdu_p %p pdu_remaining_size %d\n", rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame, pdu_mem_p, pdu_p, pdu_p->data, data, data_sdu_p,pdu_remaining_size);
-        rlc_am_mui.rrc_mui[rlc_am_mui.rrc_mui_num] = sdu_mngt_p->mui;
-        rlc_am_mui.rrc_mui_num++;
 
         memcpy(data, data_sdu_p, pdu_remaining_size);
         pdu_mngt_p->payload_size += pdu_remaining_size;
@@ -397,8 +395,6 @@ void rlc_am_segment_10 (
         continue_fill_pdu_with_sdu = 0;
         pdu_remaining_size = 0;
       } else if ((sdu_mngt_p->sdu_remaining_size + (li_length_in_bytes ^ 3)) < pdu_remaining_size ) {
-        rlc_am_mui.rrc_mui[rlc_am_mui.rrc_mui_num] = sdu_mngt_p->mui;
-        rlc_am_mui.rrc_mui_num++;
         if (fill_num_li == (RLC_AM_MAX_SDU_IN_PDU - 1)) {
           LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] [SIZE %d] REACHING RLC_AM_MAX_SDU_IN_PDU LIs -> STOP SEGMENTATION FOR THIS PDU SDU\n",
                 PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
@@ -416,6 +412,8 @@ void rlc_am_segment_10 (
           // reduce the size of the PDU
           continue_fill_pdu_with_sdu = 0;
           fi_last_byte_pdu_is_last_byte_sdu = 1;
+          rlc_am_mui.rrc_mui[rlc_am_mui.rrc_mui_num] = sdu_mngt_p->mui;
+          rlc_am_mui.rrc_mui_num++;
         } else {
           LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] Filling  PDU with %d all remaining bytes of SDU\n",
                 PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
diff --git a/openair2/LAYER2/openair2_proc.c b/openair2/LAYER2/openair2_proc.c
index 2251344c47f1c6714bfdcf9b6c3a3ea613c0248f..32c4d9788cf84a59afe502babf54db8fd4a6044c 100644
--- a/openair2/LAYER2/openair2_proc.c
+++ b/openair2/LAYER2/openair2_proc.c
@@ -176,13 +176,13 @@ int dump_eNB_l2_stats(char *buffer, int length) {
                                UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes,
                                UE_list->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes
                               );
-                len += sprintf(&buffer[len],"[MAC] UE %d (ULSCH), Status %s, Failute timer %d, RNTI %x : rx power (normalized %d,  target %d), MCS (pre %d, post %d), RB (rx %d, retx %d, total %d), Current TBS %d \n",
+                len += sprintf(&buffer[len],"[MAC] UE %d (ULSCH), Status %s, Failute timer %d, RNTI %x : snr (%d,  target %d), MCS (pre %d, post %d), RB (rx %d, retx %d, total %d), Current TBS %d \n",
                                UE_id,
                                map_int_to_str(rrc_status_names, UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status),
                                UE_list->UE_sched_ctrl[UE_id].ul_failure_timer,
                                UE_list->eNB_UE_stats[CC_id][UE_id].crnti,
-                               UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power,
-                               UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power,
+                               UE_list->eNB_UE_stats[CC_id][UE_id].snr,
+                               UE_list->eNB_UE_stats[CC_id][UE_id].target_snr,
                                UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1,
                                UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2,
                                UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_rx,
diff --git a/openair2/PHY_INTERFACE/IF_Module.c b/openair2/PHY_INTERFACE/IF_Module.c
index ad49a16cec2e52534bd4e8a1f318924c8b50878b..2cc43189c696134b92bf82d14c53411516c35f13 100644
--- a/openair2/PHY_INTERFACE/IF_Module.c
+++ b/openair2/PHY_INTERFACE/IF_Module.c
@@ -17,10 +17,34 @@ extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind);
 extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind);
 
 extern uint16_t sf_ahead;
+extern UL_RCC_IND_t  UL_RCC_INFO;
+
 uint16_t frame_cnt=0;
 void handle_rach(UL_IND_t *UL_info) {
   int i;
-
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    for(uint8_t j = 0;j < NUM_NFPAI_SUBFRAME;j++){
+     if (UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles>0) {
+
+       AssertFatal(UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles==1,"More than 1 preamble not supported\n");
+       LOG_D(MAC,"UL_info[Frame %d, Subframe %d] Calling initiate_ra_proc RACH:SFN/SF:%d\n",UL_info->frame,UL_info->subframe, NFAPI_SFNSF2DEC(UL_RCC_INFO.rach_ind[j].sfn_sf));
+       initiate_ra_proc(UL_info->module_id,
+                        UL_info->CC_id,
+                        NFAPI_SFNSF2SFN(UL_RCC_INFO.rach_ind[j].sfn_sf),
+                        NFAPI_SFNSF2SF(UL_RCC_INFO.rach_ind[j].sfn_sf),
+                        UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.preamble,
+                        UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.timing_advance,
+                        UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.rnti
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                        ,0
+#endif
+       );
+       free(UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list);
+       UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles = 0;
+       UL_RCC_INFO.rach_ind[j].header.message_id = 0;
+     }
+   }
+  }else{
   if (UL_info->rach_ind.rach_indication_body.number_of_preambles>0) {
     AssertFatal(UL_info->rach_ind.rach_indication_body.number_of_preambles==1,"More than 1 preamble not supported\n");
     UL_info->rach_ind.rach_indication_body.number_of_preambles=0;
@@ -37,6 +61,7 @@ void handle_rach(UL_IND_t *UL_info) {
 #endif
                     );
   }
+  }
 
 #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
 
@@ -72,6 +97,22 @@ void handle_sr(UL_IND_t *UL_info) {
     if (UL_info->sr_ind.sr_indication_body.number_of_srs>0) {
       oai_nfapi_sr_indication(&UL_info->sr_ind);
     }
+  } else if(NFAPI_MODE == NFAPI_MODE_VNF){
+    for(uint8_t j = 0;j < NUM_NFPAI_SUBFRAME;j++){
+      if(UL_RCC_INFO.sr_ind[j].sr_indication_body.number_of_srs > 0){
+        for (i=0;i<UL_RCC_INFO.sr_ind[j].sr_indication_body.number_of_srs;i++){
+          SR_indication(UL_info->module_id,
+              UL_info->CC_id,
+              NFAPI_SFNSF2SFN(UL_RCC_INFO.sr_ind[j].sfn_sf),
+              NFAPI_SFNSF2SF(UL_RCC_INFO.sr_ind[j].sfn_sf),
+              UL_RCC_INFO.sr_ind[j].sr_indication_body.sr_pdu_list[i].rx_ue_information.rnti,
+              UL_RCC_INFO.sr_ind[j].sr_indication_body.sr_pdu_list[i].ul_cqi_information.ul_cqi);
+        }
+        free(UL_RCC_INFO.sr_ind[j].sr_indication_body.sr_pdu_list);
+        UL_RCC_INFO.sr_ind[j].sr_indication_body.number_of_srs=0;
+        UL_RCC_INFO.sr_ind[j].header.message_id = 0;
+      }
+    }
   } else {
     for (i=0; i<UL_info->sr_ind.sr_indication_body.number_of_srs; i++)
       SR_indication(UL_info->module_id,
@@ -89,27 +130,46 @@ void handle_cqi(UL_IND_t *UL_info) {
   int i;
 
   if (NFAPI_MODE==NFAPI_MODE_PNF) {
-    if (UL_info->cqi_ind.number_of_cqis>0) {
-      LOG_D(PHY,"UL_info->cqi_ind.number_of_cqis:%d\n", UL_info->cqi_ind.number_of_cqis);
-      nfapi_cqi_indication_t ind;
-      ind.header.message_id = NFAPI_RX_CQI_INDICATION;
-      ind.sfn_sf = UL_info->frame<<4 | UL_info->subframe;
-      ind.cqi_indication_body = UL_info->cqi_ind;
-      oai_nfapi_cqi_indication(&ind);
-      UL_info->cqi_ind.number_of_cqis=0;
+    if (UL_info->cqi_ind.cqi_indication_body.number_of_cqis>0) {
+      LOG_D(PHY,"UL_info->cqi_ind.number_of_cqis:%d\n", UL_info->cqi_ind.cqi_indication_body.number_of_cqis);
+      UL_info->cqi_ind.header.message_id = NFAPI_RX_CQI_INDICATION;
+      UL_info->cqi_ind.sfn_sf = UL_info->frame<<4 | UL_info->subframe;
+
+      oai_nfapi_cqi_indication(&UL_info->cqi_ind);
+      UL_info->cqi_ind.cqi_indication_body.number_of_cqis=0;
+    }
+  } else if (NFAPI_MODE == NFAPI_MODE_VNF) {
+    for(uint8_t j = 0;j < NUM_NFPAI_SUBFRAME;j++){
+      if(UL_RCC_INFO.cqi_ind[j].cqi_indication_body.number_of_cqis > 0){
+        for (i=0;i<UL_RCC_INFO.cqi_ind[j].cqi_indication_body.number_of_cqis;i++){
+          cqi_indication(UL_info->module_id,
+                         UL_info->CC_id,
+                         NFAPI_SFNSF2SFN(UL_RCC_INFO.cqi_ind[j].sfn_sf),
+                         NFAPI_SFNSF2SF(UL_RCC_INFO.cqi_ind[j].sfn_sf),
+                         UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_pdu_list[i].rx_ue_information.rnti,
+                         &UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_pdu_list[i].cqi_indication_rel9,
+                         UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_raw_pdu_list[i].pdu,
+                         &UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_pdu_list[i].ul_cqi_information);
+        }
+
+        free(UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_pdu_list);
+        free(UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_raw_pdu_list);
+        UL_RCC_INFO.cqi_ind[j].cqi_indication_body.number_of_cqis=0;
+        UL_RCC_INFO.cqi_ind[j].header.message_id = 0;
+      }
     }
   } else {
-    for (i=0; i<UL_info->cqi_ind.number_of_cqis; i++)
+    for (i=0;i<UL_info->cqi_ind.cqi_indication_body.number_of_cqis;i++)
       cqi_indication(UL_info->module_id,
                      UL_info->CC_id,
-                     UL_info->frame,
-                     UL_info->subframe,
-                     UL_info->cqi_ind.cqi_pdu_list[i].rx_ue_information.rnti,
-                     &UL_info->cqi_ind.cqi_pdu_list[i].cqi_indication_rel9,
-                     UL_info->cqi_ind.cqi_raw_pdu_list[i].pdu,
-                     &UL_info->cqi_ind.cqi_pdu_list[i].ul_cqi_information);
-
-    UL_info->cqi_ind.number_of_cqis=0;
+          NFAPI_SFNSF2SFN(UL_info->cqi_ind.sfn_sf),
+          NFAPI_SFNSF2SF(UL_info->cqi_ind.sfn_sf),
+          UL_info->cqi_ind.cqi_indication_body.cqi_pdu_list[i].rx_ue_information.rnti,
+          &UL_info->cqi_ind.cqi_indication_body.cqi_pdu_list[i].cqi_indication_rel9,
+          UL_info->cqi_ind.cqi_indication_body.cqi_raw_pdu_list[i].pdu,
+          &UL_info->cqi_ind.cqi_indication_body.cqi_pdu_list[i].ul_cqi_information);
+
+    UL_info->cqi_ind.cqi_indication_body.number_of_cqis=0;
   }
 }
 
@@ -123,7 +183,22 @@ void handle_harq(UL_IND_t *UL_info) {
     }
 
     UL_info->harq_ind.harq_indication_body.number_of_harqs = 0;
+  }else if(NFAPI_MODE == NFAPI_MODE_VNF){
+    for(uint8_t j = 0;j < NUM_NFPAI_SUBFRAME;j++){
+      if(UL_RCC_INFO.harq_ind[j].harq_indication_body.number_of_harqs > 0){
+        for (int i=0;i<UL_RCC_INFO.harq_ind[j].harq_indication_body.number_of_harqs;i++){
+          harq_indication(UL_info->module_id,
+                         UL_info->CC_id,
+                         NFAPI_SFNSF2SFN(UL_RCC_INFO.harq_ind[j].sfn_sf),
+                         NFAPI_SFNSF2SF(UL_RCC_INFO.harq_ind[j].sfn_sf),
+                         &UL_RCC_INFO.harq_ind[j].harq_indication_body.harq_pdu_list[i]);
+        }
 
+        free(UL_RCC_INFO.harq_ind[j].harq_indication_body.harq_pdu_list);
+        UL_RCC_INFO.harq_ind[j].harq_indication_body.number_of_harqs=0;
+        UL_RCC_INFO.harq_ind[j].header.message_id = 0;
+      }
+    }
   } else {
     for (int i=0; i < UL_info->harq_ind.harq_indication_body.number_of_harqs; i++)
       harq_indication(UL_info->module_id,
@@ -151,6 +226,56 @@ void handle_ulsch(UL_IND_t *UL_info) {
       oai_nfapi_rx_ind(&UL_info->rx_ind);
       UL_info->rx_ind.rx_indication_body.number_of_pdus = 0;
     }
+  } else if(NFAPI_MODE == NFAPI_MODE_VNF){
+    for(uint8_t k = 0;k < NUM_NFPAI_SUBFRAME;k++){
+      if((UL_RCC_INFO.rx_ind[k].rx_indication_body.number_of_pdus>0) && (UL_RCC_INFO.crc_ind[k].crc_indication_body.number_of_crcs>0)){
+        for (i=0;i<UL_RCC_INFO.rx_ind[k].rx_indication_body.number_of_pdus;i++) {
+          for (j=0;j<UL_RCC_INFO.crc_ind[k].crc_indication_body.number_of_crcs;j++) {
+            // find crc_indication j corresponding rx_indication i
+            LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].rx_ue_information.rnti:%04x UL_info->rx_ind.rx_indication_body.rx_pdu_list[%d].rx_ue_information.rnti:%04x\n",
+                       j,UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list[j].rx_ue_information.rnti, i,UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti);
+            if (UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list[j].rx_ue_information.rnti == UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti) {
+              LOG_D(PHY, "UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].crc_indication_rel8.crc_flag:%d\n",
+                          j, UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list[j].crc_indication_rel8.crc_flag);
+              if (UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list[j].crc_indication_rel8.crc_flag == 1) { // CRC error indication
+                LOG_D(MAC,"Frame %d, Subframe %d Calling rx_sdu (CRC error) \n",UL_info->frame,UL_info->subframe);
+                  rx_sdu(UL_info->module_id,
+                      UL_info->CC_id,
+                      NFAPI_SFNSF2SFN(UL_RCC_INFO.rx_ind[k].sfn_sf), //UL_info->frame,
+                      NFAPI_SFNSF2SF(UL_RCC_INFO.rx_ind[k].sfn_sf), //UL_info->subframe,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti,
+                      (uint8_t *)NULL,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.timing_advance,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.ul_cqi);
+              }
+              else {
+                  LOG_D(MAC,"Frame %d, Subframe %d Calling rx_sdu (CRC ok) \n",UL_info->frame,UL_info->subframe);
+                  rx_sdu(UL_info->module_id,
+                      UL_info->CC_id,
+                      NFAPI_SFNSF2SFN(UL_RCC_INFO.rx_ind[k].sfn_sf), //UL_info->frame,
+                      NFAPI_SFNSF2SF(UL_RCC_INFO.rx_ind[k].sfn_sf), //UL_info->subframe,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].data,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.timing_advance,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.ul_cqi);
+              }
+              if(UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].data != NULL){
+                free(UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].data);
+              }
+              break;
+            } //if (UL_info->crc_ind.crc_pdu_list[j].rx_ue_information.rnti == UL_info->rx_ind.rx_pdu_list[i].rx_ue_information.rnti)
+          } //    for (j=0;j<UL_info->crc_ind.crc_indication_body.number_of_crcs;j++)
+        } //   for (i=0;i<UL_info->rx_ind.number_of_pdus;i++)
+        free(UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list);
+        free(UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list);
+        UL_RCC_INFO.crc_ind[k].crc_indication_body.number_of_crcs = 0;
+        UL_RCC_INFO.crc_ind[k].header.message_id =0;
+        UL_RCC_INFO.rx_ind[k].rx_indication_body.number_of_pdus = 0;
+        UL_RCC_INFO.rx_ind[k].header.message_id = 0;
+      }
+    }
   } else {
     if (UL_info->rx_ind.rx_indication_body.number_of_pdus>0 && UL_info->crc_ind.crc_indication_body.number_of_crcs>0) {
       for (i=0; i<UL_info->rx_ind.rx_indication_body.number_of_pdus; i++) {
@@ -574,11 +699,11 @@ void UL_indication(UL_IND_t *UL_info) {
   Sched_Rsp_t  *sched_info = &Sched_INFO[module_id][CC_id];
   IF_Module_t  *ifi        = if_inst[module_id];
   eNB_MAC_INST *mac        = RC.mac[module_id];
+
   LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rx_ind:%d harqs:%d crcs:%d cqis:%d preambles:%d sr_ind:%d]\n",
         UL_info->frame,UL_info->subframe,
         module_id,CC_id,
-        UL_info->rx_ind.rx_indication_body.number_of_pdus, UL_info->harq_ind.harq_indication_body.number_of_harqs, UL_info->crc_ind.crc_indication_body.number_of_crcs, UL_info->cqi_ind.number_of_cqis,
-        UL_info->rach_ind.rach_indication_body.number_of_preambles, UL_info->sr_ind.sr_indication_body.number_of_srs);
+        UL_info->rx_ind.rx_indication_body.number_of_pdus, UL_info->harq_ind.harq_indication_body.number_of_harqs, UL_info->crc_ind.crc_indication_body.number_of_crcs, UL_info->cqi_ind.cqi_indication_body.number_of_cqis, UL_info->rach_ind.rach_indication_body.number_of_preambles, UL_info->sr_ind.sr_indication_body.number_of_srs);
 
   if(UL_info->frame==1023&&UL_info->subframe==6) { // dl scheduling (0,0)
     frame_cnt= (frame_cnt + 1)%7; // to prevent frame_cnt get too big
@@ -604,6 +729,7 @@ void UL_indication(UL_IND_t *UL_info) {
   handle_sr(UL_info);
   handle_cqi(UL_info);
   handle_harq(UL_info);
+
   // clear HI prior to handling ULSCH
   uint8_t sf_ahead_dl = ul_subframe2_k_phich(&mac->common_channels[CC_id], UL_info->subframe);
 
@@ -634,6 +760,9 @@ void UL_indication(UL_IND_t *UL_info) {
         sched_info->UL_req      = NULL;
 
       sched_info->TX_req      = &mac->TX_req[CC_id];
+      pthread_mutex_lock(&lock_ue_freelist);
+      sched_info->UE_release_req = &mac->UE_release_req;
+      pthread_mutex_unlock(&lock_ue_freelist);
 #ifdef DUMP_FAPI
       dump_dl(sched_info);
 #endif
diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h
index b6ede7d598a05f1e06e802fb0d52b46a96510b50..c42ba992c912c9e1c008b9e4dad89e08ff5c6ffa 100644
--- a/openair2/PHY_INTERFACE/IF_Module.h
+++ b/openair2/PHY_INTERFACE/IF_Module.h
@@ -71,7 +71,7 @@ typedef struct{
   nfapi_sr_indication_t sr_ind;
 
   /// CQI indication list
-  nfapi_cqi_indication_body_t cqi_ind;
+  nfapi_cqi_indication_t cqi_ind;
 
   /// RACH indication list
   nfapi_rach_indication_t rach_ind;
@@ -90,7 +90,27 @@ typedef struct{
 } UL_IND_t;
 
 // Downlink subframe P7
+#define NUM_NFPAI_SUBFRAME 5
+typedef struct{
+  /// harq indication list
+  nfapi_harq_indication_t harq_ind[NUM_NFPAI_SUBFRAME];
+
+  /// crc indication list
+  nfapi_crc_indication_t crc_ind[NUM_NFPAI_SUBFRAME];
+
+  /// SR indication list
+  nfapi_sr_indication_t sr_ind[NUM_NFPAI_SUBFRAME];
+
+  /// CQI indication list
+  nfapi_cqi_indication_t cqi_ind[NUM_NFPAI_SUBFRAME];
+
+  /// RACH indication list
+  nfapi_rach_indication_t rach_ind[NUM_NFPAI_SUBFRAME];
+
+  /// RX indication
+  nfapi_rx_indication_t rx_ind[NUM_NFPAI_SUBFRAME];
 
+} UL_RCC_IND_t;
 
 typedef struct{
   /// Module ID
@@ -109,6 +129,8 @@ typedef struct{
   nfapi_hi_dci0_request_t *HI_DCI0_req;
   /// Pointers to DL SDUs
   nfapi_tx_request_t *TX_req;
+  /// Pointers to ue_release
+  nfapi_ue_release_request_t *UE_release_req;
 }Sched_Rsp_t;
 
 typedef struct {
diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c
index 8d625fbdc59337c86d4609e9a386314e411243c5..930387c742489c1a413cd76b3bb3a56bb3f74502 100644
--- a/openair2/PHY_INTERFACE/phy_stub_UE.c
+++ b/openair2/PHY_INTERFACE/phy_stub_UE.c
@@ -236,8 +236,8 @@ void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint16_t frame,uint8_t subfram
 	// change for mutiple UE's simulation.
 	//pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
 	pthread_mutex_lock(&fill_ul_mutex.cqi_mutex);
-	nfapi_cqi_indication_pdu_t *pdu         = &UL_INFO->cqi_ind.cqi_pdu_list[UL_INFO->cqi_ind.number_of_cqis];
-	nfapi_cqi_indication_raw_pdu_t *raw_pdu = &UL_INFO->cqi_ind.cqi_raw_pdu_list[UL_INFO->cqi_ind.number_of_cqis];
+	nfapi_cqi_indication_pdu_t *pdu         = &UL_INFO->cqi_ind.cqi_indication_body.cqi_pdu_list[UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis];
+	nfapi_cqi_indication_raw_pdu_t *raw_pdu = &UL_INFO->cqi_ind.cqi_indication_body.cqi_raw_pdu_list[UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis];
 
 	pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
 	pdu->rx_ue_information.rnti = rnti;
@@ -263,7 +263,7 @@ void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint16_t frame,uint8_t subfram
 
 
 
-  UL_INFO->cqi_ind.number_of_cqis++;
+  UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis++;
   // change for mutiple UE's simulation.
   //pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_mutex);
   pthread_mutex_unlock(&fill_ul_mutex.cqi_mutex);
diff --git a/openair2/RRC/LTE/L2_interface.c b/openair2/RRC/LTE/L2_interface.c
index 6478641438c060bd88fd09331123fc4faea6c5ef..219c905c42626b8a6753e7e2213d8909abc4b68c 100644
--- a/openair2/RRC/LTE/L2_interface.c
+++ b/openair2/RRC/LTE/L2_interface.c
@@ -309,10 +309,13 @@ mac_rrc_data_ind(
     ue_context_p = rrc_eNB_get_ue_context(RC.rrc[ctxt.module_id],rntiP);
 
     if(ue_context_p) {
-      rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt,
-          ue_context_p,
-          0);
-      ue_context_p->ue_context.Status = RRC_RECONFIGURED;
+      if (ue_context_p->ue_context.Status != RRC_RECONFIGURED) {
+        LOG_E(RRC,"[eNB %d] Received C-RNTI ,but UE %x status(%d) not RRC_RECONFIGURED\n",module_idP,rntiP,ue_context_p->ue_context.Status);
+        return (-1);
+      } else {
+        rrc_eNB_generate_defaultRRCConnectionReconfiguration(&ctxt,ue_context_p,0);
+        ue_context_p->ue_context.Status = RRC_RECONFIGURED;
+      }
     }
   }
 
@@ -362,8 +365,7 @@ void mac_eNB_rrc_ul_failure(const module_id_t Mod_instP,
     flexran_agent_get_rrc_xface(Mod_instP)->flexran_agent_notify_ue_state_change(Mod_instP,
 								     rntiP, PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED);
   }
-
-  rrc_mac_remove_ue(Mod_instP,rntiP);
+  //rrc_mac_remove_ue(Mod_instP,rntiP);
 }
 
 void mac_eNB_rrc_uplane_failure(const module_id_t Mod_instP,
diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c
index ecb21dae6cf68f3f81d1f9fb87e61c54670508ce..9303fb79f110a3d3b9d378aadb79ba1fbbb7b60d 100644
--- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c
@@ -4072,6 +4072,7 @@ do_RRCConnectionReestablishment(
   LTE_DL_CCCH_Message_t dl_ccch_msg;
   LTE_RRCConnectionReestablishment_t *rrcConnectionReestablishment = NULL;
   int i = 0;
+  ue_context_pP->ue_context.reestablishment_xid = Transaction_id;
   LTE_SRB_ToAddModList_t **SRB_configList2 = NULL;
   SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[Transaction_id];
 
diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h
index ef0598a40a78de8ccc5c9bb99462493238738cfd..21f6429c7cec8a6c23c02b4a2b7cea79efbaf423 100644
--- a/openair2/RRC/LTE/rrc_defs.h
+++ b/openair2/RRC/LTE/rrc_defs.h
@@ -348,11 +348,24 @@ typedef enum HO_STATE_e {
   HO_COMPLETE, // initiated by the target eNB
   HO_REQUEST,
   HO_ACK,
+  HO_FORWARDING,
   HO_CONFIGURED,
+  HO_END_MARKER,
+  HO_FORWARDING_COMPLETE,
   HO_RELEASE,
   HO_CANCEL
 } HO_STATE_t;
 
+typedef enum DATA_FORWARDING_STATE_e {
+  FORWARDING_EMPTY=0,
+  FORWARDING_NO_EMPTY
+} DATA_FORWARDING_STATE_t;
+
+typedef enum DATA_ENDMARK_STATE_e {
+  ENDMARK_EMPTY=0,
+  ENDMARK_NO_EMPTY
+} DATA_ENDMARK_STATE_t;
+
 typedef enum SL_TRIGGER_e {
   SL_RECEIVE_COMMUNICATION=0,
   SL_TRANSMIT_RELAY_ONE_TO_ONE,
@@ -477,6 +490,9 @@ typedef struct HANDOVER_INFO_s {
   uint8_t buf[RRC_BUF_SIZE];  /* ASN.1 encoded handoverCommandMessage */
   int size;   /* size of above message in bytes */
   int x2_id;   /* X2AP UE ID in the target eNB */
+  uint32_t x2u_teid;
+  DATA_FORWARDING_STATE_t forwarding_state;
+  DATA_ENDMARK_STATE_t endmark_state;
 } HANDOVER_INFO;
 
 typedef struct PER_EVENT_s {
@@ -693,6 +709,12 @@ typedef struct eNB_RRC_UE_s {
   uint32_t                           enb_gtp_teid[S1AP_MAX_E_RAB];
   transport_layer_addr_t             enb_gtp_addrs[S1AP_MAX_E_RAB];
   rb_id_t                            enb_gtp_ebi[S1AP_MAX_E_RAB];
+  /* Total number of e_rab already setup in the list */
+  uint8_t                            nb_x2u_e_rabs;
+  // LG: For GTPV1 TUNNELS(X2U)
+  uint32_t                           enb_gtp_x2u_teid[S1AP_MAX_E_RAB];
+  transport_layer_addr_t             enb_gtp_x2u_addrs[S1AP_MAX_E_RAB];
+  rb_id_t                            enb_gtp_x2u_ebi[S1AP_MAX_E_RAB];
   uint32_t                           ul_failure_timer;
   uint32_t                           ue_release_timer;
   uint32_t                           ue_release_timer_thres;
diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c
index 4543ff3050d1bc0d4cfa433ee983ba1a0ff9539f..d93510ac5d0794941f64507d87cfd17aa1dae99e 100644
--- a/openair2/RRC/LTE/rrc_eNB.c
+++ b/openair2/RRC/LTE/rrc_eNB.c
@@ -116,6 +116,10 @@ extern int rrc_eNB_process_security(const protocol_ctxt_t *const ctxt_pP, rrc_eN
 extern void process_eNB_security_key (const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, uint8_t *security_key_pP);
 extern int derive_keNB_star(const uint8_t *kenb_32, const uint16_t pci, const uint32_t earfcn_dl, const bool is_rel8_only, uint8_t * kenb_star);
 
+pthread_mutex_t      rrc_release_freelist;
+RRC_release_list_t   rrc_release_info;
+pthread_mutex_t      lock_ue_freelist;
+
 void
 openair_rrc_on(
   const protocol_ctxt_t *const ctxt_pP
@@ -1110,6 +1114,8 @@ void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag) {
   free_list->UE_free_ctrl[free_list->tail_freelist].rnti = rnti;
   free_list->UE_free_ctrl[free_list->tail_freelist].removeContextFlg = removeFlag;
   free_list->num_UEs++;
+  eNB_MAC->UE_release_req.ue_release_request_body.ue_release_request_TLVs_list[eNB_MAC->UE_release_req.ue_release_request_body.number_of_TLVs].rnti = rnti;
+  eNB_MAC->UE_release_req.ue_release_request_body.number_of_TLVs++;
   free_list->tail_freelist = (free_list->tail_freelist + 1) % (NUMBER_OF_UE_MAX+1);
   pthread_mutex_unlock(&lock_ue_freelist);
 }
@@ -1154,28 +1160,32 @@ void release_UE_in_freeList(module_id_t mod_id) {
 
         for (i=0; i<MAX_MOBILES_PER_ENB; i++) {
           ulsch = eNB_PHY->ulsch[i];
-
           if((ulsch != NULL) && (ulsch->rnti == rnti)) {
             void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch);
             LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti);
             clean_eNb_ulsch(ulsch);
           }
 
-          if(eNB_PHY->uci_vars[i].rnti == rnti) {
-            LOG_I(MAC, "clean eNb uci_vars[%d] UE %x \n",i, rnti);
-            memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI));
-          }
-        }
-
-        for (i=0; i<MAX_MOBILES_PER_ENB; i++) {
           dlsch = eNB_PHY->dlsch[i][0];
-
           if((dlsch != NULL) && (dlsch->rnti == rnti)) {
             void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
             LOG_I(RRC, "clean_eNb_dlsch dlsch[%d] UE %x \n", i, rnti);
             clean_eNb_dlsch(dlsch);
           }
         }
+        ulsch = eNB_PHY->ulsch[i];
+        if((ulsch != NULL) && (ulsch->rnti == rnti)) {
+          void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch);
+          LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti);
+          clean_eNb_ulsch(ulsch);
+        }
+
+        for (i=0; i<NUMBER_OF_UCI_VARS_MAX; i++) {
+          if(eNB_PHY->uci_vars[i].rnti == rnti) {
+            LOG_I(MAC, "clean eNb uci_vars[%d] UE %x \n",i, rnti);
+            memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI));
+          }
+        }
 
         if (flexran_agent_get_rrc_xface(mod_id)) {
           flexran_agent_get_rrc_xface(mod_id)->flexran_agent_notify_ue_state_change(
@@ -1237,6 +1247,34 @@ void release_UE_in_freeList(module_id_t mod_id) {
   }
 }
 
+int rrc_eNB_previous_SRB2(rrc_eNB_ue_context_t*         ue_context_pP)
+{
+  struct LTE_SRB_ToAddMod                *SRB2_config = NULL;
+  uint8_t i;
+  LTE_SRB_ToAddModList_t*                 SRB_configList = ue_context_pP->ue_context.SRB_configList;
+  LTE_SRB_ToAddModList_t**                SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[ue_context_pP->ue_context.reestablishment_xid];
+  if (*SRB_configList2 != NULL) {
+    if((*SRB_configList2)->list.count!=0){
+      LOG_D(RRC, "rrc_eNB_previous_SRB2 SRB_configList2(%p) count is %d\n           SRB_configList2->list.array[0] addr is %p",
+              SRB_configList2, (*SRB_configList2)->list.count,  (*SRB_configList2)->list.array[0]);
+    }
+    for (i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) {
+      if ((*SRB_configList2)->list.array[i]->srb_Identity == 2 ){
+        SRB2_config = (*SRB_configList2)->list.array[i];
+        break;
+      }
+    }
+  }else{
+    LOG_E(RRC, "rrc_eNB_previous_SRB2 SRB_configList2 NULL\n");
+  }
+
+  if (SRB2_config != NULL) {
+    ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config);
+  }else{
+    LOG_E(RRC, "rrc_eNB_previous_SRB2 SRB2_config NULL\n");
+  }
+  return 0;
+}
 //-----------------------------------------------------------------------------
 /*
 * Process the rrc connection setup complete message from UE (SRB1 Active)
@@ -1552,10 +1590,6 @@ rrc_eNB_generate_RRCConnectionReestablishment(
           rnti);
   }
 
-  /* Activate release timer, if RRCComplete not received after 100 frames, remove UE */
-  ue_context_pP->ue_context.ue_reestablishment_timer = 1;
-  /* Remove UE after 100 frames after LTE_RRCConnectionReestablishmentReject is triggered */
-  ue_context_pP->ue_context.ue_reestablishment_timer_thres = 1000;
 }
 
 //-----------------------------------------------------------------------------
@@ -1602,6 +1636,8 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete(
   LTE_C_RNTI_t                           *cba_RNTI                         = NULL;
   int                                    measurements_enabled;
   uint8_t next_xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id);
+  int ret = 0;
+
   ue_context_pP->ue_context.Status = RRC_CONNECTED;
   ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED
   ue_context_pP->ue_context.reestablishment_xid = next_xid;
@@ -1707,10 +1743,36 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete(
 
   create_tunnel_req.rnti       = ctxt_pP->rnti; // warning put zero above
   create_tunnel_req.num_tunnels    = j;
-  gtpv1u_update_s1u_tunnel(
+
+    ret = gtpv1u_update_s1u_tunnel(
     ctxt_pP->instance,
     &create_tunnel_req,
     reestablish_rnti);
+    if ( ret != 0 ) {
+      LOG_E(RRC,"gtpv1u_update_s1u_tunnel failed,start to release UE %x\n",reestablish_rnti);
+      // update s1u tunnel failed,reset rnti?
+      if (eNB_ue_s1ap_id > 0) {
+        h_rc = hashtable_get(rrc_instance_p->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id, (void**)&rrc_ue_s1ap_ids_p);
+        if (h_rc == HASH_TABLE_OK ) {
+          rrc_ue_s1ap_ids_p->ue_rnti = reestablish_rnti;
+        }
+      }
+      if (ue_initial_id != 0) {
+        h_rc = hashtable_get(rrc_instance_p->initial_id2_s1ap_ids, (hash_key_t)ue_initial_id, (void**)&rrc_ue_s1ap_ids_p);
+        if (h_rc == HASH_TABLE_OK ) {
+          rrc_ue_s1ap_ids_p->ue_rnti = reestablish_rnti;
+        }
+      }
+      ue_context_pP->ue_context.ue_release_timer_s1 = 1;
+      ue_context_pP->ue_context.ue_release_timer_thres_s1 = 100;
+      ue_context_pP->ue_context.ue_release_timer = 0;
+      ue_context_pP->ue_context.ue_reestablishment_timer = 0;
+      ue_context_pP->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ
+      rrc_eNB_free_UE(ctxt_pP->module_id,ue_context_pP);
+      ue_context_pP->ue_context.ul_failure_timer = 0;
+      put_UE_in_freelist(ctxt_pP->module_id, ctxt_pP->rnti, 0);
+      return;
+    }
   } /* EPC_MODE_ENABLED */
 
   /* Update RNTI in ue_context */
@@ -2232,8 +2294,9 @@ rrc_eNB_generate_RRCConnectionRelease(
     ue_context_pP->ue_context.rnti,
     rrc_eNB_mui,
     size);
-  pthread_mutex_lock(&rrc_release_freelist);
-
+  while (pthread_mutex_trylock(&rrc_release_freelist)) {
+    /* spin... */
+  }
   for (uint16_t release_num = 0; release_num < NUMBER_OF_UE_MAX; release_num++) {
     if (rrc_release_info.RRC_release_ctrl[release_num].flag == 0) {
       if (ue_context_pP->ue_context.ue_release_timer_s1 > 0) {
@@ -4056,8 +4119,40 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt
   MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0;
   MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1;
   MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6;
-  MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = (LTE_Q_OffsetRange_t *) CALLOC(1,sizeof(LTE_Q_OffsetRange_t));
-  *(MeasObj->measObject.choice.measObjectEUTRA.offsetFreq) = ue_context_pP->ue_context.measurement_info->offsetFreq;   // Default is 15 or 0dB
+//<<<<<<< HEAD
+  MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL;   // Default is 15 or 0dB
+  if (rrc_inst->carrier[0].sib1->tdd_Config!=NULL) {
+    MeasObj->measObject.choice.measObjectEUTRA.ext1 = CALLOC(1, sizeof(struct LTE_MeasObjectEUTRA__ext1));
+    MeasObj->measObject.choice.measObjectEUTRA.ext1->measCycleSCell_r10 = NULL;
+    MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10 = CALLOC(1, sizeof(struct LTE_MeasSubframePatternConfigNeigh_r10));
+    MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->present=LTE_MeasSubframePatternConfigNeigh_r10_PR_setup;
+    MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.present=LTE_MeasSubframePattern_r10_PR_subframePatternTDD_r10;
+    MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.present=LTE_MeasSubframePattern_r10__subframePatternTDD_r10_PR_subframeConfig1_5_r10;
+    MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.choice.subframeConfig1_5_r10.buf=CALLOC(3, sizeof(uint8_t));
+    MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.choice.subframeConfig1_5_r10.size=3;
+    MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.choice.subframeConfig1_5_r10.bits_unused=4; 
+    switch (rrc_inst->carrier[0].sib1->tdd_Config->subframeAssignment) {
+    case 1: //subframe 0,4,5,9
+      MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.choice.subframeConfig1_5_r10.buf[0]=0x8C;
+      MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.choice.subframeConfig1_5_r10.buf[1]=0x63;
+      MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.choice.subframeConfig1_5_r10.buf[2]=0x10;
+      break;
+
+    default: //subframe 0 , 5
+      MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.choice.subframeConfig1_5_r10.buf[0]=0x84;
+      MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.choice.subframeConfig1_5_r10.buf[1]=0x21;
+      MeasObj->measObject.choice.measObjectEUTRA.ext1->measSubframePatternConfigNeigh_r10->choice.setup.measSubframePatternNeigh_r10.choice.subframePatternTDD_r10.choice.subframeConfig1_5_r10.buf[2]=0x00;
+      break;
+    }
+  }
+
+  MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList =
+    (LTE_CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList));
+  CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList;
+//=======
+//  MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = (LTE_Q_OffsetRange_t *) CALLOC(1,sizeof(LTE_Q_OffsetRange_t));
+//  *(MeasObj->measObject.choice.measObjectEUTRA.offsetFreq) = ue_context_pP->ue_context.measurement_info->offsetFreq;   // Default is 15 or 0dB
+//>>>>>>> origin/OAI_develop
 
   if (RC.rrc[ctxt_pP->module_id]->num_neigh_cells > 0) {
     MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList =
@@ -4553,7 +4648,9 @@ rrc_eNB_process_MeasurementReport(
     /* HO info struct may not be needed anymore */
     ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info)));
     ue_context_pP->ue_context.Status = RRC_HO_EXECUTION;
+
     ue_context_pP->ue_context.handover_info->state = HO_REQUEST;
+
     /* HO Preparation message */
     msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ);
     rrc_eNB_generate_HandoverPreparationInformation(
@@ -4610,10 +4707,10 @@ rrc_eNB_generate_HandoverPreparationInformation(
   uint8_t                     *buffer,
   int                          *_size
 ) {
-  memset(buffer, 0, RRC_BUF_SIZE);
+  memset(buffer, 0, 8192);
   char *ho_buf = (char *) buffer;
   int ho_size;
-  ho_size = do_HandoverPreparation(ho_buf, 1024, ue_context_pP->ue_context.UE_Capability, ue_context_pP->ue_context.UE_Capability_size);
+  ho_size = do_HandoverPreparation(ho_buf, 8192, ue_context_pP->ue_context.UE_Capability, ue_context_pP->ue_context.UE_Capability_size);
   *_size = ho_size;
 }
 
@@ -4681,8 +4778,8 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re
   RB_INSERT(rrc_ue_tree_s, &RC.rrc[mod_id]->rrc_ue_head, ue_context_target_p);
   LOG_D(RRC, "eNB %d: Created new UE context uid %u\n", mod_id, ue_context_target_p->local_uid);
   ue_context_target_p->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_target_p->ue_context.handover_info)));
-  ue_context_target_p->ue_context.Status = RRC_HO_EXECUTION;
-  ue_context_target_p->ue_context.handover_info->state = HO_ACK;
+  //ue_context_target_p->ue_context.Status = RRC_HO_EXECUTION;
+  //ue_context_target_p->ue_context.handover_info->state = HO_ACK;
   ue_context_target_p->ue_context.handover_info->x2_id = m->x2_id;
   ue_context_target_p->ue_context.handover_info->assoc_id = m->target_assoc_id;
   memset (ue_context_target_p->ue_context.nh, 0, 32);
@@ -4756,6 +4853,10 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re
           ue_context_target_p->ue_context.e_rab[i].param.e_rab_id,
           ue_context_target_p->ue_context.e_rab[i].param.gtp_teid);
   }
+  rrc_eNB_process_X2AP_TUNNEL_SETUP_REQ(mod_id, ue_context_target_p);
+
+  ue_context_target_p->ue_context.Status = RRC_HO_EXECUTION;
+  ue_context_target_p->ue_context.handover_info->state = HO_ACK;
 }
 
 void rrc_eNB_process_handoverCommand(
@@ -4971,7 +5072,8 @@ check_handovers(
       if (ue_context_p->ue_context.handover_info->state == HO_ACK) {
         MessageDef *msg;
         // Configure target
-        ue_context_p->ue_context.handover_info->state = HO_CONFIGURED;
+        ue_context_p->ue_context.handover_info->state = HO_FORWARDING;
+
         msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ_ACK);
         rrc_eNB_generate_HO_RRCConnectionReconfiguration(ctxt_pP, ue_context_p, X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer,
             &X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size);
@@ -4984,13 +5086,162 @@ check_handovers(
         X2AP_HANDOVER_REQ_ACK(msg).nb_e_rabs_tobesetup = ue_context_p->ue_context.setup_e_rabs;
 
         for (int i=0; i<ue_context_p->ue_context.setup_e_rabs; i++) {
+          /* set gtpv teid info */
           X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].e_rab_id = ue_context_p->ue_context.e_rab[i].param.e_rab_id;
+	  X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].gtp_teid = ue_context_p->ue_context.enb_gtp_x2u_teid[i];
+          X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].eNB_addr = ue_context_p->ue_context.enb_gtp_x2u_addrs[i];
         }
 
         itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg);
         LOG_I(RRC, "RRC Sends X2 HO ACK to the source eNB at frame %d and subframe %d \n", ctxt_pP->frame,ctxt_pP->subframe);
       }
     }
+
+    if (ue_context_p->ue_context.Status == RRC_RECONFIGURED 
+	&& ue_context_p->ue_context.handover_info != NULL && 
+	ue_context_p->ue_context.handover_info->forwarding_state == FORWARDING_NO_EMPTY ) {
+
+#if defined(ENABLE_ITTI)
+      MessageDef	 *msg_p;
+      int		 result;
+      protocol_ctxt_t  ctxt;
+
+      do {
+        // Checks if a message has been sent to PDCP sub-task
+	itti_poll_msg (TASK_DATA_FORWARDING, &msg_p);
+  
+	if (msg_p != NULL) {
+  
+	  switch (ITTI_MSG_ID(msg_p)) {
+	    case GTPV1U_ENB_DATA_FORWARDING_IND:
+	    PROTOCOL_CTXT_SET_BY_MODULE_ID(
+			&ctxt,
+			GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).module_id,
+			GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).enb_flag,
+			GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rnti,
+			GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).frame, 
+		        0,
+		        GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).eNB_index);
+	    LOG_D(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
+		  PROTOCOL_CTXT_ARGS(&ctxt),
+		  ITTI_MSG_NAME (msg_p),
+		  ITTI_MSG_ORIGIN_NAME(msg_p),
+		  ITTI_MSG_INSTANCE (msg_p),
+		  GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id,
+		  GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).muip,
+		  GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).confirmp,
+		  GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).mode);
+  
+	    LOG_I(RRC, "Before calling pdcp_data_req from check_handovers! GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id: %d \n", GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id);
+            result = pdcp_data_req (&ctxt,
+				    SRB_FLAG_NO,
+			            GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id,
+				    GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).muip,
+				    GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).confirmp,
+			            GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).sdu_size,
+				    GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).sdu_p,
+				    GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).mode
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+				    , NULL, NULL
+#endif
+				    );
+	    if (result != TRUE){
+              LOG_E(RRC, "target enb send data forwarding buffer to PDCP request failed!\n");   
+            }else{
+              LOG_D(RRC, "target enb send data forwarding buffer to PDCP!\n");
+            }
+
+            // Message buffer has been processed, free it now.
+	    result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).sdu_p);
+	    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+            break;
+  
+	default:
+	  LOG_E(RRC, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
+	  break;
+	}
+  
+	result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
+	AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+      }
+    } while(msg_p != NULL);
+    ue_context_p->ue_context.handover_info->forwarding_state = FORWARDING_EMPTY;
+    }
+    if( ue_context_p->ue_context.Status == RRC_RECONFIGURED &&
+	ue_context_p->ue_context.handover_info != NULL &&
+	ue_context_p->ue_context.handover_info->forwarding_state == FORWARDING_EMPTY &&
+	ue_context_p->ue_context.handover_info->endmark_state == ENDMARK_NO_EMPTY &&
+	ue_context_p->ue_context.handover_info->state == HO_END_MARKER	  ){
+
+      MessageDef	 *msg_p;
+      int		 result;
+      protocol_ctxt_t  ctxt;
+
+      do {
+        // Checks if a message has been sent to PDCP sub-task
+        itti_poll_msg (TASK_END_MARKER, &msg_p);
+
+        if (msg_p != NULL) {
+
+	switch (ITTI_MSG_ID(msg_p)) {
+	  case GTPV1U_ENB_END_MARKER_IND:
+	    PROTOCOL_CTXT_SET_BY_MODULE_ID(
+	        &ctxt,
+		GTPV1U_ENB_END_MARKER_IND (msg_p).module_id,
+	        GTPV1U_ENB_END_MARKER_IND (msg_p).enb_flag,
+		GTPV1U_ENB_END_MARKER_IND (msg_p).rnti,
+		GTPV1U_ENB_END_MARKER_IND (msg_p).frame,
+		0,
+		GTPV1U_ENB_END_MARKER_IND (msg_p).eNB_index);
+	    LOG_I(RRC, PROTOCOL_CTXT_FMT"[check_handovers]Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
+		  PROTOCOL_CTXT_ARGS(&ctxt),
+		  ITTI_MSG_NAME (msg_p),
+		  ITTI_MSG_ORIGIN_NAME(msg_p),
+		  ITTI_MSG_INSTANCE (msg_p),
+		  GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id,
+		  GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).muip,
+		  GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).confirmp,
+		  GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).mode);
+
+	    LOG_D(RRC, "Before calling pdcp_data_req from check_handovers! GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id: %d \n", GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).rb_id);
+	    result = pdcp_data_req (&ctxt,
+		  		    SRB_FLAG_NO,
+		  		    GTPV1U_ENB_END_MARKER_IND (msg_p).rb_id,
+		  		    GTPV1U_ENB_END_MARKER_IND (msg_p).muip,
+		  		    GTPV1U_ENB_END_MARKER_IND (msg_p).confirmp,
+		  		    GTPV1U_ENB_END_MARKER_IND (msg_p).sdu_size,
+		  		    GTPV1U_ENB_END_MARKER_IND (msg_p).sdu_p,
+		  		    GTPV1U_ENB_END_MARKER_IND (msg_p).mode
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+		  		    , NULL, NULL
+#endif
+		  		   );
+	    if (result != TRUE){
+              LOG_E(RRC, "target enb send spgw buffer to PDCP request failed!\n");
+	    }else{
+	      LOG_D(RRC, "target enb send spgw buffer to PDCP!\n");
+	    }
+
+	    // Message buffer has been processed, free it now.
+	    result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), GTPV1U_ENB_END_MARKER_IND (msg_p).sdu_p);
+	    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+	    break;
+
+	    default:
+	      LOG_E(RRC, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
+	      break;
+          }
+
+          result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
+          AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+        }
+      } while(msg_p != NULL);
+
+      ue_context_p->ue_context.handover_info->endmark_state = ENDMARK_EMPTY;
+      ue_context_p->ue_context.handover_info->state = HO_FORWARDING_COMPLETE;
+
+#endif
+    }
   }
 }
 
@@ -7002,15 +7253,51 @@ rrc_eNB_decode_ccch(
             rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id);
             break;
           }
-
+      if((RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer > 0) &&
+         (RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres > 20)){
+         LOG_E(RRC,
+               PROTOCOL_RRC_CTXT_UE_FMT" RCConnectionReestablishmentComplete(Previous) don't receive, delete the c-rnti UE\n",
+               PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
+         RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1000;
+         rrc_eNB_previous_SRB2(ue_context_p);
+         ue_context_p->ue_context.ue_reestablishment_timer = 0;
+      }
+      //previous rnti
+      rnti_t previous_rnti = 0;
+      for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
+        if (reestablish_rnti_map[i][1] == c_rnti) {
+          previous_rnti = reestablish_rnti_map[i][0];
+          break;
+        }
+      }
+      if(previous_rnti != 0){
+        UE_id = find_UE_id(ctxt_pP->module_id, previous_rnti);
+        if(UE_id == -1){
+            LOG_E(RRC,
+                  PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReestablishmentRequest without UE_id(MAC) previous rnti %x, let's reject the UE\n",
+                  PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),previous_rnti);
+            rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id);
+            break;
+        }
           if((RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer > 0) &&
               (RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres > 20)) {
             LOG_E(RRC,
                   PROTOCOL_RRC_CTXT_UE_FMT" RCConnectionReestablishmentComplete(Previous) don't receive, delete the Previous UE\n",
                   PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
             RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1000;
-            ue_context_p->ue_context.ue_reestablishment_timer = 0;
-          }
+          rrc_eNB_previous_SRB2(ue_context_p);
+          ue_context_p->ue_context.ue_reestablishment_timer = 0;
+        }
+      }
+
+      //c-plane not end
+      if((ue_context_p->ue_context.Status != RRC_RECONFIGURED) && (ue_context_p->ue_context.reestablishment_cause == LTE_ReestablishmentCause_spare1)) {
+        LOG_E(RRC,
+             PROTOCOL_RRC_CTXT_UE_FMT" LTE_RRCConnectionReestablishmentRequest (UE %x c-plane is not end), let's reject the UE\n",
+             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),c_rnti);
+        rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id);
+        break;
+      }
 
           if(ue_context_p->ue_context.ue_reestablishment_timer > 0) {
             LOG_E(RRC,
@@ -7553,6 +7840,9 @@ rrc_eNB_decode_dcch(
               dedicated_DRB = 3;
               RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0;
               ue_context_p->ue_context.Status = RRC_RECONFIGURED;
+	      if(ue_context_p->ue_context.handover_info){
+	        ue_context_p->ue_context.handover_info->state = HO_CONFIGURED;
+	      }
               LOG_I(RRC,
                     PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_HO_EXECUTION (xid %ld)\n",
                     PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
@@ -7631,6 +7921,7 @@ rrc_eNB_decode_dcch(
             }
           } else if(dedicated_DRB == 0) {
             if(ue_context_p->ue_context.reestablishment_cause == LTE_ReestablishmentCause_spare1) {
+              
               rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP,
                   ue_context_p);
             } else {
@@ -7725,7 +8016,7 @@ rrc_eNB_decode_dcch(
           }
 
           RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0;
-          ue_context_p->ue_context.ue_reestablishment_timer = 0;
+          ue_context_p->ue_context.reestablishment_xid = -1;
 
           if (ul_dcch_msg->message.choice.c1.choice.rrcConnectionReestablishmentComplete.criticalExtensions.present ==
               LTE_RRCConnectionReestablishmentComplete__criticalExtensions_PR_rrcConnectionReestablishmentComplete_r8) {
@@ -8536,7 +8827,7 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
   instance = ITTI_MSG_INSTANCE(msg_p);
   /* RRC_SUBFRAME_PROCESS is sent every subframe, do not log it */
   if (ITTI_MSG_ID(msg_p) != RRC_SUBFRAME_PROCESS)
-    LOG_I(RRC,"Received message %s\n",msg_name_p);
+    LOG_D(RRC,"Received message %s\n",msg_name_p);
 
   switch (ITTI_MSG_ID(msg_p)) {
     case TERMINATE_MESSAGE:
@@ -8675,6 +8966,9 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
 
     case X2AP_HANDOVER_REQ_ACK: {
       struct rrc_eNB_ue_context_s        *ue_context_p = NULL;
+      x2ap_handover_req_ack_t 			  *x2ap_handover_req_ack = NULL;
+      hashtable_rc_t                	  hash_rc      = HASH_TABLE_KEY_NOT_EXISTS;
+      gtpv1u_ue_data_t             		  *gtpv1u_ue_data_p = NULL;
       ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], X2AP_HANDOVER_REQ_ACK(msg_p).rnti);
       if (ue_context_p == NULL) {
         /* is it possible? */
@@ -8686,7 +8980,44 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
       DevAssert(ue_context_p != NULL);
 
       if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort();
+	  
+      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, ue_context_p->ue_context.rnti, (void**)&gtpv1u_ue_data_p);
+      /* set target enb gtp teid */
+      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
+        LOG_E(RRC, "X2AP_HANDOVER_REQ_ACK func(), hashtable_get failed: while getting ue rnti %x in hashtable ue_mapping\n", ue_context_p->ue_context.rnti);
+      } else {
+        uint8_t nb_e_rabs_tobesetup = 0;
+	ebi_t   eps_bearer_id       = 0;
+	int     ip_offset           = 0;
+	in_addr_t  in_addr;
+	x2ap_handover_req_ack = &X2AP_HANDOVER_REQ_ACK(msg_p);
+	nb_e_rabs_tobesetup = x2ap_handover_req_ack->nb_e_rabs_tobesetup;
+        ue_context_p->ue_context.nb_x2u_e_rabs = nb_e_rabs_tobesetup;
+	for(int i=0; i< nb_e_rabs_tobesetup; i++){
+	  ip_offset               = 0;
+	  eps_bearer_id = x2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id;
+          ue_context_p->ue_context.enb_gtp_x2u_ebi[i] = eps_bearer_id;
+          ue_context_p->ue_context.enb_gtp_x2u_teid[i] = x2ap_handover_req_ack->e_rabs_tobesetup[i].gtp_teid;
+	  gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_teNB = x2ap_handover_req_ack->e_rabs_tobesetup[i].gtp_teid; 
+			
+	  if ((x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.length == 4) ||
+	      (x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.length == 20)) {
+	      in_addr = *((in_addr_t*)x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.buffer);
+	      ip_offset = 4;
+	      gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr = in_addr;
+              ue_context_p->ue_context.enb_gtp_x2u_addrs[i] = x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr;
+	  }
+
+	  if ((x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.length == 16) ||
+	      (x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.length == 20)) {
+	      memcpy(gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].tenb_ip6_addr.s6_addr,
+		     &x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.buffer[ip_offset],
+		     16);
+          }
 
+        }
+      }
+	  
       rrc_eNB_process_handoverCommand(instance, ue_context_p, &X2AP_HANDOVER_REQ_ACK(msg_p));
       ue_context_p->ue_context.handover_info->state = HO_PREPARE;
       break;
diff --git a/openair2/RRC/LTE/rrc_eNB_GTPV1U.c b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c
index ff8f455d6cb5d1c88e6b884984e6db5b46563e3d..d873a825ba9ee2661c5c88ec4dab6c876a4955cf 100644
--- a/openair2/RRC/LTE/rrc_eNB_GTPV1U.c
+++ b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c
@@ -27,14 +27,19 @@
  * \email: lionel.gauthier@eurecom.fr
  */
 
+//#if defined(ENABLE_USE_MME)
 # include "rrc_defs.h"
 # include "rrc_extern.h"
 # include "RRC/LTE/MESSAGES/asn1_msg.h"
 # include "rrc_eNB_GTPV1U.h"
 # include "rrc_eNB_UE_context.h"
 # include "msc.h"
+
+//# if defined(ENABLE_ITTI)
 #   include "asn1_conversions.h"
 #   include "intertask_interface.h"
+//#endif
+
 # include "common/ran_context.h"
 
 extern RAN_CONTEXT_t RC;
@@ -88,6 +93,88 @@ rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(
   }
 }
 
+//------------------------------------------------------------------------------
+boolean_t
+gtpv_data_req(
+  const protocol_ctxt_t*   const ctxt_pP,
+  const rb_id_t                  rb_idP,
+  const mui_t                    muiP,
+  const confirm_t                confirmP,
+  const sdu_size_t               sdu_sizeP,
+  uint8_t*                 const buffer_pP,
+  const pdcp_transmission_mode_t modeP,
+  uint32_t task_id
+)
+//------------------------------------------------------------------------------
+{
+  if(sdu_sizeP == 0)
+  {
+    LOG_I(GTPU,"gtpv_data_req sdu_sizeP == 0");
+    return FALSE;
+  }
+  LOG_D(GTPU,"gtpv_data_req ue rnti %x sdu_sizeP %d rb id %d", ctxt_pP->rnti, sdu_sizeP, rb_idP);
+#if defined(ENABLE_ITTI)
+  {
+    MessageDef *message_p;
+    // Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling).
+    uint8_t *message_buffer;
+
+    if(task_id == TASK_DATA_FORWARDING){
+
+      LOG_I(GTPU,"gtpv_data_req task_id = TASK_DATA_FORWARDING\n");
+
+      message_buffer = itti_malloc (TASK_GTPV1_U, TASK_DATA_FORWARDING, sdu_sizeP);
+
+      memcpy (message_buffer, buffer_pP, sdu_sizeP);
+
+      message_p = itti_alloc_new_message (TASK_GTPV1_U, GTPV1U_ENB_DATA_FORWARDING_IND);
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).frame 	= ctxt_pP->frame;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).enb_flag	= ctxt_pP->enb_flag;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rb_id 	= rb_idP;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).muip		= muiP;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).confirmp	= confirmP;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_size	= sdu_sizeP;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_p 	= message_buffer;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).mode		= modeP;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).module_id = ctxt_pP->module_id;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rnti		 = ctxt_pP->rnti;
+      GTPV1U_ENB_DATA_FORWARDING_IND (message_p).eNB_index = ctxt_pP->eNB_index;
+
+      itti_send_msg_to_task (TASK_DATA_FORWARDING, ctxt_pP->instance, message_p);
+      return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway.
+    }else if(task_id == TASK_END_MARKER){
+      
+      LOG_I(GTPU,"gtpv_data_req task_id = TASK_END_MARKER\n");
+
+      message_buffer = itti_malloc (TASK_GTPV1_U, TASK_END_MARKER, sdu_sizeP);
+
+      memcpy (message_buffer, buffer_pP, sdu_sizeP);
+
+      message_p = itti_alloc_new_message (TASK_GTPV1_U, GTPV1U_ENB_END_MARKER_IND);
+      GTPV1U_ENB_END_MARKER_IND (message_p).frame 	= ctxt_pP->frame;
+      GTPV1U_ENB_END_MARKER_IND (message_p).enb_flag	= ctxt_pP->enb_flag;
+      GTPV1U_ENB_END_MARKER_IND (message_p).rb_id 	= rb_idP;
+      GTPV1U_ENB_END_MARKER_IND (message_p).muip		= muiP;
+      GTPV1U_ENB_END_MARKER_IND (message_p).confirmp	= confirmP;
+      GTPV1U_ENB_END_MARKER_IND (message_p).sdu_size	= sdu_sizeP;
+      GTPV1U_ENB_END_MARKER_IND (message_p).sdu_p 	= message_buffer;
+      GTPV1U_ENB_END_MARKER_IND (message_p).mode		= modeP;
+      GTPV1U_ENB_END_MARKER_IND (message_p).module_id = ctxt_pP->module_id;
+      GTPV1U_ENB_END_MARKER_IND (message_p).rnti		 = ctxt_pP->rnti;
+      GTPV1U_ENB_END_MARKER_IND (message_p).eNB_index = ctxt_pP->eNB_index;
+
+      itti_send_msg_to_task (TASK_END_MARKER, ctxt_pP->instance, message_p);
+      return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway.
+    }
+  }
+#endif
+
+  return TRUE;
+
+}
+
+//#endif
+
 void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ(
   module_id_t enb_mod_idP,
   const rrc_eNB_ue_context_t* const ue_context_pP
@@ -112,3 +199,5 @@ void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ(
   }
   itti_send_msg_to_task(TASK_GTPV1_U, ENB_MODULE_ID_TO_INSTANCE(enb_mod_idP), msg);
 }
+
+
diff --git a/openair2/RRC/LTE/rrc_eNB_GTPV1U.h b/openair2/RRC/LTE/rrc_eNB_GTPV1U.h
index 23806f6a0482544ee0bb8845dc89d043760422d5..00c7490359031a138200ee8c59db35023dcd4957 100644
--- a/openair2/RRC/LTE/rrc_eNB_GTPV1U.h
+++ b/openair2/RRC/LTE/rrc_eNB_GTPV1U.h
@@ -53,4 +53,16 @@ void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ(
   const rrc_eNB_ue_context_t* const ue_context_pP
 );
 
+boolean_t
+gtpv_data_req(
+  const protocol_ctxt_t*   const ctxt_pP,
+  const rb_id_t                  rb_idP,
+  const mui_t                    muiP,
+  const confirm_t                confirmP,
+  const sdu_size_t               sdu_sizeP,
+  uint8_t*                 const buffer_pP,
+  const pdcp_transmission_mode_t modeP,
+  uint32_t task_id
+);
+
 #endif /* RRC_ENB_GTPV1U_H_ */
diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c
index dabe5b1524638ae853db20df68e8cdea9af3d55c..23284b4b4f190888800187165c873321c459101e 100644
--- a/openair2/RRC/LTE/rrc_eNB_S1AP.c
+++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c
@@ -257,6 +257,15 @@ rrc_eNB_S1AP_get_ue_ids(
         }
 
         if (ue_desc_p != NULL) {
+          struct s1ap_eNB_ue_context_s *s1ap_ue_context_p = NULL;
+          if ((s1ap_ue_context_p = RB_REMOVE(s1ap_ue_map, &s1ap_eNB_instance_p->s1ap_ue_head, ue_desc_p)) != NULL) {
+            LOG_E(RRC, "Removed UE context eNB_ue_s1ap_id %u\n", s1ap_ue_context_p->eNB_ue_s1ap_id);
+            s1ap_eNB_free_ue_context(s1ap_ue_context_p);
+          } else {
+            LOG_E(RRC, "Removing UE context eNB_ue_s1ap_id %u: did not find context\n",ue_desc_p->eNB_ue_s1ap_id);
+          }
+          return NULL; //skip the operation below to avoid loop
+          result = rrc_eNB_S1AP_get_ue_ids(rrc_instance_pP, ue_desc_p->ue_initial_id, eNB_ue_s1ap_id);
           if (ue_desc_p->ue_initial_id != UE_INITIAL_ID_INVALID) {
             result = rrc_eNB_S1AP_get_ue_ids(rrc_instance_pP, ue_desc_p->ue_initial_id, eNB_ue_s1ap_id);
 
@@ -935,6 +944,8 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
   gtpv1u_enb_create_tunnel_req_t  create_tunnel_req;
   gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
   uint8_t                         inde_list[NB_RB_MAX - 3]= {0};
+  int                             ret;
+
   struct rrc_eNB_ue_context_s *ue_context_p = NULL;
   protocol_ctxt_t              ctxt;
   ue_initial_id  = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).ue_initial_id;
@@ -976,10 +987,23 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
 
       create_tunnel_req.rnti       = ue_context_p->ue_context.rnti; // warning put zero above
       //      create_tunnel_req.num_tunnels    = i;
-      gtpv1u_create_s1u_tunnel(
+
+      ret = gtpv1u_create_s1u_tunnel(
         instance,
         &create_tunnel_req,
         &create_tunnel_resp);
+      if ( ret != 0 ) {
+        LOG_E(RRC,"rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ : gtpv1u_create_s1u_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti);
+        ue_context_p->ue_context.ue_release_timer_s1 = 1;
+        ue_context_p->ue_context.ue_release_timer_thres_s1 = 100;
+        ue_context_p->ue_context.ue_release_timer = 0;
+        ue_context_p->ue_context.ue_reestablishment_timer = 0;
+        ue_context_p->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ
+        rrc_eNB_free_UE(ctxt.module_id,ue_context_p);
+        ue_context_p->ue_context.ul_failure_timer = 0;
+        return (0);
+      }
+
       rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(
         &ctxt,
         &create_tunnel_resp,
@@ -1252,6 +1276,8 @@ int rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(MessageDef *msg_p, const char *msg_name
   struct rrc_eNB_ue_context_s *ue_context_p = NULL;
   protocol_ctxt_t              ctxt;
   uint8_t                      e_rab_done;
+  int                          ret = 0;
+
   ue_initial_id  = S1AP_E_RAB_SETUP_REQ (msg_p).ue_initial_id;
   eNB_ue_s1ap_id = S1AP_E_RAB_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
   ue_context_p   = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
@@ -1314,10 +1340,22 @@ int rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(MessageDef *msg_p, const char *msg_name
       create_tunnel_req.rnti       = ue_context_p->ue_context.rnti; // warning put zero above
       create_tunnel_req.num_tunnels    = e_rab_done;
       // NN: not sure if we should create a new tunnel: need to check teid, etc.
-      gtpv1u_create_s1u_tunnel(
+      ret = gtpv1u_create_s1u_tunnel(
         instance,
         &create_tunnel_req,
         &create_tunnel_resp);
+      if ( ret != 0 ) {
+        LOG_E(RRC,"rrc_eNB_process_S1AP_E_RAB_SETUP_REQ : gtpv1u_create_s1u_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti);
+        ue_context_p->ue_context.ue_release_timer_s1 = 1;
+        ue_context_p->ue_context.ue_release_timer_thres_s1 = 100;
+        ue_context_p->ue_context.ue_release_timer = 0;
+        ue_context_p->ue_context.ue_reestablishment_timer = 0;
+        ue_context_p->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ
+        rrc_eNB_free_UE(ctxt.module_id,ue_context_p);
+        ue_context_p->ue_context.ul_failure_timer = 0;
+        return (0);
+      }
+
       rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(
         &ctxt,
         &create_tunnel_resp,
@@ -2040,6 +2078,69 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP,
   return 0;
 }
 
+int rrc_eNB_process_X2AP_TUNNEL_SETUP_REQ(instance_t instance, rrc_eNB_ue_context_t* const ue_context_target_p) {
+  gtpv1u_enb_create_x2u_tunnel_req_t  create_tunnel_req;
+  gtpv1u_enb_create_x2u_tunnel_resp_t create_tunnel_resp;
+  uint8_t                      		  e_rab_done;
+  uint8_t                         	  inde_list[NB_RB_MAX - 3]= {0};
+  
+  if (ue_context_target_p == NULL) {
+    
+    return (-1);
+  } else {
+    
+    /* Save e RAB information for later */
+    {
+      LOG_I(RRC, "[eNB %d] rrc_eNB_process_X2AP_TUNNEL_SETUP_REQ: rnti %u nb_of_e_rabs %d\n",
+            instance, ue_context_target_p->ue_context.rnti, ue_context_target_p->ue_context.nb_of_e_rabs);
+      int i;
+      memset(&create_tunnel_req, 0, sizeof(create_tunnel_req));
+      uint8_t nb_e_rabs_tosetup = ue_context_target_p->ue_context.nb_of_e_rabs;
+      e_rab_done = 0;
+
+      for (i = 0;i < nb_e_rabs_tosetup; i++) {
+
+        if(ue_context_target_p->ue_context.e_rab[i].status >= E_RAB_STATUS_DONE)
+          continue;
+
+        create_tunnel_req.eps_bearer_id[e_rab_done]       = ue_context_target_p->ue_context.e_rab[i].param.e_rab_id;
+        LOG_I(RRC,"x2 tunnel setup: local index %d UE id %x, eps id %d \n",
+              i,
+              ue_context_target_p->ue_context.rnti,
+              create_tunnel_req.eps_bearer_id[i] );
+		inde_list[i] = e_rab_done;
+        e_rab_done++;
+      }
+
+      create_tunnel_req.rnti           = ue_context_target_p->ue_context.rnti; // warning put zero above
+      create_tunnel_req.num_tunnels    = e_rab_done;
+      // NN: not sure if we should create a new tunnel: need to check teid, etc.
+      gtpv1u_create_x2u_tunnel(
+        instance,
+        &create_tunnel_req,
+        &create_tunnel_resp);
+
+          ue_context_target_p->ue_context.nb_x2u_e_rabs = create_tunnel_resp.num_tunnels;
+	  for (i = 0; i < create_tunnel_resp.num_tunnels; i++) {
+		ue_context_target_p->ue_context.enb_gtp_x2u_teid[inde_list[i]]  = create_tunnel_resp.enb_X2u_teid[i];
+	    ue_context_target_p->ue_context.enb_gtp_x2u_addrs[inde_list[i]] = create_tunnel_resp.enb_addr;
+		ue_context_target_p->ue_context.enb_gtp_x2u_ebi[inde_list[i]]   = create_tunnel_resp.eps_bearer_id[i];
+
+		LOG_I(RRC, "rrc_eNB_process_X2AP_TUNNEL_SETUP_REQ tunnel (%u, %u) bearer UE context index %u, msg index %u, eps bearer id %u, gtp addr len %d \n",
+            create_tunnel_resp.enb_X2u_teid[i],
+            ue_context_target_p->ue_context.enb_gtp_x2u_teid[inde_list[i]],            
+            inde_list[i],
+	    	i,
+            create_tunnel_resp.eps_bearer_id[i],
+	    	create_tunnel_resp.enb_addr.length);
+	  }
+    }
+
+    return (0);
+  }
+}
+
+
 int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance) {
   uint16_t                        ue_initial_id;
   uint32_t                        eNB_ue_s1ap_id;
diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.h b/openair2/RRC/LTE/rrc_eNB_S1AP.h
index 5feb55d635c63461b237b439f5f1654d9e2882dc..e5ff9c27d600d6371132e3f33782caeb4a3a96eb 100644
--- a/openair2/RRC/LTE/rrc_eNB_S1AP.h
+++ b/openair2/RRC/LTE/rrc_eNB_S1AP.h
@@ -278,6 +278,7 @@ int rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(const protocol_ctxt_t *const ctxt_p
 
 int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP,
                                  rrc_eNB_ue_context_t          *const ue_context_pP);
+int rrc_eNB_process_X2AP_TUNNEL_SETUP_REQ(instance_t instance, rrc_eNB_ue_context_t* const ue_context_target_p);
 int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance);
 
 int rrc_eNB_send_X2AP_UE_CONTEXT_RELEASE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP);
diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h
index e7e5e71d8093f4d05bb14ddb1a64dd702f8024d5..a8ee7ecabe043b127ab51a8d1bd45d5e340cbba9 100644
--- a/openair2/RRC/LTE/rrc_proto.h
+++ b/openair2/RRC/LTE/rrc_proto.h
@@ -667,9 +667,11 @@ void openair_rrc_top_init_ue(
                         uint8_t cba_group_active,
                         uint8_t HO_active
 );
-pthread_mutex_t      rrc_release_freelist;
-RRC_release_list_t rrc_release_info;
-pthread_mutex_t      lock_ue_freelist;
+
+extern pthread_mutex_t      rrc_release_freelist;
+extern RRC_release_list_t   rrc_release_info;
+extern pthread_mutex_t      lock_ue_freelist;
+
 void remove_UE_from_freelist(module_id_t mod_id, rnti_t rnti);
 void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag);
 void release_UE_in_freeList(module_id_t mod_id);
diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h
index e1a8b506bcabeea022da333856c3b0a03626b481..03d8216b5666a0904fac6492c264384eef0862bd 100644
--- a/openair2/X2AP/x2ap_eNB_defs.h
+++ b/openair2/X2AP/x2ap_eNB_defs.h
@@ -173,6 +173,8 @@ typedef struct x2ap_eNB_instance_s {
   lte_frame_type_t        frame_type[MAX_NUM_CCs];
   uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
   uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  uint32_t                subframeAssignment[MAX_NUM_CCs];
+  uint32_t                specialSubframe[MAX_NUM_CCs];
   int                     num_cc;
 
   net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c
index 53ec8574fd80e4305fc5e6744d5b8b7748d8f459..38ebd732ac390c02832b9f9645c67b96e63fd84e 100644
--- a/openair2/X2AP/x2ap_eNB_generate_messages.c
+++ b/openair2/X2AP/x2ap_eNB_generate_messages.c
@@ -144,7 +144,92 @@ int x2ap_eNB_generate_x2_setup_request(
           }
         }
         else {
-          AssertFatal(0,"X2Setuprequest not supported for TDD!");
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_tDD;
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.eARFCN = instance_p->fdd_earfcn_DL[i];
+          switch (instance_p->subframeAssignment[i]) {
+            case 0:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa0;
+              break;
+            case 1:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa1;
+              break;
+            case 2:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa2;
+              break;
+            case 3:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa3;
+              break;
+            case 4:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa4;
+              break;
+            case 5:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa5;
+              break;
+            case 6:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa6;
+              break;
+            default:
+              AssertFatal(0,"Failed: Check value for subframeAssignment");
+              break;
+          }
+          switch (instance_p->specialSubframe[i]) {
+            case 0:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp0;
+              break;
+            case 1:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp1;
+              break;
+            case 2:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp2;
+              break;
+            case 3:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp3;
+              break;
+            case 4:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp4;
+              break;
+            case 5:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp5;
+              break;
+            case 6:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp6;
+              break;
+            case 7:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp7;
+              break;
+            case 8:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp8;
+              break;
+            default:
+              AssertFatal(0,"Failed: Check value for subframeAssignment");
+              break;
+          }
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.cyclicPrefixDL=X2AP_CyclicPrefixDL_normal;
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.cyclicPrefixUL=X2AP_CyclicPrefixUL_normal;
+          
+          switch (instance_p->N_RB_DL[i]) {
+            case 6:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
+              break;
+            case 15:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
+              break;
+            case 25:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
+              break;
+            case 50:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
+              break;
+            case 75:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
+              break;
+            case 100:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
+              break;
+            default:
+              AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+              break;
+          }
         }
       }
       ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
@@ -279,7 +364,92 @@ int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_instance_t *instance_p, x2ap_eN
           }
         }
         else {
-          AssertFatal(0,"X2Setupresponse not supported for TDD!");
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_tDD;
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.eARFCN = instance_p->fdd_earfcn_DL[i];
+          switch (instance_p->subframeAssignment[i]) {
+            case 0:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa0;
+              break;
+            case 1:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa1;
+              break;
+            case 2:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa2;
+              break;
+            case 3:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa3;
+              break;
+            case 4:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa4;
+              break;
+            case 5:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa5;
+              break;
+            case 6:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa6;
+              break;
+            default:
+              AssertFatal(0,"Failed: Check value for subframeAssignment");
+              break;
+          }
+          switch (instance_p->specialSubframe[i]) {
+            case 0:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp0;
+              break;
+            case 1:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp1;
+              break;
+            case 2:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp2;
+              break;
+            case 3:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp3;
+              break;
+            case 4:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp4;
+              break;
+            case 5:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp5;
+              break;
+            case 6:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp6;
+              break;
+            case 7:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp7;
+              break;
+            case 8:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp8;
+              break;
+            default:
+              AssertFatal(0,"Failed: Check value for subframeAssignment");
+              break;
+          }
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.cyclicPrefixDL=X2AP_CyclicPrefixDL_normal;
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.cyclicPrefixUL=X2AP_CyclicPrefixUL_normal;
+          
+          switch (instance_p->N_RB_DL[i]) {
+            case 6:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
+              break;
+            case 15:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
+              break;
+            case 25:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
+              break;
+            case 50:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
+              break;
+            case 75:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
+              break;
+            case 100:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
+              break;
+            default:
+              AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+              break;
+          }
         }
       }
       ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
@@ -627,6 +797,27 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_instance_t *instance_p,
         e_RABs_Admitted_Item = &e_RABS_Admitted_ItemIEs->value.choice.E_RABs_Admitted_Item;
         {
           e_RABs_Admitted_Item->e_RAB_ID = x2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id;
+	  e_RABs_Admitted_Item->uL_GTP_TunnelEndpoint = NULL;
+	  e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint = (X2AP_GTPtunnelEndpoint_t *)calloc(1, sizeof(*e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint));
+		  
+	  e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.size = (uint8_t)x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.length;
+          e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.bits_unused = 0;
+          e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.buf =
+                        calloc(1, e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.size);
+
+          memcpy (e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.buf,
+                  x2ap_handover_req_ack->e_rabs_tobesetup[i].eNB_addr.buffer,
+                  e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.size);
+
+          X2AP_DEBUG("X2 handover response target ip addr. length %lu bits_unused %d buf %d.%d.%d.%d\n",
+		  e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.size,
+		  e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.bits_unused,
+		  e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.buf[0],
+		  e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.buf[1],
+		  e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.buf[2],
+		  e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.buf[3]);
+		  
+          INT32_TO_OCTET_STRING(x2ap_handover_req_ack->e_rabs_tobesetup[i].gtp_teid, &e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->gTP_TEID);
         }
         ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_List.list, e_RABS_Admitted_ItemIEs);
       }
diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c
index 2a44501a337a3008d7940aed17ba974d03774bcd..33fd9c5295fb8ad890f297a4de96bb564f1f4b00 100644
--- a/openair2/X2AP/x2ap_eNB_handler.c
+++ b/openair2/X2AP/x2ap_eNB_handler.c
@@ -730,7 +730,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
 
   X2AP_RRC_Context_t *c = &ie->value.choice.UE_ContextInformation.rRC_Context;
 
-  if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s*/)
+  if (c->size > 8192 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_s */)
     { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
 
   memcpy(X2AP_HANDOVER_REQ(msg).rrc_buffer, c->buf, c->size);
@@ -749,6 +749,8 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
 {
   X2AP_HandoverRequestAcknowledge_t             *x2HandoverRequestAck;
   X2AP_HandoverRequestAcknowledge_IEs_t         *ie;
+  X2AP_E_RABs_Admitted_ItemIEs_t		 		*e_RABS_Admitted_ItemIEs;
+  X2AP_E_RABs_Admitted_Item_t 		   			*e_RABs_Admitted_Item;
 
   x2ap_eNB_instance_t                           *instance_p;
   x2ap_eNB_data_t                               *x2ap_eNB_data;
@@ -816,12 +818,62 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
 
   X2AP_HANDOVER_REQ_ACK(msg).rnti = rnti;
 
+
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
+                             X2AP_ProtocolIE_ID_id_E_RABs_Admitted_List, true);
+
+  if (ie == NULL ) {
+    X2AP_ERROR("%s %d: ie is a NULL pointer \n", __FILE__, __LINE__);
+    return -1;
+  }else{
+    if (ie->value.choice.E_RABs_Admitted_List.list.count > 0) {
+  
+      uint8_t nb_e_rabs_tobesetup;
+      nb_e_rabs_tobesetup = ie->value.choice.E_RABs_Admitted_List.list.count;
+      X2AP_HANDOVER_REQ_ACK(msg).nb_e_rabs_tobesetup = nb_e_rabs_tobesetup;
+  
+      for (int i=0; i<nb_e_rabs_tobesetup; i++) {
+        e_RABS_Admitted_ItemIEs = (X2AP_E_RABs_Admitted_ItemIEs_t *) ie->value.choice.E_RABs_Admitted_List.list.array[i];
+	e_RABs_Admitted_Item = &e_RABS_Admitted_ItemIEs->value.choice.E_RABs_Admitted_Item;
+  
+	X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].e_rab_id = e_RABs_Admitted_Item->e_RAB_ID ;
+	X2AP_ERROR("x2u tunnel: index %d e_rab_id %d\n", i, X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].e_rab_id);
+		  
+	if(e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint == NULL){
+	  X2AP_DEBUG("%s %d: X2AP_E_RABs_Admitted_Item_t->dL_GTP_TunnelEndpoint is a NULL pointer \n", __FILE__, __LINE__);
+	  continue;
+	}
+		  
+         memcpy(X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].eNB_addr.buffer,
+		e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.buf,
+		e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.size);
+  
+	X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].eNB_addr.length = e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->transportLayerAddress.size;
+  
+	OCTET_STRING_TO_INT32(&e_RABs_Admitted_Item->dL_GTP_TunnelEndpoint->gTP_TEID,
+			      X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].gtp_teid);
+  
+  
+        X2AP_DEBUG("x2u tunnel: index %d target enb ip %d.%d.%d.%d length %d gtp teid %u\n", 
+		    i, 
+		    X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].eNB_addr.buffer[0],
+		    X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].eNB_addr.buffer[1],
+		    X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].eNB_addr.buffer[2],
+		    X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].eNB_addr.buffer[3],
+		    X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].eNB_addr.length,
+	            X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].gtp_teid);
+        }
+	
+      }
+
+    }
+  
   X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
                              X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true);
 
   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*/)
+  if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s */)
     { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
 
   memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size);
diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c
index fcadb0530e45be25a03b1985234ffa95cbd2c91a..e56edb8fe6b54f5e811d1f9fbe33fe79d746724c 100644
--- a/openair3/GTPV1-U/gtpv1u_eNB.c
+++ b/openair3/GTPV1-U/gtpv1u_eNB.c
@@ -50,12 +50,18 @@
 #include "common/ran_context.h"
 #include "gtpv1u_eNB_defs.h"
 #include "gtpv1u_eNB_task.h"
+#include "rrc_eNB_GTPV1U.h"
 
 #undef GTP_DUMP_SOCKET
 
 extern unsigned char NB_eNB_INST;
 extern RAN_CONTEXT_t RC;
 
+extern struct rrc_eNB_ue_context_s*
+rrc_eNB_get_ue_context(
+  eNB_RRC_INST* rrc_instance_pP,
+  rnti_t rntiP);
+
 #if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
 #include <linux/if.h>
 static int           gtpv1u_dump_socket_g;
@@ -105,6 +111,27 @@ static void gtpv1u_eNB_write_dump_socket(uint8_t *buffer_pP, uint32_t buffer_len
 
 #endif
 
+//-----------------------------------------------------------------------------
+static int gtpv1u_eNB_get_msgsource(struct rrc_eNB_ue_context_s *ue_context_p, teid_t teid)
+{
+  int erab_index = 0;
+
+  /* source enb */
+  if(ue_context_p->ue_context.handover_info != NULL && ue_context_p->ue_context.handover_info->state == HO_COMPLETE)
+  {
+    return GTPV1U_MSG_FROM_SPGW; 
+  }
+
+  /* target enb */
+  for (erab_index = 0; erab_index < ue_context_p->ue_context.nb_x2u_e_rabs; erab_index++) {
+    if(ue_context_p->ue_context.enb_gtp_x2u_teid[erab_index] == teid){
+      return GTPV1U_MSG_FROM_SOURCE_ENB;  
+    }
+  }
+  
+  return GTPV1U_MSG_FROM_SPGW;  
+}
+
 //-----------------------------------------------------------------------------
 static int gtpv1u_eNB_send_init_udp(const Gtpv1uS1Req *req) {
   // Create and alloc new message
@@ -198,10 +225,16 @@ NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
     case NW_GTPV1U_ULP_API_RECV_TPDU: {
       uint8_t              buffer[4096];
       uint32_t             buffer_len;
+      struct rrc_eNB_ue_context_s        *ue_context_p;	
+      uint16_t             msgType = NW_GTP_GPDU;
+      NwGtpv1uMsgT 		 *pMsg = NULL;
+
       /* Nw-gptv1u stack has processed a PDU. we can schedule it to PDCP
        * for transmission.
        */
       teid = pUlpApi->apiInfo.recvMsgInfo.teid;
+      pMsg = (NwGtpv1uMsgT *) pUlpApi->apiInfo.recvMsgInfo.hMsg;
+      msgType = pMsg->msgType;
 
       if (NW_GTPV1U_OK != nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg,
                                              buffer, &buffer_len)) {
@@ -243,6 +276,158 @@ NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
           0,0,
           (gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4,
           buffer_len);
+
+    ue_context_p = rrc_eNB_get_ue_context(RC.rrc[ctxt.module_id], ctxt.rnti);
+    if((ue_context_p != NULL) && 
+       (ue_context_p->ue_context.handover_info != NULL) &&
+       (ue_context_p->ue_context.handover_info->state < HO_FORWARDING_COMPLETE)) {
+
+      if(msgType == NW_GTP_END_MARKER){
+        /* in the source enb, UE in RRC_HO_EXECUTION mode */
+        if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION && ue_context_p->ue_context.handover_info->state == HO_COMPLETE) {
+          /* set handover state */
+          //ue_context_p->ue_context.handover_info->state = HO_END_MARKER;
+                
+          MessageDef *msg;
+          // Configure end marker
+          msg = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_END_MARKER_REQ);
+          GTPV1U_ENB_END_MARKER_REQ(msg).buffer = itti_malloc(TASK_GTPV1_U, TASK_GTPV1_U, GTPU_HEADER_OVERHEAD_MAX + buffer_len);
+          memcpy(&GTPV1U_ENB_END_MARKER_REQ(msg).buffer[GTPU_HEADER_OVERHEAD_MAX], buffer, buffer_len);
+          GTPV1U_ENB_END_MARKER_REQ(msg).length = buffer_len;
+          GTPV1U_ENB_END_MARKER_REQ(msg).rnti   = ctxt.rnti;
+          GTPV1U_ENB_END_MARKER_REQ(msg).rab_id = gtpv1u_teid_data_p->eps_bearer_id;
+          GTPV1U_ENB_END_MARKER_REQ(msg).offset = GTPU_HEADER_OVERHEAD_MAX;
+          LOG_I(GTPU, "Send End Marker to GTPV1-U at frame %d and subframe %d \n", ctxt.frame,ctxt.subframe);
+          itti_send_msg_to_task(TASK_GTPV1_U, ENB_MODULE_ID_TO_INSTANCE(ctxt.module_id), msg);
+          return NW_GTPV1U_OK;
+	}
+      }
+	  
+      if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION || ue_context_p->ue_context.Status == RRC_RECONFIGURED) {
+
+        int msgsrc = gtpv1u_eNB_get_msgsource(ue_context_p, teid);
+
+        LOG_D(GTPU,"UE INFO.ueStatus %d, handover state %d, forwarding state %d, from %s. message type %s\n", 
+              ue_context_p->ue_context.Status, 
+              ue_context_p->ue_context.handover_info->state,
+              ue_context_p->ue_context.handover_info->forwarding_state,
+              msgsrc == GTPV1U_MSG_FROM_SOURCE_ENB?"Source eNB":"EPC",
+              msgsrc != GTPV1U_MSG_FROM_SOURCE_ENB? "UDP DATA" :
+              msgType == NW_GTP_END_MARKER?"END MARKER":"DATA FORWARDING");
+
+	/* target enb */
+	if(msgType == NW_GTP_END_MARKER){
+	  LOG_I(GTPU, "target end receive END MARKER\n");
+	  ue_context_p->ue_context.handover_info->state = HO_END_MARKER;
+          gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req;
+          memset(&delete_tunnel_req, 0 , sizeof(delete_tunnel_req));
+          delete_tunnel_req.rnti = ctxt.rnti;
+    	  gtpv1u_delete_x2u_tunnel(ctxt.module_id, &delete_tunnel_req, GTPV1U_TARGET_ENB);
+	  return NW_GTPV1U_OK;
+	}
+
+        /* form source eNB message */
+        if(msgsrc == GTPV1U_MSG_FROM_SOURCE_ENB)
+        {
+          LOG_I(GTPU, "Received a message data forwarding length %d\n", buffer_len);
+
+#if defined(LOG_GTPU) && LOG_GTPU > 0
+          LOG_T(GTPU, "forwarding data info:\n", buffer_len);	  
+
+          for(int i=1;i<=buffer_len; i++){
+	    LOG_T(GTPU, "%02x ", buffer[i-1]);
+	    if(i%20 == 0)LOG_T(GTPU, "\n");
+	  }
+	  LOG_T(GTPU, "\n");
+#endif
+			
+	  result = gtpv_data_req(
+				&ctxt,
+				(gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4,
+				0, // mui
+				SDU_CONFIRM_NO, // confirm
+				buffer_len,
+				buffer,
+				PDCP_TRANSMISSION_MODE_DATA,
+                                TASK_DATA_FORWARDING
+				);
+			
+          if ( result == FALSE ) {
+	    LOG_W(GTPU, "DATA FORWARDING message save failed\n");	
+	    return NW_GTPV1U_FAILURE;
+	  }
+	  ue_context_p->ue_context.handover_info->forwarding_state = FORWARDING_NO_EMPTY;
+          return NW_GTPV1U_OK;
+	}
+        /* from epc message */
+        else
+        {
+          /* in the source enb, UE in RRC_HO_EXECUTION mode */
+          if (ue_context_p->ue_context.handover_info->state == HO_COMPLETE) {
+          MessageDef *msg;
+          // Configure target
+          msg = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_DATA_FORWARDING_REQ);
+          GTPV1U_ENB_DATA_FORWARDING_REQ(msg).buffer = itti_malloc(TASK_GTPV1_U, TASK_GTPV1_U, GTPU_HEADER_OVERHEAD_MAX + buffer_len);
+          memcpy(&GTPV1U_ENB_DATA_FORWARDING_REQ(msg).buffer[GTPU_HEADER_OVERHEAD_MAX], buffer, buffer_len);
+          GTPV1U_ENB_DATA_FORWARDING_REQ(msg).length = buffer_len;
+          GTPV1U_ENB_DATA_FORWARDING_REQ(msg).rnti   = ctxt.rnti;
+          GTPV1U_ENB_DATA_FORWARDING_REQ(msg).rab_id = gtpv1u_teid_data_p->eps_bearer_id;
+          GTPV1U_ENB_DATA_FORWARDING_REQ(msg).offset = GTPU_HEADER_OVERHEAD_MAX;
+
+#if defined(LOG_GTPU) && LOG_GTPU > 0
+
+          LOG_T(GTPU, "Send data forwarding sdu_buffer to target enb. len %d info\n", buffer);
+          for(int i=1; i<=buffer_len; i++){
+            LOG_T(GTPU, "%02x ", buffer[i-1]);
+            if(i%20 == 0)LOG_T(GTPU, "\n");
+          }
+          LOG_T(GTPU, "\n");
+#endif
+
+          LOG_I(GTPU, "Send data forwarding to GTPV1-U at frame %d and subframe %d \n", ctxt.frame,ctxt.subframe);
+          itti_send_msg_to_task(TASK_GTPV1_U, ENB_MODULE_ID_TO_INSTANCE(ctxt.module_id), msg);
+          return NW_GTPV1U_OK;
+        }
+
+          /* target eNB. x2ho forwarding is processing. spgw message save to TASK_END_MARKER */
+          if(ue_context_p->ue_context.handover_info->state != HO_COMPLETE &&
+             ue_context_p->ue_context.handover_info->state != HO_END_MARKER )
+          {
+            LOG_I(GTPU, "x2ho forwarding is processing. Received a spgw message. length %d\n", buffer_len);
+#if defined(LOG_GTPU) && LOG_GTPU > 0				
+	  LOG_T(GTPU, "spgw data info:\n", buffer_len);			
+	  for(int i=1;i<=buffer_len; i++){
+	    LOG_T(GTPU, "%02x ", buffer[i-1]);
+	    if(i%20 == 0)LOG_T(GTPU, "\n");
+	  }
+	  LOG_T(GTPU, "\n");
+#endif
+			
+	  result = gtpv_data_req(
+			&ctxt,
+			(gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4,
+			0, // mui
+			SDU_CONFIRM_NO, // confirm
+			buffer_len,
+			buffer,
+			PDCP_TRANSMISSION_MODE_DATA,
+		        TASK_END_MARKER
+			);
+
+	if ( result == FALSE ) {
+	  LOG_W(GTPU, "DATA FORWARDING message save failed\n");
+	  return NW_GTPV1U_FAILURE;
+        }
+
+	ue_context_p->ue_context.handover_info->endmark_state = ENDMARK_NO_EMPTY;
+        return NW_GTPV1U_OK;
+      }
+
+     }
+
+    }
+
+  }
         result = pdcp_data_req(
                    &ctxt,
                    SRB_FLAG_NO,
@@ -259,7 +444,7 @@ NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
 
         if ( result == FALSE ) {
           if (ctxt.configured == FALSE )
-            LOG_W(GTPU, "PDCP data request failed, cause: RB is not configured!\n") ;
+            LOG_W(GTPU, "PDCP data request failed, cause: [UE:%x]RB is not configured!\n", ctxt.rnti) ;
           else
             LOG_W(GTPU, "PDCP data request failed\n");
 
@@ -550,6 +735,154 @@ gtpv1u_new_data_req(
   return 0;
 }
 
+//-----------------------------------------------------------------------------
+int
+gtpv1u_create_x2u_tunnel(
+  const instance_t                              instanceP,
+  const gtpv1u_enb_create_x2u_tunnel_req_t * const  create_tunnel_req_pP,
+        gtpv1u_enb_create_x2u_tunnel_resp_t * const create_tunnel_resp_pP
+  )
+{
+  /* Create a new nw-gtpv1-u stack req using API */
+  NwGtpv1uUlpApiT          stack_req;
+  NwGtpv1uRcT              rc                   = NW_GTPV1U_FAILURE;
+  /* Local tunnel end-point identifier */
+  teid_t                   x2u_teid             = 0;
+  gtpv1u_teid_data_t      *gtpv1u_teid_data_p   = NULL;
+  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
+  int                      i;
+  ebi_t                    eps_bearer_id        = 0;
+
+  MSC_LOG_RX_MESSAGE(
+		  MSC_GTPU_ENB,
+		  MSC_RRC_ENB,
+		  NULL,0,
+		  MSC_AS_TIME_FMT" CREATE_X2U_TUNNEL_REQ RNTI %"PRIx16" inst %u ntuns %u ebid %u enb-x2u teid %u",
+		  0,0,create_tunnel_req_pP->rnti, instanceP,
+		  create_tunnel_req_pP->num_tunnels, create_tunnel_req_pP->eps_bearer_id[0],
+		  create_tunnel_req_pP->tenb_X2u_teid[0]);
+
+  create_tunnel_resp_pP->rnti        = create_tunnel_req_pP->rnti;
+  create_tunnel_resp_pP->status      = 0;
+  create_tunnel_resp_pP->num_tunnels = 0;
+
+  for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
+    eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
+    LOG_D(GTPU, "Rx GTPV1U_ENB_CREATE_X2U_TUNNEL_REQ ue rnti %x eps bearer id %u\n",
+          create_tunnel_req_pP->rnti, eps_bearer_id);
+    memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
+
+    stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
+
+    do {
+      x2u_teid = gtpv1u_new_teid();
+      LOG_D(GTPU, "gtpv1u_create_x2u_tunnel() 0x%x %u(dec)\n", x2u_teid, x2u_teid);
+      stack_req.apiInfo.createTunnelEndPointInfo.teid          = x2u_teid;
+      stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession   = 0;
+      stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0;
+
+      rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
+      LOG_D(GTPU, ".\n");
+    } while (rc != NW_GTPV1U_OK);
+
+      memcpy(&create_tunnel_resp_pP->enb_addr.buffer,
+             &RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
+             sizeof (in_addr_t));
+
+      LOG_D(GTPU, "gtpv1u_create_x2u_tunnel() end addr %d.%d.%d.%d\n",
+		create_tunnel_resp_pP->enb_addr.buffer[0],
+		create_tunnel_resp_pP->enb_addr.buffer[1],
+		create_tunnel_resp_pP->enb_addr.buffer[2],
+		create_tunnel_resp_pP->enb_addr.buffer[3]);
+
+    create_tunnel_resp_pP->enb_addr.length  = sizeof (in_addr_t);
+    create_tunnel_resp_pP->eps_bearer_id[i] = eps_bearer_id;
+    create_tunnel_resp_pP->num_tunnels      += 1;
+
+    //-----------------------
+    // GTPV1U->PDCP mapping
+    //-----------------------
+    create_tunnel_resp_pP->enb_X2u_teid[i] = x2u_teid;
+    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, x2u_teid, (void**)&gtpv1u_teid_data_p);
+
+    if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
+      gtpv1u_teid_data_p = calloc (1, sizeof(gtpv1u_teid_data_t));
+      gtpv1u_teid_data_p->enb_id        = 0; // TO DO
+      gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
+      gtpv1u_teid_data_p->eps_bearer_id = eps_bearer_id;
+      hash_rc = hashtable_insert(RC.gtpv1u_data_g->teid_mapping, x2u_teid, gtpv1u_teid_data_p);
+      AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable");
+    } else {
+      create_tunnel_resp_pP->enb_X2u_teid[i] = 0;
+      create_tunnel_resp_pP->status         = 0xFF;
+    }
+  }
+  MSC_LOG_TX_MESSAGE(
+		  MSC_GTPU_ENB,
+		  MSC_RRC_ENB,
+		  NULL,0,
+		  "0 GTPV1U_ENB_CREATE_TUNNEL_RESP rnti %x teid %x",
+		  create_tunnel_resp_pP->rnti,
+		  x2u_teid);
+
+  LOG_D(GTPU, "Tx GTPV1U_ENB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
+        create_tunnel_req_pP->rnti,
+        create_tunnel_resp_pP->status);
+  return 0;
+}
+
+//-----------------------------------------------------------------------------
+int gtpv1u_delete_x2u_tunnel(
+  const instance_t                             instanceP,
+  const gtpv1u_enb_delete_tunnel_req_t * const req_pP,
+  int                             enbflag)
+{
+  gtpv1u_ue_data_t        *gtpv1u_ue_data_p     = NULL;
+  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
+  int                      erab_index           = 0;
+  ebi_t                    eps_bearer_id        = 0;
+  struct rrc_eNB_ue_context_s *ue_context_p     = NULL;
+
+  ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instanceP], req_pP->rnti);
+  if(ue_context_p != NULL){
+    /* in the source enb */
+    if(enbflag == GTPV1U_SOURCE_ENB){
+      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, req_pP->rnti, (void**)&gtpv1u_ue_data_p);
+
+      if (hash_rc == HASH_TABLE_OK) {
+        for (erab_index = 0; erab_index < ue_context_p->ue_context.nb_x2u_e_rabs; erab_index++) {
+          eps_bearer_id = ue_context_p->ue_context.enb_gtp_x2u_ebi[erab_index];
+          LOG_I(GTPU, "gtpv1u_delete_x2u_tunnel user rnti %x teNB X2U teid %u eps bearer id %u\n",
+            req_pP->rnti, 
+            gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_teNB,
+            ue_context_p->ue_context.enb_gtp_x2u_ebi[erab_index]);
+          
+          gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_teNB = 0;
+          gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr = 0;
+          //gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].tenb_ip6_addr = 0;
+        }
+        ue_context_p->ue_context.nb_x2u_e_rabs = 0;
+      }
+    }
+    /* in the target enb */
+    else{
+      for (erab_index = 0; erab_index < ue_context_p->ue_context.nb_x2u_e_rabs; erab_index++) {
+        //-----------------------
+        // GTPV1U->PDCP mapping
+        //-----------------------
+        hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, ue_context_p->ue_context.enb_gtp_x2u_teid[erab_index]);
+        LOG_I(GTPU, "Removed user rnti %x , enb X2U teid %u\n", req_pP->rnti, ue_context_p->ue_context.enb_gtp_x2u_teid[erab_index]);
+
+        if (hash_rc != HASH_TABLE_OK) {
+          LOG_D(GTPU, "Removed user rnti %x , enb X2U teid %u not found\n", req_pP->rnti, ue_context_p->ue_context.enb_gtp_x2u_teid[erab_index]);
+        }
+      }
+      ue_context_p->ue_context.nb_x2u_e_rabs = 0;
+    }
+  }
+  return 0;
+}
+
 //-----------------------------------------------------------------------------
 int
 gtpv1u_create_s1u_tunnel(
@@ -572,6 +905,10 @@ gtpv1u_create_s1u_tunnel(
   int                      ip_offset            = 0;
   in_addr_t                in_addr;
   int                      addrs_length_in_bytes= 0;
+  int                      loop_counter         = 0;
+  int                      ret                  = 0;
+
+
   MSC_LOG_RX_MESSAGE(
     MSC_GTPU_ENB,
     MSC_RRC_ENB,
@@ -586,6 +923,7 @@ gtpv1u_create_s1u_tunnel(
 
   for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
     ip_offset               = 0;
+    loop_counter            = 0;
     eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
     LOG_D(GTPU, "Rx GTPV1U_ENB_CREATE_TUNNEL_REQ ue rnti %x eps bearer id %u\n",
           create_tunnel_req_pP->rnti, eps_bearer_id);
@@ -600,7 +938,13 @@ gtpv1u_create_s1u_tunnel(
       stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0;
       rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
       LOG_D(GTPU, ".\n");
-    } while (rc != NW_GTPV1U_OK);
+      loop_counter++;
+    } while (rc != NW_GTPV1U_OK && loop_counter < 10);
+    if ( rc != NW_GTPV1U_OK && loop_counter == 10 ) {
+      LOG_E(GTPU,"NwGtpv1uCreateTunnelEndPoint failed 10 times,start next loop\n");
+      ret = -1;
+      continue;
+    }
 
     //-----------------------
     // PDCP->GTPV1U mapping
@@ -682,7 +1026,8 @@ gtpv1u_create_s1u_tunnel(
   LOG_D(GTPU, "Tx GTPV1U_ENB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
         create_tunnel_req_pP->rnti,
         create_tunnel_resp_pP->status);
-  return 0;
+  //return 0;
+  return ret;
 }
 
 int gtpv1u_update_s1u_tunnel(
@@ -713,9 +1058,15 @@ int gtpv1u_update_s1u_tunnel(
   memcpy(gtpv1u_ue_data_new_p,gtpv1u_ue_data_p,sizeof(gtpv1u_ue_data_t));
   gtpv1u_ue_data_new_p->ue_id       = create_tunnel_req_pP->rnti;
   hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_new_p);
-  AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
+  //AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
+  if ( hash_rc != HASH_TABLE_OK ) {
+    LOG_E(GTPU,"Failed to insert ue_mapping(rnti=%x) in GTPV1U hashtable\n",create_tunnel_req_pP->rnti);
+    return -1;
+  } else {
   LOG_I(GTPU, "inserting ue_mapping(rnti=%x) in GTPV1U hashtable\n",
         create_tunnel_req_pP->rnti);
+  }
+
   hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, prior_rnti);
   LOG_I(GTPU, "hashtable_remove ue_mapping(rnti=%x) in GTPV1U hashtable\n",
         prior_rnti);
@@ -1043,6 +1394,176 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) {
     }
     break;
 
+    case GTPV1U_ENB_DATA_FORWARDING_REQ: {
+    gtpv1u_enb_data_forwarding_req_t *data_req_p           = NULL;
+    NwGtpv1uUlpApiT               stack_req;
+    NwGtpv1uRcT                   rc                   = NW_GTPV1U_FAILURE;
+    hashtable_rc_t                hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
+    gtpv1u_ue_data_t             *gtpv1u_ue_data_p     = NULL;
+    teid_t                        enb_s1u_teid         = 0;
+    teid_t                        tenb_x2u_teid         = 0;
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
+    data_req_p = &GTPV1U_ENB_DATA_FORWARDING_REQ(received_message_p);
+    //ipv4_send_data(ipv4_data_p->sd, data_ind_p->buffer, data_ind_p->length);
+
+#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
+    gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
+#endif
+    memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
+
+    hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void**)&gtpv1u_ue_data_p);
+
+    if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
+      LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
+    } else {
+      if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id <= max_val_LTE_DRB_Identity)) {
+        enb_s1u_teid                        = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_eNB;
+        tenb_x2u_teid                       = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_teNB; // target enb teid
+        stack_req.apiType                   = NW_GTPV1U_ULP_API_SEND_TPDU;
+        stack_req.apiInfo.sendtoInfo.teid   = tenb_x2u_teid;
+        stack_req.apiInfo.sendtoInfo.ipAddr = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr;// target enb ip
+
+        rc = nwGtpv1uGpduMsgNew(
+               RC.gtpv1u_data_g->gtpv1u_stack,
+               tenb_x2u_teid,
+               NW_FALSE,
+               RC.gtpv1u_data_g->seq_num++,
+               data_req_p->buffer,
+               data_req_p->length,
+               data_req_p->offset,
+               &(stack_req.apiInfo.sendtoInfo.hMsg));
+
+        if (rc != NW_GTPV1U_OK) {
+          LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
+          MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
+          		enb_s1u_teid,tenb_x2u_teid,data_req_p->length);
+          (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
+        } else {
+          rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
+
+          if (rc != NW_GTPV1U_OK) {
+            LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
+            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
+            		enb_s1u_teid,tenb_x2u_teid,data_req_p->length);
+          } else {
+            MSC_LOG_TX_MESSAGE(
+            		MSC_GTPU_ENB,
+            		MSC_GTPU_SGW,
+            		NULL,
+            		0,
+            		MSC_AS_TIME_FMT" G-PDU ltid %u rtid %u size %u",
+            		0,0,
+            		enb_s1u_teid,
+            		tenb_x2u_teid,
+            		data_req_p->length);
+
+        }
+
+        rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
+                               stack_req.apiInfo.sendtoInfo.hMsg);
+
+        if (rc != NW_GTPV1U_OK) {
+          LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
+        }
+      }
+    }
+  }
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
+  /* Buffer still needed, do not free it */
+  //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer)
+  }
+  break;
+
+  case GTPV1U_ENB_END_MARKER_REQ:{
+    gtpv1u_enb_end_marker_req_t   *data_req_p           = NULL;
+    NwGtpv1uUlpApiT               stack_req;
+    NwGtpv1uRcT                   rc                    = NW_GTPV1U_FAILURE;
+    hashtable_rc_t                hash_rc               = HASH_TABLE_KEY_NOT_EXISTS;
+    gtpv1u_ue_data_t              *gtpv1u_ue_data_p     = NULL;
+    teid_t                        enb_s1u_teid          = 0;
+    teid_t                        tenb_x2u_teid         = 0;
+    NwGtpv1uMsgT		  *pMsg                 = NULL;
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
+    data_req_p = &GTPV1U_ENB_END_MARKER_REQ(received_message_p);
+    //ipv4_send_data(ipv4_data_p->sd, data_ind_p->buffer, data_ind_p->length);
+
+#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
+    gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
+#endif
+    memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
+
+    hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void**)&gtpv1u_ue_data_p);
+
+    if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
+      LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
+    } else {
+      if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id <= max_val_LTE_DRB_Identity)) {
+        enb_s1u_teid                        = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_eNB;
+        tenb_x2u_teid                       = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_teNB; // target enb teid
+        stack_req.apiType                   = NW_GTPV1U_ULP_API_SEND_TPDU;
+        stack_req.apiInfo.sendtoInfo.teid   = tenb_x2u_teid;
+        stack_req.apiInfo.sendtoInfo.ipAddr = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr;// target enb ip
+
+	rc = nwGtpv1uGpduMsgNew(
+               RC.gtpv1u_data_g->gtpv1u_stack,
+               tenb_x2u_teid,
+               NW_FALSE,
+               RC.gtpv1u_data_g->seq_num++,
+               data_req_p->buffer,
+               data_req_p->length,
+               data_req_p->offset,
+               &(stack_req.apiInfo.sendtoInfo.hMsg));
+
+        if (rc != NW_GTPV1U_OK) {
+          LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
+          MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
+            		enb_s1u_teid,tenb_x2u_teid,data_req_p->length);
+          (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
+        } else {
+	  pMsg = (NwGtpv1uMsgT *) stack_req.apiInfo.sendtoInfo.hMsg;
+	  pMsg->msgType = NW_GTP_END_MARKER;
+          rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
+
+          if (rc != NW_GTPV1U_OK) {
+            LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
+            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
+              		enb_s1u_teid,tenb_x2u_teid,data_req_p->length);
+          } else {
+            MSC_LOG_TX_MESSAGE(
+            	        MSC_GTPU_ENB,
+            	        MSC_GTPU_SGW,
+            		NULL,
+            		0,
+            		MSC_AS_TIME_FMT" G-PDU ltid %u rtid %u size %u",
+            		0,0,
+            		enb_s1u_teid,
+            		tenb_x2u_teid,
+            		data_req_p->length);
+
+          }
+
+          rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
+                                 stack_req.apiInfo.sendtoInfo.hMsg);
+
+          if (rc != NW_GTPV1U_OK) {
+            LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
+          }
+
+          gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req;
+          memset(&delete_tunnel_req, 0 , sizeof(delete_tunnel_req));
+          delete_tunnel_req.rnti = data_req_p->rnti;
+	  gtpv1u_delete_x2u_tunnel(instance, &delete_tunnel_req, GTPV1U_SOURCE_ENB);
+        }
+       }
+      }
+
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
+    }
+    break;
+
     case TERMINATE_MESSAGE: {
       if (RC.gtpv1u_data_g->ue_mapping != NULL) {
         hashtable_destroy (&(RC.gtpv1u_data_g->ue_mapping));
diff --git a/openair3/GTPV1-U/gtpv1u_eNB_defs.h b/openair3/GTPV1-U/gtpv1u_eNB_defs.h
index 978a3c58bc01731a463bde048fcac72cb07a836a..79d9a1dcdd54cb28c850d38b0cd161c6d3478719 100644
--- a/openair3/GTPV1-U/gtpv1u_eNB_defs.h
+++ b/openair3/GTPV1-U/gtpv1u_eNB_defs.h
@@ -40,6 +40,11 @@
 
 #define GTPV1U_MAX_BEARERS_ID     (max_val_LTE_DRB_Identity - GTPV1U_BEARER_OFFSET)
 
+#define GTPV1U_SOURCE_ENB (0)
+#define GTPV1U_TARGET_ENB (1)
+#define GTPV1U_MSG_FROM_SOURCE_ENB (0)
+#define GTPV1U_MSG_FROM_SPGW (1)
+
 typedef enum {
   BEARER_DOWN = 0,
   BEARER_IN_CONFIG,
@@ -65,6 +70,9 @@ typedef struct gtpv1u_bearer_s {
   teid_t          teid_sgw;                ///< Remote TEID
   in_addr_t       sgw_ip_addr;
   struct in6_addr sgw_ip6_addr;
+  teid_t          teid_teNB;
+  in_addr_t       tenb_ip_addr;				///< target eNB ipv4
+  struct in6_addr tenb_ip6_addr;				///< target eNB ipv6
   tcp_udp_port_t  port;
   //NwGtpv1uStackSessionHandleT stack_session;
   bearer_state_t state;
diff --git a/openair3/GTPV1-U/gtpv1u_eNB_task.h b/openair3/GTPV1-U/gtpv1u_eNB_task.h
index 9830ea6169975439e708a840e20e29ea4af91cee..a6e26259415bee26adf21407707cc01d3d46baf2 100644
--- a/openair3/GTPV1-U/gtpv1u_eNB_task.h
+++ b/openair3/GTPV1-U/gtpv1u_eNB_task.h
@@ -44,6 +44,12 @@ int   gtpv1u_eNB_init(void);
 void *gtpv1u_eNB_process_itti_msg(void*);
 void *gtpv1u_eNB_task(void *args);
 
+int
+gtpv1u_create_x2u_tunnel(
+  const instance_t instanceP,
+  const gtpv1u_enb_create_x2u_tunnel_req_t *  const create_tunnel_req_pP,
+        gtpv1u_enb_create_x2u_tunnel_resp_t * const create_tunnel_resp_pP);
+
 int
 gtpv1u_create_s1u_tunnel(
   const instance_t instanceP,
@@ -55,4 +61,9 @@ gtpv1u_update_s1u_tunnel(
     const instance_t                              instanceP,
     const gtpv1u_enb_create_tunnel_req_t * const  create_tunnel_req_pP,
     const rnti_t                                  prior_rnti);
+
+int gtpv1u_delete_x2u_tunnel(
+  const instance_t                             instanceP,
+  const gtpv1u_enb_delete_tunnel_req_t * const req_pP,
+  int                             enbflag);
 #endif /* GTPV1U_ENB_TASK_H_ */
diff --git a/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c b/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c
index 3e8da5d015faa56051c35f48185908137d81afeb..0c7663921b71dbd85c74323715c30ab19b316995 100644
--- a/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c
+++ b/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c
@@ -378,9 +378,14 @@ NwGtpv1uCreateTunnelEndPoint( NW_IN  NwGtpv1uStackT *thiz,
       *phStackSession = (NwGtpv1uStackSessionHandleT) pTunnelEndPoint;
       pTunnelEndPoint = RB_FIND(NwGtpv1uTunnelEndPointIdentifierMap,
                                 &(thiz->teidMap), pTunnelEndPoint);
-      NW_ASSERT(pTunnelEndPoint);
-      GTPU_DEBUG("Tunnel end-point 0x%p creation successful for teid 0x%x %u(dec)",
-                 pTunnelEndPoint, (unsigned int)teid, (unsigned int)teid);
+      //NW_ASSERT(pTunnelEndPoint);
+      if (!pTunnelEndPoint) {
+        GTPU_ERROR("Tunnel end-point cannot be NULL");
+        rc = NW_GTPV1U_FAILURE;
+      } else {
+        GTPU_DEBUG("Tunnel end-point 0x%p creation successful for teid 0x%x %u(dec)",
+                   pTunnelEndPoint, (unsigned int)teid, (unsigned int)teid);
+      }
     }
 
   } else {
@@ -893,8 +898,14 @@ nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
     break;
 
   case NW_GTP_END_MARKER:
-    GTPU_DEBUG("NW_GTP_END_MARKER\n");
-    ret = NW_GTPV1U_OK;
+#if defined(LOG_GTPU) && LOG_GTPU > 0
+    for(int i =1; i<= udpDataLen; i++){
+      printf("%02x ", udpData[i-1]);
+      if(i % 20 == 0)printf("\n");
+    }
+#endif  	
+    GTPU_INFO("NW_GTP_END_MARKER\n");
+    ret = nwGtpv1uProcessGpdu(thiz, udpData, udpDataLen, peerIp);
     break;
 
   default:
diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c
index e2396d015f6734089731f81166f7bae7f9d2eb3b..e773ae6a207d034bad7d26e37422f2388eb5b00b 100644
--- a/openair3/S1AP/s1ap_eNB_handlers.c
+++ b/openair3/S1AP/s1ap_eNB_handlers.c
@@ -1518,7 +1518,7 @@ 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;
+    //return -1;
   }
 
   if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
diff --git a/openair3/SCTP/sctp_default_values.h b/openair3/SCTP/sctp_default_values.h
index 5008ea0b72bf6d9202bc633f44595e3b415eccce..528ffb5a05114aea3c37ea584e8a55f871210ddc 100644
--- a/openair3/SCTP/sctp_default_values.h
+++ b/openair3/SCTP/sctp_default_values.h
@@ -26,6 +26,6 @@
 #define SCTP_IN_STREAMS         (16)
 #define SCTP_MAX_ATTEMPTS       (2)
 #define SCTP_TIMEOUT            (5)
-#define SCTP_RECV_BUFFER_SIZE   (1024)
+#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 e93488817832d9e52a59a14b9603f2c52cfe351c..3cb64254fccbcc4a9378f68f4b9cc523eb101c27 100644
--- a/openair3/SCTP/sctp_eNB_task.c
+++ b/openair3/SCTP/sctp_eNB_task.c
@@ -955,6 +955,11 @@ sctp_eNB_read_from_socket(
         return;
     }
 
+    if (!(flags & MSG_EOR)) {
+      SCTP_ERROR("fatal: partial SCTP messages are not handled\n");
+      exit(1);
+    }
+
     if (flags & MSG_NOTIFICATION) {
         union sctp_notification *snp;
         snp = (union sctp_notification *)buffer;
diff --git a/openair3/UDP/udp_eNB_task.c b/openair3/UDP/udp_eNB_task.c
index 27f754badc28af6d805eda340143c34912de03ef..90ee87900df1136baf30eb536cf53d8225a07c57 100644
--- a/openair3/UDP/udp_eNB_task.c
+++ b/openair3/UDP/udp_eNB_task.c
@@ -371,13 +371,13 @@ void *udp_eNB_task(void *args_p)
         udp_sd = udp_sock_p->sd;
         pthread_mutex_unlock(&udp_socket_list_mutex);
 
-#if defined(LOG_UDP) && LOG_UDP > 0
+//#if defined(LOG_UDP) && LOG_UDP > 0
         LOG_D(UDP_, "[%d] Sending message of size %u to "IPV4_ADDR" and port %u\n",
               udp_sd,
               udp_data_req_p->buffer_length,
               IPV4_ADDR_FORMAT(udp_data_req_p->peer_address),
               udp_data_req_p->peer_port);
-#endif
+//#endif
         bytes_written = sendto(
                           udp_sd,
                           &udp_data_req_p->buffer[udp_data_req_p->buffer_offset],
diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h
index 31a7173630801357386e9a478967ca68a20a8d4c..c9d0027bf299be9e2071965fecebb9783b14c3e7 100644
--- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h
+++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h
@@ -27,7 +27,7 @@
 #include <libbladeRF.h>
 
 #include "common_lib.h"
-#include "log.h"
+#include "LOG/log.h"
 
 /** @addtogroup _BLADERF_PHY_RF_INTERFACE_
  * @{
diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c
index c1685e11ecd5beab3aeed890c8fee63a634132c1..010f54a3ba4e45d4203256388022dfa15f2a5dcf 100644
--- a/targets/ARCH/COMMON/common_lib.c
+++ b/targets/ARCH/COMMON/common_lib.c
@@ -105,7 +105,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param
   if ( IS_SOFTMODEM_BASICSIM ) {
     libname=OAI_BASICSIM_LIBNAME;
     shlib_fdesc[0].fname="device_init";
-  } else if ( IS_SOFTMODEM_RFSIM ) {
+  } else if ( IS_SOFTMODEM_RFSIM && flag == RAU_LOCAL_RADIO_HEAD) {
     libname=OAI_RFSIM_LIBNAME;
     shlib_fdesc[0].fname="device_init";
   } else if (flag == RAU_LOCAL_RADIO_HEAD) {
diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c
index 2deb0ee89506157e915d59b0dd7b8f6b139ad370..638f5ed9890d763d5a7191ff08443df174e0fe94 100644
--- a/targets/ARCH/rfsimulator/simulator.c
+++ b/targets/ARCH/rfsimulator/simulator.c
@@ -65,8 +65,8 @@ pthread_mutex_t Sockmutex;
 
 typedef struct buffer_s {
   int conn_sock;
-  bool alreadyRead;
-  uint64_t lastReceivedTS;
+  openair0_timestamp lastReceivedTS;
+  openair0_timestamp lastWroteTS;
   bool headerMode;
   samplesBlockHeader_t th;
   char *transferPtr;
@@ -78,7 +78,7 @@ typedef struct buffer_s {
 
 typedef struct {
   int listen_sock, epollfd;
-  uint64_t nextTimestamp;
+  openair0_timestamp nextTimestamp;
   uint64_t typeStamp;
   char *ip;
   uint16_t port;
@@ -123,9 +123,9 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si
   // Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ?
   // the parameter "-s" is declared as SNR, but the input power is not well defined
   // −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise)
-  const double rxGain= 132.24 - snr_dB; 
+  const double rxGain= 132.24 - snr_dB;
   // sqrt(4*noise_figure_watt) is the thermal noise factor (volts)
-  // fixme: the last constant is pure trial results to make decent noise 
+  // fixme: the last constant is pure trial results to make decent noise
   const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10;
   // Fixme: we don't fill the offset length samples at begining ?
   // anyway, in today code, channel_offset=0
@@ -154,9 +154,6 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si
     }
 
     out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
-    printf("in: %d, out %d= %f*%f + %f*%f\n",
-      input_sig[((TS+i)*nbTx)%CirSize].r, out_ptr->r , rx_tmp.x,
-      pathLossLinear, noise_per_sample,gaussdouble(0.0,1.0));
     out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
     out_ptr++;
   }
@@ -175,8 +172,8 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
   AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
   ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
   ptr->conn_sock=sock;
-  ptr->alreadyRead=false;
   ptr->lastReceivedTS=0;
+  ptr->lastWroteTS=0;
   ptr->headerMode=true;
   ptr->transferPtr=(char *)&ptr->th;
   ptr->remainToTransfer=sizeof(samplesBlockHeader_t);
@@ -379,21 +376,22 @@ sin_addr:
 
   setblocking(sock, notBlocking);
   allocCirBuf(t, sock);
-  t->buf[sock].alreadyRead=true; // UE will start blocking on read
   return 0;
 }
 
-uint64_t lastW=-1;
 int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
   rfsimulator_state_t *t = device->priv;
   LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp);
 
+
   for (int i=0; i<FD_SETSIZE; i++) {
-    buffer_t *ptr=&t->buf[i];
+    buffer_t *b=&t->buf[i];
 
-    if (ptr->conn_sock >= 0 ) {
+    if (b->conn_sock >= 0 ) {
+      if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize)
+	LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS);
       samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
-      fullwrite(ptr->conn_sock,&header, sizeof(header), t);
+      fullwrite(b->conn_sock,&header, sizeof(header), t);
       sample_t tmpSamples[nsamps][nbAnt];
 
       for(int a=0; a<nbAnt; a++) {
@@ -403,17 +401,17 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi
           tmpSamples[s][a]=in[s];
       }
 
-      if (ptr->conn_sock >= 0 )
-        fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t);
+      if (b->conn_sock >= 0 ) {
+        fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t);
+        b->lastWroteTS=timestamp+nsamps;
+      }
     }
   }
 
-  lastW=timestamp;
   LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n",
         nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) );
   // Let's verify we don't have incoming data
   // This is mandatory when the opposite side don't transmit
-  // This is mandatory when the opposite side don't transmit
   flushInput(t, 0);
   pthread_mutex_unlock(&Sockmutex);
   return nsamps;
@@ -485,7 +483,6 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) {
         AssertFatal( (t->typeStamp == UE_MAGICDL_FDD  && b->th.magic==ENB_MAGICDL_FDD) ||
                      (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol");
         b->headerMode=false;
-        b->alreadyRead=true;
 
         if ( b->lastReceivedTS != b->th.timestamp) {
           int nbAnt= b->th.nbAnt;
@@ -501,8 +498,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) {
         }
 
         b->lastReceivedTS=b->th.timestamp;
-        AssertFatal(lastW == -1 || ( abs((double)lastW-b->lastReceivedTS) < (double)CirSize),
-                    "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", lastW, b->lastReceivedTS);
+        AssertFatal(b->lastWroteTS == 0 || ( abs((double)b->lastWroteTS-b->lastReceivedTS) < (double)CirSize),
+                    "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS);
         b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize];
         b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt);
       }
@@ -561,15 +558,33 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
       return nsamps;
     }
   } else {
+    
     bool have_to_wait;
 
     do {
       have_to_wait=false;
 
       for ( int sock=0; sock<FD_SETSIZE; sock++) {
-        if ( t->buf[sock].circularBuf && t->buf[sock].alreadyRead )
-          if ( t->buf[sock].lastReceivedTS == 0 ||
-               (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) {
+	buffer_t *b=&t->buf[sock];
+        if ( b->circularBuf) {
+          LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n",
+                sock, b->lastWroteTS,
+                b->lastReceivedTS,
+                t->nextTimestamp+nsamps);
+	  if (  b->lastReceivedTS > b->lastWroteTS ) {
+	    // The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance
+	    // This occurs for example when UE is in sync mode: it doesn't transmit
+	    // with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power
+	    struct complex16 v={0};
+	    void *samplesVoid[b->th.nbAnt];
+	    for ( int i=0; i <b->th.nbAnt; i++)
+	      samplesVoid[i]=(void*)&v;
+	    rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0);
+	  }
+	}
+
+        if ( b->circularBuf )
+          if ( t->nextTimestamp+nsamps > b->lastReceivedTS ) {
             have_to_wait=true;
             break;
           }
@@ -592,7 +607,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
   for (int sock=0; sock<FD_SETSIZE; sock++) {
     buffer_t *ptr=&t->buf[sock];
 
-    if ( ptr->circularBuf && ptr->alreadyRead ) {
+    if ( ptr->circularBuf ) {
       bool reGenerateChannel=false;
 
       //fixme: when do we regenerate
diff --git a/targets/COMMON/openairinterface5g_limits.h b/targets/COMMON/openairinterface5g_limits.h
index 644952ca794a041a046d86efdf054ccaff1b7c39..b81fd091471b135c9ebfe4fbec22a3134b7787a9 100644
--- a/targets/COMMON/openairinterface5g_limits.h
+++ b/targets/COMMON/openairinterface5g_limits.h
@@ -12,13 +12,16 @@
 // This problem will be fixed in the future.
 #            ifndef UESIM_EXPANSION
 #                define NUMBER_OF_UE_MAX 16
+#                define NUMBER_OF_UCI_VARS_MAX 56
 #                define NUMBER_OF_CONNECTED_eNB_MAX 3
 #            else
 #                define NUMBER_OF_UE_MAX 256
+#                define NUMBER_OF_UCI_VARS_MAX 256
 #                define NUMBER_OF_CONNECTED_eNB_MAX 1
 #            endif
 #        else
 #                define NUMBER_OF_UE_MAX 256
+#                define NUMBER_OF_UCI_VARS_MAX 256
 #                define NUMBER_OF_CONNECTED_eNB_MAX 1
 #        endif
 #else
@@ -32,13 +35,16 @@ and the other are using MAX_MOBILES_PER_ENB in for-loop.
 */
 #            ifndef UESIM_EXPANSION
 #                define NUMBER_OF_UE_MAX 16
+#                define NUMBER_OF_UCI_VARS_MAX 56
 #                define NUMBER_OF_CONNECTED_eNB_MAX 3
 #            else
 #                define NUMBER_OF_UE_MAX 256
+#                define NUMBER_OF_UCI_VARS_MAX 256
 #                define NUMBER_OF_CONNECTED_eNB_MAX 1
 #            endif
 #        else
 #                define NUMBER_OF_UE_MAX 256
+#                define NUMBER_OF_UCI_VARS_MAX 256
 #                define NUMBER_OF_CONNECTED_eNB_MAX 1
 #        endif
 #        if defined(STANDALONE) && STANDALONE==1
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 3105b7c8554e6197086930f410f0c87b50a75585..1ad25febac2003cbbb260be42153e2c7a4b1ba2e 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -189,14 +189,14 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name
         eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs ||
         eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs ||
         eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles ||
-        eNB->UL_INFO.cqi_ind.number_of_cqis
+        eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis
        ) {
       LOG_D(PHY, "UL_info[rx_ind:%05d:%d harqs:%05d:%d crcs:%05d:%d preambles:%05d:%d cqis:%d] RX:%04d%d TX:%04d%d num_pdcch_symbols:%d\n",
             NFAPI_SFNSF2DEC(eNB->UL_INFO.rx_ind.sfn_sf),   eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus,
             NFAPI_SFNSF2DEC(eNB->UL_INFO.harq_ind.sfn_sf), eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs,
             NFAPI_SFNSF2DEC(eNB->UL_INFO.crc_ind.sfn_sf),  eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs,
             NFAPI_SFNSF2DEC(eNB->UL_INFO.rach_ind.sfn_sf), eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles,
-            eNB->UL_INFO.cqi_ind.number_of_cqis,
+          eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis, 
             proc->frame_rx, proc->subframe_rx,
             proc->frame_tx, proc->subframe_tx, eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols);
     }
@@ -218,9 +218,11 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name
     wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
 #endif
   }
-
-  release_UE_in_freeList(eNB->Mod_id);
-
+  if (NFAPI_MODE!=NFAPI_MODE_PNF) {
+    release_UE_in_freeList(eNB->Mod_id);
+  } else {
+    release_rnti_of_phy(eNB->Mod_id);
+  }
   // UE-specific RX processing for subframe n
   if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
     phy_procedures_eNB_uespec_RX(eNB, proc);
@@ -429,13 +431,12 @@ static void *L1_thread( void *param ) {
     }
 
     LOG_D(PHY,"L1 RX %d.%d done\n",proc->frame_rx,proc->subframe_rx);
-
-    if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT)              phy_procedures_eNB_TX(eNB, proc, 1);
-
-
     if (NFAPI_MODE!=NFAPI_MODE_VNF) {
-      if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)      wakeup_tx(eNB,proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx);
-      else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT)     wakeup_txfh(eNB,proc,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx);
+      if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)     wakeup_tx(eNB,proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx); 
+      else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) {
+        phy_procedures_eNB_TX(eNB, proc, 1);
+        wakeup_txfh(eNB,proc,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx);
+      }
     }
 
     if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break;
@@ -635,15 +636,12 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
 
     AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU_PRACH))==0,"mutex_lock return %d\n",ret);
     for (i=0; i<eNB->num_RU; i++) {
-      if (ru == eNB->RU_list[i]) {
-        LOG_D(PHY,"frame %d, subframe %d: RU %d for eNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,eNB->Mod_id,proc->RU_mask_prach,eNB->num_RU);
-
-        if ((proc->RU_mask_prach&(1<<i)) > 0)
-          LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information (PRACH) from RU %d (num_RU %d, mask %x) has not been served yet!\n",
-                eNB->Mod_id,frame,subframe,ru->idx,eNB->num_RU,proc->RU_mask_prach);
-
-        proc->RU_mask_prach |= (1<<i);
-      }
+    	if (ru == eNB->RU_list[i] && eNB->RU_list[i]->wait_cnt == 0) {
+        	LOG_D(PHY,"frame %d, subframe %d: RU %d for eNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,eNB->Mod_id,proc->RU_mask_prach,eNB->num_RU);
+		proc->RU_mask_prach |= (1<<i);
+        } else if (eNB->RU_list[i]->state == RU_SYNC || eNB->RU_list[i]->wait_cnt > 0) {
+	        proc->RU_mask_prach |= (1<<i);
+      	}
     }
 
     if (proc->RU_mask_prach != (1<<eNB->num_RU)-1) {  // not all RUs have provided their information so return
@@ -929,7 +927,9 @@ void init_eNB_proc(int inst) {
 
     LOG_I(PHY,"eNB->single_thread_flag:%d\n", eNB->single_thread_flag);
 
-    if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) && NFAPI_MODE!=NFAPI_MODE_VNF) {
+    if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) && NFAPI_MODE!=NFAPI_MODE_VNF) {
+      pthread_create( &L1_proc->pthread, attr0, L1_thread, proc );
+    } else if ((get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) && NFAPI_MODE!=NFAPI_MODE_VNF) {
       pthread_create( &L1_proc->pthread, attr0, L1_thread, proc );
       pthread_create( &L1_proc_tx->pthread, attr1, L1_thread_tx, proc);
     } else if (NFAPI_MODE==NFAPI_MODE_VNF) { // this is neccesary in VNF or L2 FAPI simulator.
@@ -940,10 +940,12 @@ void init_eNB_proc(int inst) {
       pthread_create( &L1_proc_tx->pthread, attr1, L1_thread, L1_proc_tx);
     }
 
-    pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB );
+    if (NFAPI_MODE!=NFAPI_MODE_VNF) {
+      pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, eNB );
 #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
-    pthread_create( &proc->pthread_prach_br, attr_prach_br, eNB_thread_prach_br, eNB );
+      pthread_create( &proc->pthread_prach_br, attr_prach_br, eNB_thread_prach_br, eNB );
 #endif
+    }
     AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach);
 
     if (opp_enabled == 1) pthread_create(&proc->process_stats_thread,NULL,process_stats_thread,(void *)eNB);
@@ -1104,6 +1106,7 @@ void init_transport(PHY_VARS_eNB *eNB) {
   LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
   LOG_I(PHY, "Initialise transport\n");
 
+if (NFAPI_MODE!=NFAPI_MODE_VNF) {
   for (i=0; i<NUMBER_OF_UE_MAX; i++) {
     LOG_D(PHY,"Allocating Transport Channel Buffers for DLSCH, UE %d\n",i);
 
@@ -1146,6 +1149,7 @@ void init_transport(PHY_VARS_eNB *eNB) {
   LOG_D(PHY,"eNB %d.%d : RA %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_ra);
   eNB->dlsch_MCH = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp);
   LOG_D(PHY,"eNB %d.%d : MCH %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_MCH);
+}
   eNB->rx_total_gain_dB=130;
 
   for(i=0; i<NUMBER_OF_UE_MAX; i++)
@@ -1283,8 +1287,8 @@ void init_eNB(int single_thread_flag,int wait_for_sync) {
       eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = eNB->crc_pdu_list;
       eNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = eNB->sr_pdu_list;
       eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list;
-      eNB->UL_INFO.cqi_ind.cqi_pdu_list = eNB->cqi_pdu_list;
-      eNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list;
+      eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_pdu_list = eNB->cqi_pdu_list;
+      eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list;
       eNB->prach_energy_counter = 0;
     }
   }
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index 8ed220da8e8f5293f5f22ace0a0014c8ea5b6932..89abd124999abc6d964670340d9f57997e7c96ff 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -217,6 +217,7 @@ void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) {
   if (proc->symbol_mask[*subframe]==0) { // this is normal case, if not true then we received a PULTICK before the previous subframe was finished 
      do {
        recv_IF4p5(ru, &f, &sf, &packet_type, &symbol_number);
+	 LOG_D(PHY,"fh_if4p5_south_in: RU %d, frame %d, subframe %d, f %d, sf %d\n",ru->idx,*frame,*subframe,f,sf);
        if (oai_exit == 1 || ru->cmd== STOP_RU) break;
        if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sf] = proc->symbol_mask[sf] | (1<<symbol_number);
        else if (packet_type == IF4p5_PULTICK) {           
@@ -230,8 +231,8 @@ void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) {
        } else if (packet_type == IF4p5_PRACH) {
       // nothing in RU for RAU
        }
-       LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*subframe,proc->symbol_mask[*subframe]);
-     } while(proc->symbol_mask[*subframe] != symbol_mask_full);    
+       LOG_D(PHY,"rx_fh_if4p5 for RU %d: subframe %d, sf %d, symbol mask %x\n",ru->idx,*subframe,sf,proc->symbol_mask[sf]);
+     } while(proc->symbol_mask[sf] != symbol_mask_full);    
   }
   else {
    f = *frame;
@@ -437,10 +438,13 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {
       proc->first_tx = 0;
       symbol_mask_full = ((subframe_select(fp,*subframe) == SF_S) ? (1<<fp->dl_symbols_in_S_subframe) : (1<<fp->symbols_per_tti))-1;
     } else {
-      AssertFatal(frame_tx == *frame,
+     /* AssertFatal(frame_tx == *frame,
                   "frame_tx %d is not what we expect %d\n",frame_tx,*frame);
       AssertFatal(subframe_tx == *subframe,
 		  "In frame_tx %d : subframe_tx %d is not what we expect %d\n",frame_tx,subframe_tx,*subframe);
+     */
+      *frame    = frame_tx;
+      *subframe = subframe_tx;
     }
 
     if (packet_type == IF4p5_PDLFFT) {
@@ -1661,7 +1665,7 @@ void *ru_thread( void *param ) {
       proc->instance_cnt_asynch_rxtx=0;
       pthread_cond_signal(&proc->cond_asynch_rxtx);
       AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_asynch_rxtx))==0,"mutex_unlock returns %d\n",ret);
-    } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx);
+    } else LOG_D(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 == 1) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru);
@@ -1872,7 +1876,8 @@ void *ru_thread_synch(void *arg) {
 				   &avg);
       LOG_I(PHY,"RU synch cnt %d: %d, val %llu (%d dB,%d dB)\n",cnt,ru->rx_offset,(unsigned long long)peak_val,dB_fixed64(peak_val),dB_fixed64(avg));
       cnt++;
-      if (/*ru->rx_offset >= 0*/dB_fixed(peak_val)>=85 && cnt>10) {
+      //if (/*ru->rx_offset >= 0*/dB_fixed(peak_val)>=85 && cnt>10) {
+      if (ru->rx_offset >= 0 && avg>0 && dB_fixed(peak_val/avg)>=15 && cnt>10) {
 	LOG_I(PHY,"Estimated peak_val %d dB, avg %d => timing offset %llu\n",dB_fixed(peak_val),dB_fixed(avg),(unsigned long long int)ru->rx_offset);
 	ru->in_synch = 1;
 /*
@@ -2628,7 +2633,11 @@ void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t ti
     // NOTE: multiple CC_id are not handled here yet!
     ru->openair0_cfg.clock_source  = clock_source;
     ru->openair0_cfg.time_source = time_source;
-//    ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0;
+    //ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0;
+    if ((ru->is_slave == 0) && (ru->ota_sync_enable == 1))
+      ru->generate_dmrs_sync = 1;
+    else
+      ru->generate_dmrs_sync = 0;
     if (ru->generate_dmrs_sync == 1) {
       generate_ul_ref_sigs();
       ru->dmrssync = (int16_t*)malloc16_clear(ru->frame_parms.ofdm_symbol_size*2*sizeof(int16_t)); 	
@@ -2915,10 +2924,15 @@ void RCconfig_RU(void) {
           printf("RU %d is_slave=%s\n",j,*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr));
           if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) RC.ru[j]->is_slave=1;
           else RC.ru[j]->is_slave=0;
+          printf("RU %d ota_sync_enabled=%s\n",j,*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr));
+          if (strcmp(*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr), "yes") == 0) RC.ru[j]->ota_sync_enable=1;
+          else RC.ru[j]->ota_sync_enable=0;
 	}
 	RC.ru[j]->max_pdschReferenceSignalPower     = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);;
 	RC.ru[j]->max_rxgain                        = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr);
 	RC.ru[j]->num_bands                         = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt;
+	/* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */
+        RC.ru[j]->sf_extension                      = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr);
 	for (i=0;i<RC.ru[j]->num_bands;i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; 
       } //strcmp(local_rf, "yes") == 0
       else {
diff --git a/targets/RT/USER/lte-softmodem-common.c b/targets/RT/USER/lte-softmodem-common.c
index dd91f540047e7108102f04bb6102216395ce60b7..a5fee5397fdd7cababcceb9dce14af44d273c6b5 100644
--- a/targets/RT/USER/lte-softmodem-common.c
+++ b/targets/RT/USER/lte-softmodem-common.c
@@ -62,6 +62,7 @@ void get_common_options(void) {
   uint32_t nonbiot;
   uint32_t rfsim;
   uint32_t basicsim;
+  char *logmem_filename = NULL;
   uint32_t do_forms;
   paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
   paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
@@ -83,6 +84,13 @@ void get_common_options(void) {
     load_module_shlib("telnetsrv",NULL,0,NULL);
   }
 
+  if (logmem_filename != NULL && strlen(logmem_filename) > 0) {
+    log_mem_filename = &logmem_filename[0];
+    log_mem_flag = 1;
+    printf("Enabling OPT for log save at memory %s\n",log_mem_filename);
+    logInit_log_mem();
+  }
+
   if (noS1) {
     set_softmodem_optmask(SOFTMODEM_NOS1_BIT);
   }
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 119e0c39e448bb95ef2fad59848d6e112d5f3100..70b458a7fea8724c6542bcdf3025fc4cf7342a9c 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -261,7 +261,7 @@ void exit_function(const char *file, const char *function, const int line, const
   if (s != NULL) {
     printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
   }
-
+  close_log_mem();
   oai_exit = 1;
 
   if (RC.ru == NULL)
@@ -524,6 +524,7 @@ int main( int argc, char **argv ) {
   int i;
   int CC_id = 0;
   int ru_id;
+  int node_type = ngran_eNB;
 
   if ( load_configmodule(argc,argv,0) == NULL) {
     exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
@@ -604,12 +605,13 @@ int main( int argc, char **argv ) {
       RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration;
       itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
     }
+    node_type = RC.rrc[0]->node_type;
   } else {
     printf("RC.nb_inst = 0, Initializing L1\n");
     RCconfig_L1();
   }
 
-  if (RC.nb_inst > 0 && NODE_IS_CU(RC.rrc[0]->node_type)) {
+  if (RC.nb_inst > 0 && NODE_IS_CU(node_type)) {
     protocol_ctxt_t ctxt;
     ctxt.module_id = 0 ;
     ctxt.instance = 0;
@@ -621,7 +623,7 @@ int main( int argc, char **argv ) {
   }
     
   /* start threads if only L1 or not a CU */
-  if (RC.nb_inst == 0 || !NODE_IS_CU(RC.rrc[0]->node_type)) {
+  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) {
     // init UE_PF_PO and mutex lock
     pthread_mutex_init(&ue_pf_po_mutex, NULL);
     memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs);
@@ -720,7 +722,7 @@ int main( int argc, char **argv ) {
   LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit);
   // stop threads
 
-  if (RC.nb_inst == 0 || !NODE_IS_CU(RC.rrc[0]->node_type)) {
+  if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
     if(IS_SOFTMODEM_DOFORMS)
       end_forms();
 
diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h
index b9a775509dba534ae9a410db1dda70da47328218..15154fea0b0484c08c195beeaa33df0a46ad5c7d 100644
--- a/targets/RT/USER/lte-softmodem.h
+++ b/targets/RT/USER/lte-softmodem.h
@@ -225,6 +225,7 @@
     {"g" ,           CONFIG_HLP_LOGL, 0,      uptr:&glog_level,     defintval:0,         TYPE_UINT,     0},        \
     {"telnetsrv",        CONFIG_HLP_TELN, PARAMFLAG_BOOL,   uptr:&start_telnetsrv,    defintval:0,         TYPE_UINT,     0},        \
     {"msc",                CONFIG_HLP_MSC,  PARAMFLAG_BOOL,   uptr:&START_MSC,            defintval:0,         TYPE_UINT,     0},                    \
+    {"log-mem",      NULL,            0,      strptr:(char **)&logmem_filename,    defstrval:NULL,          TYPE_STRING,   0},    \
   }
 #define CMDLINE_ONLINELOG_IDX     0
 #define CMDLINE_GLOGLEVEL_IDX     1
@@ -236,6 +237,7 @@
     { .s2=  { config_check_intrange,           {0,4}}},               \
     { .s5= {NULL }} ,                   \
     { .s5= {NULL }} ,                   \
+    { .s5= {NULL }} ,                   \
   }
 
 /***************************************************************************************************************************************/
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index 89b58bd7764f451e8be236d19b095c03aca1b911..42ec7d216d7f33f650fe24daeba0d1f2d126b3c8 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -1053,9 +1053,9 @@ static void *UE_phy_stub_single_thread_rxn_txnp4(void *arg) {
       UL_INFO->harq_ind.harq_indication_body.number_of_harqs = 0;
       UL_INFO->sr_ind.sr_indication_body.sr_pdu_list = (nfapi_sr_indication_pdu_t *)malloc(NB_UE_INST*sizeof(nfapi_sr_indication_pdu_t));
       UL_INFO->sr_ind.sr_indication_body.number_of_srs = 0;
-      UL_INFO->cqi_ind.cqi_pdu_list =  (nfapi_cqi_indication_pdu_t *)malloc(NB_UE_INST*sizeof(nfapi_cqi_indication_pdu_t));
-      UL_INFO->cqi_ind.cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t *)malloc(NB_UE_INST*sizeof(nfapi_cqi_indication_raw_pdu_t));
-      UL_INFO->cqi_ind.number_of_cqis = 0;
+      UL_INFO->cqi_ind.cqi_indication_body.cqi_pdu_list =  (nfapi_cqi_indication_pdu_t *)malloc(NB_UE_INST*sizeof(nfapi_cqi_indication_pdu_t));
+      UL_INFO->cqi_ind.cqi_indication_body.cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t *)malloc(NB_UE_INST*sizeof(nfapi_cqi_indication_raw_pdu_t));
+      UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis = 0;
 
       if (pthread_mutex_lock(&phy_stub_ticking->mutex_single_thread) != 0) {
         LOG_E( MAC, "[SCHED][UE] error locking mutex for ue_thread_id %d (mutex_single_thread)\n",ue_thread_id);
@@ -1262,10 +1262,10 @@ static void *UE_phy_stub_single_thread_rxn_txnp4(void *arg) {
       free(UL_INFO->sr_ind.sr_indication_body.sr_pdu_list);
       UL_INFO->sr_ind.sr_indication_body.sr_pdu_list = NULL;
       //}
-      free(UL_INFO->cqi_ind.cqi_pdu_list);
-      UL_INFO->cqi_ind.cqi_pdu_list = NULL;
-      free(UL_INFO->cqi_ind.cqi_raw_pdu_list);
-      UL_INFO->cqi_ind.cqi_raw_pdu_list = NULL;
+      free(UL_INFO->cqi_ind.cqi_indication_body.cqi_pdu_list);
+      UL_INFO->cqi_ind.cqi_indication_body.cqi_pdu_list = NULL;
+      free(UL_INFO->cqi_ind.cqi_indication_body.cqi_raw_pdu_list);
+      UL_INFO->cqi_ind.cqi_indication_body.cqi_raw_pdu_list = NULL;
       free(UL_INFO);
       UL_INFO = NULL;