From 5690aa0fe3700f5ca1e0a0dae14ccfbb51799da9 Mon Sep 17 00:00:00 2001 From: rakesh mundlamuri Date: Fri, 22 Aug 2025 15:46:42 +0530 Subject: [PATCH 01/24] first_half index correction in PRS channel estimation while copying memory Previously, we were using int16_t for the variable ch_tmp which was later harmonized to use c16_t while leaving <<1. This introduced the bug while accessing the address of the element at first_half of the ch_tmp variable. --- .../nr_dl_channel_estimation.c | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 6a49a17608..0d9399ce27 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -315,10 +315,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, //Start pilot c16_t ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fl, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fl, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -331,10 +328,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k]; ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fml, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fml, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -352,10 +346,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, for(int pIdx = 2; pIdx < num_pilots-2; pIdx++) { c16_t ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fmm, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fmm, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -372,10 +363,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, //End pilot ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fmr, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fmr, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -388,10 +376,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k]; ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fr, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fr, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -437,7 +422,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, if(first_half > 0) memcpy((int16_t *)&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half * sizeof(int32_t)); if(second_half > 0) - memcpy((int16_t *)&chF_interpol[rxAnt][0], &ch_tmp[first_half << 1], second_half * sizeof(int32_t)); + memcpy((int16_t *)&chF_interpol[rxAnt][0], &ch_tmp[first_half], second_half * sizeof(int32_t)); // Convert to time domain freq2time(NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size, From 825c6803adac44a3e4d3315f6b90a2df052e5f26 Mon Sep 17 00:00:00 2001 From: rakesh mundlamuri Date: Tue, 26 Aug 2025 12:59:50 +0530 Subject: [PATCH 02/24] harmonize IQ samples in prs channel estimation to use c16_t --- .../nr_dl_channel_estimation.c | 18 +++++++++--------- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 0d9399ce27..45060eaacd 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -47,12 +47,12 @@ #define NO_INTERP 1 /* Generic function to find the peak of channel estimation buffer */ -void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val) +void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val) { int32_t max_val = 0, max_idx = 0, abs_val = 0; for(int k = 0; k < buf_len; k++) { - abs_val = squaredMod(((c16_t*)buffer)[k]); + abs_val = squaredMod(buffer[k]); if(abs_val > max_val) { max_val = abs_val; @@ -83,8 +83,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, prs_config_t *prs_cfg = &ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_cfg; prs_meas_t **prs_meas = ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_meas; c16_t ch_tmp_buf[ ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); - int32_t chF_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); - int32_t chT_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); + c16_t chF_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); + c16_t chT_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); memset(ch_tmp_buf,0,sizeof(ch_tmp_buf)); memset(chF_interpol,0,sizeof(chF_interpol)); memset(chT_interpol,0,sizeof(chF_interpol)); @@ -420,9 +420,9 @@ int nr_prs_channel_estimation(uint8_t gNB_id, // Place PRS channel estimates in FFT shifted format if(first_half > 0) - memcpy((int16_t *)&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half * sizeof(int32_t)); + memcpy(&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half * sizeof(c16_t)); if(second_half > 0) - memcpy((int16_t *)&chF_interpol[rxAnt][0], &ch_tmp[first_half], second_half * sizeof(int32_t)); + memcpy(&chF_interpol[rxAnt][0], &ch_tmp[first_half], second_half * sizeof(c16_t)); // Convert to time domain freq2time(NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size, @@ -481,7 +481,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, // T tracer dump T(T_UE_PHY_INPUT_SIGNAL, T_INT(gNB_id), T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx), - T_INT(rxAnt), T_BUFFER(&rxdataF[rxAnt][0], frame_params->samples_per_slot_wCP*sizeof(int32_t))); + T_INT(rxAnt), T_BUFFER(&rxdataF[rxAnt][0], frame_params->samples_per_slot_wCP*sizeof(c16_t))); T(T_UE_PHY_DL_CHANNEL_ESTIMATE_FREQ, T_INT(gNB_id), @@ -489,7 +489,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx), T_INT(rxAnt), - T_BUFFER(&chF_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(int32_t))); + T_BUFFER(&chF_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(c16_t))); T(T_UE_PHY_DL_CHANNEL_ESTIMATE, T_INT(gNB_id), @@ -497,7 +497,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx), T_INT(rxAnt), - T_BUFFER(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(int32_t))); + T_BUFFER(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(c16_t))); } return(0); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 85b8999118..d0d868197c 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -39,7 +39,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); /* Generic function to find the peak of channel estimation buffer */ -void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val); +void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val); /*! \brief This function performs channel estimation including frequency and temporal interpolation From a72abe3cc8c25763859f28700fa523d0de41f429 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 19 Sep 2025 12:31:59 +0200 Subject: [PATCH 03/24] Refactor dl_toa setting to separate function --- .../NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 45060eaacd..4151752f11 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -71,6 +71,11 @@ void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t * } } +void set_prs_dl_toa(prs_meas_t *prs_meas, float dl_toa) +{ + prs_meas->dl_toa = dl_toa; +} + int nr_prs_channel_estimation(uint8_t gNB_id, uint8_t rsc_id, uint8_t rep_num, @@ -448,9 +453,9 @@ int nr_prs_channel_estimation(uint8_t gNB_id, prs_meas[rxAnt]->slot = proc->nr_slot_rx; prs_meas[rxAnt]->rxAnt_idx = rxAnt; prs_meas[rxAnt]->dl_aoa = rsc_id; - prs_meas[rxAnt]->dl_toa = prs_toa / (float)NR_PRS_IDFT_OVERSAMP_FACTOR; - if ((frame_params->ofdm_symbol_size - prs_meas[rxAnt]->dl_toa) < frame_params->ofdm_symbol_size / 2) - prs_meas[rxAnt]->dl_toa -= (frame_params->ofdm_symbol_size); + float dl_toa = prs_toa / (float)NR_PRS_IDFT_OVERSAMP_FACTOR; + if ((frame_params->ofdm_symbol_size - dl_toa) < frame_params->ofdm_symbol_size / 2) + dl_toa -= (frame_params->ofdm_symbol_size); LOG_I(PHY, "[gNB %d][rsc %d][Rx %d][sfn %d][slot %d] DL PRS ToA ==> %.1f / %d samples, peak channel power %.1f dBm, SNR %+.1f dB, rsrp %+.1f dBm\n", gNB_id, @@ -458,12 +463,14 @@ int nr_prs_channel_estimation(uint8_t gNB_id, rxAnt, proc->frame_rx, proc->nr_slot_rx, - prs_meas[rxAnt]->dl_toa, + dl_toa, frame_params->ofdm_symbol_size, ch_pwr_dbm, prs_meas[rxAnt]->snr, prs_meas[rxAnt]->rsrp_dBm); + set_prs_dl_toa(prs_meas[rxAnt], dl_toa); + #ifdef DEBUG_PRS_CHEST sprintf(filename, "%s%i%s", "PRSpilot_", rxAnt, ".m"); LOG_M(filename, "prs_loc", mod_prs, num_pilots, 1, 1); From b8e249fc4a61aea48918577eaf21a327b07c9b7a Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 3 Nov 2025 13:09:24 +0100 Subject: [PATCH 04/24] CI: Add new Jenkinsfiles Created Jenkinsfiles: - Jenkinsfile: for stadard test pipelines - Jenkinsfile-oc: for deployments with OC These 2 Jenkinsfiles covers all current test pipelines. --- ci-scripts/Jenkinsfile | 195 +++++++++++++++++++++++++++++++++++++ ci-scripts/Jenkinsfile-oc | 199 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 394 insertions(+) create mode 100644 ci-scripts/Jenkinsfile create mode 100644 ci-scripts/Jenkinsfile-oc diff --git a/ci-scripts/Jenkinsfile b/ci-scripts/Jenkinsfile new file mode 100644 index 0000000000..329caa5834 --- /dev/null +++ b/ci-scripts/Jenkinsfile @@ -0,0 +1,195 @@ +#!/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 + */ + +def pythonExecutor = params.pythonExecutor +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true +def JOB_TIMESTAMP + +// Choose test stage name or fallback default +def testStageName = params.pipelineTestStageName != null ? params.pipelineTestStageName : 'Template Test Stage' + +// Name of the resource +def lockResources = [] +if (params.LockResources != null && params.LockResources.trim().length() > 0) + params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]} + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def sourceRepository = params.eNB_Repository ?: env.GIT_URL +def sourceBranch = params.eNB_Branch ?: env.GIT_BRANCH +def targetRepository = params.Target_Repository ?: sourceRepository +def targetBranch = params.eNB_TargetBranch ?: 'develop' +def commitID = params.eNB_CommitID ?: env.GIT_COMMIT +def is_MR = params.eNB_mergeRequest ?: false + +def flexricOption = "" + +//------------------------------------------------------------------------------- +// Pipeline start +pipeline { + agent { + label pythonExecutor + } + options { + timestamps() + ansiColor('xterm') + lock(extra: lockResources) + } + + stages { + stage("Build Init") { + steps { + script { + echo '\u2705 \u001B[94mBuild Init\u001B[0m' + JOB_TIMESTAMP = sh(returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"').trim() + } + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Branch : ${sourceBranch}" + } + } + stage ('Verify Parameters') { + steps { + script { + echo '\u2705 \u001B[94mVerify Parameters\u001B[0m' + def allParametersPresent = true + + if (params.LockResources == null) { + echo "no LockResources given" + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + echo "no eNB_SourceCodePath given" + allParametersPresent = false + } + + if (params.Flexric_Tag != null) { + echo "This pipeline is configured to run with a FlexRIC deployment." + echo "Appending FlexRicTag option to the list of options" + flexricOption = "--FlexRicTag=${params.Flexric_Tag}" + echo "Using new Flexric option: ${flexricOption}" + } + + echo "CI executor node : ${pythonExecutor}" + echo "Source Repository : ${sourceRepository}" + echo "Source Branch : ${sourceBranch}" + echo "Target Repository : ${targetRepository}" + echo "Target Branch : ${targetBranch}" + echo "Commit ID : ${commitID}" + + if (allParametersPresent) { + echo '\u2705 \u001B[94m All parameters are present\u001B[0m' + if (is_MR) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${sourceBranch} --src-commit ${commitID} --target-branch ${targetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${commitID}" + } + } else { + echo "\u274C Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + + stage ("Deploy and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[94m Deploy and Test: ${testStageName}\u001B[0m" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } else { + echo "Test XML file ${xmlFile}: no such file" + } + } + sh """ + python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + ${flexricOption} ${mainPythonAllXmlFiles} + """ + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + timeout (time: 60, unit: 'MINUTES') { + sh """ + python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \ + ${flexricOption} + """ + } + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" + } + } + } + } + stage ("Log Collection") { + steps { + script { + echo '\u2705 \u001B[94mLog Collection\u001B[0m' + dir ('ci-scripts') { + // Zipping all archived log files + sh "mkdir test_logs" + sh "mv *.log* test_logs || true" + // Zip all log files matching cmake_targets/{*.log*,log/*} into test_logs_XXXX.zip + if (fileExists('../cmake_targets/log')) { + sh "mv ../cmake_targets/log/* test_logs || true" + } + sh "zip -r -qq test_logs_${env.BUILD_ID}.zip *test_log*/" + sh "rm -rf *test_log*/" + if (fileExists("test_logs_${env.BUILD_ID}.zip")) { + archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip" + } + if (fileExists("test_results.html")) { + def reportName = "test_results_${env.JOB_NAME}.html" + sh "mv test_results.html ${reportName}" + sh """ + sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' \ + -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: ${BUILD_ID}#' \ + -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' ${reportName} + """ + archiveArtifacts artifacts: "${reportName}" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-oc b/ci-scripts/Jenkinsfile-oc new file mode 100644 index 0000000000..01a8022c12 --- /dev/null +++ b/ci-scripts/Jenkinsfile-oc @@ -0,0 +1,199 @@ +#!/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 + */ + +def pythonExecutor = params.pythonExecutor +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true +def JOB_TIMESTAMP + +// Choose test stage name or fallback default +def testStageName = params.pipelineTestStageName != null ? params.pipelineTestStageName : 'Template Test Stage' + +// Name of the resource +def lockResources = [] +if (params.LockResources != null && params.LockResources.trim().length() > 0) + params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]} + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters + +def sourceRepository = params.eNB_Repository ?: env.GIT_URL +def sourceBranch = params.eNB_Branch ?: env.GIT_BRANCH +def targetRepository = params.Target_Repository ?: sourceRepository +def targetBranch = params.eNB_TargetBranch ?: 'develop' +def commitID = params.eNB_CommitID ?: env.GIT_COMMIT +def is_MR = params.eNB_mergeRequest ?: false + +//------------------------------------------------------------------------------- +// Pipeline start +pipeline { + agent { + label pythonExecutor + } + options { + timestamps() + ansiColor('xterm') + lock(extra: lockResources) + } + + stages { + stage("Build Init") { + steps { + script { + echo '\u2705 \u001B[94mBuild Init\u001B[0m' + JOB_TIMESTAMP = sh(returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"').trim() + } + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Branch : ${sourceBranch}" + } + } + stage ('Verify Parameters') { + steps { + script { + echo '\u2705 \u001B[94mVerify Parameters\u001B[0m' + def allParametersPresent = true + + if (params.LockResources == null) { + echo "no LockResources given" + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + echo "no eNB_SourceCodePath given" + allParametersPresent = false + } + if (params.OC_Credentials == null) { + echo "no OC_Credentials given" + allParametersPresent = false + } + if (params.OC_ProjectName == null) { + echo "no OC_ProjectName given" + allParametersPresent = false + } + + echo "CI executor node : ${pythonExecutor}" + echo "Source Repository : ${sourceRepository}" + echo "Source Branch : ${sourceBranch}" + echo "Target Repository : ${targetRepository}" + echo "Target Branch : ${targetBranch}" + echo "Commit ID : ${commitID}" + + if (allParametersPresent) { + echo '\u2705 \u001B[94m All parameters are present\u001B[0m' + if (is_MR) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${sourceBranch} --src-commit ${commitID} --target-branch ${targetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${commitID}" + } + } else { + echo "\u274C Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + + stage ("Deploy and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[94m Deploy and Test: ${testStageName}\u001B[0m" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } else { + echo "Test XML file ${xmlFile}: no such file" + } + } + withCredentials([ + usernamePassword(credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password') + ]) { + sh """ + python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + ${mainPythonAllXmlFiles} + """ + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + timeout (time: 60, unit: 'MINUTES') { + sh """ + python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \ + --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} + """ + } + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" + } + } + } + } + } + stage ("Log Collection") { + steps { + script { + echo '\u2705 \u001B[94mLog Collection\u001B[0m' + dir ('ci-scripts') { + // Zipping all archived log files + sh "mkdir test_logs" + sh "mv *.log* test_logs || true" + // Zip all log files matching cmake_targets/{*.log*,log/*} into test_logs_XXXX.zip + if (fileExists('../cmake_targets/log')) { + sh "mv ../cmake_targets/log/* test_logs || true" + } + sh "zip -r -qq test_logs_${env.BUILD_ID}.zip *test_log*/" + sh "rm -rf *test_log*/" + if (fileExists("test_logs_${env.BUILD_ID}.zip")) { + archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip" + } + if (fileExists("test_results.html")) { + def reportName = "test_results_${env.JOB_NAME}.html" + sh "mv test_results.html ${reportName}" + sh """ + sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' \ + -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: ${BUILD_ID}#' \ + -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' ${reportName} + """ + archiveArtifacts artifacts: "${reportName}" + } + } + } + } + } + } +} From a5689f5b8c90a35c13868606b2ba9966bfea5bbd Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 27 Oct 2025 14:18:37 +0100 Subject: [PATCH 05/24] CI: Remove unused code --- ci-scripts/args_parse.py | 6 +----- ci-scripts/main.py | 19 +------------------ 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index 4953f049fb..3a3ea52fa0 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -43,10 +43,6 @@ import constants as CONST def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): - - py_param_file_present = False - py_params={} - force_local = False while len(argvs) > 1: myArgv = argvs.pop(1) # 0th is this file's name @@ -172,4 +168,4 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): HELP.GenericHelp(CONST.Version) sys.exit('Invalid Parameter: ' + myArgv) - return py_param_file_present, py_params, mode, force_local + return mode, force_local diff --git a/ci-scripts/main.py b/ci-scripts/main.py index ac4ac2c3be..873976a8db 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -85,14 +85,6 @@ def CheckClassValidity(xml_class_list,action,id): resp=True return resp -#assigning parameters to object instance attributes (even if the attributes do not exist !!) -def AssignParams(params_dict): - - for key,value in params_dict.items(): - setattr(CiTestObj, key, value) - setattr(RAN, key, value) - setattr(HTML, key, value) - def ExecuteActionWithParam(action, ctx): global RAN global HTML @@ -399,16 +391,7 @@ CLUSTER = cls_cluster.Cluster() import args_parse # Force local execution, move all execution targets to localhost force_local = False -py_param_file_present, py_params, mode, force_local = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER) - - - -#----------------------------------------------------------- -# TEMPORARY params management (UNUSED) -#----------------------------------------------------------- -#temporary solution for testing: -if py_param_file_present == True: - AssignParams(py_params) +mode, force_local = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER) #----------------------------------------------------------- # mode amd XML class (action) analysis From 9e0540fbed97466cbf89130411d34c136ca17035 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 27 Oct 2025 14:28:28 +0100 Subject: [PATCH 06/24] Simplify node management in CI Some CI tasks/commands like Iperf(), Ping() get multiple nodes (via XML parameter "nodes") to potentially run UEs on different nodes (hosts) at the same time. However, I argue that this is not good: - we don't actually use this -- where we specify multiple UEs, it's always "localhost localhost..." - it is inconsistent, as we typically have a single "node", not nodes, and there is a possibility to harmonize (see also next commit) - if we needed it, there would be better ways to achieve the same. First, for hardware-based UEs, the ci_infra.yaml can specify different UEs. For simulated UEs, it would be feasible to have multiple XML steps run in parallel, e.g., in the XML tag, which would clarify that multiple UEs on different hosts run in parallel - it reduces code. Hence, make a single for these XML steps. --- ci-scripts/cls_oaicitest.py | 41 +++++++------- ci-scripts/main.py | 56 +++++-------------- ci-scripts/tests/ping-iperf.py | 10 ++-- .../xml_files/container_4g_l2sim_tdd.xml | 10 ++-- .../container_4g_rfsim_fdd_05MHz.xml | 10 ++-- .../container_4g_rfsim_fdd_05MHz_noS1.xml | 8 +-- .../container_4g_rfsim_fdd_10MHz.xml | 10 ++-- .../container_4g_rfsim_fdd_20MHz.xml | 10 ++-- .../xml_files/container_4g_rfsim_fembms.xml | 2 +- .../xml_files/container_4g_rfsim_mbms.xml | 2 +- .../container_4g_rfsim_tdd_05MHz.xml | 8 +-- .../xml_files/container_5g_e1_rfsim.xml | 4 +- .../xml_files/container_5g_f1_rfsim.xml | 10 ++-- .../xml_files/container_5g_fdd_rfsim.xml | 10 ++-- .../xml_files/container_5g_flexric_rfsim.xml | 6 +- ci-scripts/xml_files/container_5g_rfsim.xml | 24 ++++---- .../xml_files/container_5g_rfsim_24prb.xml | 10 ++-- .../xml_files/container_5g_rfsim_2x2.xml | 10 ++-- .../container_5g_rfsim_fdd_phytest.xml | 8 +-- .../container_5g_rfsim_fr2_32prb.xml | 6 +- .../xml_files/container_5g_rfsim_multiue.xml | 20 +++---- .../xml_files/container_5g_rfsim_n2_ho.xml | 10 ++-- .../xml_files/container_5g_rfsim_ntn_geo.xml | 8 +-- .../xml_files/container_5g_rfsim_ntn_leo.xml | 6 +- .../xml_files/container_5g_rfsim_simple.xml | 6 +- .../xml_files/container_5g_rfsim_tdd_dora.xml | 4 +- .../xml_files/container_5g_rfsim_u0_25prb.xml | 14 ++--- 27 files changed, 146 insertions(+), 177 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 144bc24da6..f64972f253 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -304,13 +304,12 @@ class OaiCiTest(): self.finalStatus = False self.air_interface='' self.ue_ids = [] - self.nodes = [] self.svr_node = None self.svr_id = None self.cmd_prefix = '' # prefix before {lte,nr}-uesoftmodem - def InitializeUE(self, HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def InitializeUE(self, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] messages = [] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.initialize) for ue in ues] @@ -321,8 +320,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('N/A', 'OK', messages) return True - def AttachUE(self, HTML): - ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)] + def AttachUE(self, node, HTML): + ues = [cls_module.Module_UE(ue_id, node) for ue_id in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.attach) for ue in ues] attached = [f.result() for f in futures] @@ -337,8 +336,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not retrieve UE IP address(es) or MTU(s) wrong!"]) return success - def DetachUE(self, HTML): - ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)] + def DetachUE(self, node, HTML): + ues = [cls_module.Module_UE(ue_id, node) for ue_id in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.detach) for ue in ues] [f.result() for f in futures] @@ -346,8 +345,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('NA', 'OK', messages) return True - def DataDisableUE(self, HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def DataDisableUE(self, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.dataDisable) for ue in ues] status = [f.result() for f in futures] @@ -360,8 +359,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not disable UE data!"]) return success - def DataEnableUE(self, HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def DataEnableUE(self, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] logging.debug(f'disabling data for UEs {ues}') with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.dataEnable) for ue in ues] @@ -375,8 +374,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not enable UE data!"]) return success - def CheckStatusUE(self,HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def CheckStatusUE(self, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] logging.debug(f'checking status of UEs {ues}') messages = [] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: @@ -446,10 +445,10 @@ class OaiCiTest(): return (True, message) - def Ping(self, ctx, HTML, infra_file="ci_infra.yaml"): + def Ping(self, ctx, node, HTML, infra_file="ci_infra.yaml"): if self.ue_ids == [] or self.svr_id == None: raise Exception("no module names in self.ue_ids or/and self.svr_id provided") - ues = [cls_module.Module_UE(ue_id, server_name, infra_file) for ue_id, server_name in zip(self.ue_ids, self.nodes)] + ues = [cls_module.Module_UE(ue_id, node, infra_file) for ue_id in self.ue_ids] cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file) with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(self.Ping_common, ctx, cn, ue) for ue in ues] @@ -520,12 +519,12 @@ class OaiCiTest(): return (status, f'{ue_header}\n{msg}') - def Iperf(self, ctx, HTML, infra_file="ci_infra.yaml"): + def Iperf(self, ctx, node, HTML, infra_file="ci_infra.yaml"): logging.debug(f'Iperf: iperf_args "{self.iperf_args}" iperf_packetloss_threshold "{self.iperf_packetloss_threshold}" iperf_bitrate_threshold "{self.iperf_bitrate_threshold}" iperf_profile "{self.iperf_profile}" iperf_options "{self.iperf_options}"') if self.ue_ids == [] or self.svr_id == None: raise Exception("no module names in self.ue_ids or/and self.svr_id provided") - ues = [cls_module.Module_UE(ue_id, server_name, infra_file) for ue_id, server_name in zip(self.ue_ids, self.nodes)] + ues = [cls_module.Module_UE(ue_id, node, infra_file) for ue_id in self.ue_ids] cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file) with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(self.Iperf_Module, ctx, cn, ue, i, len(ues)) for i, ue in enumerate(ues)] @@ -549,10 +548,10 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', messages) return success - def Iperf2_Unidir(self, ctx, HTML, infra_file="ci_infra.yaml"): + def Iperf2_Unidir(self, ctx, node, HTML, infra_file="ci_infra.yaml"): if self.ue_ids == [] or self.svr_id == None or len(self.ue_ids) != 1: raise Exception("no module names in self.ue_ids or/and self.svr_id provided, multi UE scenario not supported") - ue = cls_module.Module_UE(self.ue_ids[0].strip(),self.nodes[0].strip(), infra_file) + ue = cls_module.Module_UE(self.ue_ids[0].strip(), node, infra_file) cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file) ueIP = ue.getIP() if not ueIP: @@ -852,8 +851,8 @@ class OaiCiTest(): global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return global_status - def TerminateUE(self, ctx, HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def TerminateUE(self, ctx, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.terminate, ctx) for ue in ues] archives = [f.result() for f in futures] diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 873976a8db..6b51c180a3 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -150,31 +150,21 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Terminate_UE' or action == 'CheckStatusUE' or action == 'DataEnable_UE' or action == 'DataDisable_UE': CiTestObj.ue_ids = test.findtext('id').split(' ') - if force_local: - # Change all execution targets to localhost - CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids) - else: - if test.findtext('nodes'): - CiTestObj.nodes = test.findtext('nodes').split(' ') - if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): - logging.error('Number of Nodes are not equal to the total number of UEs') - sys.exit("Mismatch in number of Nodes and UIs") - else: - CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) + node = test.findtext('node') if not force_local else 'localhost' if action == 'Initialize_UE': - success = CiTestObj.InitializeUE(HTML) + success = CiTestObj.InitializeUE(node, HTML) elif action == 'Attach_UE': - success = CiTestObj.AttachUE(HTML) + success = CiTestObj.AttachUE(node, HTML) elif action == 'Detach_UE': - success = CiTestObj.DetachUE(HTML) + success = CiTestObj.DetachUE(node, HTML) elif action == 'Terminate_UE': - success = CiTestObj.TerminateUE(ctx, HTML) + success = CiTestObj.TerminateUE(ctx, node, HTML) elif action == 'CheckStatusUE': - success = CiTestObj.CheckStatusUE(HTML) + success = CiTestObj.CheckStatusUE(node, HTML) elif action == 'DataEnable_UE': - success = CiTestObj.DataEnableUE(HTML) + success = CiTestObj.DataEnableUE(node, HTML) elif action == 'DataDisable_UE': - success = CiTestObj.DataDisableUE(HTML) + success = CiTestObj.DataDisableUE(node, HTML) elif action == 'Ping': CiTestObj.ping_args = test.findtext('ping_args') @@ -183,35 +173,15 @@ def ExecuteActionWithParam(action, ctx): CiTestObj.svr_id = test.findtext('svr_id') or None if test.findtext('svr_node'): CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost' - if force_local: - # Change all execution targets to localhost - CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids) - else: - if test.findtext('nodes'): - CiTestObj.nodes = test.findtext('nodes').split(' ') - if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): - logging.error('Number of Nodes are not equal to the total number of UEs') - sys.exit("Mismatch in number of Nodes and UIs") - else: - CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) + node = test.findtext('node') if not force_local else 'localhost' ping_rttavg_threshold = test.findtext('ping_rttavg_threshold') or '' - success = CiTestObj.Ping(ctx, HTML) + success = CiTestObj.Ping(ctx, node, HTML) elif action == 'Iperf' or action == 'Iperf2_Unidir': CiTestObj.iperf_args = test.findtext('iperf_args') CiTestObj.ue_ids = test.findtext('id').split(' ') CiTestObj.svr_id = test.findtext('svr_id') or None - if force_local: - # Change all execution targets to localhost - CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids) - else: - if test.findtext('nodes'): - CiTestObj.nodes = test.findtext('nodes').split(' ') - if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): - logging.error('Number of Nodes are not equal to the total number of UEs') - sys.exit("Mismatch in number of Nodes and UIs") - else: - CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) + node = test.findtext('node') if not force_local else 'localhost' if test.findtext('svr_node'): CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost' CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') @@ -226,9 +196,9 @@ def ExecuteActionWithParam(action, ctx): logging.error('test-case has wrong option ' + CiTestObj.iperf_options) CiTestObj.iperf_options = 'check' if action == 'Iperf': - success = CiTestObj.Iperf(ctx, HTML) + success = CiTestObj.Iperf(ctx, node, HTML) elif action == 'Iperf2_Unidir': - success = CiTestObj.Iperf2_Unidir(ctx, HTML) + success = CiTestObj.Iperf2_Unidir(ctx, node, HTML) elif action == 'IdleSleep': st = test.findtext('idle_sleep_time_in_sec') or "5" diff --git a/ci-scripts/tests/ping-iperf.py b/ci-scripts/tests/ping-iperf.py index bd30768a9f..3450a2b3e9 100644 --- a/ci-scripts/tests/ping-iperf.py +++ b/ci-scripts/tests/ping-iperf.py @@ -23,7 +23,7 @@ class TestPingIperf(unittest.TestCase): self.html.testCaseId = "000000" self.ci = cls_oaicitest.OaiCiTest() self.ci.ue_ids = ["test"] - self.ci.nodes = ["localhost"] + self.node = "localhost" self.ctx = TestCaseCtx.Default(tempfile.mkdtemp()) def tearDown(self): with cls_cmd.LocalCmd() as c: @@ -35,7 +35,7 @@ class TestPingIperf(unittest.TestCase): self.ci.svr_id = "test" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Ping(self.ctx, self.html, infra_file=infra_file) + success = self.ci.Ping(self.ctx, self.node, self.html, infra_file=infra_file) self.assertTrue(success) def test_iperf(self): @@ -50,7 +50,7 @@ class TestPingIperf(unittest.TestCase): self.ci.iperf_profile = "balanced" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Iperf(self.ctx, self.html, infra_file=infra_file) + success = self.ci.Iperf(self.ctx, self.node, self.html, infra_file=infra_file) self.assertTrue(success) def test_iperf2_unidir(self): @@ -62,7 +62,7 @@ class TestPingIperf(unittest.TestCase): self.ci.iperf_profile = "balanced" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Iperf2_Unidir(self.ctx, self.html, infra_file=infra_file) + success = self.ci.Iperf2_Unidir(self.ctx, self.node, self.html, infra_file=infra_file) self.assertTrue(success) def test_iperf_highrate(self): @@ -77,7 +77,7 @@ class TestPingIperf(unittest.TestCase): self.ci.iperf_profile = "balanced" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Iperf(self.ctx, self.html, infra_file=infra_file) + success = self.ci.Iperf(self.ctx, self.node, self.html, infra_file=infra_file) self.assertTrue(success) if __name__ == '__main__': diff --git a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml index d9ac14038b..8a010b9308 100644 --- a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml +++ b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml @@ -88,14 +88,14 @@ Attach_UE Attach OAI UE l2sim4g_ue - localhost + localhost Ping Ping trf-gen from LTE-UE 1 l2sim4g_ue - localhost + localhost l2sim4g_ext_dn localhost -c 20 @@ -106,7 +106,7 @@ Ping Ping LTE-UE 1 from trf-gen l2sim4g_ext_dn - localhost + localhost l2sim4g_ue localhost -c 20 @@ -117,7 +117,7 @@ Iperf Iperf UDP Downlink l2sim4g_ue - localhost + localhost l2sim4g_ext_dn localhost -u -t 30 -b 1M -R @@ -129,7 +129,7 @@ Iperf Iperf UDP Uplink l2sim4g_ue - localhost + localhost l2sim4g_ext_dn localhost -u -t 30 -b 3M diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml index 562856b00c..3606957af6 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml @@ -103,14 +103,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim4g_ue - localhost + localhost Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -c 20 @@ -121,7 +121,7 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - localhost + localhost rfsim4g_ue localhost -c 20 @@ -136,7 +136,7 @@ -u -t 30 -b 2M -R 25 80 - localhost + localhost localhost @@ -148,7 +148,7 @@ -u -t 30 -b 1M 25 80 - localhost + localhost localhost diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml index 1773d5d439..1d7194f44f 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml @@ -83,7 +83,7 @@ Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - localhost + localhost rfsim4g_enb_nos1 localhost -c 20 @@ -94,7 +94,7 @@ Ping Ping LTE-UE from eNB rfsim4g_enb_nos1 - localhost + localhost rfsim4g_ue localhost -c 20 @@ -105,7 +105,7 @@ Iperf Iperf UDP DL rfsim4g_ue - localhost + localhost rfsim4g_enb_nos1 localhost -u -t 30 -b 2M -R @@ -117,7 +117,7 @@ Iperf Iperf UDP UL rfsim4g_ue - localhost + localhost rfsim4g_enb_nos1 localhost -u -t 30 -b 1M diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml index 7861d8f332..a5b642ebe0 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml @@ -103,14 +103,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim4g_ue - localhost + localhost Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -c 20 @@ -121,7 +121,7 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - localhost + localhost rfsim4g_ue localhost -c 20 @@ -132,7 +132,7 @@ Iperf Iperf UDP DL rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -u -t 30 -b 2M -R @@ -144,7 +144,7 @@ Iperf Iperf UDP UL rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -u -t 30 -b 1M diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml index 9199f276e7..592c80de68 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml @@ -103,14 +103,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim4g_ue - localhost + localhost Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -c 20 @@ -121,7 +121,7 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - localhost + localhost rfsim4g_ue localhost -c 20 @@ -132,7 +132,7 @@ Iperf Iperf UDP DL rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -u -t 30 -b 2M -R @@ -144,7 +144,7 @@ Iperf Iperf UDP UL rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -u -t 30 -b 1M diff --git a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml index 73c01f2b32..21d2acc4eb 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml @@ -80,7 +80,7 @@ Iperf2_Unidir Iperf2 UDP DL rfsim4g_ue_fembms - localhost + localhost rfsim4g_enb_fembms localhost -u -t 30 -b 2M diff --git a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml index ea00caa09e..70d5db33cb 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml @@ -80,7 +80,7 @@ Iperf Iperf UDP DL rfsim4g_ue - localhost + localhost rfsim4g_enb_nos1 localhost -u -t 30 -b 2M -R diff --git a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml index d3129e0c68..60054cb305 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml @@ -103,7 +103,7 @@ Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -c 20 @@ -114,7 +114,7 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - localhost + localhost rfsim4g_ue localhost -c 20 @@ -125,7 +125,7 @@ Iperf Iperf UDP DL rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -u -t 30 -b 2M -R @@ -137,7 +137,7 @@ Iperf Iperf UDP UL rfsim4g_ue - localhost + localhost rfsim4g_ext_dn localhost -u -t 30 -b 1M diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml index 54b34e0cff..5c0fa2b99e 100644 --- a/ci-scripts/xml_files/container_5g_e1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -76,14 +76,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 - localhost localhost localhost + localhost Ping Ping ext-dn from all NR-UEs rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 - localhost localhost localhost + localhost rfsim5g_5gc_fixed_ip localhost -c 20 -i0.25 diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 49a28e4a9f..f17be0215d 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -107,7 +107,7 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost @@ -122,7 +122,7 @@ Ping Ping ext-dn from all NR-UEs rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i0.25 @@ -141,7 +141,7 @@ Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -153,7 +153,7 @@ Iperf (UL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -171,7 +171,7 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i0.5 -w25 diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml index 3c4e30c97b..44ccb3a3d2 100644 --- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml @@ -70,14 +70,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -88,7 +88,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue localhost -c 20 -i 0.25 @@ -100,7 +100,7 @@ Iperf (DL/3Mbps/UDP)(30 sec) -u -b 3M -t 30 -R rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -112,7 +112,7 @@ Iperf (UL/3Mbps/UDP)(30 sec) -u -b 3M -t 30 rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 diff --git a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml index 8ee9326b5e..536952a2bc 100644 --- a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml @@ -121,7 +121,7 @@ Ping Ping ext-dn from both UEs rfsim5g_ue rfsim5g_ue2 - carabe carabe + carabe oai_ext_dn carabe -c 20 @@ -132,14 +132,14 @@ Attach_UE Attach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - carabe carabe + carabe Detach_UE Detach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - carabe carabe + carabe diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index 89cbe35dfa..43d2072040 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -125,14 +125,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 - localhost localhost localhost localhost localhost localhost localhost localhost localhost localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -143,7 +143,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue localhost -c 20 -i 0.25 @@ -154,7 +154,7 @@ Ping Ping ext-dn from Second NR-UE rfsim5g_ue2 - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -165,7 +165,7 @@ Ping Ping Second NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue2 localhost -c 20 -i 0.25 @@ -176,7 +176,7 @@ Ping Ping ext-dn from both UEs rfsim5g_ue rfsim5g_ue2 - localhost localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -187,7 +187,7 @@ Ping Ping ext-dn from all UEs rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 - localhost localhost localhost localhost localhost localhost localhost localhost localhost localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 -s 1016 @@ -199,7 +199,7 @@ Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -211,7 +211,7 @@ Iperf (UL/1Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -222,21 +222,21 @@ Attach_UE Attach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - localhost localhost + localhost Detach_UE Detach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - localhost localhost + localhost Detach_UE Detach OAI UE 3 to 10 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 - localhost localhost localhost localhost localhost localhost localhost localhost + localhost diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index 470c5e9539..b8e01c7edc 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -88,7 +88,7 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost @@ -101,7 +101,7 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i0.5 @@ -112,7 +112,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue localhost -c 20 -i0.2 @@ -124,7 +124,7 @@ Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -136,7 +136,7 @@ Iperf (UL/1Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 636df9e729..236106d966 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -70,14 +70,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -88,7 +88,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue localhost -c 20 -i 0.25 @@ -100,7 +100,7 @@ Iperf (DL/10Mbps/UDP)(20 sec) -u -b 10M -t 20 -R rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -112,7 +112,7 @@ Iperf (UL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml index 2a180440d0..4b695063e7 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml @@ -77,7 +77,7 @@ Ping Ping gNB from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_gnb_nos1 localhost -c20 -i0.2 @@ -88,7 +88,7 @@ Ping Ping NR-UE from gNB rfsim5g_gnb_nos1 - localhost + localhost rfsim5g_ue localhost -c20 -i0.2 @@ -100,7 +100,7 @@ Iperf (DL/30kbps/UDP)(20 sec) -u -b 0.03M -t 20 -R -c 10.0.1.1 rfsim5g_ue - localhost + localhost rfsim5g_gnb_nos1 localhost 5 @@ -112,7 +112,7 @@ Iperf (UL/30kbps/UDP)(20 sec) -u -b 0.03M -t 20 -c 10.0.1.1 rfsim5g_ue - localhost + localhost rfsim5g_gnb_nos1 localhost 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml index 37b90f2385..224a64c757 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml @@ -70,14 +70,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i0.2 @@ -88,7 +88,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue localhost -c 20 -i0.2 diff --git a/ci-scripts/xml_files/container_5g_rfsim_multiue.xml b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml index 4296fdf970..8022741c6c 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_multiue.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml @@ -84,14 +84,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 - localhost localhost localhost localhost localhost localhost localhost localhost localhost localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_multiue1 - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -102,7 +102,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_multiue1 localhost -c 20 -i 0.25 @@ -113,7 +113,7 @@ Ping Ping ext-dn from Second NR-UE rfsim5g_multiue2 - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -124,7 +124,7 @@ Ping Ping Second NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_multiue2 localhost -c 20 -i 0.25 @@ -135,7 +135,7 @@ Ping Ping ext-dn from both UEs rfsim5g_multiue1 rfsim5g_multiue2 - localhost localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -146,7 +146,7 @@ Ping Ping ext-dn from all UEs rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 - localhost localhost localhost localhost localhost localhost localhost localhost localhost localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 -s 1016 @@ -158,7 +158,7 @@ Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_multiue1 - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -170,7 +170,7 @@ Iperf (UL/1Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_multiue1 - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -181,7 +181,7 @@ Detach_UE Detach OAI UEs rfsim5g_multiue1 - localhost + localhost diff --git a/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml b/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml index 814f258e0a..37cab0ddb5 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml @@ -85,7 +85,7 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost @@ -100,7 +100,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue localhost -c 50 -i 0.25 @@ -111,7 +111,7 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 50 -i 0.25 @@ -123,7 +123,7 @@ Iperf (DL/10Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -135,7 +135,7 @@ Iperf (UL/4Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml index 32bbbc683d..66f725ca53 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml @@ -74,14 +74,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -92,7 +92,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue localhost -c 20 -i 0.25 @@ -111,7 +111,7 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i0.5 -w25 diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml index dd9fb56067..cde84b00e7 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml @@ -69,14 +69,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -87,7 +87,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue localhost -c 20 -i 0.25 diff --git a/ci-scripts/xml_files/container_5g_rfsim_simple.xml b/ci-scripts/xml_files/container_5g_rfsim_simple.xml index 738ce1a077..3dd5a560e0 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_simple.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_simple.xml @@ -63,14 +63,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -81,7 +81,7 @@ Detach_UE Detach OAI UE 1 rfsim5g_ue - localhost + localhost diff --git a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml index a9f7f2c3aa..6a09b8138d 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -83,7 +83,7 @@ Ping Ping gNB from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_gnb_nos1 localhost -c20 -i0.2 @@ -94,7 +94,7 @@ Ping Ping NR-UE from gNB rfsim5g_gnb_nos1 - localhost + localhost rfsim5g_ue localhost -c20 -i0.2 diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index c7668c5022..d563b3aab4 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -72,14 +72,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -90,7 +90,7 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - localhost + localhost rfsim5g_ue localhost -c 20 -i 0.25 @@ -101,14 +101,14 @@ Attach_UE Verify 2nd PDU session is up rfsim5g_ue_pdu_2 - localhost + localhost Ping Ping ext-dn from NR-UE on PDU session ID 2 rfsim5g_ue_pdu_2 - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -120,7 +120,7 @@ Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 @@ -132,7 +132,7 @@ Iperf (UL/1Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost 5 From b0106f27b5381e1c01967791740a8d18b0573042 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 27 Oct 2025 18:34:18 +0100 Subject: [PATCH 07/24] Centralize node for all XML steps All XML steps take a single node. We can thus "centralize" reading this parameter in the main loop and pass it to ExecuteActionWithParam(). --- ci-scripts/main.py | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 6b51c180a3..7e96389bf7 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -85,7 +85,7 @@ def CheckClassValidity(xml_class_list,action,id): resp=True return resp -def ExecuteActionWithParam(action, ctx): +def ExecuteActionWithParam(action, ctx, node): global RAN global HTML global CONTAINERS @@ -94,7 +94,6 @@ def ExecuteActionWithParam(action, ctx): if action == 'Build_eNB' or action == 'Build_Image' or action == 'Build_Proxy' or action == "Build_Cluster_Image" or action == "Build_Run_Tests": RAN.Build_eNB_args=test.findtext('Build_eNB_args') CONTAINERS.imageKind=test.findtext('kind') - node = test.findtext('node') proxy_commit = test.findtext('proxy_commit') if proxy_commit is not None: CONTAINERS.proxyCommit = proxy_commit @@ -110,7 +109,6 @@ def ExecuteActionWithParam(action, ctx): success = CONTAINERS.BuildRunTests(ctx, node, HTML) elif action == 'Initialize_eNB': - node = test.findtext('node') datalog_rt_stats_file=test.findtext('rt_stats_cfg') if datalog_rt_stats_file is None: RAN.datalog_rt_stats_file='datalog_rt_stats.default.yaml' @@ -131,7 +129,6 @@ def ExecuteActionWithParam(action, ctx): success = RAN.InitializeeNB(ctx, node, HTML) elif action == 'Terminate_eNB': - node = test.findtext('node') #retx checkers string_field = test.findtext('d_retx_th') if (string_field is not None): @@ -150,7 +147,6 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Terminate_UE' or action == 'CheckStatusUE' or action == 'DataEnable_UE' or action == 'DataDisable_UE': CiTestObj.ue_ids = test.findtext('id').split(' ') - node = test.findtext('node') if not force_local else 'localhost' if action == 'Initialize_UE': success = CiTestObj.InitializeUE(node, HTML) elif action == 'Attach_UE': @@ -173,7 +169,6 @@ def ExecuteActionWithParam(action, ctx): CiTestObj.svr_id = test.findtext('svr_id') or None if test.findtext('svr_node'): CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost' - node = test.findtext('node') if not force_local else 'localhost' ping_rttavg_threshold = test.findtext('ping_rttavg_threshold') or '' success = CiTestObj.Ping(ctx, node, HTML) @@ -181,7 +176,6 @@ def ExecuteActionWithParam(action, ctx): CiTestObj.iperf_args = test.findtext('iperf_args') CiTestObj.ue_ids = test.findtext('id').split(' ') CiTestObj.svr_id = test.findtext('svr_id') or None - node = test.findtext('node') if not force_local else 'localhost' if test.findtext('svr_node'): CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost' CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') @@ -206,7 +200,6 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Deploy_Run_OC_PhySim': oc_release = test.findtext('oc_release') - node = test.findtext('node') or None script = "scripts/oc-deploy-physims.sh" image_tag = cls_containerize.CreateTag(CLUSTER.ranCommitID, CLUSTER.ranBranch, CLUSTER.ranAllowMerge) options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {CLUSTER.eNBSourceCodePath}" @@ -214,7 +207,6 @@ def ExecuteActionWithParam(action, ctx): success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options) elif action == 'Build_Deploy_Docker_PhySim' or action == 'Build_Deploy_Source_PhySim': - node = test.findtext('node') or None ctest_opt = test.findtext('ctest-opt') or '' script = "scripts/docker-build-and-deploy-physims.sh" if action == 'Build_Deploy_Docker_PhySim' else 'scripts/source-deploy-physims.sh' options = f"{CONTAINERS.eNBSourceCodePath} {ctest_opt}" @@ -227,7 +219,6 @@ def ExecuteActionWithParam(action, ctx): success = core_op(cn_id, ctx, HTML) elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace": - node = test.findtext('node') CONTAINERS.yamlPath = test.findtext('yaml_path') string_field=test.findtext('d_retx_th') if (string_field is not None): @@ -249,15 +240,12 @@ def ExecuteActionWithParam(action, ctx): success = CONTAINERS.Create_Workspace(node, HTML) elif action == 'LicenceAndFormattingCheck': - node = test.findtext('node') success = SCA.LicenceAndFormattingCheck(ctx, node, HTML) elif action == 'Cppcheck_Analysis': - node = test.findtext('node') success = SCA.CppCheckAnalysis(ctx, node, HTML) elif action == 'Push_Local_Registry': - node = test.findtext('node') tag_prefix = test.findtext('tag_prefix') or "" success = CONTAINERS.Push_Image_to_Local_Registry(node, HTML, tag_prefix) @@ -265,7 +253,6 @@ def ExecuteActionWithParam(action, ctx): if force_local: # Do not pull or remove images when running locally. User is supposed to handle image creation & cleanup return True - node = test.findtext('node') tag_prefix = test.findtext('tag_prefix') or "" images = test.findtext('images').split() # hack: for FlexRIC, we need to overwrite the tag to use @@ -278,17 +265,12 @@ def ExecuteActionWithParam(action, ctx): success = CONTAINERS.Clean_Test_Server_Images(HTML, node, images, tag=tag) elif action == 'Custom_Command': - node = test.findtext('node') - if force_local: - # Change all execution targets to localhost - node = 'localhost' command = test.findtext('command') # Allow referencing repository workspace path in XML via %%workspace%% command = command.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath) success = cls_oaicitest.Custom_Command(HTML, node, command) elif action == 'Custom_Script': - node = test.findtext('node') script = test.findtext('script') # Allow referencing repository workspace path in XML via %%workspace%% script = script.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath) @@ -297,7 +279,6 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Pull_Cluster_Image': tag_prefix = test.findtext('tag_prefix') or "" images = test.findtext('images').split() - node = test.findtext('node') success = CLUSTER.PullClusterImage(HTML, node, images, tag_prefix=tag_prefix) else: @@ -525,6 +506,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re ctx = TestCaseCtx(i, int(id), logPath) HTML.testCase_id=CiTestObj.testCase_id desc = test.findtext('desc') + node = test.findtext('node') if not force_local else 'localhost' always_exec = test.findtext('always_exec') in ['True', 'true', 'Yes', 'yes'] may_fail = test.findtext('may_fail') in ['True', 'true', 'Yes', 'yes'] HTML.desc = desc @@ -539,7 +521,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re HTML.CreateHtmlTestRowQueue(msg, "SKIP", []) break try: - test_succeeded = ExecuteActionWithParam(action, ctx) + test_succeeded = ExecuteActionWithParam(action, ctx, node) if not test_succeeded and may_fail: logging.warning(f"test ID {test_case_id} action {action} may or may not fail, proceeding despite error") elif not test_succeeded: From 19c6d20b451ebb78da35de4d219906e9eab6b71b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 28 Oct 2025 09:32:32 +0100 Subject: [PATCH 08/24] Bugfix: "or None" is useless "or None" would assign if the first term is false-y. But not specifying it would already lead to the variable being set to None. --- ci-scripts/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 7e96389bf7..b56d8d7b87 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -166,7 +166,7 @@ def ExecuteActionWithParam(action, ctx, node): CiTestObj.ping_args = test.findtext('ping_args') CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') CiTestObj.ue_ids = test.findtext('id').split(' ') - CiTestObj.svr_id = test.findtext('svr_id') or None + CiTestObj.svr_id = test.findtext('svr_id') if test.findtext('svr_node'): CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost' ping_rttavg_threshold = test.findtext('ping_rttavg_threshold') or '' @@ -175,7 +175,7 @@ def ExecuteActionWithParam(action, ctx, node): elif action == 'Iperf' or action == 'Iperf2_Unidir': CiTestObj.iperf_args = test.findtext('iperf_args') CiTestObj.ue_ids = test.findtext('id').split(' ') - CiTestObj.svr_id = test.findtext('svr_id') or None + CiTestObj.svr_id = test.findtext('svr_id') if test.findtext('svr_node'): CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost' CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') From 032fc5e9c24f97726e078e7a752f0099d3a1a990 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 31 Oct 2025 12:25:54 +0100 Subject: [PATCH 09/24] fix bugs in scope for pdcch, and optimize cpu cost of pdcch decoding by not processing useless samples in one symbol --- openair1/PHY/NR_REFSIG/nr_dmrs_rx.c | 17 ++------ openair1/PHY/NR_REFSIG/refsig_defs_ue.h | 5 +-- .../nr_dl_channel_estimation.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 39 +++++++++---------- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- 5 files changed, 25 insertions(+), 40 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index e25d9700da..62dc85e90c 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -150,22 +150,11 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, return(0); } -int nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, - c16_t *output, - unsigned short p, - unsigned short nb_rb_coreset) +void nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_coreset) { - if (p==2000) { - for (int i=0; i<((nb_rb_coreset*6)>>1); i++) { - output[i] = get_modulated(nr_gold_pdcch, i, true); -#ifdef DEBUG_PDCCH - if (i<8) - printf("i %d idx %d pdcch mod_dmrs %d %d\n", i, idx, output[i].r, output[i].i); -#endif - } + for (int i = 0; i < ((nb_rb_coreset * 6) >> 1); i++) { + output[i] = get_modulated(nr_gold_pdcch, i, true); } - - return(0); } void nr_pbch_dmrs_rx(int symbol, const unsigned int *nr_gold_pbch, c16_t *output, bool sidelink) diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index 414dae9976..d9d1ef4534 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -35,10 +35,7 @@ void nr_pbch_dmrs_rx(int dmrss, const unsigned int *nr_gold_pbch, c16_t *output, /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS. @param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables */ -int nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, - c16_t *output, - unsigned short p, - unsigned short nb_rb_corset); +void nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_corset); int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned int Ns, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 6a49a17608..f310c0236b 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -846,7 +846,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS const uint32_t *gold = nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, slot, symbol); - nr_pdcch_dmrs_rx(gold, pilot, 2000, (nb_rb_coreset + dmrs_ref)); + nr_pdcch_dmrs_rx(gold, pilot, nb_rb_coreset + dmrs_ref); for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 9e48f52a03..d956ca7cc3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -294,8 +294,9 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, } static void nr_pdcch_channel_compensation(int arraySz, - c16_t rxdataF_ext[][arraySz], - c16_t dl_ch_estimates_ext[][arraySz], + int sz2, + c16_t rxdataF_ext[][sz2], + c16_t dl_ch_estimates_ext[][sz2], c16_t rxdataF_comp[][arraySz], int antRx, uint8_t output_shift) @@ -306,17 +307,17 @@ static void nr_pdcch_channel_compensation(int arraySz, } } -static void nr_pdcch_detection_mrc(int sz, c16_t rxdataF_comp[][sz]) +static void nr_pdcch_detection_mrc(int nb_ant, int sz, c16_t rxdataF_comp[][sz]) { - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); c16_t *rx0 = rxdataF_comp[0]; - c16_t *rx1 = rxdataF_comp[1]; - // MRC on each re of rb // input always aligned and accepting tail padding to process all actual samples - for (int i = 0; i < sz; i += 4) { - *(simde__m128i *)(rx0 + i) = - simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), simde_mm_srai_epi16(*(simde__m128i *)(rx1 + i), 1)); + for (int a = 1; a < nb_ant; a++) { + c16_t *rx = rxdataF_comp[a]; + for (int i = 0; i < sz; i += 4) { + *(simde__m128i *)(rx0 + i) = simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), + simde_mm_srai_epi16(*(simde__m128i *)(rx + i), 1)); + } } } @@ -334,7 +335,7 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *fp = &ue->frame_parms; NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; fapi_nr_coreset_t *coreset = &phy_pdcch_config->pdcch_config[ss_idx].coreset; - int32_t pdcch_est_size = ((((fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH) + 15) / 16) * 16); + int32_t pdcch_est_size = ceil_mod(fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH, 16); __attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size]; nr_pdcch_channel_estimation(ue, @@ -347,12 +348,9 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, pdcch_dl_ch_estimates, rxdataF); - const int32_t rx_size = ((4 * fp->N_RB_DL * 12 + 31) >> 5) << 5; + const int32_t rx_size = ceil_mod(fp->N_RB_DL * 12, 32); __attribute__((aligned(32))) c16_t rxdataF_ext[fp->nb_antennas_rx][rx_size]; - __attribute__((aligned(32))) c16_t rxdataF_comp[fp->nb_antennas_rx][rx_size]; __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[fp->nb_antennas_rx][rx_size]; - memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); - int n_rb; int rb_offset; get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset); @@ -376,20 +374,21 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, for (int i = 1; i < fp->nb_antennas_rx; i++) avgs = cmax(avgs, avg[i]); const int log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; - - nr_pdcch_channel_compensation(rx_size, + int rx_comp_sz = ceil_mod(llr_size_symbol, 4); + __attribute__((aligned(32))) c16_t rxdataF_comp[fp->nb_antennas_rx][rx_comp_sz]; + memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); + nr_pdcch_channel_compensation(rx_comp_sz, + rx_size, rxdataF_ext, pdcch_dl_ch_estimates_ext, rxdataF_comp, fp->nb_antennas_rx, log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), fp->nb_antennas_rx, rx_size, 0); - if (fp->nb_antennas_rx > 1) { - nr_pdcch_detection_mrc(rx_size, rxdataF_comp); + nr_pdcch_detection_mrc(fp->nb_antennas_rx, rx_comp_sz, rxdataF_comp); } - + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp[0], sizeof(c16_t), 1, llr_size_symbol, 0); nr_pdcch_llr(llr_size_symbol, rxdataF_comp[0], llr); } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index cbef1dc62a..51c7bf2c55 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1041,7 +1041,7 @@ void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ nr_pdcch_generate_llr(ue, proc, symbol, phy_data, llr_size_symbol, num_monitoring_occ, max_nb_symb_pdcch, rxdataF_symb, pdcch_llr); if (symbol == last_symb_pdcch) { nr_pdcch_dci_indication(proc, llr_size_symbol * max_nb_symb_pdcch, num_monitoring_occ, ue, phy_data, pdcch_llr); - UEscopeCopy(ue, pdcchLlr, pdcch_llr, sizeof(c16_t), 1, sizeof(pdcch_llr), 0); + UEscopeCopy(ue, pdcchLlr, pdcch_llr, sizeof(c16_t), 1, sizeof(pdcch_llr) / sizeof(c16_t), 0); } } stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); From f982d9b5df9f713699ba6eedd52dac714503f6c0 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 3 Nov 2025 20:24:37 +0100 Subject: [PATCH 10/24] rename a function to what it does (it generate a reference signal) and minor readability changes --- openair1/PHY/NR_REFSIG/nr_dmrs_rx.c | 2 +- openair1/PHY/NR_REFSIG/refsig_defs_ue.h | 2 +- .../nr_dl_channel_estimation.c | 58 ++++++++----------- 3 files changed, 25 insertions(+), 37 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 62dc85e90c..3624d754e9 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -150,7 +150,7 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, return(0); } -void nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_coreset) +void nr_pdcch_dmrs_ref(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_coreset) { for (int i = 0; i < ((nb_rb_coreset * 6) >> 1); i++) { output[i] = get_modulated(nr_gold_pdcch, i, true); diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index d9d1ef4534..fb7dce4489 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -35,7 +35,7 @@ void nr_pbch_dmrs_rx(int dmrss, const unsigned int *nr_gold_pbch, c16_t *output, /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS. @param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables */ -void nr_pdcch_dmrs_rx(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_corset); +void nr_pdcch_dmrs_ref(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_corset); int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned int Ns, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index f310c0236b..823c38c88d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -807,10 +807,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t pdcch_dl_ch_estimates[][pdcch_est_size], c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]) { + const int symb_sz = ue->frame_parms.ofdm_symbol_size; int slot = proc->nr_slot_rx; - unsigned char aarx; - unsigned short k; - unsigned int pilot_cnt; int nb_rb_coreset=0; int coreset_start_rb=0; @@ -824,14 +822,6 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short coreset_start_subcarrier = first_carrier_offset+(BWPStart + coreset_start_rb)*12; -#ifdef DEBUG_PDCCH - printf("PDCCH Channel Estimation : OFDM size %d, Ncp=%d, slot=%d, symbol %d\n", - ue->frame_parms.ofdm_symbol_size, - ue->frame_parms.Ncp, - slot, - symbol); -#endif - #if CH_INTERP int16_t *fl = filt16a_l1; int16_t *fm = filt16a_m1; @@ -846,14 +836,13 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS const uint32_t *gold = nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, slot, symbol); - nr_pdcch_dmrs_rx(gold, pilot, nb_rb_coreset + dmrs_ref); + nr_pdcch_dmrs_ref(gold, pilot, nb_rb_coreset + dmrs_ref); - for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { - - k = coreset_start_subcarrier; + for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) { + int k = coreset_start_subcarrier; c16_t *pil = &pilot[dmrs_ref * 3]; c16_t *rxF = &rxdataF[aarx][k + 1]; - c16_t *dl_ch = &pdcch_dl_ch_estimates[aarx][0]; + c16_t *dl_ch = pdcch_dl_ch_estimates[aarx]; memset(dl_ch, 0, sizeof(c16_t) * ue->frame_parms.ofdm_symbol_size); @@ -871,36 +860,36 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, rxF += 4; k += 2; - if (k >= ue->frame_parms.ofdm_symbol_size) { - k -= ue->frame_parms.ofdm_symbol_size; + if (k >= symb_sz) { + k -= symb_sz; rxF = &rxdataF[aarx][k + 1]; } multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1)]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1)]; multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); dl_ch += 12; - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; - for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt += 3) { + for (int pilot_cnt = 3; pilot_cnt < (3 * nb_rb_coreset); pilot_cnt += 3) { multadd_real_vector_complex_scalar(fl, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); dl_ch += 12; - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; } - #else //ELSE CH_INTERP +#else //ELSE CH_INTERP c32_t ch_sum = {0, 0}; - for (pilot_cnt = 0; pilot_cnt < 3*nb_rb_coreset; pilot_cnt++) { + for (int pilot_cnt = 0; pilot_cnt < 3 * nb_rb_coreset; pilot_cnt++) { #ifdef DEBUG_PDCCH printf("pilot[%u] = (%d, %d)\trxF[%d] = (%d, %d)\n", pilot_cnt, pil[0], pil[1], k+1, rxF[0], rxF[1]); @@ -908,8 +897,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t ch = c16mulShift(*pil++, *rxF, 15); ch_sum.r += ch.r; ch_sum.i += ch.i; - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][k + 1]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; if (pilot_cnt % 3 == 2) { ch.r = ch_sum.r / 3; @@ -923,11 +912,10 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, ch_sum = (c32_t){0}; } } - #endif //END CH_INTERP +#endif //END CH_INTERP //} - } } From ab14e3ad229f1042030c506c3343136a138699ac Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 3 Nov 2025 20:33:20 +0100 Subject: [PATCH 11/24] move all antennas comon code of begining of nr_pdcch_channel_estimation to prepare the future move of the antenna loop above the serial call of functions to decode pdcch --- .../nr_dl_channel_estimation.c | 29 +++++-------------- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 11 +++---- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 27 ++++++++++++----- 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 823c38c88d..a95ef9f6f8 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -797,23 +797,18 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp, return(0); } -void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - fapi_nr_coreset_t *coreset, +void nr_pdcch_channel_estimation(const PHY_VARS_NR_UE *ue, + int nb_rb_coreset, + int coreset_start_rb, + int dmrs_ref, uint16_t first_carrier_offset, uint16_t BWPStart, int32_t pdcch_est_size, c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]) + c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size], + c16_t *pilot) { const int symb_sz = ue->frame_parms.ofdm_symbol_size; - int slot = proc->nr_slot_rx; - - int nb_rb_coreset=0; - int coreset_start_rb=0; - get_coreset_rballoc(coreset->frequency_domain_resource,&nb_rb_coreset,&coreset_start_rb); - if(nb_rb_coreset==0) return; #ifdef DEBUG_PDCCH printf("pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d, coreset_nb_rb %d\n", @@ -828,23 +823,13 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, int16_t *fr = filt16a_r1; #endif - unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id; - int dmrs_ref = 0; - if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) - dmrs_ref = BWPStart; - // generate pilot - c16_t pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16))); - // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS - const uint32_t *gold = nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, slot, symbol); - nr_pdcch_dmrs_ref(gold, pilot, nb_rb_coreset + dmrs_ref); - for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) { int k = coreset_start_subcarrier; c16_t *pil = &pilot[dmrs_ref * 3]; c16_t *rxF = &rxdataF[aarx][k + 1]; c16_t *dl_ch = pdcch_dl_ch_estimates[aarx]; - memset(dl_ch, 0, sizeof(c16_t) * ue->frame_parms.ofdm_symbol_size); + memset(dl_ch, 0, sizeof(c16_t) * symb_sz); #ifdef DEBUG_PDCCH printf("pdcch ch est pilot addr %p RB_DL %d\n",&pilot[dmrs_ref*3], ue->frame_parms.N_RB_DL); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 85b8999118..4ed05ce9cf 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -44,15 +44,16 @@ void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t /*! \brief This function performs channel estimation including frequency and temporal interpolation */ -void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - fapi_nr_coreset_t *coreset, +void nr_pdcch_channel_estimation(const PHY_VARS_NR_UE *ue, + int nb_rb, + int rb_offset, + int dmrs_ref, uint16_t first_carrier_offset, uint16_t BWPStart, int32_t pdcch_est_size, c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]); + c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size], + c16_t *pilot); c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp, const UE_nr_rxtx_proc_t *proc, diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index d956ca7cc3..4c5c6e6f39 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -40,7 +40,7 @@ #include "PHY/sse_intrin.h" #include "common/utils/nr/nr_common.h" #include -#include "openair1/PHY/NR_REFSIG/nr_refsig_common.h" +#include "openair1/PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "assertions.h" @@ -337,23 +337,34 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, fapi_nr_coreset_t *coreset = &phy_pdcch_config->pdcch_config[ss_idx].coreset; int32_t pdcch_est_size = ceil_mod(fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH, 16); __attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size]; + int n_rb; + int rb_offset; + get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset); + unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id; + int dmrs_ref = 0; + if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) + dmrs_ref = phy_pdcch_config->pdcch_config[ss_idx].BWPStart; + // generate pilot + c16_t pilot[(n_rb + dmrs_ref) * 3] __attribute__((aligned(16))); + // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS + const uint32_t *gold = + nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, proc->nr_slot_rx, symbol); + nr_pdcch_dmrs_ref(gold, pilot, n_rb + dmrs_ref); nr_pdcch_channel_estimation(ue, - proc, - symbol, - coreset, + n_rb, + rb_offset, + dmrs_ref, fp->first_carrier_offset, phy_pdcch_config->pdcch_config[ss_idx].BWPStart, pdcch_est_size, pdcch_dl_ch_estimates, - rxdataF); + rxdataF, + pilot); const int32_t rx_size = ceil_mod(fp->N_RB_DL * 12, 32); __attribute__((aligned(32))) c16_t rxdataF_ext[fp->nb_antennas_rx][rx_size]; __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[fp->nb_antennas_rx][rx_size]; - int n_rb; - int rb_offset; - get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset); nr_pdcch_extract_rbs_single(ue->frame_parms.ofdm_symbol_size, rxdataF, From f7eaafa8358b3825a0b8953047bd630696b20e2b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 3 Nov 2025 19:03:03 +0100 Subject: [PATCH 12/24] CI test runner: handle SIGINT Handle SIGINT and mark any subsequent steps as failed. Receiving SIGINT a second time will abort the script immediately (as is the case before this commit). Note that Python seems to relay the signal to the "controlled" process (e.g., Ping), which would return immediately with an error. So some steps like Ping will abort immediately, others (e.g., IdleSleep) will finish their step, and then the present logic will mark subsequent steps as failed. --- ci-scripts/main.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index b56d8d7b87..99500fff12 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -296,8 +296,16 @@ def test_in_list(test, list): return True return False +test_runner_abort = False def receive_signal(signum, frame): - sys.exit(1) + global test_runner_abort + if not test_runner_abort: + logging.warning("received signal, canceling steps") + logging.info("send signal again to exit immediately") + test_runner_abort = True + else: + logging.warning("received signal again, exiting") + sys.exit(1) def ShowTestID(ctx, desc): logging.info(f'\u001B[1m----------------------------------------\u001B[0m') @@ -488,7 +496,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re #logging.info('test will be run: ' + test) todo_tests.append(test) - signal.signal(signal.SIGUSR1, receive_signal) + signal.signal(signal.SIGINT, receive_signal) HTML.CreateHtmlTabHeader() @@ -498,6 +506,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re i = 0 for test_case_id in todo_tests: for test in all_tests: + if test_runner_abort: + task_set_succeeded = False id = test.get('id') if test_case_id != id: continue From 579d263a9c594c2cfb5dfdf0243d53f12c43958d Mon Sep 17 00:00:00 2001 From: Chieh-Chun Chen Date: Tue, 4 Nov 2025 09:48:07 +0100 Subject: [PATCH 13/24] Bugfix: save old tunnel info to remain the user plane connection while rolling back to source DU due to F1 handover failure --- openair2/RRC/NR/rrc_gNB.c | 15 +++++++++++++++ openair2/RRC/NR/rrc_gNB_mobility.c | 6 ++++++ openair2/RRC/NR/rrc_gNB_mobility.h | 2 ++ 3 files changed, 23 insertions(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 97d0feda67..dcc17ec2c0 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1283,6 +1283,20 @@ static rrc_gNB_ue_context_t *rrc_gNB_get_ue_context_source_cell(gNB_RRC_INST *rr return NULL; } +/** + * @brief Rollback F1-U DL TL and TEID in RRC + */ +static void f1u_dl_gtp_rollback(gNB_RRC_UE_t *UE) +{ + DevAssert(UE != NULL); + DevAssert(UE->ho_context->source != NULL); + + FOR_EACH_SEQ_ARR(drb_t *, drb, &UE->drbs) { + drb->du_tunnel_config = UE->ho_context->source->old_du_tunnel_config; + LOG_W(NR_RRC, "DRB id %d rollback to tunnel TEID %x\n", drb->drb_id, drb->du_tunnel_config.teid); + } +} + static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id, const NR_RRCReestablishmentRequest_IEs_t *req, @@ -1361,6 +1375,7 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, } source_ctx->ho_cancel(rrc, UE); + f1u_dl_gtp_rollback(UE); /* we need the original CellGroupConfig */ ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 552cc881d6..bfe5dece8c 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -160,6 +160,12 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, ho_ctx->source->du_ue_id = ue_data.secondary_ue; ho_ctx->source->old_rnti = ue->rnti; + // Save the GTP-U tunnel info for source DU before process UE context setup request/response + // since tunnel info will be updated by calling store_du_f1u_tunnel() in rrc_CU_process_ue_context_setup_response() + FOR_EACH_SEQ_ARR(drb_t *, drb, &ue->drbs) { + ho_ctx->source->old_du_tunnel_config = drb->du_tunnel_config; + } + int result = asn_copy(&asn_DEF_NR_CellGroupConfig, (void **)&ho_ctx->source->old_cellGroupConfig, ue->masterCellGroup); AssertFatal(result == 0, "error during asn_copy() of CellGroupConfig\n"); } diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index 7010cc83ba..bd0fd8e22c 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -56,6 +56,8 @@ typedef struct nr_ho_source_cu { ho_cancel_t ho_cancel; /// status transfer ho_status_transfer_t ho_status_transfer; + /// old (source) downlink tunnel + gtpu_tunnel_t old_du_tunnel_config; } nr_ho_source_cu_t; /* acknowledgement of handover request. buf+len is the RRC Reconfiguration */ From 7655604d3c785f5a6df6728bc9caec36b8a7a931 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Wed, 5 Nov 2025 00:08:55 +0800 Subject: [PATCH 14/24] NR UE: fix PDCCH LLR indexing for different search space RB sizes When multiple search spaces have different CORESET configurations (different number of RBs), the LLR buffer stride must be calculated based on the maximum RB size across all search spaces, not the current search space's RB size. The LLR buffer is allocated with size based on get_pdcch_max_rbs(), but the demapping function was using coreset_nbr_rb (current search space) for symbol stride calculation, causing incorrect LLR extraction when search spaces have different RB configurations. --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 9e48f52a03..00821b03cc 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -81,7 +81,8 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb, uint8_t n_shift, uint8_t number_of_candidates, uint16_t *CCE, - uint8_t *L) + uint8_t *L, + int llr_stride_per_symbol) { /* * This function will do demapping and deinterleaving from llr containing demodulated symbols @@ -168,7 +169,7 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb, for (int cce_count = 0; cce_count < L[c_id]; cce_count++) { for (int k = 0; k < NR_NB_REG_PER_CCE / reg_bundle_size_L; k++) { // loop over REG bundles int f = f_bundle_j_list_ord[c_id][k + NR_NB_REG_PER_CCE * cce_count / reg_bundle_size_L]; - c16_t *in = llr + (f * B_rb + symbol_idx * coreset_nbr_rb) * RE_PER_RB_OUT_DMRS; + c16_t *in = llr + f * B_rb * RE_PER_RB_OUT_DMRS + symbol_idx * llr_stride_per_symbol; // loop over the RBs of the bundle memcpy(e_rx + RE_PER_RB_OUT_DMRS * rb_count, in, B_rb * RE_PER_RB_OUT_DMRS * sizeof(*e_rx)); rb_count += B_rb; @@ -497,6 +498,7 @@ void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[ss_idx]; uint8_t unused_start_symb[NR_SYMBOLS_PER_SLOT] = {0}; const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, unused_start_symb); + const int llr_stride = llr_size / rel15->coreset.duration; int n_rb; int rb_offset; @@ -515,7 +517,8 @@ void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc, rel15->coreset.ShiftIndex, rel15->number_of_candidates, rel15->CCE, - rel15->L); + rel15->L, + llr_stride); nr_dci_decoding_procedure(ue, proc, pdcch_e_rx, rel15, &dci_ind); } From b95b4c09d662f8bef48d67097e47a86380cf9f67 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 19 Sep 2025 12:34:26 +0200 Subject: [PATCH 15/24] Write DL ToA into circular buffer In a future commit, we will look up the maximum ToA over the last transmissions. Introduce a buffer in which we write the last 16 measurements. --- openair1/PHY/INIT/nr_init_ue.c | 2 ++ openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 5 ++++- openair1/PHY/defs_nr_common.h | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index e617b08172..2dce10d9dc 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -157,6 +157,8 @@ void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue) for (int j=0; jnb_antennas_rx; j++) { prs_vars[idx]->prs_resource[k].prs_meas[j] = malloc16_clear(sizeof(prs_meas_t)); AssertFatal((prs_vars[idx]->prs_resource[k].prs_meas[j]!=NULL), "%s: PRS measurements malloc failed for gNB_id %d, rx_ant %d\n", __FUNCTION__, idx, j); + prs_meas_t *m = prs_vars[idx]->prs_resource[k].prs_meas[j]; + m->next_dl_toa = m->dl_toa; } } } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 4151752f11..3af0937c48 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -73,7 +73,10 @@ void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t * void set_prs_dl_toa(prs_meas_t *prs_meas, float dl_toa) { - prs_meas->dl_toa = dl_toa; + *prs_meas->next_dl_toa++ = dl_toa; + if (prs_meas->next_dl_toa >= prs_meas->dl_toa + sizeofArray(prs_meas->dl_toa)) + prs_meas->next_dl_toa = prs_meas->dl_toa; + LOG_D(NR_PHY, "next_dl_toa %p\n", prs_meas->next_dl_toa); } int nr_prs_channel_estimation(uint8_t gNB_id, diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index f4681020eb..b4d61d32f9 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -312,7 +312,9 @@ typedef struct { int32_t sfn; int8_t slot; int8_t rxAnt_idx; - float dl_toa; + // circular buffer to be able to read maximum of last estimations + float dl_toa[128]; // set through set_prs_dl_toa() + float *next_dl_toa; int32_t dl_aoa; float snr; float rsrp; From d682b6c5123012c3a356e71ba802141c28e49cd9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 19 Sep 2025 12:44:37 +0200 Subject: [PATCH 16/24] Add function to read max DL ToA Protect with mutex to allow reading from another thread. --- openair1/PHY/INIT/nr_init_ue.c | 1 + .../nr_dl_channel_estimation.c | 18 ++++++++++++++++++ openair1/PHY/defs_nr_common.h | 3 +++ 3 files changed, 22 insertions(+) diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 2dce10d9dc..7ab8a8863d 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -159,6 +159,7 @@ void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue) AssertFatal((prs_vars[idx]->prs_resource[k].prs_meas[j]!=NULL), "%s: PRS measurements malloc failed for gNB_id %d, rx_ant %d\n", __FUNCTION__, idx, j); prs_meas_t *m = prs_vars[idx]->prs_resource[k].prs_meas[j]; m->next_dl_toa = m->dl_toa; + pthread_mutex_init(&m->dl_toa_mtx, NULL); } } } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 3af0937c48..de0b6d2b29 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -73,10 +73,28 @@ void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t * void set_prs_dl_toa(prs_meas_t *prs_meas, float dl_toa) { + int rc = pthread_mutex_lock(&prs_meas->dl_toa_mtx); + AssertFatal(rc == 0, "pthread_mutex_lock() failed: errno %d, %s\n", errno, strerror(errno)); *prs_meas->next_dl_toa++ = dl_toa; if (prs_meas->next_dl_toa >= prs_meas->dl_toa + sizeofArray(prs_meas->dl_toa)) prs_meas->next_dl_toa = prs_meas->dl_toa; LOG_D(NR_PHY, "next_dl_toa %p\n", prs_meas->next_dl_toa); + rc = pthread_mutex_unlock(&prs_meas->dl_toa_mtx); + AssertFatal(rc == 0, "pthread_mutex_unlock() failed: errno %d, %s\n", errno, strerror(errno)); +} + +float get_prs_max_dl_toa(prs_meas_t *prs_meas) +{ + float max = 0.0f; + int rc = pthread_mutex_lock(&prs_meas->dl_toa_mtx); + AssertFatal(rc == 0, "pthread_mutex_lock() failed: errno %d, %s\n", errno, strerror(errno)); + for (int i = 0; i < sizeofArray(prs_meas->dl_toa); ++i) { + max = cmax(max, prs_meas->dl_toa[i]); + LOG_I(NR_PHY, "i %d dl_toa %.3f max %.3f\n", i, prs_meas->dl_toa[i], max); + } + rc = pthread_mutex_unlock(&prs_meas->dl_toa_mtx); + AssertFatal(rc == 0, "pthread_mutex_unlock() failed: errno %d, %s\n", errno, strerror(errno)); + return max; } int nr_prs_channel_estimation(uint8_t gNB_id, diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index b4d61d32f9..23972fc9f2 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -38,6 +38,8 @@ #include "impl_defs_nr.h" #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" +#include + #define MAX_NUM_SUBCARRIER_SPACING 5 #define NR_MAX_OFDM_SYMBOL_SIZE 8192 @@ -312,6 +314,7 @@ typedef struct { int32_t sfn; int8_t slot; int8_t rxAnt_idx; + pthread_mutex_t dl_toa_mtx; // protect reading of max from write // circular buffer to be able to read maximum of last estimations float dl_toa[128]; // set through set_prs_dl_toa() float *next_dl_toa; From 34e002a80063bbb05633971957290a3231f57da9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 19 Sep 2025 12:59:01 +0200 Subject: [PATCH 17/24] Add get_max_dl_toa() for ciUE telnet module --- common/utils/telnetsrv/telnetsrv_ciUE.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/common/utils/telnetsrv/telnetsrv_ciUE.c b/common/utils/telnetsrv/telnetsrv_ciUE.c index 90e044ed86..88320a6ce0 100644 --- a/common/utils/telnetsrv/telnetsrv_ciUE.c +++ b/common/utils/telnetsrv/telnetsrv_ciUE.c @@ -37,6 +37,8 @@ #include "openair2/LAYER2/NR_MAC_UE/mac_defs.h" #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" #include "openair2/RRC/NR_UE/rrc_proto.h" +#include "openair1/PHY/phy_extern_nr_ue.h" +#include "openair1/PHY/defs_nr_common.h" #define TELNETSERVERCODE #include "telnetsrv.h" @@ -110,6 +112,26 @@ static int force_deregistration(char *buf, int debug, telnet_printfunc_t prnt) return 0; } +extern float get_prs_max_dl_toa(prs_meas_t *prs_meas); +static int get_dl_toa(char *buf, int debug, telnet_printfunc_t prnt) +{ + // TODO multiple antennas, resources, gNBs? + int gNB_id = 0; + int rsc_id = 0; + int ant = 0; + + PHY_VARS_NR_UE *UE = PHY_vars_UE_g[0][0]; + if (!UE || !UE->prs_vars[gNB_id]) + ERROR_MSG_RET("no UE/prs_vars found!\n"); + NR_PRS_RESOURCE_t *prs_res = &UE->prs_vars[gNB_id]->prs_resource[rsc_id]; + if (!prs_res->prs_meas || !prs_res->prs_meas[ant]) + ERROR_MSG_RET("prs_meas not initialized!\n"); + + float max = get_prs_max_dl_toa(prs_res->prs_meas[ant]); + prnt("UE max PRS DL ToA %.3f\n", max); + return 0; +} + /* Telnet shell command definitions */ static telnetshell_cmddef_t cicmds[] = { {"sync_state", "[UE_ID(int,opt)]", get_sync_state}, @@ -117,6 +139,7 @@ static telnetshell_cmddef_t cicmds[] = { {"force_RRC_IDLE", "", force_RRC_IDLE}, {"force_crnti_ra", "", force_crnti_ra}, {"deregistration", "", force_deregistration}, + {"get_max_dl_toa", "[ant]", get_dl_toa}, {"", "", NULL}, }; From 1dca20ba85cac8228bf44a34c492271685419a9c Mon Sep 17 00:00:00 2001 From: rakesh mundlamuri Date: Tue, 23 Sep 2025 14:34:09 +0530 Subject: [PATCH 18/24] Introduce a bash script to test PRS using estimated ToA Set RFsim (DL) distance and use PRS to estimate the new distance. This is verified by comparing the distance set in RFsim with the distance reported through ToA estimation at the UE. Note that since RFsim telnet output is asynchronous (it uses a queue internally), we use grep --max-count 1 to wait for the matching line, together with ncat --idle 0.3 to keep ncat open for some time. The --max-count option will terminate grep after the first occurrence. For this to work reliably, we need to use grep <(echo | ncat) as opposod to simply echo | ncat | grep, as the latter does not seem to reliably make grep exit after the occurrence. Co-authored-by: Robert Schmidt --- .../scripts/set-and-verify-distance-prs.sh | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100755 ci-scripts/scripts/set-and-verify-distance-prs.sh diff --git a/ci-scripts/scripts/set-and-verify-distance-prs.sh b/ci-scripts/scripts/set-and-verify-distance-prs.sh new file mode 100755 index 0000000000..e54c8897a2 --- /dev/null +++ b/ci-scripts/scripts/set-and-verify-distance-prs.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +die() { echo -e "$@"; exit 1; } + +[[ -z "$1" ]] && die "Usage: $0 " + +IP=192.168.71.150 +PORT=8091 +distance=$1 + +set_and_verify_distance() { + local distance=$1 + echo "Testing PRS ToA estimation for distance: $distance m" + + # it sems that grep returns immediately with this syntax, but not echo | ncat | grep + # so prefer this to receive new distance immediately. We use --idle to keep + # ncat open for some additional time + local setdist_resp="$(grep --max-count 1 new_offset <(echo rfsimu setdistance rfsimu_channel_enB0 $distance | ncat --idle 1 ${IP} ${PORT}))" + echo "> response: ${setdist_resp}" + local gettoa_resp="$(echo ciUE get_max_dl_toa | ncat ${IP} ${PORT} | grep "UE max PRS DL ToA")" + echo "> response: ${gettoa_resp}" + + [[ "$setdist_resp" =~ new_offset\ ([0-9]+) ]] || die "Set ToA extraction failed for distance: $distance m\nLOG: $setdist_resp" + local set_toa="${BASH_REMATCH[1]}" + + [[ "$gettoa_resp" =~ UE\ max\ PRS\ DL\ ToA\ ([0-9]+) ]] || die "Estimated ToA extraction failed for distance: $distance m\nLOG: $gettoa_resp" + local est_toa="${BASH_REMATCH[1]}" + + [[ $set_toa == $est_toa ]] || die "PRS FAILURE for distance: $distance m\nActual ToA = $set_toa, Estimated ToA = $est_toa" + + echo "PRS SUCCESS for distance: $distance m" +} + +# Set distance to 0 initially and then set the actual distance +sleep 4 +set_and_verify_distance 0 + +sleep 4 +set_and_verify_distance $distance From 0d2212ca38e6da4dd4873de98d6a0f09bd278114 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 24 Sep 2025 08:01:35 +0000 Subject: [PATCH 19/24] CI: Extend Custom_Script to accept arguments --- ci-scripts/cls_oaicitest.py | 4 ++-- ci-scripts/main.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 144bc24da6..485653851c 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -233,10 +233,10 @@ def Custom_Command(HTML, node, command): HTML.CreateHtmlTestRowQueue(command, status, message) return status == 'OK' or status == 'Warning' -def Custom_Script(HTML, node, script): +def Custom_Script(HTML, node, script, args): logging.info(f"Executing custom script on {node}") with cls_cmd.getConnection(node) as c: - ret = c.exec_script(script, 90) + ret = c.exec_script(script, 90, args) logging.debug(f"Custom_Script: {script} on node: {node} - return code {ret.returncode}, output:\n{ret.stdout}") status = 'OK' message = [ret.stdout] diff --git a/ci-scripts/main.py b/ci-scripts/main.py index ac4ac2c3be..ff0b9ddb18 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -328,9 +328,10 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Custom_Script': node = test.findtext('node') script = test.findtext('script') + args = test.findtext('args') # Allow referencing repository workspace path in XML via %%workspace%% script = script.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath) - success = cls_oaicitest.Custom_Script(HTML, node, script) + success = cls_oaicitest.Custom_Script(HTML, node, script, args) elif action == 'Pull_Cluster_Image': tag_prefix = test.findtext('tag_prefix') or "" From 871b813c12c89b8b1e54f22432bb211f43517939 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 3 Nov 2025 11:45:49 +0530 Subject: [PATCH 20/24] Modify the script with a retry logic for a failed test and print summary This commit inputs several distances at once and obtain the summary of successful and failed tests. We look for the number of successful tests that are geater than 0. We do that here since we sometimes dont receive a response for a telnet command from the rfsim although the command is applied. This is related to the queing telnet commands in the rfsim. The script for the distances 50, 100 and 150 are called as follows, ./set-and-verify-distance-prs.sh 50 100 150 The summary can be viewed as follows, ==================== SUMMARY ==================== Total tests run : 3 Successful tests: 3 Failed tests : 0 ================================================= --- .../scripts/set-and-verify-distance-prs.sh | 92 ++++++++++++++----- 1 file changed, 71 insertions(+), 21 deletions(-) diff --git a/ci-scripts/scripts/set-and-verify-distance-prs.sh b/ci-scripts/scripts/set-and-verify-distance-prs.sh index e54c8897a2..73012a4484 100755 --- a/ci-scripts/scripts/set-and-verify-distance-prs.sh +++ b/ci-scripts/scripts/set-and-verify-distance-prs.sh @@ -1,39 +1,89 @@ #!/bin/bash -die() { echo -e "$@"; exit 1; } - -[[ -z "$1" ]] && die "Usage: $0 " +[[ $# -lt 1 ]] && { echo "Usage: $0 "; exit 1; } +DISTANCES=("$@") IP=192.168.71.150 PORT=8091 -distance=$1 +NCAT_TIMEOUT=1 #s +SLEEP_WAIT=4 #s +MAX_RETRIES=3 set_and_verify_distance() { local distance=$1 echo "Testing PRS ToA estimation for distance: $distance m" - # it sems that grep returns immediately with this syntax, but not echo | ncat | grep + # it seems that grep returns immediately with this syntax, but not echo | ncat | grep # so prefer this to receive new distance immediately. We use --idle to keep # ncat open for some additional time - local setdist_resp="$(grep --max-count 1 new_offset <(echo rfsimu setdistance rfsimu_channel_enB0 $distance | ncat --idle 1 ${IP} ${PORT}))" + local setdist_resp="$(grep --max-count 1 new_offset <(echo rfsimu setdistance rfsimu_channel_enB0 $distance | ncat --idle ${NCAT_TIMEOUT} ${IP} ${PORT}))" echo "> response: ${setdist_resp}" - local gettoa_resp="$(echo ciUE get_max_dl_toa | ncat ${IP} ${PORT} | grep "UE max PRS DL ToA")" + + local gettoa_resp="$(echo "ciUE get_max_dl_toa" | ncat ${IP} ${PORT} | grep "UE max PRS DL ToA")" echo "> response: ${gettoa_resp}" - [[ "$setdist_resp" =~ new_offset\ ([0-9]+) ]] || die "Set ToA extraction failed for distance: $distance m\nLOG: $setdist_resp" - local set_toa="${BASH_REMATCH[1]}" - - [[ "$gettoa_resp" =~ UE\ max\ PRS\ DL\ ToA\ ([0-9]+) ]] || die "Estimated ToA extraction failed for distance: $distance m\nLOG: $gettoa_resp" - local est_toa="${BASH_REMATCH[1]}" - - [[ $set_toa == $est_toa ]] || die "PRS FAILURE for distance: $distance m\nActual ToA = $set_toa, Estimated ToA = $est_toa" - - echo "PRS SUCCESS for distance: $distance m" + [[ -z "$setdist_resp" || -z "$gettoa_resp" ]] && return 1 + + # Extract ToA values + [[ "$setdist_resp" =~ new_offset\ ([0-9]+) ]] && local set_toa="${BASH_REMATCH[1]}" || { echo "> Set ToA extraction failed for distance: $distance m"; return 1; } + + [[ "$gettoa_resp" =~ UE\ max\ PRS\ DL\ ToA\ ([0-9]+) ]] && local est_toa="${BASH_REMATCH[1]}" || { echo "> Estimated ToA extraction failed for distance: $distance m"; return 1; } + + # Compare extracted ToA values + [[ $set_toa == $est_toa ]] && echo "PRS SUCCESS for distance: $distance m" || { echo "PRS FAILURE for distance: $distance m (Actual ToA=$set_toa, Estimated ToA=$est_toa)" ; return 1; } + } -# Set distance to 0 initially and then set the actual distance -sleep 4 -set_and_verify_distance 0 +test_distance() { + local distance=$1 retries=0 -sleep 4 -set_and_verify_distance $distance + # retry loop incase we didn't receive the response + while (( retries < MAX_RETRIES )); do + echo " Attempt $((retries + 1))/$MAX_RETRIES" + + # Always reset to 0 m before testing target distance + if ! set_and_verify_distance 0; then + echo " Set distance 0 m failed during attempt $((retries + 1))" + else + sleep "$SLEEP_WAIT" + # Now test the actual target distance + if set_and_verify_distance "$distance"; then + return 0 + fi + fi + + ((retries++)) + if (( retries < MAX_RETRIES )); then + sleep "$SLEEP_WAIT" + else + echo " ERROR: No valid response after $MAX_RETRIES retries for distance: $distance m" + return 1 + fi + done +} + +num_success=0 +num_fail=0 + +for d in "${DISTANCES[@]}"; do + if test_distance "$d"; then + ((num_success++)) + else + ((num_fail++)) + fi + sleep "$SLEEP_WAIT" +done + +# ---- Summary ---- +echo +echo "==================== SUMMARY ====================" +echo "Total tests run : ${#DISTANCES[@]}" +echo "Successful tests: ${num_success}" +echo "Failed tests : ${num_fail}" +echo "=================================================" + +if [ $num_success -gt 0 ]; then + exit 0 +else + exit 1 +fi From c625a95042e110f9628f840f2a19eaca49ed33b3 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Fri, 12 Sep 2025 12:55:22 +0200 Subject: [PATCH 21/24] CI: add rfsim test with PRS Use the bash script from a parent commit to verify PRS functionality. --- .../gnb.sa.band78.106prb.rfsim.prs.conf | 256 ++++++++++++++++++ .../conf_files/nrue.band78.106prb.prs.conf | 89 ++++++ .../xml_files/container_5g_rfsim_prs.xml | 100 +++++++ .../5g_rfsimulator_prs/docker-compose.yaml | 71 +++++ 4 files changed, 516 insertions(+) create mode 100644 ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.prs.conf create mode 100644 ci-scripts/conf_files/nrue.band78.106prb.prs.conf create mode 100644 ci-scripts/xml_files/container_5g_rfsim_prs.xml create mode 100644 ci-scripts/yaml_files/5g_rfsimulator_prs/docker-compose.yaml diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.prs.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.prs.conf new file mode 100644 index 0000000000..3b6b591d85 --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.prs.conf @@ -0,0 +1,256 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 97; mnc_length = 2;}); + + ////////// Physical parameters: + + min_rxtxtime = 6; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 + absoluteFrequencySSB = 621312; + # this is 3300.60 MHz + dl_absoluteFrequencyPointA = 620040; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + +#uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -104; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spar e1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + +#tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "CI_MME_IP_ADDR"; }); + + NETWORK_INTERFACES : + { + + GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR"; + GNB_IPV4_ADDRESS_FOR_NGU = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; +} +); + +prs_config = ( +{ + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [0]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [0]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + sf_extension = 0; + eNB_instances = [0]; +} +); + + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level = "info"; + hw_log_level = "info"; + phy_log_level = "info"; + mac_log_level = "info"; + rlc_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + f1ap_log_level = "debug"; +}; diff --git a/ci-scripts/conf_files/nrue.band78.106prb.prs.conf b/ci-scripts/conf_files/nrue.band78.106prb.prs.conf new file mode 100644 index 0000000000..1bf92fd0d6 --- /dev/null +++ b/ci-scripts/conf_files/nrue.band78.106prb.prs.conf @@ -0,0 +1,89 @@ +PRSs = +( + { + Active_gNBs = 1; + prs_config0 = ( + { + gNB_id = 0; + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [0]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [0]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; + } + ); + + prs_config1 = ( + { + gNB_id = 1; + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [1]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [1]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; + } + ); + + prs_config2 = ( + { + gNB_id = 2; + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [2]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [2]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; + } + ); + + prs_config3 = ( + { + gNB_id = 3; + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [3]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [3]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; + } + ); + } +); diff --git a/ci-scripts/xml_files/container_5g_rfsim_prs.xml b/ci-scripts/xml_files/container_5g_rfsim_prs.xml new file mode 100644 index 0000000000..456ae62c1a --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_prs.xml @@ -0,0 +1,100 @@ + + + rfsim-5gnr-prs + Monolithic gNB with PRS + wrench + + 111111 + 800813 + 000012 + 000013 + 040001 + 040023 + 100011 + 222222 + + + + + Pull_Local_Registry + Pull Images from Local Registry + localhost + oai-gnb-asan oai-nr-ue-asan + + + + Create_Workspace + Create new Workspace + localhost + + + + Deploy_Object + Deploy OAI 5G gNB+UE RF sim SA + localhost + ci-scripts/yaml_files/5g_rfsimulator_prs + oai-gnb oai-nr-ue + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_ue + localhost + + + + IdleSleep + Sleep + 2 + + + + Custom_Script + true + Set and verify distance at 50, 100, 150 m + localhost + + 50 100 150 + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + localhost + ci-scripts/yaml_files/5g_rfsimulator_prs + 30,100,100,100 + 30,100,100,100 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + localhost + oai-gnb-asan oai-nr-ue-asan + + + diff --git a/ci-scripts/yaml_files/5g_rfsimulator_prs/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_prs/docker-compose.yaml new file mode 100644 index 0000000000..c6b6c338de --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_prs/docker-compose.yaml @@ -0,0 +1,71 @@ +services: + oai-gnb: + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-gnb + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: --phy-test --rfsim -E + --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 + networks: + public_net: + ipv4_address: 192.168.71.140 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/gnb.sa.band78.106prb.rfsim.prs.conf:/opt/oai-gnb/etc/gnb.conf + - rrc.config:/opt/oai-gnb/ + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-nr-ue: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: --phy-test --rfsim -E + --reconfig-file etc/rrc/reconfig.raw --rbconfig-file etc/rrc/rbconfig.raw + --rfsimulator.serveraddr 192.168.71.140 + --log_config.global_log_options level,nocolor,time + --telnetsrv --telnetsrv.listenaddr 192.168.71.150 --telnetsrv.listenport 8091 + --telnetsrv.shrmod ciUE + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.band78.106prb.prs.conf:/opt/oai-nr-ue/etc/nr-ue.conf + - rrc.config:/opt/oai-nr-ue/etc/rrc/ + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.150 + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +volumes: + rrc.config: + +networks: + public_net: + driver: bridge + name: rfsim5g-oai-public-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-public" From d4aac07ae9d8f84beb0e42d9e6ea25d1cec58f29 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 5 Nov 2025 11:13:31 +0100 Subject: [PATCH 22/24] Remove write-only code --- ci-scripts/cls_oaicitest.py | 3 +-- ci-scripts/main.py | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index f64972f253..cd5f8ecdf7 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -299,7 +299,6 @@ class OaiCiTest(): self.iperf_packetloss_threshold = '' self.iperf_bitrate_threshold = '' self.iperf_profile = '' - self.iperf_options = '' self.iperf_tcp_rate_target = '' self.finalStatus = False self.air_interface='' @@ -520,7 +519,7 @@ class OaiCiTest(): return (status, f'{ue_header}\n{msg}') def Iperf(self, ctx, node, HTML, infra_file="ci_infra.yaml"): - logging.debug(f'Iperf: iperf_args "{self.iperf_args}" iperf_packetloss_threshold "{self.iperf_packetloss_threshold}" iperf_bitrate_threshold "{self.iperf_bitrate_threshold}" iperf_profile "{self.iperf_profile}" iperf_options "{self.iperf_options}"') + logging.debug(f'Iperf: iperf_args "{self.iperf_args}" iperf_packetloss_threshold "{self.iperf_packetloss_threshold}" iperf_bitrate_threshold "{self.iperf_bitrate_threshold}" iperf_profile "{self.iperf_profile}"') if self.ue_ids == [] or self.svr_id == None: raise Exception("no module names in self.ue_ids or/and self.svr_id provided") diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 99500fff12..f427d1c023 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -185,10 +185,6 @@ def ExecuteActionWithParam(action, ctx, node): if CiTestObj.iperf_profile != 'balanced' and CiTestObj.iperf_profile != 'unbalanced' and CiTestObj.iperf_profile != 'single-ue': logging.error(f'test-case has wrong profile {CiTestObj.iperf_profile}, forcing balanced') CiTestObj.iperf_profile = 'balanced' - CiTestObj.iperf_options = test.findtext('iperf_options') or 'check' - if CiTestObj.iperf_options != 'check' and CiTestObj.iperf_options != 'sink': - logging.error('test-case has wrong option ' + CiTestObj.iperf_options) - CiTestObj.iperf_options = 'check' if action == 'Iperf': success = CiTestObj.Iperf(ctx, node, HTML) elif action == 'Iperf2_Unidir': From cf507115e4eb379c0b36c1666e57c9e8d14540a4 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Wed, 5 Nov 2025 20:51:02 +0000 Subject: [PATCH 23/24] Fix unsigned to signed decoding parameters to allow for 'no affinity'/'no pin' threads to CPUs By default, 'L1_rx_thread_core', 'L1_tx_thread_core', 'ru_thread_core' are set to '-1' but the values were decoded from config file as unsigned instead of signed types, thus, it was not allowing to set them with '-1' from config file --- openair2/ENB_APP/enb_paramdef.h | 2 +- openair2/GNB_APP/L1_nr_paramdef.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 7bc8f677d8..7be234262f 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -217,7 +217,7 @@ typedef enum { {CONFIG_STRING_RU_NUM_TP_CORES, HLP_RU_NUM_TP_CORES, 0, .uptr=NULL, .defintval=2, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_NUM_INTERFACES, HLP_RU_NUM_INTERFACES, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION, HLP_RU_HALF_SLOT_PARALLELIZATION, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \ - {CONFIG_STRING_RU_RU_THREAD_CORE, HLP_RU_RU_THREAD_CORE, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \ + {CONFIG_STRING_RU_RU_THREAD_CORE, HLP_RU_RU_THREAD_CORE, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ {CONFIG_STRING_RU_GPIO_CONTROL, HLP_RU_GPIO_CONTROL, 0, .strptr=NULL, .defstrval="generic", TYPE_STRING, 0}, \ } // clang-format on diff --git a/openair2/GNB_APP/L1_nr_paramdef.h b/openair2/GNB_APP/L1_nr_paramdef.h index b2b4ab93c1..d140275fa5 100644 --- a/openair2/GNB_APP/L1_nr_paramdef.h +++ b/openair2/GNB_APP/L1_nr_paramdef.h @@ -84,8 +84,8 @@ {CONFIG_STRING_L1_PUSCH_DTX_THRESHOLD, NULL, 0, .uptr=NULL, .defintval=50, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_SRS_DTX_THRESHOLD, NULL, 0, .uptr=NULL, .defintval=30, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_MAX_LDPC_ITERATIONS, NULL, 0, .uptr=NULL, .defintval=8, TYPE_UINT, 0}, \ - {CONFIG_STRING_L1_RX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \ - {CONFIG_STRING_L1_TX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \ + {CONFIG_STRING_L1_RX_THREAD_CORE, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ + {CONFIG_STRING_L1_TX_THREAD_CORE, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ {CONFIG_STRING_L1_TX_AMP_BACKOFF_dB, HLP_L1TX_BO,0, .uptr=NULL, .defintval=36, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_PHASE_COMP, HLP_L1_PHASE_COMP,PARAMFLAG_BOOL, .uptr=NULL,.defintval=1, TYPE_UINT, 0}, \ {CONFIG_STRING_NUM_ANTENNAS_PER_THREAD, HLP_NUM_ARX,0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \ From 95e9f4a47cef2b25a6db71ab772f81598390909f Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 5 Nov 2025 12:22:38 +0100 Subject: [PATCH 24/24] Use a single Jenkinsfile Combine Jenkinsfile and Jenkinsfile-oc from parrent commit into a single file. --- ci-scripts/Jenkinsfile | 82 +++++++++++----- ci-scripts/Jenkinsfile-oc | 199 -------------------------------------- 2 files changed, 60 insertions(+), 221 deletions(-) delete mode 100644 ci-scripts/Jenkinsfile-oc diff --git a/ci-scripts/Jenkinsfile b/ci-scripts/Jenkinsfile index 329caa5834..abb2e3942c 100644 --- a/ci-scripts/Jenkinsfile +++ b/ci-scripts/Jenkinsfile @@ -36,6 +36,7 @@ if (params.LockResources != null && params.LockResources.trim().length() > 0) // Global Parameters. Normally they should be populated when the master job // triggers the slave job with parameters + def sourceRepository = params.eNB_Repository ?: env.GIT_URL def sourceBranch = params.eNB_Branch ?: env.GIT_BRANCH def targetRepository = params.Target_Repository ?: sourceRepository @@ -44,6 +45,7 @@ def commitID = params.eNB_CommitID ?: env.GIT_COMMIT def is_MR = params.eNB_mergeRequest ?: false def flexricOption = "" +def runWithOC = false //------------------------------------------------------------------------------- // Pipeline start @@ -83,7 +85,14 @@ pipeline { echo "no eNB_SourceCodePath given" allParametersPresent = false } - + if (params.OC_Credentials != null) { + echo "This pipeline is configured to run with Opensift Cluster." + runWithOC = true + if (params.OC_ProjectName == null) { + echo "no OC_ProjectName given" + allParametersPresent = false + } + } if (params.Flexric_Tag != null) { echo "This pipeline is configured to run with a FlexRIC deployment." echo "Appending FlexRicTag option to the list of options" @@ -114,7 +123,6 @@ pipeline { } } } - stage ("Deploy and Test") { steps { script { @@ -130,30 +138,60 @@ pipeline { } } sh """ - python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \ - --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ - --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ - ${flexricOption} ${mainPythonAllXmlFiles} + python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + ${flexricOption} ${mainPythonAllXmlFiles} """ - for (xmlFile in myXmlTestSuite) { - if (fileExists(xmlFile)) { - try { - timeout (time: 60, unit: 'MINUTES') { - sh """ - python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \ - --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ - --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ - --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \ - ${flexricOption} - """ + if (runWithOC) { + withCredentials([usernamePassword(credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password')]) { + sh """ + python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + ${flexricOption} ${mainPythonAllXmlFiles} + """ + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + timeout (time: 60, unit: 'MINUTES') { + sh """ + python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \ + --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} \ + ${flexricOption} + """ + } + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + } + } else { + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + timeout (time: 60, unit: 'MINUTES') { + sh """ + python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \ + ${flexricOption} + """ + } + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false } - } catch (Exception e) { - currentBuild.result = 'FAILURE' - buildStageStatus = false } } } - sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" } } } @@ -176,7 +214,7 @@ pipeline { archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip" } if (fileExists("test_results.html")) { - def reportName = "test_results_${env.JOB_NAME}.html" + def reportName = "test_results-${env.JOB_NAME}.html" sh "mv test_results.html ${reportName}" sh """ sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' \ diff --git a/ci-scripts/Jenkinsfile-oc b/ci-scripts/Jenkinsfile-oc deleted file mode 100644 index 01a8022c12..0000000000 --- a/ci-scripts/Jenkinsfile-oc +++ /dev/null @@ -1,199 +0,0 @@ -#!/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 - */ - -def pythonExecutor = params.pythonExecutor -def testXMLFile = params.pythonTestXmlFile -def mainPythonAllXmlFiles = "" -def buildStageStatus = true -def JOB_TIMESTAMP - -// Choose test stage name or fallback default -def testStageName = params.pipelineTestStageName != null ? params.pipelineTestStageName : 'Template Test Stage' - -// Name of the resource -def lockResources = [] -if (params.LockResources != null && params.LockResources.trim().length() > 0) - params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]} - -// Global Parameters. Normally they should be populated when the master job -// triggers the slave job with parameters - -def sourceRepository = params.eNB_Repository ?: env.GIT_URL -def sourceBranch = params.eNB_Branch ?: env.GIT_BRANCH -def targetRepository = params.Target_Repository ?: sourceRepository -def targetBranch = params.eNB_TargetBranch ?: 'develop' -def commitID = params.eNB_CommitID ?: env.GIT_COMMIT -def is_MR = params.eNB_mergeRequest ?: false - -//------------------------------------------------------------------------------- -// Pipeline start -pipeline { - agent { - label pythonExecutor - } - options { - timestamps() - ansiColor('xterm') - lock(extra: lockResources) - } - - stages { - stage("Build Init") { - steps { - script { - echo '\u2705 \u001B[94mBuild Init\u001B[0m' - JOB_TIMESTAMP = sh(returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"').trim() - } - // update the build name and description - buildName "${params.eNB_MR}" - buildDescription "Branch : ${sourceBranch}" - } - } - stage ('Verify Parameters') { - steps { - script { - echo '\u2705 \u001B[94mVerify Parameters\u001B[0m' - def allParametersPresent = true - - if (params.LockResources == null) { - echo "no LockResources given" - allParametersPresent = false - } - if (params.eNB_SourceCodePath == null) { - echo "no eNB_SourceCodePath given" - allParametersPresent = false - } - if (params.OC_Credentials == null) { - echo "no OC_Credentials given" - allParametersPresent = false - } - if (params.OC_ProjectName == null) { - echo "no OC_ProjectName given" - allParametersPresent = false - } - - echo "CI executor node : ${pythonExecutor}" - echo "Source Repository : ${sourceRepository}" - echo "Source Branch : ${sourceBranch}" - echo "Target Repository : ${targetRepository}" - echo "Target Branch : ${targetBranch}" - echo "Commit ID : ${commitID}" - - if (allParametersPresent) { - echo '\u2705 \u001B[94m All parameters are present\u001B[0m' - if (is_MR) { - sh "git fetch" - sh "./ci-scripts/doGitLabMerge.sh --src-branch ${sourceBranch} --src-commit ${commitID} --target-branch ${targetBranch} --target-commit latest" - } else { - sh "git fetch" - sh "git checkout -f ${commitID}" - } - } else { - echo "\u274C Some parameters are missing" - sh "./ci-scripts/fail.sh" - } - } - } - } - - stage ("Deploy and Test") { - steps { - script { - dir ('ci-scripts') { - echo "\u2705 \u001B[94m Deploy and Test: ${testStageName}\u001B[0m" - String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") - for (xmlFile in myXmlTestSuite) { - if (fileExists(xmlFile)) { - mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " - echo "Test XML file : ${xmlFile}" - } else { - echo "Test XML file ${xmlFile}: no such file" - } - } - withCredentials([ - usernamePassword(credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password') - ]) { - sh """ - python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \ - --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ - --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ - ${mainPythonAllXmlFiles} - """ - for (xmlFile in myXmlTestSuite) { - if (fileExists(xmlFile)) { - try { - timeout (time: 60, unit: 'MINUTES') { - sh """ - python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \ - --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ - --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ - --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \ - --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} - """ - } - } catch (Exception e) { - currentBuild.result = 'FAILURE' - buildStageStatus = false - } - } - } - sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" - } - } - } - } - } - stage ("Log Collection") { - steps { - script { - echo '\u2705 \u001B[94mLog Collection\u001B[0m' - dir ('ci-scripts') { - // Zipping all archived log files - sh "mkdir test_logs" - sh "mv *.log* test_logs || true" - // Zip all log files matching cmake_targets/{*.log*,log/*} into test_logs_XXXX.zip - if (fileExists('../cmake_targets/log')) { - sh "mv ../cmake_targets/log/* test_logs || true" - } - sh "zip -r -qq test_logs_${env.BUILD_ID}.zip *test_log*/" - sh "rm -rf *test_log*/" - if (fileExists("test_logs_${env.BUILD_ID}.zip")) { - archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip" - } - if (fileExists("test_results.html")) { - def reportName = "test_results_${env.JOB_NAME}.html" - sh "mv test_results.html ${reportName}" - sh """ - sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' \ - -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: ${BUILD_ID}#' \ - -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' ${reportName} - """ - archiveArtifacts artifacts: "${reportName}" - } - } - } - } - } - } -}