diff --git a/ci-scripts/Jenkinsfile-poll-gNB-UE b/ci-scripts/Jenkinsfile-poll-gNB-UE
new file mode 100644
index 0000000000000000000000000000000000000000..532415b016b36efbc57eb875080ac9151d2ef955
--- /dev/null
+++ b/ci-scripts/Jenkinsfile-poll-gNB-UE
@@ -0,0 +1,374 @@
+#!/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
+*/
+
+
+// Abstraction function to send social media messages:
+// like on Slack or Mattermost
+def sendSocialMediaMessage(pipeChannel, pipeColor, pipeMessage) {
+    if (params.pipelineUsesSlack != null) {
+        if (params.pipelineUsesSlack) {
+            slackSend channel: pipeChannel, color: pipeColor, message: pipeMessage
+        }
+    }
+}
+
+// Location of the test XML file to be run
+def testXMLFile = params.pythonTestXmlFile
+def mainPythonAllXmlFiles = ""
+
+// Name of the phone resource
+def ciUSRPsResource = params.USRPsResource
+
+// Terminate Status
+def termUE = 0
+def termENB = 1
+def termStatusArray = new Boolean[2]
+termStatusArray[termUE] = false
+termStatusArray[termENB] = false
+
+// Global Parameters.
+def eNB_Repository
+def eNB_Branch
+def eNB_CommitID
+def eNB_AllowMergeRequestProcess = false
+def eNB_TargetBranch
+def PROJECT_NAME = "test-boris"
+def GIT_COMMIT_AUTHORi
+def GIT_COMMIT_EMAIL
+// Reversing list because pop() will take the last (right-most) element
+//def modeList = ['TesteNB', 'TestUE', 'TesteNB'].reverse()
+
+// Global Parameters not to break the main.py command line and code.
+def ADB_IPAddress = "none"
+def ADB_Username = "none"
+def ADB_Password = "none"
+def EPC_IPAddress = "none"
+def EPC_Username = "none"
+def EPC_Password = "none"
+
+
+
+pipeline {
+    agent {
+        label pythonExecutor 
+    }
+    options {
+        disableConcurrentBuilds()
+        gitLabConnection('OAI GitLab')
+        ansiColor('xterm')
+	lock (ciUSRPsResource)
+    }
+
+    stages {
+        stage ('Retrieve latest from branch') {
+            steps {
+	        script {
+	            checkout([$class: 'GitSCM', branches: [[name: "${params.Branch}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[url: 'https://gitlab.eurecom.fr/oai/openairinterface5g.git']]])
+	            sh "git clean -x -d -ff"
+	            sh "git log -n1"
+	        }
+            }
+        }
+        stage ("print latest commit info") {
+            steps {
+        	    script {
+        	        echo "Building on: "
+        	        echo "  Repository -- ${GIT_URL}"
+        	        echo "  Branch -- ${GIT_BRANCH}"
+        	        echo "  Commit -- ${GIT_COMMIT}"
+        	    }
+            }
+        }
+        stage ("Verify Parameters") {
+            steps {
+                script {
+                    JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
+                    JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
+
+                    echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
+                    def allParametersPresent = true
+
+                    // It is already too late to check it
+                    if (params.pythonExecutor != null) {
+                       echo "eNB CI executor node  :   ${pythonExecutor}"
+                    }
+                    if (params.eNB_Repository == null) {
+                        eNB_Repository = GIT_URL 
+                    } else {
+                        eNB_Repository = params.eNB_Repository
+                    }
+                    echo "eNB_Repository = ${eNB_Repository}"
+                    if (params.eNB_Branch== null) {
+                        eNB_Branch = GIT_BRANCH
+                    } else {
+                        eNB_Branch = params.eNB_Branch
+                    }
+                    echo "eNB_Branch = ${eNB_Branch}"
+                    if (params.eNB_CommitID == null) {
+                        eNB_CommitID = GIT_COMMIT 
+                    } else {
+                        eNB_CommitID = params.eNB_CommitID
+                    }
+                    echo "eNB_CommitID = ${eNB_CommitID}"
+                    // If not present picking a default XML file
+                    if (params.pythonTestXmlFile == null) {
+                        // picking default
+                        testXMLFile = 'xml_files/gnb_usrp_build.xml'
+                        echo "Test XML file(default):   ${testXMLFile}"
+                        mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
+                    } else {
+                        String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
+                        for (xmlFile in myXmlTestSuite) {
+                            if (fileExists("ci-scripts/" + xmlFile)) {
+                        	mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
+                        	echo "Test XML file         :   ${xmlFile}"
+                            }
+                        }
+                    }
+                    // If not present picking a default Stage Name
+                    if (params.pipelineTestStageName == null) {
+                        // picking default
+                        testStageName = 'Template Test Stage'
+                    }
+
+                    if (params.USRPsResource == null) {
+                        allParametersPresent = false
+                    }
+	
+                    if (params.eNB_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.UE_IPAddress == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB_SourceCodePath == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.eNB_Credentials == null) {
+                        allParametersPresent = false
+                    }
+                    if (params.UE_Credentials == null) {
+                        allParametersPresent = false
+                    }
+                    GIT_COMMIT_AUTHOR = sh (
+                        script: 'git show -s --pretty=%an',
+                        returnStdout: true
+                    ).trim()
+                    echo "The author of the commit is: ${GIT_COMMIT_AUTHOR}"
+                    GIT_COMMIT_EMAIL = sh (
+                        script: 'git show -s --pretty=%ae',
+                        returnStdout: true
+                    ).trim()
+                    echo "The email of the author is: ${GIT_COMMIT_EMAIL}"
+                    if (allParametersPresent) {
+                        echo "All parameters are present"
+                    } else {
+                        echo "Some parameters are missing"
+                        sh "./ci-scripts/fail.sh"
+                    }
+                }
+            }
+        }
+
+        stage ("Build and Test") {
+            steps {
+        	    script {
+        	        dir ('ci-scripts') {
+        	    	withCredentials([
+        	    	    [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'],
+        	    	    [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password']
+        	    	]) {
+        	    	    sh "python3 main.py --mode=InitiateHtml --eNBRepository=${eNB_Repository} --eNBBranch=${eNB_Branch} --eNBCommitID=${eNB_CommitID} --eNB_AllowMerge=${eNB_AllowMergeRequestProcess} --ADBIPAddress=${ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} ${mainPythonAllXmlFiles}"
+        	    	    String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
+        	    	    for (xmlFile in myXmlTestSuite) {
+        	    	    if (fileExists(xmlFile)) {
+        	    	        try {
+        	    	            sh "python3 main.py --mode=TesteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --UEIPAddress=${params.eNB_IPAddress} --UEUserName=${eNB_Username} --UEPassword=${eNB_Password} --eNBBranch=${eNB_Branch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --UESourceCodePath=${params.eNB_SourceCodePath} --eNBRepository=${eNB_Repository} --eNBCommitID=${eNB_CommitID} --ADBIPAddress=${ADB_IPAddress} --EPCIPAddress=${EPC_IPAddress} --XMLTestFile=${xmlFile}"
+        	    	        } catch (Exception e) {
+        	    	            currentBuild.result = 'FAILURE'
+        	    	        }
+        	    	    }
+        	    	    }
+        	        }
+        	    }
+                }
+            }
+	}	
+	
+        stage ("Terminate") {
+            parallel {
+        	stage('Terminate NR UE') {
+        	    steps {
+        		echo '\u2705 \u001B[32mTerminate NR UE\u001B[0m'
+                        withCredentials([
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password']
+                        ]) {
+                            sh "python3 ci-scripts/main.py --mode=TerminateOAIUE --UEIPAddress=${params.eNB_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password}"
+                        }
+        	    }
+        	    post {
+        		success {
+        		    script {
+        			termStatusArray[termUE] = true
+        		    }
+        		}
+        	    }
+        	}
+       	    stage('Terminate NR eNB') {
+       	        steps {
+		    echo '\u2705 \u001B[32mTerminate NR eNB\u001B[0m'
+                        withCredentials([
+                            [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
+                        ]) {
+                            sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}"
+                        }
+        	      }
+                    post {
+        	        success {
+                            script {
+        		        termStatusArray[termENB] = true
+        		    }
+                        }
+        	    }
+                }
+            }
+        }
+
+        stage('Log Collection') {
+            parallel {
+        	stage('Log Collection (gNB and NR UE - Build)') {
+        	    steps {
+        		withCredentials([
+        		     [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
+        		]) {
+        		    echo '\u2705 \u001B[32mLog Collection (gNB and NR UE - 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 (gNB and NR UE - 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 (gNB - Run)') {
+        	    steps {
+        		withCredentials([
+        		     [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
+        		]) {
+        		    echo '\u2705 \u001B[32mLog Collection (gNB - 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 (gNB - 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"
+        		    }
+        		}
+        	    }
+        	}
+        	stage('Log Collection (NR UE - Run)') {
+        	    steps {
+        		withCredentials([
+        		     [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
+        		]) {
+        		    echo '\u2705 \u001B[32mLog Collection (gNB - Run)\u001B[0m'
+        		    sh "python3 ci-scripts/main.py --mode=LogCollectOAIUE --UEIPAddress=${params.eNB_IPAddress} --UEUserName=${eNB_Username} --UEPassword=${eNB_Password} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --UESourceCodePath=${params.eNB_SourceCodePath}"
+        
+        		    echo '\u2705 \u001B[32mLog Transfer (gNB - Run)\u001B[0m'
+        		    sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/ue.log.zip ./ue.log.${env.BUILD_ID}.zip || true"
+        		}
+        		script {
+        		    if(fileExists("ue.log.${env.BUILD_ID}.zip")) {
+        			archiveArtifacts "ue.log.${env.BUILD_ID}.zip"
+        		    }
+        		}
+        	    }
+        	}
+            }
+        }
+    }
+
+    post {
+        always {
+            script {
+                if ("MERGE".equals(env.gitlabActionType)) {
+                    echo "This is a MERGE event"
+                } else {
+                    gitlabCommitStatus(name: "Test-gNB-nrUE") {
+                        if ((currentBuild.result == null) || (currentBuild.result == 'SUCCESS')) {
+                            echo "Setting the gitlab commit status to pass"
+                        } else {
+                            sh "./ci-scripts/fail.sh"
+                        }
+                    }
+                }
+                emailext attachmentsPattern: '*results*.html',
+                     body: '''Hi,
+Here are attached HTML report files for $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!
+
+Regards,
+OAI CI Team''',
+                     replyTo: 'no-reply@openairinterface.org',
+                     subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!',
+                     to: GIT_COMMIT_EMAIL
+	    }
+        }
+        success {
+            script {
+                def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")"
+                if ("MERGE".equals(env.gitlabActionType)) {
+                    echo "This is a MERGE event"
+                    //addGitLabMRComment comment: message
+                    def message2 = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ") -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")"
+                    sendSocialMediaMessage('ci-test', 'good', message2)
+                } else {
+                    sendSocialMediaMessage('ci-test', 'good', message)
+                }
+            }
+        }
+        failure {
+            script {
+                def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")"
+                if ("MERGE".equals(env.gitlabActionType)) {
+                    echo "This is a MERGE event"
+                    //addGitLabMRComment comment: message
+                    def message2 = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ") -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")"
+                    sendSocialMediaMessage('ci-test', 'danger', message2)
+                } else {
+                    sendSocialMediaMessage('ci-test', 'danger', message)
+                }
+            }
+        }
+    }
+}
+
diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
new file mode 100644
index 0000000000000000000000000000000000000000..e71bb00ffbe9879646bde948ad759653401b790e
--- /dev/null
+++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -0,0 +1,298 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});	 
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function                                                 = "3GPP_gNODEB";
+      node_timing                                                   = "synch_to_ext_device";
+      node_synch_ref                                                = 0;
+      frame_type                                                    = "TDD";
+      DL_prefix_type                                                = "NORMAL";
+      UL_prefix_type                                                = "NORMAL";
+      eutra_band                                                    = 78;
+      downlink_frequency                                            = 3510000000L;
+      uplink_frequency_offset                                       = -120000000;
+      Nid_cell                                                      = 0;
+      N_RB_DL                                                       = 106;
+      nb_antenna_ports                                              = 1;
+      nb_antennas_tx                                                = 1;
+      nb_antennas_rx                                                = 1;
+      tx_gain                                                       = 90;
+      rx_gain                                                       = 125;
+      MIB_subCarrierSpacingCommon                                   = 30;
+      MIB_ssb_SubcarrierOffset                                      = 0;
+      MIB_dmrs_TypeA_Position                                       = 2;
+      pdcch_ConfigSIB1                                              = 0;
+      SIB1_frequencyOffsetSSB                                       = "khz5";
+      SIB1_ssb_PeriodicityServingCell                               = 5;
+      SIB1_ss_PBCH_BlockPower                                       = -60;
+      absoluteFrequencySSB                                          = 0;
+      DL_FreqBandIndicatorNR                                        = 15;
+      DL_absoluteFrequencyPointA                                    = 15;
+      DL_offsetToCarrier                                            = 15;
+      DL_SCS_SubcarrierSpacing                                      = "kHz30";
+      DL_SCS_SpecificCarrier_k0                                     = 0;
+      DL_carrierBandwidth                                           = 15;
+      DL_locationAndBandwidth                                       = 15;
+      DL_BWP_SubcarrierSpacing                                      = "kHz30";
+      DL_BWP_prefix_type                                            = "NORMAL";
+      UL_FreqBandIndicatorNR                                        = 15;
+      UL_absoluteFrequencyPointA                                    = 13;
+      UL_additionalSpectrumEmission                                 = 3;
+      UL_p_Max                                                      = -1;
+      UL_frequencyShift7p5khz                                       = "TRUE";
+      UL_offsetToCarrier                                            = 10;
+      UL_SCS_SubcarrierSpacing                                      = "kHz30";
+      UL_SCS_SpecificCarrier_k0                                     = 0;
+      UL_carrierBandwidth                                           = 15;
+      UL_locationAndBandwidth                                       = 15;
+      UL_BWP_SubcarrierSpacing                                      = "kHz30";
+      UL_BWP_prefix_type                                            = "NORMAL";
+      UL_timeAlignmentTimerCommon                                   = "infinity";
+      ServingCellConfigCommon_n_TimingAdvanceOffset                 = "n0"
+      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x01;
+      ServingCellConfigCommon_ssb_periodicityServingCell            = 10;
+      ServingCellConfigCommon_dmrs_TypeA_Position                   = 2;
+      NIA_SubcarrierSpacing                                         = "kHz15"; 
+      ServingCellConfigCommon_ss_PBCH_BlockPower                    = -60;
+      referenceSubcarrierSpacing                                    = "kHz15";
+      dl_UL_TransmissionPeriodicity                                 = "ms0p5";
+      nrofDownlinkSlots                                             = 10;
+      nrofDownlinkSymbols                                           = 10;
+      nrofUplinkSlots                                               = 10;
+      nrofUplinkSymbols                                             = 10;
+      rach_totalNumberOfRA_Preambles                                = 63;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice         = "oneEighth";
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneEighth      = 4;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneFourth      = 8;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneHalf        = 16;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_one            = 24;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_two            = 32;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_four           = 8;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_eight          = 4;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_sixteen        = 2;
+      rach_groupBconfigured                                         = "ENABLE";
+      rach_ra_Msg3SizeGroupA                                        = 56;
+      rach_messagePowerOffsetGroupB                                 = "dB0";
+      rach_numberOfRA_PreamblesGroupA                               = 32;
+      rach_ra_ContentionResolutionTimer                             = 8;
+      rsrp_ThresholdSSB                                             = 64;
+      rsrp_ThresholdSSB_SUL                                         = 64;
+      prach_RootSequenceIndex_choice                                = "l839";
+      prach_RootSequenceIndex_l839                                  = 0;
+      prach_RootSequenceIndex_l139                                  = 0;
+      prach_msg1_SubcarrierSpacing                                  = "kHz30";
+      restrictedSetConfig                                           = "unrestrictedSet";
+      msg3_transformPrecoding                                       = "ENABLE";
+      prach_ConfigurationIndex                                      = 10;
+      prach_msg1_FDM                                                = "one";
+      prach_msg1_FrequencyStart                                     = 10;
+      zeroCorrelationZoneConfig                                     = 10;
+      preambleReceivedTargetPower                                   = -150;
+      preambleTransMax                                              = 6;
+      powerRampingStep                                              = "dB0";
+      ra_ResponseWindow                                             = 8;
+      groupHoppingEnabledTransformPrecoding                         = "ENABLE";
+      msg3_DeltaPreamble                                            = 0;
+      p0_NominalWithGrant                                           = 0;
+      PUSCH_TimeDomainResourceAllocation_k2                         = 0;
+      PUSCH_TimeDomainResourceAllocation_mappingType                = "typeA";
+      PUSCH_TimeDomainResourceAllocation_startSymbolAndLength       = 0;
+      pucch_ResourceCommon                                          = 0;
+      pucch_GroupHopping                                            = "neither";
+      hoppingId                                                     = 0;
+      p0_nominal                                                    = -30;
+      PDSCH_TimeDomainResourceAllocation_k0                         = 2;
+      PDSCH_TimeDomainResourceAllocation_mappingType                = "typeA";
+      PDSCH_TimeDomainResourceAllocation_startSymbolAndLength       = 0;
+      rateMatchPatternId                                            = 0;
+      RateMatchPattern_patternType                                  = "bitmaps";
+      symbolsInResourceBlock                                        = "oneSlot";
+      periodicityAndPattern                                         = 2;
+      RateMatchPattern_controlResourceSet                           = 5;
+      RateMatchPattern_subcarrierSpacing                            = "kHz30";
+      RateMatchPattern_mode                                         = "dynamic";
+      controlResourceSetZero                                        = 0;
+      searchSpaceZero                                               = 0;
+      searchSpaceSIB1                                               = 10;
+      searchSpaceOtherSystemInformation                             = 10;
+      pagingSearchSpace                                             = 10;
+      ra_SearchSpace                                                = 10;
+      PDCCH_common_controlResourceSetId                             = 5;
+      PDCCH_common_ControlResourceSet_duration                      = 2;
+      PDCCH_cce_REG_MappingType                                     = "nonInterleaved";
+      PDCCH_reg_BundleSize                                          = 3;
+      PDCCH_interleaverSize                                         = 3;
+      PDCCH_shiftIndex                                              = 10;  
+      PDCCH_precoderGranularity                                     = "sameAsREG-bundle";
+      PDCCH_TCI_StateId                                             = 32;
+      tci_PresentInDCI                                              = "ENABLE";
+      PDCCH_DMRS_ScramblingID                                       = 0;
+      SearchSpaceId                                                 = 10;
+      commonSearchSpaces_controlResourceSetId                       = 5;
+      SearchSpace_monitoringSlotPeriodicityAndOffset_choice         = "sl1";
+      SearchSpace_monitoringSlotPeriodicityAndOffset_value          = 0;
+      SearchSpace_duration                                          = 2;
+      SearchSpace_nrofCandidates_aggregationLevel1                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel2                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel4                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel8                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel16                 = 0;
+      SearchSpace_searchSpaceType                                   = "common";
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel1     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel2     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel4     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel8     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel16    = 1; 
+      Common_dci_Format2_3_monitoringPeriodicity                    = 1;
+      Common_dci_Format2_3_nrofPDCCH_Candidates                     = 1;
+      ue_Specific__dci_Formats                                      = "formats0-0-And-1-0";
+      RateMatchPatternLTE_CRS_carrierFreqDL                         = 6;
+      RateMatchPatternLTE_CRS_carrierBandwidthDL                    = 6;
+      RateMatchPatternLTE_CRS_nrofCRS_Ports                         = 1;
+      RateMatchPatternLTE_CRS_v_Shift                               = 0;
+      RateMatchPatternLTE_CRS_radioframeAllocationPeriod            = 1;
+      RateMatchPatternLTE_CRS_radioframeAllocationOffset            = 0;
+      RateMatchPatternLTE_CRS_subframeAllocation_choice             = "oneFrame";
+      }
+    );
+
+
+    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       = "192.168.12.26";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
+        GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        }  
+);
+
+RUs = (
+    {		  
+       local_rf       = "yes"
+         nb_tx          = 1
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 114;
+         eNB_instances  = [0];
+	 sdr_addrs = "addr=192.168.20.2,second_addr=192.168.10.2,mgmt_addr=192.168.20.2,clock_source=external,time_source=external";
+
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+NETWORK_CONTROLLER :
+{
+    FLEXRAN_ENABLED        = "no";
+    FLEXRAN_INTERFACE_NAME = "lo";
+    FLEXRAN_IPV4_ADDRESS   = "127.0.0.1";
+    FLEXRAN_PORT           = 2210;
+    FLEXRAN_CACHE          = "/mnt/oai_agent_cache";
+    FLEXRAN_AWAIT_RECONF   = "no";
+};
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/ci-scripts/main.py b/ci-scripts/main.py
index dc101fe7ea5ada09483869f08efdb0c27033e157..b6bac27831b5588fb94ff454cd9898b0389167bf 100644
--- a/ci-scripts/main.py
+++ b/ci-scripts/main.py
@@ -1,3 +1,4 @@
+# dummy commit
 #/*
 # * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 # * contributor license agreements.  See the NOTICE file distributed with
@@ -43,6 +44,9 @@ ENB_PROCESS_SEG_FAULT = -11
 ENB_PROCESS_ASSERTION = -12
 ENB_PROCESS_REALTIME_ISSUE = -13
 ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14
+UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20
+UE_PROCESS_COULD_NOT_SYNC = -21
+UE_PROCESS_ASSERTION = -22
 HSS_PROCESS_FAILED = -2
 HSS_PROCESS_OK = +2
 MME_PROCESS_FAILED = -3
@@ -64,6 +68,7 @@ import xml.etree.ElementTree as ET
 import logging
 import datetime
 import signal
+#import platform
 from multiprocessing import Process, Lock, SimpleQueue
 logging.basicConfig(
 	level=logging.DEBUG,
@@ -98,8 +103,11 @@ class SSHConnection():
 		self.desc = ''
 		self.Build_eNB_args = ''
 		self.Initialize_eNB_args = ''
+		self.air_interface = 'lte'
 		self.eNBLogFile = ''
 		self.eNB_instance = ''
+		self.eNBOptions = ''
+		self.rruOptions = ''
 		self.ping_args = ''
 		self.ping_packetloss_threshold = ''
 		self.iperf_args = ''
@@ -120,13 +128,25 @@ class SSHConnection():
 		self.htmlTabNames = []
 		self.htmlTabIcons = []
 		self.finalStatus = False
+		self.OsVersion = ''
+		self.KernelVersion = ''
+		self.UhdVersion = ''
+		self.UsrpBoard = ''
+		self.CpuNb = ''
+		self.CpuModel = ''
+		self.CpuMHz = ''
+		self.UEIPAddress = ''
+		self.UEUserName = ''
+		self.UEPassword = ''
+		self.UE_instance = ''
+		self.UELogFile = ''
+		self.UESourceCodePath = ''
+		self.Build_OAI_UE_args = ''
+		self.Initialize_OAI_UE_args = ''
+		self.Initialize_OAI_eNB_args = ''
+		self.clean_repository = True
 		self.eNBOsVersion = ''
-		self.eNBKernelVersion = ''
-		self.eNBUhdVersion = ''
-		self.eNBCpuNb = ''
-		self.eNBCpuModel = ''
-		self.eNBCpuMHz = ''
-
+		
 	def open(self, ipaddress, username, password):
 		count = 0
 		connect_status = False
@@ -321,11 +341,48 @@ class SSHConnection():
 		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)
-		# Workaround to run with develop-nr
-		self.command('if [ -e ran_build ]; then cp -rf ran_build lte_build_oai; fi', '\$', 30)
 		self.close()
 		self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK)
 
+	def BuildOAIUE(self):
+		if self.UEIPAddress == '' or self.eNBRepository == '' or self.eNBBranch == '' 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)
+		# 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)
+		if self.clean_repository:
+			pass
+			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 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'):
+					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)
+		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_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee -a compile_oai_ue.log', 'Bypassing the Tests', 600)
+		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_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5)
+		self.close()
+		self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE')
+
+
 	def InitializeHSS(self):
 		if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '':
 			Usage()
@@ -411,6 +468,7 @@ class SSHConnection():
 		self.command('cd ' + self.eNBSourceCodePath, '\$', 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 = ''
 		extIdx = full_config_file.find('.conf')
 		if (extIdx > 0):
 			extra_options = full_config_file[extIdx + 5:]
@@ -431,6 +489,16 @@ class SSHConnection():
 		result = re.search('rru', str(config_file))
 		if result is not None:
 			rruCheck = True
+		# do not reset board twice in IF4.5 case
+		result = re.search('rru|enb', str(config_file))
+		if result is not None:
+			self.command('echo ' + self.eNBPassword + ' | sudo -S uhd_find_devices', '\$', 30)
+			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 sudo b2xx_fx3_utils --reset-device', '\$', 5)
+				# Reloading FGPA bin firmware
+				self.command('echo ' + self.eNBPassword + ' | sudo -S uhd_find_devices', '\$', 30)
 		# 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);
@@ -438,12 +506,20 @@ 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 && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + self.eNBSourceCodePath + '/' + 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)
+		self.command('echo ' + self.eNBPassword + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5)				
+		#to use daemon on CentOS we need to source the function
+		#linux_distro = platform.linux_distribution()[0]
+		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
+		#self.command('source /etc/init.d/functions', '\$', 5)
+		#use nohup instead of daemon
+		#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)
+		self.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh' + ' > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log' + ' 2>&1 &', self.eNBUserName, 5)		
 		if not rruCheck:
 			self.eNBLogFile = 'enb_' + self.testCase_id + '.log'
+			if extra_options != '':
+				self.eNBOptions = extra_options
 		time.sleep(6)
 		doLoop = True
 		loopCounter = 10
@@ -482,6 +558,8 @@ 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')
 
@@ -517,6 +595,165 @@ class SSHConnection():
 			job.join()
 		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
+	def InitializeOAIUE(self):
+		if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
+			Usage()
+			sys.exit('Insufficient Parameter')
+		#initialize_OAI_UE_flag = True
+		#pStatus = self.CheckOAIUEProcessExist(initialize_OAI_UE_flag)
+		#if (pStatus < 0):
+		#	self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus)
+		#	self.CreateHtmlTabFooter(False)
+		#	sys.exit(1)
+		self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
+		# b2xx_fx3_utils reset procedure
+		self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 30)
+		result = re.search('type: n3xx', str(self.ssh.before))
+		if result is not None:
+			pass
+			logging.debug('Found a B2xx device --> resetting it')
+			self.command('echo ' + self.UEPassword + ' | sudo -S sudo b2xx_fx3_utils --reset-device', '\$', 5)
+			# Reloading FGPA bin firmware
+			self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 30)
+		else:
+			logging.debug('Did not find any B2xx device')
+		self.command('cd ' + self.UESourceCodePath, '\$', 5)
+		# Initialize_OAI_UE_args usually start with -C and followed by the location in repository
+		self.command('source oaienv', '\$', 5)
+		self.command('cd cmake_targets/ran_build/build', '\$', 5)
+		self.command('echo "ulimit -c unlimited && ./'+ self.air_interface +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
+		self.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
+		self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5)
+		#to use daemon on CentOS we need to source the function
+		#linux_distro = platform.linux_distribution()[0]		
+		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
+			#self.command('source /etc/init.d/functions', '\$', 5)
+		#use nohup instead of daemon
+		self.command('echo $USER; nohup sudo ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5)
+		#self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/ran_build/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
+		self.UELogFile = 'ue_' + self.testCase_id + '.log'
+		time.sleep(6)
+		self.command('cd ../..', '\$', 5)
+		doLoop = True
+		loopCounter = 10
+		while (doLoop):
+			loopCounter = loopCounter - 1
+			if (loopCounter == 0):
+				self.close()
+				doLoop = False
+				logging.error('\u001B[1;37;41m UE logging system did not show got sync! \u001B[0m')
+				self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE')
+				self.CreateHtmlTabFooter(False)
+				sys.exit(1)
+			else:
+				self.command('stdbuf -o0 cat ' + self.UELogFile + ' | egrep --text --color=never -i "wait|sync"', '\$', 4)
+				if self.air_interface == 'nr':
+					result = re.search('Starting sync detection', str(self.ssh.before))
+				else:
+					result = re.search('got sync', str(self.ssh.before))
+				if result is None:
+					time.sleep(10)
+				else:
+					doLoop = False
+					self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE')
+					logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m')
+		self.close()
+
+	def InitializeOAIeNB(self):
+		if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.eNBSourceCodePath == '':
+			Usage()
+			sys.exit('Insufficient Parameter')
+		#initialize_OAI_eNB_flag = True
+		#pStatus = self.CheckOAIeNBProcessExist(initialize_OAI_eNB_flag)
+		#if (pStatus < 0):
+		#	self.CreateHtmlTestRow(self.Initialize_OAI_eNB_args, 'KO', pStatus)
+		#	self.CreateHtmlTabFooter(False)
+		#	sys.exit(1)
+		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
+		self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
+		# Initialize_OAI_eNB_args usually start with -C and followed by the location in repository
+		#full_config_file = self.Initialize_OAI_eNB_args.replace('-O ','')
+		#extIdx = full_config_file.find('.conf')
+		#if (extIdx > 0):
+		#	extra_options = full_config_file[extIdx + 5:]
+		#	# if tracer options is on, compiling and running T Tracer
+		#	result = re.search('T_stdout', str(extra_options))
+		##	if result is not None:
+		#		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)
+		#	full_config_file = full_config_file[:extIdx + 5]
+		#	config_path, config_file = os.path.split(full_config_file)
+		#ci_full_config_file = config_path + '/ci-' + config_file
+		#rruCheck = False
+		#result = re.search('rru', str(config_file))
+		#if result is not None:
+		#	rruCheck = True
+		## 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_eNB_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2);
+		# Launch eNB with the modified config file
+		self.command('source oaienv', '\$', 5)
+		self.command('cd cmake_targets/ran_build/build', '\$', 5)
+		#self.command('echo "ulimit -c unlimited && ./' + self.air_interface + '-softmodem ' + self.Initialize_OAI_eNB_args + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
+		self.eNBLogFile = 'enb_' + self.testCase_id + '.log'
+		self.command('echo "ulimit -c unlimited && ./' + self.air_interface + '-softmodem ' + self.Initialize_OAI_eNB_args + '|& tee ' + self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFile + '" > ./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 ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log', '\$', 5)
+		#to use daemon on CentOS we need to source the function
+		#linux_distro = platform.linux_distribution()[0]		
+		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
+			#self.command('source /etc/init.d/functions', '\$', 5)
+		#use nohup instead of daemon
+		self.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh' + ' > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log' + ' 2>&1 &', self.eNBUserName, 5)
+		#self.command('echo ' + self.eNBPassword + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + self.eNBSourceCodePath + '/cmake_targets/ran_build/build -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
+		time.sleep(6)
+		self.command('cd ../..', '\$', 5)
+		doLoop = True
+		loopCounter = 10
+		print('gNB log file: ' + self.eNBLogFile)
+		while (doLoop):
+			loopCounter = loopCounter - 1
+			if (loopCounter == 0):
+				# In case of T tracer recording, we may need to kill it
+				#result = re.search('T_stdout', str(self.Initialize_OAI_eNB_args))
+				#if result is not None:
+				#	self.command('killall --signal SIGKILL record', '\$', 5)
+				self.close()
+				doLoop = False
+				logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m')
+				self.CreateHtmlTestRow(self.Initialize_OAI_eNB_args, 'KO', ALL_PROCESSES_OK, 'OAI eNB')
+				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_OAI_eNB_args))
+				#if result is not None:
+				#	self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
+				#	logging.debug('\u001B[1m Stopping tshark \u001B[0m')
+				#	self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5)
+				#	self.close()
+				#	time.sleep(1)
+				#	pcap_log_file = 'enb_' + self.testCase_id + '_s1log.pcap'
+				#	copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + pcap_log_file, '.')
+				#	if (copyin_res == 0):
+				#		self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, pcap_log_file, self.eNBSourceCodePath + '/cmake_targets/.')
+				sys.exit(1)
+			else:
+				#print('current directory: ' + os.getcwd())
+				#self.command('pwd', '\$', 4)
+				#print('self.command pwd: ' + str(self.ssh.before))
+				self.command('stdbuf -o0 cat ' + self.eNBLogFile + ' | egrep --text --color=never -i "wait|sync"', '\$', 30)
+				#print(self.ssh.before)
+				result = re.search('got sync', str(self.ssh.before))
+				if result is None:
+					time.sleep(11)
+				else:
+					doLoop = False
+					self.CreateHtmlTestRow(self.Initialize_OAI_eNB_args, 'OK', ALL_PROCESSES_OK, 'OAI eNB')
+					logging.debug('\u001B[1m Initialize OAI eNB Completed\u001B[0m')
+		self.close()
+
 	def checkDevTTYisUnlocked(self):
 		self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword)
 		count = 0
@@ -604,21 +841,150 @@ class SSHConnection():
 		time.sleep(4)
 		# We should check if we register
 		count = 0
-		while count < 3:
+		attach_cnt = 0
+		attach_status = False
+		while count < 5:
 			self.command('AT+CEREG?', 'OK', 5)
-			result = re.search('CEREG: 2,(?P<state>[0-9\-]+)', str(self.ssh.before))
+			result = re.search('CEREG: 2,(?P<state>[0-9\-]+),', str(self.ssh.before))
 			if result is not None:
 				mDataConnectionState = int(result.group('state'))
 				if mDataConnectionState is not None:
-					logging.debug('+CEREG: 2,' + str(mDataConnectionState))
+					if mDataConnectionState == 1:
+						count = 10
+						attach_status = True
+						result = re.search('CEREG: 2,1,"(?P<networky>[0-9A-Z]+)","(?P<networkz>[0-9A-Z]+)"', str(self.ssh.before))
+						if result is not None:
+							networky = result.group('networky')
+							networkz = result.group('networkz')
+							logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m')
+						else:
+							logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m')
+					else:
+						logging.debug('+CEREG: 2,' + str(mDataConnectionState))
+						attach_cnt = attach_cnt + 1
 			else:
 				logging.debug(str(self.ssh.before))
+				attach_cnt = attach_cnt + 1
 			count = count + 1
 			time.sleep(1)
+		if attach_status:
+			self.command('AT+CESQ', 'OK', 5)
+			result = re.search('CESQ: 99,99,255,255,(?P<rsrq>[0-9]+),(?P<rsrp>[0-9]+)', str(self.ssh.before))
+			if result is not None:
+				nRSRQ = int(result.group('rsrq'))
+				nRSRP = int(result.group('rsrp'))
+				if (nRSRQ is not None) and (nRSRP is not None):
+					logging.debug('    RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB')
+					logging.debug('    RSRP = ' + str(-140+nRSRP) + ' dBm')
 		self.close()
 		self.picocom_closure = False
-		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
+		html_queue = SimpleQueue()
 		self.checkDevTTYisUnlocked()
+		if attach_status:
+			html_cell = '<pre style="background-color:white">CAT-M module\nAttachment Completed in ' + str(attach_cnt+4) + ' seconds'
+			if (nRSRQ is not None) and (nRSRP is not None):
+				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
+				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm</pre>'
+			else:
+				html_cell += '</pre>'
+			html_queue.put(html_cell)
+			self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue)
+		else:
+			html_cell = '<pre style="background-color:white">CAT-M module\nAttachment Failed</pre>'
+			html_queue.put(html_cell)
+			self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue)
+
+	def PingCatM(self):
+		if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '':
+			Usage()
+			sys.exit('Insufficient Parameter')
+		initialize_eNB_flag = False
+		pStatus = self.CheckProcessExist(initialize_eNB_flag)
+		if (pStatus < 0):
+			self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
+			self.CreateHtmlTabFooter(False)
+			sys.exit(1)
+		try:
+			statusQueue = SimpleQueue()
+			lock = Lock()
+			self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
+			self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
+			self.command('cd scripts', '\$', 5)
+			if re.match('OAI', self.EPCType, re.IGNORECASE):
+				logging.debug('Using the OAI EPC HSS: not implemented yet')
+				self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus)
+				self.CreateHtmlTabFooter(False)
+				sys.exit(1)
+			else:
+				self.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5)
+				result = re.search('Allocated ipv4 addr: (?P<ipaddr>[0-9\.]+) from Pool', str(self.ssh.before))
+				if result is not None:
+					moduleIPAddr = result.group('ipaddr')
+				else:
+					return
+			ping_time = re.findall("-c (\d+)",str(self.ping_args))
+			device_id = 'catm'
+			ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee -a ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5)
+			# TIMEOUT CASE
+			if ping_status < 0:
+				message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!'
+				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
+				self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message)
+				return
+			result = re.search(', (?P<packetloss>[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before))
+			if result is None:
+				message = 'Packet Loss Not Found!'
+				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
+				self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message)
+				return
+			packetloss = result.group('packetloss')
+			if float(packetloss) == 100:
+				message = 'Packet Loss is 100%'
+				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
+				self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message)
+				return
+			result = re.search('rtt min\/avg\/max\/mdev = (?P<rtt_min>[0-9\.]+)\/(?P<rtt_avg>[0-9\.]+)\/(?P<rtt_max>[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before))
+			if result is None:
+				message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!'
+				logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m')
+				self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message)
+				return
+			rtt_min = result.group('rtt_min')
+			rtt_avg = result.group('rtt_avg')
+			rtt_max = result.group('rtt_max')
+			pal_msg = 'Packet Loss : ' + packetloss + '%'
+			min_msg = 'RTT(Min)    : ' + rtt_min + ' ms'
+			avg_msg = 'RTT(Avg)    : ' + rtt_avg + ' ms'
+			max_msg = 'RTT(Max)    : ' + rtt_max + ' ms'
+			lock.acquire()
+			logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m')
+			logging.debug('\u001B[1;34m    ' + pal_msg + '\u001B[0m')
+			logging.debug('\u001B[1;34m    ' + min_msg + '\u001B[0m')
+			logging.debug('\u001B[1;34m    ' + avg_msg + '\u001B[0m')
+			logging.debug('\u001B[1;34m    ' + max_msg + '\u001B[0m')
+			qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg
+			packetLossOK = True
+			if packetloss is not None:
+				if float(packetloss) > float(self.ping_packetloss_threshold):
+					qMsg += '\nPacket Loss too high'
+					logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m')
+					packetLossOK = False
+				elif float(packetloss) > 0:
+					qMsg += '\nPacket Loss is not 0%'
+					logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m')
+			lock.release()
+			self.close()
+			html_cell = '<pre style="background-color:white">CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '</pre>'
+			statusQueue.put(html_cell)
+			if (packetLossOK):
+				self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue)
+			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:
@@ -1527,11 +1893,53 @@ class SSHConnection():
 						result = logStatus
 			return result
 
+	def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag):
+		multi_jobs = []
+		status_queue = SimpleQueue()
+		if initialize_OAI_UE_flag == False:
+			p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,))
+			p.daemon = True
+			p.start()
+			multi_jobs.append(p)
+		for job in multi_jobs:
+			job.join()
+
+		if (status_queue.empty()):
+			return -15
+		else:
+			result = 0
+			while (not status_queue.empty()):
+				status = status_queue.get()
+				if (status < 0):
+					result = status
+			if result == OAI_UE_PROCESS_FAILED:
+				fileCheck = re.search('enb_', str(self.UELogFile))
+				if fileCheck is not None:
+					self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.')
+					logStatus = self.AnalyzeLogFile_UE(self.UELogFile)
+					if logStatus < 0:
+						result = logStatus
+			return result
+
+	def CheckOAIUEProcess(self, status_queue):
+		try:
+			self.open(self.OAIUEIPAddress, self.OAIUEUserName, self.OAIUEPassword)
+			self.command('stdbuf -o0 ps -aux | grep -v grep | grep --color=never ' + self.air_interface + '-uesoftmodem', '\$', 5)
+			result = re.search(self.air_interface + '-uesoftmodem', str(self.ssh.before))
+			if result is None:
+				logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m')
+				status_queue.put(OAI_UE_PROCESS_FAILED)
+			else:
+				status_queue.put(OAI_UE_PROCESS_OK)
+			self.close()
+		except:
+			os.kill(os.getppid(),signal.SIGUSR1)
+
 	def CheckeNBProcess(self, status_queue):
 		try:
 			self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
-			self.command('stdbuf -o0 ps -aux | grep -v grep | grep --color=never lte-softmodem', '\$', 5)
-			result = re.search('lte-softmodem', str(self.ssh.before))
+			self.command('stdbuf -o0 ps -aux | grep -v grep | grep --color=never ' + self.air_interface + '-softmodem', '\$', 5)
+			result = re.search(self.air_interface + '-softmodem', str(self.ssh.before))
 			if result is None:
 				logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m')
 				status_queue.put(ENB_PROCESS_FAILED)
@@ -1615,7 +2023,18 @@ class SSHConnection():
 		uciStatMsgCount = 0
 		pdcpFailure = 0
 		ulschFailure = 0
+		self.htmleNBFailureMsg = ''
 		for line in enb_log_file.readlines():
+			if self.rruOptions != '':
+				res1 = re.search('max_rxgain (?P<requested_option>[0-9]+)', self.rruOptions)
+				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'
+					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'
 			result = re.search('[Ss]egmentation [Ff]ault', str(line))
 			if result is not None:
 				foundSegFault = True
@@ -1734,17 +2153,172 @@ class SSHConnection():
 			return ENB_PROCESS_REALTIME_ISSUE
 		return 0
 
+	def AnalyzeLogFile_UE(self, UElogFile):
+		if (not os.path.isfile('./' + UElogFile)):
+			return -1
+		ue_log_file = open('./' + UElogFile, 'r')
+		foundAssertion = False
+		msgAssertion = ''
+		msgLine = 0
+		foundSegFault = False
+		foundRealTimeIssue = False
+		rlcDiscardBuffer = 0
+		rachCanceledProcedure = 0
+		uciStatMsgCount = 0
+		pdcpFailure = 0
+		ulschFailure = 0
+		no_cell_sync_found = False
+		mib_found = False
+		frequency_found = False
+		self.htmlUEFailureMsg = ''
+		for line in ue_log_file.readlines():
+			result = re.search('[Ss]egmentation [Ff]ault', str(line))
+			if result is not None:
+				foundSegFault = True
+			result = re.search('[Cc]ore [dD]ump', str(line))
+			if result is not None:
+				foundSegFault = True
+			result = re.search('[Aa]ssertion', str(line))
+			if result is not None:
+				foundAssertion = True
+			result = re.search('LLL', str(line))
+			if result is not None:
+				foundRealTimeIssue = True
+			if foundAssertion and (msgLine < 3):
+				msgLine += 1
+				msgAssertion += str(line)
+			result = re.search('uci->stat', str(line))
+			if result is not None:
+				uciStatMsgCount += 1
+			# No cell synchronization found, abandoning
+			result = re.search('No cell synchronization found, abandoning', str(line))
+			if result is not None:
+				no_cell_sync_found = True
+			result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P<nidcell>\d{1,3}), N_RB_DL (?P<n_rb_dl>\d{1,3}), PHICH DURATION (?P<phich_duration>\d), PHICH RESOURCE (?P<phich_resource>.{1,4}), TX_ANT (?P<tx_ant>\d)", str(line))
+			if result is not None and (not mib_found):
+				try:
+					mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2)
+					self.htmlUEFailureMsg += mibMsg + '\n'
+					logging.debug('\033[94m' + mibMsg + '\033[0m')
+					mibMsg = "    nidcell = " + result.group('nidcell')
+					self.htmlUEFailureMsg += mibMsg
+					logging.debug('\033[94m' + mibMsg + '\033[0m')
+					mibMsg = "    n_rb_dl = " + result.group('n_rb_dl')
+					self.htmlUEFailureMsg += mibMsg + '\n'
+					logging.debug('\033[94m' + mibMsg + '\033[0m')
+					mibMsg = "    phich_duration = " + result.group('phich_duration')
+					self.htmlUEFailureMsg += mibMsg
+					logging.debug('\033[94m' + mibMsg + '\033[0m')
+					mibMsg = "    phich_resource = " + result.group('phich_resource')
+					self.htmlUEFailureMsg += mibMsg + '\n'
+					logging.debug('\033[94m' + mibMsg + '\033[0m')
+					mibMsg = "    tx_ant = " + result.group('tx_ant')
+					self.htmlUEFailureMsg += mibMsg + '\n'
+					logging.debug('\033[94m' + mibMsg + '\033[0m')
+					mib_found = True
+				except Exception as e:
+					logging.error('\033[91m' + "MIB marker was not found" + '\033[0m')
+			result = re.search("Measured Carrier Frequency (?P<measured_carrier_frequency>\d{1,15}) Hz", str(line))
+			if result is not None and (not frequency_found):
+				try:
+					mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz'
+					self.htmlUEFailureMsg += mibMsg + '\n'
+					logging.debug('\033[94m' + mibMsg + '\033[0m')
+					frequency_found = True
+				except Exception as e:
+					logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m')
+			result = re.search("Found (?P<operator>[\w,\s]{1,15}) \(name from internal table\)", str(line))
+			if result is not None:
+				try:
+					mibMsg = "The operator is: " + result.group('operator')
+					self.htmlUEFailureMsg += mibMsg + '\n'
+					logging.debug('\033[94m' + mibMsg + '\033[0m')
+				except Exception as e:
+					logging.error('\033[91m' + "Operator name not found" + '\033[0m')
+			result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line))
+			if result is not None:
+				try:
+					mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2)
+					self.htmlUEFailureMsg += mibMsg + ' -> '
+					logging.debug('\033[94m' + mibMsg + '\033[0m')
+				except Exception as e:
+					logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m')
+			result = re.search("DL Carrier Frequency/ARFCN : (?P<carrier_frequency>\d{1,15}/\d{1,4})", str(line))
+			if result is not None:
+				try:
+					freq = result.group('carrier_frequency')
+					new_freq = re.sub('/[0-9]+','',freq)
+					float_freq = float(new_freq) / 1000000
+					self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz'
+					logging.debug('\033[94m' + "    DL Carrier Frequency is: " + freq + '\033[0m')
+				except Exception as e:
+					logging.error('\033[91m' + "    DL Carrier Frequency not found" + '\033[0m')
+			result = re.search("AllowedMeasBandwidth : (?P<allowed_bandwidth>\d{1,7})", str(line))
+			if result is not None:
+				try:
+					prb = result.group('allowed_bandwidth')
+					self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n'
+					logging.debug('\033[94m' + "    AllowedMeasBandwidth: " + prb + '\033[0m')
+				except Exception as e:
+					logging.error('\033[91m' + "    AllowedMeasBandwidth not found" + '\033[0m')
+		ue_log_file.close()
+		if uciStatMsgCount > 0:
+			statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)'
+			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
+			self.htmlUEFailureMsg += statMsg + '\n'
+		if pdcpFailure > 0:
+			statMsg = 'UE showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)'
+			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
+			self.htmlUEFailureMsg += statMsg + '\n'
+		if ulschFailure > 0:
+			statMsg = 'UE showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)'
+			logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m')
+			self.htmlUEFailureMsg += statMsg + '\n'
+		if rachCanceledProcedure > 0:
+			rachMsg = 'UE cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)'
+			logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m')
+			self.htmlUEFailureMsg += rachMsg + '\n'
+		if foundSegFault:
+			logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m')
+			return ENB_PROCESS_SEG_FAULT
+		if foundAssertion:
+			logging.debug('\u001B[1;37;43m UE ended with an assertion! \u001B[0m')
+			# removed for esthetics
+			#self.htmlUEFailureMsg += msgAssertion
+			self.htmlUEFailureMsg += 'UE ended with an assertion!\n'
+			if not mib_found or not frequency_found:
+				return UE_PROCESS_ASSERTION
+		if foundRealTimeIssue:
+			logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m')
+			self.htmlUEFailureMsg += 'UE faced real time issues!\n'
+			#return ENB_PROCESS_REALTIME_ISSUE
+		if no_cell_sync_found and not mib_found:
+			logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m')
+			self.htmlUEFailureMsg += 'UE could not synchronize!\n'
+			return UE_PROCESS_COULD_NOT_SYNC
+		if rlcDiscardBuffer > 0:
+			rlcMsg = 'UE RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)'
+			logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m')
+			self.htmlUEFailureMsg += rlcMsg + '\n'
+			return ENB_PROCESS_REALTIME_ISSUE
+		return 0
+
 	def TerminateeNB(self):
 		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
 		self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5)
+		#to use daemon on CentOS we need to source the function
+		#linux_distro = platform.linux_distribution()[0]		
+		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
+			#self.command('source /etc/init.d/functions', '\$', 5)
+		#use nohup instead of daemon
 		self.command('echo ' + self.eNBPassword + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5)
 		self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5)
-		self.command('echo ' + self.eNBPassword + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5)
+		self.command('echo ' + self.eNBPassword + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5)
 		time.sleep(5)
-		self.command('stdbuf -o0  ps -aux | grep -v grep | grep lte-softmodem', '\$', 5)
-		result = re.search('lte-softmodem', str(self.ssh.before))
+		self.command('stdbuf -o0  ps -aux | grep softmodem | grep -v grep', '\$', 5)
+		result = re.search('-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 ' + self.eNBPassword + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5)
 			time.sleep(5)
 		self.close()
 		# If tracer options is on, stopping tshark on EPC side
@@ -1810,6 +2384,10 @@ class SSHConnection():
 			self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
 			self.command('cd scripts', '\$', 5)
 			self.command('rm -f ./kill_hss.sh', '\$', 5)
+			#to use daemon on CentOS we need to source the function
+			#linux_distro = platform.linux_distribution()[0]         
+			#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
+				#self.command('source /etc/init.d/functions', '\$', 5)
 			self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5)
 			time.sleep(1)
 			self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5)
@@ -1874,6 +2452,50 @@ class SSHConnection():
 			job.join()
 		self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK)
 
+	def TerminateOAIUE(self):
+		self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
+		self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5)
+		#to use daemon on CentOS we need to source the function
+		#linux_distro = platform.linux_distribution()[0]
+		#if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE):
+			#self.command('source /etc/init.d/functions', '\$', 5)
+		#self.command('echo ' + self.UEPassword + ' | sudo -S daemon --name=ue' + str(self.UE_instance) + '_daemon --stop', '\$', 5)
+		self.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5)
+		self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT -r .*-uesoftmodem || true', '\$', 5)
+		time.sleep(5)
+		self.command('stdbuf -o0  ps -aux | grep uesoftmodem | grep -v grep', '\$', 5)
+		result = re.search('-uesoftmodem', str(self.ssh.before))
+		if result is not None:
+			self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL -r .*-uesoftmodem || true', '\$', 5)
+			time.sleep(5)
+		self.close()
+		result = re.search('ue_', str(self.UELogFile))
+		if result is not None:
+			copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.')
+			if (copyin_res == -1):
+				logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m')
+				optionsMsg = '<pre style="background-color:white">Could not copy UE logfile to analyze it!</pre>'
+				self.CreateHtmlTestRow(optionsMsg, 'KO', UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE')
+				self.UELogFile = ''
+				return
+			logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m')
+			logStatus = self.AnalyzeLogFile_UE(self.UELogFile)
+			if (logStatus < 0):
+				optionsMsg = '<pre style="background-color:white"><b>Sniffing Unsuccessful</b>\n'
+				optionsMsg += self.htmlUEFailureMsg
+				optionsMsg += '</pre>'
+				self.CreateHtmlTestRow(optionsMsg, 'KO', logStatus, 'UE')
+				self.CreateHtmlTabFooter(False)
+				sys.exit(1)
+			else:
+				optionsMsg = '<pre style="background-color:white"><b>Sniffing Successful</b>\n'
+				optionsMsg += self.htmlUEFailureMsg
+				optionsMsg += '</pre>'
+				self.CreateHtmlTestRow(optionsMsg, 'OK', ALL_PROCESSES_OK)
+			self.UELogFile = ''
+		else:
+			self.CreateHtmlTestRow('<pre style="background-color:white">No Log File to analyze</pre>', 'OK', ALL_PROCESSES_OK)
+
 	def AutoTerminateUEandeNB(self):
 		self.testCase_id = 'AUTO-KILL-UE'
 		self.desc = 'Automatic Termination of UE'
@@ -1890,8 +2512,20 @@ class SSHConnection():
 		self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK)
 
 	def LogCollectBuild(self):
-		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
-		self.command('cd ' + self.eNBSourceCodePath, '\$', 5)
+		if (self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != ''):
+			IPAddress = self.eNBIPAddress
+			UserName = self.eNBUserName
+			Password = self.eNBPassword
+			SourceCodePath = self.eNBSourceCodePath
+		elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''):
+			IPAddress = self.UEIPAddress
+			UserName = self.UEUserName
+			Password = self.UEPassword
+			SourceCodePath = self.UESourceCodePath
+		else:
+			sys.exit('Insufficient Parameter')
+		self.open(IPAddress, UserName, Password)
+		self.command('cd ' + SourceCodePath, '\$', 5)
 		self.command('cd cmake_targets', '\$', 5)
 		self.command('rm -f build.log.zip', '\$', 5)
 		self.command('zip build.log.zip build_log_*/*', '\$', 60)
@@ -1907,6 +2541,7 @@ class SSHConnection():
 		self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5)
 		self.close()
 
+
 	def LogCollectPing(self):
 		self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword)
 		self.command('cd ' + self.EPCSourceCodePath, '\$', 5)
@@ -1964,43 +2599,69 @@ class SSHConnection():
 			self.command('zip spgw.log.zip xGwLog.0', '\$', 60)
 		self.close()
 
+	def LogCollectOAIUE(self):
+		self.open(self.UEIPAddress, self.UEUserName, self.UEPassword)
+		self.command('cd ' + self.UESourceCodePath, '\$', 5)
+		self.command('cd cmake_targets', '\$', 5)
+		self.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5)
+		self.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60)
+		self.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5)
+		self.close()
+
 	def RetrieveSystemVersion(self):
 		if self.eNBIPAddress == 'none':
-			self.eNBOsVersion = 'Ubuntu 16.04.5 LTS'
-			self.eNBKernelVersion = '4.15.0-45-generic'
-			self.eNBUhdVersion = '3.13.0.1-0'
-			self.eNBCpuNb = '4'
-			self.eNBCpuModel = 'Intel(R) Core(TM) i5-6200U'
-			self.eNBCpuMHz = '2399.996 MHz'
+			self.OsVersion = 'Ubuntu 16.04.5 LTS'
+			self.KernelVersion = '4.15.0-45-generic'
+			self.UhdVersion = '3.13.0.1-0'
+			self.UsrpBoard = 'B210'
+			self.CpuNb = '4'
+			self.CpuModel = 'Intel(R) Core(TM) i5-6200U'
+			self.CpuMHz = '2399.996 MHz'
 			return
-		if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '':
+		machine = None
+		if self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != '':
+			machine = 'eNB'
+			IPAddress = self.eNBIPAddress
+			UserName = self.eNBUserName
+			Password = self.eNBPassword
+		elif self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '':
+			machine = 'UE'
+			IPAddress = self.UEIPAddress
+			UserName = self.UEUserName
+			Password = self.UEPassword
+		if machine is None:
 			Usage()
 			sys.exit('Insufficient Parameter')
-		self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword)
+		self.open(IPAddress, UserName, Password)
 		self.command('lsb_release -a', '\$', 5)
 		result = re.search('Description:\\\\t(?P<os_type>[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before))
 		if result is not None:
-			self.eNBOsVersion = result.group('os_type')
-			logging.debug('OS is: ' + self.eNBOsVersion)
+			self.OsVersion = result.group('os_type')
+			logging.debug('OS is: ' + self.OsVersion)
 		self.command('uname -r', '\$', 5)
 		result = re.search('uname -r\\\\r\\\\n(?P<kernel_version>[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before))
 		if result is not None:
-			self.eNBKernelVersion = result.group('kernel_version')
-			logging.debug('Kernel Version is: ' + self.eNBKernelVersion)
+			self.KernelVersion = result.group('kernel_version')
+			logging.debug('Kernel Version is: ' + self.KernelVersion)
 		self.command('dpkg --list | egrep --color=never libuhd003', '\$', 5)
 		result = re.search('libuhd003:amd64 *(?P<uhd_version>[0-9\.]+)', str(self.ssh.before))
 		if result is not None:
-			self.eNBUhdVersion = result.group('uhd_version')
-			logging.debug('UHD Version is: ' + self.eNBUhdVersion)
+			self.UhdVersion = result.group('uhd_version')
+			logging.debug('UHD Version is: ' + self.UhdVersion)
+		self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 12)
+		result = re.search('product: (?P<usrp_board>[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before))
+		if result is not None:
+			self.UsrpBoard = result.group('usrp_board')
+			logging.debug('USRP Board  is: ' + self.UsrpBoard)
 		self.command('lscpu', '\$', 5)
 		result = re.search('CPU\(s\): *(?P<nb_cpus>[0-9]+).*Model name: *(?P<model>[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P<cpu_mhz>[0-9\.]+)', str(self.ssh.before))
 		if result is not None:
-			self.eNBCpuNb = result.group('nb_cpus')
-			logging.debug('nb_cpus: ' + self.eNBCpuNb)
-			self.eNBCpuModel = result.group('model')
-			logging.debug('model: ' + self.eNBCpuModel)
-			self.eNBCpuMHz = result.group('cpu_mhz') + ' MHz'
-			logging.debug('cpu_mhz: ' + self.eNBCpuMHz)
+			self.CpuNb = result.group('nb_cpus')
+			logging.debug('nb_cpus: ' + self.CpuNb)
+			self.CpuModel = result.group('model')
+			logging.debug('model: ' + self.CpuModel)
+			self.CpuMHz = result.group('cpu_mhz') + ' MHz'
+			logging.debug('cpu_mhz: ' + self.CpuMHz)
 		self.close()
 
 #-----------------------------------------------------------
@@ -2008,6 +2669,9 @@ class SSHConnection():
 #-----------------------------------------------------------
 	def CreateHtmlHeader(self):
 		if (not self.htmlHeaderCreated):
+			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
+			logging.debug('\u001B[1m  Creating HTML header \u001B[0m')
+			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
 			self.htmlFile = open('test_results.html', 'w')
 			self.htmlFile.write('<!DOCTYPE html>\n')
 			self.htmlFile.write('<html class="no-js" lang="en-US">\n')
@@ -2085,18 +2749,13 @@ class SSHConnection():
 				self.htmlFile.write('     </tr>\n')
 			self.htmlFile.write('  </table>\n')
 
-			terminate_ue_flag = True
 			if (self.ADBIPAddress != 'none'):
+				terminate_ue_flag = True
 				self.GetAllUEDevices(terminate_ue_flag)
 				self.GetAllCatMDevices(terminate_ue_flag)
-			else:
-				self.UEDevices.append('doughq9rehg')
-				self.UEDevices.append('dnsgiuahgia')
-				self.UEDevices.append('uehgieng9')
-			self.htmlUEConnected = len(self.UEDevices)
-
-			self.htmlFile.write('  <h2><span class="glyphicon glyphicon-phone"></span> <span class="glyphicon glyphicon-menu-right"></span> ' + str(len(self.UEDevices)) + ' UE(s) is(are) connected to ADB bench server</h2>\n')
-			self.htmlFile.write('  <h2><span class="glyphicon glyphicon-phone"></span> <span class="glyphicon glyphicon-menu-right"></span> ' + str(len(self.CatMDevices)) + ' CAT-M UE(s) is(are) connected to bench server</h2>\n')
+				self.htmlUEConnected = len(self.UEDevices)
+				self.htmlFile.write('  <h2><span class="glyphicon glyphicon-phone"></span> <span class="glyphicon glyphicon-menu-right"></span> ' + str(len(self.UEDevices)) + ' UE(s) is(are) connected to ADB bench server</h2>\n')
+				self.htmlFile.write('  <h2><span class="glyphicon glyphicon-phone"></span> <span class="glyphicon glyphicon-menu-right"></span> ' + str(len(self.CatMDevices)) + ' CAT-M UE(s) is(are) connected to bench server</h2>\n')
 			self.htmlFile.write('  <br>\n')
 			self.htmlFile.write('  <ul class="nav nav-pills">\n')
 			count = 0
@@ -2163,6 +2822,9 @@ class SSHConnection():
 
 	def CreateHtmlFooter(self, passStatus):
 		if (os.path.isfile('test_results.html')):
+			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
+			logging.debug('\u001B[1m  Creating HTML footer \u001B[0m')
+			logging.debug('\u001B[1m----------------------------------------\u001B[0m')
 			self.RetrieveSystemVersion()
 			self.htmlFile = open('test_results.html', 'a')
 			self.htmlFile.write('</div>\n')
@@ -2173,19 +2835,23 @@ class SSHConnection():
 			self.htmlFile.write('      </tr>\n')
 			self.htmlFile.write('      <tr>\n')
 			self.htmlFile.write('        <td>OS Version</td>\n')
-			self.htmlFile.write('        <td><span class="label label-default">' + self.eNBOsVersion + '</span></td>\n')
+			self.htmlFile.write('        <td><span class="label label-default">' + self.OsVersion + '</span></td>\n')
 			self.htmlFile.write('        <td>Kernel Version</td>\n')
-			self.htmlFile.write('        <td><span class="label label-default">' + self.eNBKernelVersion + '</span></td>\n')
+			self.htmlFile.write('        <td><span class="label label-default">' + self.KernelVersion + '</span></td>\n')
 			self.htmlFile.write('        <td>UHD Version</td>\n')
-			self.htmlFile.write('        <td><span class="label label-default">' + self.eNBUhdVersion + '</span></td>\n')
+			self.htmlFile.write('        <td><span class="label label-default">' + self.UhdVersion + '</span></td>\n')
+			self.htmlFile.write('        <td>USRP Board</td>\n')
+			self.htmlFile.write('        <td><span class="label label-default">' + self.UsrpBoard + '</span></td>\n')
 			self.htmlFile.write('      </tr>\n')
 			self.htmlFile.write('      <tr>\n')
 			self.htmlFile.write('        <td>Nb CPUs</td>\n')
-			self.htmlFile.write('        <td><span class="label label-default">' + self.eNBCpuNb + '</span></td>\n')
+			self.htmlFile.write('        <td><span class="label label-default">' + self.CpuNb + '</span></td>\n')
 			self.htmlFile.write('        <td>CPU Model Name</td>\n')
-			self.htmlFile.write('        <td><span class="label label-default">' + self.eNBCpuModel + '</span></td>\n')
+			self.htmlFile.write('        <td><span class="label label-default">' + self.CpuModel + '</span></td>\n')
 			self.htmlFile.write('        <td>CPU Frequency</td>\n')
-			self.htmlFile.write('        <td><span class="label label-default">' + self.eNBCpuMHz + '</span></td>\n')
+			self.htmlFile.write('        <td><span class="label label-default">' + self.CpuMHz + '</span></td>\n')
+			self.htmlFile.write('        <td></td>\n')
+			self.htmlFile.write('        <td></td>\n')
 			self.htmlFile.write('      </tr>\n')
 			self.htmlFile.write('      <tr>\n')
 			self.htmlFile.write('        <th colspan=4 bgcolor = "#33CCFF">Final Status</th>\n')
@@ -2201,7 +2867,7 @@ class SSHConnection():
 			self.htmlFile.write('</html>\n')
 			self.htmlFile.close()
 
-	def CreateHtmlTestRow(self, options, status, processesStatus):
+	def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'):
 		if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
 			self.htmlFile.write('      <tr>\n')
 			self.htmlFile.write('        <td bgcolor = "lightcyan" >' + self.testCase_id  + '</td>\n')
@@ -2213,15 +2879,17 @@ class SSHConnection():
 				if (processesStatus == 0):
 					self.htmlFile.write('        <td bgcolor = "lightcoral" >' + str(status)  + '</td>\n')
 				elif (processesStatus == ENB_PROCESS_FAILED):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - eNB process not found</td>\n')
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process not found</td>\n')
 				elif (processesStatus == ENB_PROCESS_SEG_FAULT):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - eNB process ended in Segmentation Fault</td>\n')
-				elif (processesStatus == ENB_PROCESS_ASSERTION):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - eNB process ended in Assertion</td>\n')
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Segmentation Fault</td>\n')
+				elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == UE_PROCESS_ASSERTION):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - ' + machine + ' process ended in Assertion</td>\n')
 				elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE):
-					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - eNB process faced Real Time issue(s)</td>\n')
-				elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE):
-					self.htmlFile.write('        <td bgcolor = "orange" >OK</td>\n')
+					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 == UE_PROCESS_NOLOGFILE_TO_ANALYZE):
+					self.htmlFile.write('        <td bgcolor = "orange" >OK?</td>\n')
+				elif (processesStatus == UE_PROCESS_COULD_NOT_SYNC):
+					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - UE could not sync</td>\n')
 				elif (processesStatus == HSS_PROCESS_FAILED):
 					self.htmlFile.write('        <td bgcolor = "lightcoral" >KO - HSS process not found</td>\n')
 				elif (processesStatus == MME_PROCESS_FAILED):
@@ -2325,8 +2993,11 @@ def Usage():
 	print('  --XMLTestFile=[XML Test File to be run]')
 	print('------------------------------------------------------------')
 
+#def GetModeFromXML():
+#	SSH.mode = test.findtext('mode')
+
 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 != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' 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 != 'IdleSleep':
+	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 != 'Initialize_OAI_eNB' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' 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':
 		logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action)
 		return False
 	return True
@@ -2340,11 +3011,21 @@ def GetParametersFromXML(action):
 		SSH.eNB_instance = test.findtext('eNB_instance')
 		if (SSH.eNB_instance is None):
 			SSH.eNB_instance = '0'
-
+		SSH.air_interface = test.findtext('air_interface')
+		if (SSH.air_interface is None):
+			SSH.air_interface = 'lte'
+		else:
+			SSH.air_interface = SSH.air_interface.lower()
+	
 	if action == 'Terminate_eNB':
 		SSH.eNB_instance = test.findtext('eNB_instance')
 		if (SSH.eNB_instance is None):
 			SSH.eNB_instance = '0'
+		SSH.air_interface = test.findtext('air_interface')
+		if (SSH.air_interface is None):
+			SSH.air_interface = 'lte'
+		else:
+			SSH.air_interface = SSH.air_interface.lower()
 
 	if action == 'Attach_UE':
 		nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach')
@@ -2353,7 +3034,42 @@ def GetParametersFromXML(action):
 		else:
 			SSH.nbMaxUEtoAttach = int(nbMaxUEtoAttach)
 
-	if action == 'Ping':
+	if action == 'Build_OAI_UE':
+		SSH.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args')
+		SSH.clean_repository = test.findtext('clean_repository')
+		if (SSH.clean_repository == 'false'):
+			SSH.clean_repository = False
+		else:
+			SSH.clean_repository = True
+
+	if action == 'Initialize_OAI_UE':
+		SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args')
+		SSH.UE_instance = test.findtext('UE_instance')
+		if (SSH.UE_instance is None):
+			SSH.UE_instance = '0'
+		SSH.air_interface = test.findtext('air_interface')
+		if (SSH.air_interface is None):
+			SSH.air_interface = 'lte'
+		else:
+			SSH.air_interface = SSH.air_interface.lower()
+	
+	if action == 'Initialize_OAI_eNB':
+		SSH.Initialize_OAI_eNB_args = test.findtext('Initialize_OAI_eNB_args')
+		SSH.UE_instance = test.findtext('eNB_instance')
+		if (SSH.eNB_instance is None):
+			SSH.eNB_instance = '0'
+		SSH.air_interface = test.findtext('air_interface')
+		if (SSH.air_interface is None):
+			SSH.air_interface = 'lte'
+		else:
+			SSH.air_interface = SSH.air_interface.lower()
+
+	if action == 'Terminate_OAI_UE':
+		SSH.eNB_instance = test.findtext('UE_instance')
+		if (SSH.UE_instance is None):
+			SSH.UE_instance = '0'
+
+	if action == 'Ping' or action == 'Ping_CatM_module':
 		SSH.ping_args = test.findtext('ping_args')
 		SSH.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold')
 
@@ -2395,6 +3111,7 @@ SSH = SSHConnection()
 
 argvs = sys.argv
 argc = len(argvs)
+cwd = os.getcwd()
 
 while len(argvs) > 1:
 	myArgv = argvs.pop(1)	# 0th is this file's name
@@ -2403,6 +3120,9 @@ while len(argvs) > 1:
 		sys.exit(0)
 	elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE):
 		matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE)
+		#if matchReg and mode is not None:
+			#print('Warning: the mode is defined in both xml file and command line')
+			#print('ignoring the mode defined in the xml file')
 		mode = matchReg.group(1)
 	elif re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE):
 		matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE)
@@ -2467,6 +3187,18 @@ while len(argvs) > 1:
 		matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE)
 		SSH.testXMLfiles.append(matchReg.group(1))
 		SSH.nbTestXMLfiles += 1
+	elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE):
+		matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE)
+		SSH.UEIPAddress = matchReg.group(1)
+	elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE):
+		matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE)
+		SSH.UEUserName = matchReg.group(1)
+	elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE):
+		matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE)
+		SSH.UEPassword = matchReg.group(1)
+	elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE):
+		matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE)
+		SSH.UESourceCodePath = matchReg.group(1)
 	elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE):
 		matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE)
 		finalStatus = matchReg.group(1)
@@ -2482,11 +3214,17 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE):
 		sys.exit('Insufficient Parameter')
 	SSH.TerminateeNB()
 elif re.match('^TerminateUE$', mode, re.IGNORECASE):
-	if SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '':
+	if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''):
 		Usage()
 		sys.exit('Insufficient Parameter')
 	signal.signal(signal.SIGUSR1, receive_signal)
 	SSH.TerminateUE()
+elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE):
+	if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '':
+		Usage()
+		sys.exit('Insufficient Parameter')
+	signal.signal(signal.SIGUSR1, receive_signal)
+	SSH.TerminateOAIUE()
 elif re.match('^TerminateHSS$', mode, re.IGNORECASE):
 	if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '':
 		Usage()
@@ -2503,7 +3241,7 @@ elif re.match('^TerminateSPGW$', mode, re.IGNORECASE):
 		sys.exit('Insufficient Parameter')
 	SSH.TerminateSPGW()
 elif re.match('^LogCollectBuild$', mode, re.IGNORECASE):
-	if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '':
+	if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == ''):
 		Usage()
 		sys.exit('Insufficient Parameter')
 	SSH.LogCollectBuild()
@@ -2537,16 +3275,24 @@ elif re.match('^LogCollectIperf$', mode, re.IGNORECASE):
 		Usage()
 		sys.exit('Insufficient Parameter')
 	SSH.LogCollectIperf()
+elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE):
+	if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '':
+		Usage()
+		sys.exit('Insufficient Parameter')
+	SSH.LogCollectOAIUE()
 elif re.match('^InitiateHtml$', mode, re.IGNORECASE):
-	if SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '':
+	if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''):
 		Usage()
 		sys.exit('Insufficient Parameter')
 	count = 0
 	foundCount = 0
 	while (count < SSH.nbTestXMLfiles):
-		xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[count]
+		xml_test_file = cwd + "/" + SSH.testXMLfiles[count]
 		if (os.path.isfile(xml_test_file)):
-			xmlTree = ET.parse(xml_test_file)
+			try:
+				xmlTree = ET.parse(xml_test_file)
+			except:
+				print("Error while parsing file: " + xml_test_file)
 			xmlRoot = xmlTree.getroot()
 			SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count)))
 			SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count)))
@@ -2558,20 +3304,33 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE):
 	SSH.CreateHtmlHeader()
 elif re.match('^FinalizeHtml$', mode, re.IGNORECASE):
 	SSH.CreateHtmlFooter(SSH.finalStatus)
-elif 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 == '':
-		Usage()
-		sys.exit('Insufficient Parameter')
+elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE):
+	if re.match('^TesteNB$', mode, re.IGNORECASE):
+		if (SSH.eNBRepository == '' or SSH.eNBBranch == '' or SSH.eNBSourceCodePath == ''):
+			Usage()
+			sys.exit('Insufficient Parameter')
+		if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == ''):
+			Usage()
+			sys.exit('Insufficient Parameter')
+		elif SSH.ADBIPAddress == 'none' and SSH.EPCIPAddress == 'none':
+			pass
+		elif 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 != ''):
+			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 == '':
+			Usage()
+			sys.exit('UE: Insufficient Parameter')
 
-	if (SSH.EPCIPAddress != 'none'):
-		SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, sys.path[0] + "/tcp_iperf_stats.awk", "/tmp")
-		SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, sys.path[0] + "/active_net_interfaces.awk", "/tmp")
 	#read test_case_list.xml file
         # if no parameters for XML file, use default value
 	if (SSH.nbTestXMLfiles != 1):
-		xml_test_file = sys.path[0] + "/test_case_list.xml"
+		xml_test_file = cwd + "/test_case_list.xml"
 	else:
-		xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[0]
+		xml_test_file = cwd + "/" + SSH.testXMLfiles[0]
 
 	xmlTree = ET.parse(xml_test_file)
 	xmlRoot = xmlTree.getroot()
@@ -2627,6 +3386,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE):
 			SSH.testCase_id = id
 			SSH.desc = test.findtext('desc')
 			action = test.findtext('class')
+			mode = test.findtext('mode')
 			if (CheckClassValidity(action, id) == False):
 				continue
 			SSH.ShowTestID()
@@ -2648,6 +3408,14 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE):
 				SSH.AttachUE()
 			elif action == 'Detach_UE':
 				SSH.DetachUE()
+			elif action == 'Build_OAI_UE':
+				SSH.BuildOAIUE()
+			elif action == 'Initialize_OAI_UE':
+				SSH.InitializeOAIUE()
+			elif action == 'Terminate_OAI_UE':
+				SSH.TerminateOAIUE()
+			elif action == 'Initialize_OAI_eNB':
+				SSH.InitializeOAIeNB()
 			elif action == 'Initialize_CatM_module':
 				SSH.InitializeCatM()
 			elif action == 'Terminate_CatM_module':
@@ -2656,6 +3424,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE):
 				SSH.AttachCatM()
 			elif action == 'Detach_CatM_module':
 				SSH.TerminateCatM()
+			elif action == 'Ping_CatM_module':
+				SSH.PingCatM()
 			elif action == 'Ping':
 				SSH.Ping()
 			elif action == 'Iperf':
diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c8cf457c710c57a91765ec90cc778aa8c9bc4d2e
--- /dev/null
+++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml
@@ -0,0 +1,64 @@
+<!--
+
+ 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>run OAI gNB and OAI NR UE USRP</htmlTabRef>
+        <htmlTabName>run-OAI-gNB-NR-UE-USRP</htmlTabName>
+        <htmlTabIcon>tasks</htmlTabIcon>	
+	<TestCaseRequestedList>
+090101 000001 090102 000001 090108 090109
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+	
+        <testCase id="090101">
+                <class>Initialize_OAI_eNB</class>
+                <desc>Initialize gNB USRP</desc>
+		<Initialize_OAI_eNB_args>-O ../../../ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf</Initialize_OAI_eNB_args>
+		<air_interface>NR</air_interface>
+        </testCase>
+
+	<testCase id="000001">
+		<class>IdleSleep</class>
+		<desc>Sleep</desc>
+		<idle_sleep_time_in_sec>5</idle_sleep_time_in_sec>
+	</testCase>
+
+        <testCase id="090102">
+                <class>Initialize_OAI_UE</class>
+                <desc>Initialize NR UE USRP</desc>
+		<Initialize_OAI_UE_args>-C 3510000000 --numerology 1 -r 106 --phy-test --usrp-args "addr=192.168.30.2,clock_source=external,time_source=external" --threadoffset 16</Initialize_OAI_UE_args>
+		<air_interface>NR</air_interface>
+        </testCase>
+
+        <testCase id="090108">
+                <class>Terminate_OAI_UE</class>
+                <desc>Terminate NR UE</desc>
+		<air_interface>NR</air_interface>
+        </testCase>
+
+        <testCase id="090109">
+                <class>Terminate_eNB</class>
+                <desc>Terminate gNB</desc>
+		<air_interface>NR</air_interface>
+        </testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..91db988fd88a0d4495240a66861b86a7d1938ebb
--- /dev/null
+++ b/ci-scripts/xml_files/gnb_usrp_build.xml
@@ -0,0 +1,39 @@
+<!--
+
+ 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-gNB</htmlTabName>
+	<htmlTabIcon>wrench</htmlTabIcon>
+	<TestCaseRequestedList>
+010101
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="010101">
+		<mode>TesteNB</mode>	
+		<class>Build_eNB</class>
+		<desc>Build gNB (USRP)</desc>
+		<Build_eNB_args>--gNB -w USRP</Build_eNB_args>
+	</testCase>
+
+</testCaseList>
diff --git a/ci-scripts/xml_files/nr_ue_usrp_build.xml b/ci-scripts/xml_files/nr_ue_usrp_build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..63c4d4f58b3361fcef7241c777bef04ea3137607
--- /dev/null
+++ b/ci-scripts/xml_files/nr_ue_usrp_build.xml
@@ -0,0 +1,40 @@
+<!--
+
+ 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-NR-UE</htmlTabName>
+	<htmlTabIcon>wrench</htmlTabIcon>
+	<TestCaseRequestedList>
+010102
+	</TestCaseRequestedList>
+	<TestCaseExclusionList></TestCaseExclusionList>
+
+	<testCase id="010102">
+		<mode>TestUE</mode>
+		<class>Build_OAI_UE</class>
+		<desc>Build NR UE (USRP)</desc>
+		<Build_OAI_UE_args>--nrUE -w USRP</Build_OAI_UE_args>
+		<clean_repository>false</clean_repository>
+	</testCase>
+
+</testCaseList>
diff --git a/targets/RT/USER/nr-softmodem.c b/targets/RT/USER/nr-softmodem.c
index 55612586943252ed71f7465f272710a2cbbb5c7b..1495d8b1f105d44f7439a1e348ffb9bcbfc58674 100644
--- a/targets/RT/USER/nr-softmodem.c
+++ b/targets/RT/USER/nr-softmodem.c
@@ -1237,6 +1237,8 @@ int main( int argc, char **argv )
 
   // wait for end of program
   printf("TYPE <CTRL-C> TO TERMINATE\n");
+  fflush(stdout);
+  fflush(stderr);
   //getchar();
 
 #if defined(ENABLE_ITTI)