diff --git a/CMakeLists.txt b/CMakeLists.txt
index 70ea409d36..2730c510e0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -979,6 +979,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c
+ ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ntn_l1.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c
@@ -1038,11 +1039,11 @@ pkg_check_modules(lapacke REQUIRED lapacke)
add_library(PHY_UE ${PHY_SRC_UE})
target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL)
-# RHEL needs also cblas, but Ubuntu does not have it. So `cblas_LIBRARIES` will
-# be empty for Ubuntu, a no-op
+# RHEL needs also cblas, but Ubuntu does not have it. So `cblas_LIBRARIES` and
+# `cblas_INCLUDE_DIRS` will be empty for Ubuntu, a no-op
pkg_check_modules(cblas cblas)
target_link_libraries(PHY_UE PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapacke_LIBRARIES})
-target_include_directories(PHY_UE PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS})
+target_include_directories(PHY_UE PRIVATE ${blas_INCLUDE_DIRS} ${cblas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS})
add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
target_link_libraries(PHY_NR_COMMON PUBLIC UTIL)
diff --git a/ci-scripts/Jenkinsfile-cluster b/ci-scripts/Jenkinsfile-cluster
deleted file mode 100644
index 174ccab62f..0000000000
--- a/ci-scripts/Jenkinsfile-cluster
+++ /dev/null
@@ -1,228 +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
- */
-
-// Location of the executor node
-def pythonExecutor = params.pythonExecutor
-
-// Location of the test XML file to be run
-def testXMLFile = params.pythonTestXmlFile
-def mainPythonAllXmlFiles = ""
-def buildStageStatus = true
-
-// Name of the test stage
-def testStageName = params.pipelineTestStageName
-
-// Name of the 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 eNB_Repository
-def eNB_Branch
-def eNB_CommitID
-def eNB_AllowMergeRequestProcess = false
-def eNB_TargetBranch
-
-def directoryExistsGlob(fileNameWithGlob) {
- /* if multiple directories match, will join their names and call fileExists() on that */
- def dir = sh returnStdout: true, script: 'find . -name \'' + fileNameWithGlob + '\' -type d'
- dir = dir.replaceAll("\n", "").trim()
- echo "matching '" + fileNameWithGlob + "' found: '" + dir + "'"
- if (dir == "")
- return false
- return fileExists(dir)
-}
-
-//-------------------------------------------------------------------------------
-// Pipeline start
-pipeline {
- agent {
- label pythonExecutor
- }
- options {
- timestamps()
- ansiColor('xterm')
- lock(extra: lockResources)
- }
-
- stages {
- stage("Build Init") {
- steps {
- // update the build name and description
- buildName "${params.eNB_MR}"
- buildDescription "Branch : ${params.eNB_Branch}"
- }
- }
- stage ('Verify Parameters') {
- steps {
- script {
- echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
-
- JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
- JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
-
- def allParametersPresent = true
-
- // It is already to late to check it
- if (params.pythonExecutor != null) {
- echo "eNB CI executor node : ${pythonExecutor}"
- }
- // If not present picking a default Stage Name
- if (params.pipelineTestStageName == null) {
- // picking default
- testStageName = 'Template Test Stage'
- }
-
- if (params.LockResources == null) {
- echo "no LockResources given"
- allParametersPresent = false
- }
- if (params.eNB_SourceCodePath == null) {
- echo "no eNB_SourceCodePath given"
- allParametersPresent = false
- }
- // the following 4 parameters should be pushed by the master trigger
- // if not present, take the job GIT variables (used for developing)
- if (params.eNB_Repository == null) {
- eNB_Repository = env.GIT_URL
- } else {
- eNB_Repository = params.eNB_Repository
- }
- echo "eNB_Repository : ${eNB_Repository}"
- if (params.eNB_Branch == null) {
- eNB_Branch = env.GIT_BRANCH
- } else {
- eNB_Branch = params.eNB_Branch
- }
- echo "eNB_Branch : ${eNB_Branch}"
- if (params.eNB_CommitID == null) {
- eNB_CommitID = env.GIT_COMMIT
- } else {
- eNB_CommitID = params.eNB_CommitID
- }
- echo "eNB_CommitID : ${eNB_CommitID}"
- if (params.eNB_mergeRequest != null) {
- eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
- if (eNB_AllowMergeRequestProcess) {
- if (params.eNB_TargetBranch != null) {
- eNB_TargetBranch = params.eNB_TargetBranch
- } else {
- eNB_TargetBranch = 'develop'
- }
- echo "eNB_TargetBranch : ${eNB_TargetBranch}"
- }
- } else {
- echo "no eNB_mergeRequest given - not merging develop"
- }
-
- if (params.OC_Credentials == null) {
- echo "no OC_Credentials given"
- allParametersPresent = false
- }
- if (params.OC_ProjectName == null) {
- echo "no OC_ProjectName given"
- allParametersPresent = false
- }
- if (params.pythonTestXmlFile == null) {
- echo "no pythonTestXmlFile given"
- allParametersPresent = false
- }
- if (allParametersPresent) {
- echo "All parameters are present"
- if (eNB_AllowMergeRequestProcess) {
- sh "git fetch"
- sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
- } else {
- sh "git fetch"
- sh "git checkout -f ${eNB_CommitID}"
- }
- } else {
- echo "Some parameters are missing"
- sh "./ci-scripts/fail.sh"
- }
- }
- }
- }
-
- stage ("Deploy and Test") {
- steps {
- script {
- dir ('ci-scripts') {
- echo "\u2705 \u001B[32m${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([
- [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password']
- ]) {
- sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- try {
- timeout (time: 60, unit: 'MINUTES') {
- sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_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 {
- dir ('ci-scripts') {
- if (directoryExistsGlob("build_log_*")) {
- sh "zip -r -qq build_log_${env.BUILD_ID}.zip build_log_*/*"
- sh "rm -rf build_log_*/"
- archiveArtifacts artifacts: "build_log_${env.BUILD_ID}.zip"
- }
- if (directoryExistsGlob("test_log_*")) {
- sh "zip -r -qq test_log_${env.BUILD_ID}.zip test_log_*/*"
- sh "rm -rf test_log_*/"
- archiveArtifacts artifacts: "test_log_${env.BUILD_ID}.zip"
- }
- if (fileExists("test_results.html")) {
- sh "mv test_results.html test_results-${env.JOB_NAME}.html"
- sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
- archiveArtifacts artifacts: "test_results-${env.JOB_NAME}.html"
- }
- }
- }
- }
- }
- }
-}
diff --git a/ci-scripts/Jenkinsfile-nrue b/ci-scripts/Jenkinsfile-nrue
deleted file mode 100644
index 3f7ef9b9ed..0000000000
--- a/ci-scripts/Jenkinsfile-nrue
+++ /dev/null
@@ -1,223 +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
- */
-
-// Location of the executor node
-def pythonExecutor = params.pythonExecutor
-
-// Location of the test XML file to be run
-def testXMLFile = params.pythonTestXmlFile
-def mainPythonAllXmlFiles = ""
-def buildStageStatus = true
-
-// Name of the test stage
-def testStageName = params.pipelineTestStageName
-
-// Name of the 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 eNB_Repository
-def eNB_Branch
-def eNB_CommitID
-def eNB_AllowMergeRequestProcess = false
-def eNB_TargetBranch
-
-// Flags
-def scmEvent = false
-def upstreamEvent = false
-
-//-------------------------------------------------------------------------------
-// Pipeline start
-pipeline {
- agent {
- label pythonExecutor
- }
- options {
- timestamps()
- ansiColor('xterm')
- lock(extra: lockResources)
- }
-
- stages {
- stage("Build Init") {
- steps {
- // update the build name and description
- buildName "${params.eNB_MR}"
- buildDescription "Branch : ${params.eNB_Branch}"
- }
- }
- stage ('Verify Parameters') {
- steps {
- script {
- echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
-
- JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
- JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
-
- def allParametersPresent = true
-
- // It is already to late to check it
- if (params.pythonExecutor != null) {
- echo "eNB CI executor node : ${pythonExecutor}"
- }
- // If not present picking a default Stage Name
- if (params.pipelineTestStageName == null) {
- // picking default
- testStageName = 'Template Test Stage'
- }
- if (params.LockResources == null) {
- echo "no LockResources given"
- allParametersPresent = false
- }
- if (params.eNB_SourceCodePath == null) {
- allParametersPresent = false
- }
- // the following 4 parameters should be pushed by the master trigger
- // if not present, take the job GIT variables (used for developing)
- if (params.eNB_Repository == null) {
- eNB_Repository = env.GIT_URL
- } else {
- eNB_Repository = params.eNB_Repository
- }
- echo "eNB_Repository : ${eNB_Repository}"
- if (params.eNB_Branch == null) {
- eNB_Branch = env.GIT_BRANCH
- } else {
- eNB_Branch = params.eNB_Branch
- }
- echo "eNB_Branch : ${eNB_Branch}"
- if (params.eNB_CommitID == null) {
- eNB_CommitID = env.GIT_COMMIT
- } else {
- eNB_CommitID = params.eNB_CommitID
- }
- echo "eNB_CommitID : ${eNB_CommitID}"
- if (params.eNB_mergeRequest != null) {
- eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
- if (eNB_AllowMergeRequestProcess) {
- if (params.eNB_TargetBranch != null) {
- eNB_TargetBranch = params.eNB_TargetBranch
- } else {
- eNB_TargetBranch = 'develop'
- }
- echo "eNB_TargetBranch : ${eNB_TargetBranch}"
- }
- }
-
- if (params.OC_Credentials == null) {
- allParametersPresent = false
- }
- if (params.OC_ProjectName == null) {
- allParametersPresent = false
- }
- if (allParametersPresent) {
- echo "All parameters are present"
- if (eNB_AllowMergeRequestProcess) {
- sh "git fetch"
- sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
- } else {
- sh "git fetch"
- sh "git checkout -f ${eNB_CommitID}"
- }
- } else {
- echo "Some parameters are missing"
- sh "./ci-scripts/fail.sh"
- }
- }
- }
- }
-
- stage ("Deploy and Test") {
- steps {
- script {
- dir ('ci-scripts') {
- echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
- // If not present picking a default XML file
- if (params.pythonTestXmlFile == null) {
- // picking default
- testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
- echo "Test XML file(default): ${testXMLFile}"
- mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
- } else {
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
- echo "Test XML file : ${xmlFile}"
- } else {
- echo "Test XML file ${xmlFile}: no such file"
- }
- }
- }
- withCredentials([
- [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password']
- ]) {
- sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- try {
- timeout (time: 60, unit: 'MINUTES') {
- sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_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 {
- 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")) {
- sh "mv test_results.html test_results-${env.JOB_NAME}.html"
- sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
- archiveArtifacts artifacts: "test_results-${env.JOB_NAME}.html"
- }
- }
- }
- }
- }
- }
-}
diff --git a/ci-scripts/Jenkinsfile-physim-deploy b/ci-scripts/Jenkinsfile-physim-deploy
deleted file mode 100644
index e3d243d07b..0000000000
--- a/ci-scripts/Jenkinsfile-physim-deploy
+++ /dev/null
@@ -1,224 +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
- */
-
-// Location of the executor node
-def pythonExecutor = params.pythonExecutor
-
-// Location of the test XML file to be run
-def testXMLFile = params.pythonTestXmlFile
-def mainPythonAllXmlFiles = ""
-def buildStageStatus = true
-
-// Name of the test stage
-def testStageName = params.pipelineTestStageName
-
-// Name of the 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 eNB_Repository
-def eNB_Branch
-def eNB_CommitID
-def eNB_AllowMergeRequestProcess = false
-def eNB_TargetBranch
-
-// Flags
-def scmEvent = false
-def upstreamEvent = false
-
-//-------------------------------------------------------------------------------
-// Pipeline start
-pipeline {
- agent {
- label pythonExecutor
- }
- options {
- timestamps()
- ansiColor('xterm')
- lock(extra: lockResources)
- }
-
- stages {
- stage("Build Init") {
- steps {
- // update the build name and description
- buildName "${params.eNB_MR}"
- buildDescription "Branch : ${params.eNB_Branch}"
- }
- }
- stage ('Verify Parameters') {
- steps {
- script {
- echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
-
- JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
- JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
-
- def allParametersPresent = true
-
- // It is already to late to check it
- if (params.pythonExecutor != null) {
- echo "eNB CI executor node : ${pythonExecutor}"
- }
- // If not present picking a default Stage Name
- if (params.pipelineTestStageName == null) {
- // picking default
- testStageName = 'Template Test Stage'
- }
-
- if (params.LockResources == null) {
- echo "no LockResources given"
- allParametersPresent = false
- }
- if (params.eNB_SourceCodePath == null) {
- allParametersPresent = false
- }
- // the following 4 parameters should be pushed by the master trigger
- // if not present, take the job GIT variables (used for developing)
- if (params.eNB_Repository == null) {
- eNB_Repository = env.GIT_URL
- } else {
- eNB_Repository = params.eNB_Repository
- }
- echo "eNB_Repository : ${eNB_Repository}"
- if (params.eNB_Branch == null) {
- eNB_Branch = env.GIT_BRANCH
- } else {
- eNB_Branch = params.eNB_Branch
- }
- echo "eNB_Branch : ${eNB_Branch}"
- if (params.eNB_CommitID == null) {
- eNB_CommitID = env.GIT_COMMIT
- } else {
- eNB_CommitID = params.eNB_CommitID
- }
- echo "eNB_CommitID : ${eNB_CommitID}"
- if (params.eNB_mergeRequest != null) {
- eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
- if (eNB_AllowMergeRequestProcess) {
- if (params.eNB_TargetBranch != null) {
- eNB_TargetBranch = params.eNB_TargetBranch
- } else {
- eNB_TargetBranch = 'develop'
- }
- echo "eNB_TargetBranch : ${eNB_TargetBranch}"
- }
- }
-
- if (params.OC_Credentials == null) {
- allParametersPresent = false
- }
- if (params.OC_ProjectName == null) {
- allParametersPresent = false
- }
- if (allParametersPresent) {
- echo "All parameters are present"
- if (eNB_AllowMergeRequestProcess) {
- sh "git fetch"
- sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
- } else {
- sh "git fetch"
- sh "git checkout -f ${eNB_CommitID}"
- }
- } else {
- echo "Some parameters are missing"
- sh "./ci-scripts/fail.sh"
- }
- }
- }
- }
-
- stage ("Deploy and Test") {
- steps {
- script {
- dir ('ci-scripts') {
- echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
- // If not present picking a default XML file
- if (params.pythonTestXmlFile == null) {
- // picking default
- testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
- echo "Test XML file(default): ${testXMLFile}"
- mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
- } else {
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
- echo "Test XML file : ${xmlFile}"
- } else {
- echo "Test XML file ${xmlFile}: no such file"
- }
- }
- }
- withCredentials([
- [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password']
- ]) {
- sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- try {
- timeout (time: 60, unit: 'MINUTES') {
- sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_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 {
- 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")) {
- sh "mv test_results.html test_results-${env.JOB_NAME}.html"
- sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
- archiveArtifacts artifacts: "test_results-${env.JOB_NAME}.html"
- }
- }
- }
- }
- }
- }
-}
diff --git a/ci-scripts/Jenkinsfile-tmp-full-ran b/ci-scripts/Jenkinsfile-tmp-full-ran
deleted file mode 100644
index 07b10ab980..0000000000
--- a/ci-scripts/Jenkinsfile-tmp-full-ran
+++ /dev/null
@@ -1,250 +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
- */
-
-// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
-
-// Location of the python executor node shall be in the same subnet as the others servers
-def pythonExecutor = params.pythonExecutor
-
-// Location of the test XML file to be run
-def testXMLFile = params.pythonTestXmlFile
-def mainPythonAllXmlFiles = ""
-def buildStageStatus = true
-
-// Name of the test stage
-def testStageName = params.pipelineTestStageName
-
-def lockResources = []
-if (params.LockResources != null && params.LockResources.trim().length() > 0)
- params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
-
-// Terminate Status
-def termENB = 0
-def termStatusArray = new Boolean[termENB + 1]
-termStatusArray[termENB] = false
-
-// Global Parameters. Normally they should be populated when the master job
-// triggers the slave job with parameters
-def eNB_Repository
-def eNB_Branch
-def eNB_CommitID
-def eNB_AllowMergeRequestProcess = false
-def eNB_TargetBranch
-
-def doEpcLogCollection = true
-
-
-
-pipeline {
- agent {
- label pythonExecutor
- }
- options {
- ansiColor('xterm')
- lock(extra: lockResources)
- }
-
- stages {
- stage("Build Init") {
- steps {
- // update the build name and description
- buildName "${params.eNB_MR}"
- buildDescription "Branch : ${params.eNB_Branch}"
- }
- }
- stage ("Verify Parameters") {
- steps {
- script {
- echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
- def allParametersPresent = true
-
- // It is already to late to check it
- if (params.pythonExecutor != null) {
- echo "eNB CI executor node : ${pythonExecutor}"
- }
- // If not present picking a default Stage Name
- if (params.pipelineTestStageName == null) {
- // picking default
- testStageName = 'Template Test Stage'
- }
-
- if (params.LockResources == null) {
- echo "no LockResources given"
- allParametersPresent = false
- }
- if (params.eNB_SourceCodePath == null) {
- allParametersPresent = false
- }
- // the following 4 parameters should be pushed by the master trigger
- // if not present, take the job GIT variables (used for developing)
- if (params.eNB_Repository == null) {
- eNB_Repository = env.GIT_URL
- } else {
- eNB_Repository = params.eNB_Repository
- }
- echo "eNB_Repository : ${eNB_Repository}"
- if (params.eNB_Branch == null) {
- eNB_Branch = env.GIT_BRANCH
- } else {
- eNB_Branch = params.eNB_Branch
- }
- echo "eNB_Branch : ${eNB_Branch}"
- if (params.eNB_CommitID == null) {
- eNB_CommitID = env.GIT_COMMIT
- } else {
- eNB_CommitID = params.eNB_CommitID
- }
- echo "eNB_CommitID : ${eNB_CommitID}"
- if (params.eNB_mergeRequest != null) {
- eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
- if (eNB_AllowMergeRequestProcess) {
- if (params.eNB_TargetBranch != null) {
- eNB_TargetBranch = params.eNB_TargetBranch
- } else {
- eNB_TargetBranch = 'develop'
- }
- echo "eNB_TargetBranch : ${eNB_TargetBranch}"
- }
- }
-
- if (allParametersPresent) {
- echo "All parameters are present"
- if (eNB_AllowMergeRequestProcess) {
- sh "git fetch"
- sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
- } else {
- sh "git fetch"
- sh "git checkout -f ${eNB_CommitID}"
- }
- } else {
- currentBuild.result = 'ABORTED'
- error('Stopping early because some parameters are missing')
- }
- }
- }
- }
- stage ("Build and Test") {
- steps {
- script {
- dir ('ci-scripts') {
- echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
- // If not present picking a default XML file
- if (params.pythonTestXmlFile == null) {
- // picking default
- testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
- echo "Test XML file(default): ${testXMLFile}"
- mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
- } else {
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
- echo "Test XML file : ${xmlFile}"
- } else {
- echo "Test XML file ${xmlFile}: no such file"
- }
- }
- }
- sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- try {
- timeout (time: 60, unit: 'MINUTES') {
- sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}"
- }
- } catch (Exception e) {
- currentBuild.result = 'FAILURE'
- buildStageStatus = false
- }
- }
- }
- sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
- }
- }
- }
- }
- stage ("Terminate") {
- parallel {
- stage('Terminate eNB') {
- steps {
- echo '\u2705 \u001B[32mTerminate eNB\u001B[0m'
- sh "python3 ci-scripts/main.py --mode=TerminateeNB"
- }
- post {
- success {
- script {
- termStatusArray[termENB] = true
- }
- }
- }
- }
- }
- }
- stage('Log Collection') {
- parallel {
- stage('Log Collection (eNB - Run)') {
- steps {
- echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
- sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}"
-
- script {
- if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
- archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
- }
- if(fileExists("ci-scripts/test_results.html")) {
- sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
- sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
- archiveArtifacts "test_results-${JOB_NAME}.html"
- }
- }
- }
- }
- }
- }
- }
-
- post {
- always {
- script {
- if (params.pipelineZipsConsoleLog != null) {
- if (params.pipelineZipsConsoleLog) {
- echo "Archiving Jenkins console log"
- sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
- sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
- if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
- archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
- }
- }
- }
- }
- }
- // Making sure that we really shutdown every thing before leaving
- failure {
- script {
- if (!termStatusArray[termENB]) {
- sh "python3 ci-scripts/main.py --mode=TerminateeNB"
- }
- }
- }
- }
-}
diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb b/ci-scripts/Jenkinsfile-tmp-multi-enb
deleted file mode 100644
index c01c8daf7e..0000000000
--- a/ci-scripts/Jenkinsfile-tmp-multi-enb
+++ /dev/null
@@ -1,225 +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
- */
-
-// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
-
-// Location of the python executor node shall be in the same subnet as the others servers
-def pythonExecutor = params.pythonExecutor
-
-// Location of the test XML file to be run
-def testXMLFile = params.pythonTestXmlFile
-def mainPythonAllXmlFiles = ""
-def buildStageStatus = true
-
-// Name of the test stage
-def testStageName = params.pipelineTestStageName
-
-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 eNB_Repository
-def eNB_Branch
-def eNB_CommitID
-def eNB_AllowMergeRequestProcess = false
-def eNB_TargetBranch
-
-pipeline {
- agent {
- label pythonExecutor
- }
- options {
- ansiColor('xterm')
- lock(extra: lockResources)
- }
- stages {
- stage("Build Init") {
- steps {
- // update the build name and description
- buildName "${params.eNB_MR}"
- buildDescription "Branch : ${params.eNB_Branch}"
- }
- }
- stage ("Verify Parameters") {
- steps {
- script {
- echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
- def allParametersPresent = true
-
- // It is already to late to check it
- if (params.pythonExecutor != null) {
- echo "eNB CI executor node : ${pythonExecutor}"
- }
- // If not present picking a default Stage Name
- if (params.pipelineTestStageName == null) {
- // picking default
- testStageName = 'Template Test Stage'
- }
-
- if (params.LockResources == null) {
- echo "no LockResources given"
- allParametersPresent = false
- }
- if (params.eNB_SourceCodePath == null) {
- allParametersPresent = false
- }
- // the following 4 parameters should be pushed by the master trigger
- // if not present, take the job GIT variables (used for developing)
- if (params.eNB_Repository == null) {
- eNB_Repository = env.GIT_URL
- } else {
- eNB_Repository = params.eNB_Repository
- }
- echo "eNB_Repository : ${eNB_Repository}"
- if (params.eNB_Branch == null) {
- eNB_Branch = env.GIT_BRANCH
- } else {
- eNB_Branch = params.eNB_Branch
- }
- echo "eNB_Branch : ${eNB_Branch}"
- if (params.eNB_CommitID == null) {
- eNB_CommitID = env.GIT_COMMIT
- } else {
- eNB_CommitID = params.eNB_CommitID
- }
- echo "eNB_CommitID : ${eNB_CommitID}"
- if (params.eNB_mergeRequest != null) {
- eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
- if (eNB_AllowMergeRequestProcess) {
- if (params.eNB_TargetBranch != null) {
- eNB_TargetBranch = params.eNB_TargetBranch
- } else {
- eNB_TargetBranch = 'develop'
- }
- echo "eNB_TargetBranch : ${eNB_TargetBranch}"
- }
- }
-
- if (allParametersPresent) {
- echo "All parameters are present"
- if (eNB_AllowMergeRequestProcess) {
- sh "git fetch"
- sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
- } else {
- sh "git fetch"
- sh "git checkout -f ${eNB_CommitID}"
- }
- } else {
- echo "Some parameters are missing"
- sh "./ci-scripts/fail.sh"
- }
- }
- }
- }
- stage ("Build and Test") {
- steps {
- script {
- dir ('ci-scripts') {
- echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
- // If not present picking a default XML file
- if (params.pythonTestXmlFile == null) {
- // picking default
- testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
- echo "Test XML file(default): ${testXMLFile}"
- mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
- } else {
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
- echo "Test XML file : ${xmlFile}"
- } else {
- echo "Test XML file ${xmlFile}: no such file"
- }
- }
- }
- sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- try {
- timeout (time: 60, unit: 'MINUTES') {
- sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}"
- }
- } catch (Exception e) {
- currentBuild.result = 'FAILURE'
- buildStageStatus = false
- }
- }
- }
- sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
- }
- }
- }
- }
- stage ("Terminate") {
- parallel {
- stage('Terminate eNB') {
- steps {
- echo '\u2705 \u001B[32mTerminate eNB\u001B[0m'
- sh "python3 ci-scripts/main.py --mode=TerminateeNB"
- }
- }
- }
- }
- stage('Log Collection') {
- parallel {
- stage('Log Collection (eNB - Run)') {
- steps {
- echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
- sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}"
-
- script {
- if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
- archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
- }
- if(fileExists("ci-scripts/test_results.html")) {
- sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
- sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
- archiveArtifacts "test_results-${JOB_NAME}.html"
- }
- }
- }
- }
- }
- }
- }
-
- post {
- always {
- script {
- if (params.pipelineZipsConsoleLog != null) {
- if (params.pipelineZipsConsoleLog) {
- echo "Archiving Jenkins console log"
- sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
- sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
- if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
- archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
- }
- }
- }
- }
- }
- }
-}
diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa
deleted file mode 100644
index 67aa6b4511..0000000000
--- a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa
+++ /dev/null
@@ -1,216 +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
- */
-
-// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
-
-// Location of the python executor node shall be in the same subnet as the others servers
-def pythonExecutor = params.pythonExecutor
-
-// Location of the test XML file to be run
-def testXMLFile = params.pythonTestXmlFile
-def mainPythonAllXmlFiles = ""
-def buildStageStatus = true
-
-// Name of the test stage
-def testStageName = params.pipelineTestStageName
-
-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 eNB_Repository
-def eNB_Branch
-def eNB_CommitID
-def eNB_AllowMergeRequestProcess
-def eNB_TargetBranch
-
-//Status fed to the database
-def StatusForDb = ""
-
-
-pipeline {
- agent {label pythonExecutor}
- options {
- ansiColor('xterm')
- lock(extra: lockResources)
- }
- stages {
- stage("Build Init") {
- steps {
- // update the build name and description
- buildName "${params.eNB_MR}"
- buildDescription "Branch : ${params.eNB_Branch}"
- }
- }
- stage ("Verify Parameters") {
- steps {
- script {
- echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
- def allParametersPresent = true
-
- // It is already to late to check it
- if (params.pythonExecutor != null) {
- echo "eNB CI executor node : ${pythonExecutor}"
- }
- // If not present picking a default Stage Name
- if (params.pipelineTestStageName == null) {
- // picking default
- testStageName = 'Template Test Stage'
- }
-
- if (params.LockResources == null) {
- echo "no LockResources given"
- allParametersPresent = false
- }
- if (params.eNB_SourceCodePath == null) {
- allParametersPresent = false
- }
- // the following 4 parameters should be pushed by the master trigger
- // if not present, take the job GIT variables (used for developing)
- if (params.eNB_Repository == null) {
- eNB_Repository = env.GIT_URL
- } else {
- eNB_Repository = params.eNB_Repository
- }
- echo "eNB_Repository : ${eNB_Repository}"
- if (params.eNB_Branch == null) {
- eNB_Branch = env.GIT_BRANCH
- } else {
- eNB_Branch = params.eNB_Branch
- }
- echo "eNB_Branch : ${eNB_Branch}"
- if (params.eNB_CommitID == null) {
- eNB_CommitID = env.GIT_COMMIT
- } else {
- eNB_CommitID = params.eNB_CommitID
- }
- echo "eNB_CommitID : ${eNB_CommitID}"
- if (params.eNB_mergeRequest!= null) {
- eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
- if (eNB_AllowMergeRequestProcess) {
- if (params.eNB_TargetBranch != null) {
- eNB_TargetBranch = params.eNB_TargetBranch
- } else {
- eNB_TargetBranch = 'develop'
- }
- echo "eNB_TargetBranch : ${eNB_TargetBranch}"
- }
- }
-
- if (allParametersPresent) {
- echo "All parameters are present"
- if (eNB_AllowMergeRequestProcess) {
- sh "git fetch"
- sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
- } else {
- sh "git fetch"
- sh "git checkout -f ${eNB_CommitID}"
- }
- } else {
- echo "Some parameters are missing"
- sh "./ci-scripts/fail.sh"
- }
- }
- }
- }
- stage ("Build and Test") {
- steps {
- script {
- dir ('ci-scripts') {
- echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
- // If not present picking a default XML file
- if (params.pythonTestXmlFile == null) {
- // picking default
- testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
- echo "Test XML file(default): ${testXMLFile}"
- mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
- } else {
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
- echo "Test XML file : ${xmlFile}"
- } else {
- echo "Test XML file ${xmlFile}: no such file"
- }
- }
- }
- sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- try {
- timeout (time: 60, unit: 'MINUTES') {
- sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}"
- }
- } catch (Exception e) {
- currentBuild.result = 'FAILURE'
- buildStageStatus = false
- }
- }
- }
- sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
- }
- }
- }
- }
- stage('Log Collection') {
- parallel {
- stage('Log Collection (eNB - Run)') {
- steps {
- echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
- sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}"
- script {
- if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
- archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
- }
- }
- }
- }
- }
- }
- }
-
- post {
- always {
- script {
- if(fileExists("ci-scripts/test_results.html")) {
- sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
- sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
- archiveArtifacts "test_results-${JOB_NAME}.html"
- }
- if (params.pipelineZipsConsoleLog != null) {
- if (params.pipelineZipsConsoleLog) {
- echo "Archiving Jenkins console log"
- sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
- sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
- if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
- archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
- }
- }
- }
- }
- }
- }
-}
diff --git a/ci-scripts/Jenkinsfile-tmp-ran b/ci-scripts/Jenkinsfile-tmp-ran
deleted file mode 100644
index 526899a5a2..0000000000
--- a/ci-scripts/Jenkinsfile-tmp-ran
+++ /dev/null
@@ -1,260 +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
- */
-
-// Template Jenkins Declarative Pipeline script to run Test w/ RF HW
-
-// Location of the python executor node shall be in the same subnet as the others servers
-def pythonExecutor = params.pythonExecutor
-
-// Location of the test XML file to be run
-def testXMLFile = params.pythonTestXmlFile
-def mainPythonAllXmlFiles = ""
-def buildStageStatus = true
-
-// Name of the test stage
-def testStageName = params.pipelineTestStageName
-
-def lockResources = []
-if (params.LockResources != null && params.LockResources.trim().length() > 0)
- params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
-
-// Terminate Status
-def termUE = 0
-def termENB = 1
-def termSPGW = 2
-def termMME = 3
-def termHSS = 4
-def termStatusArray = new Boolean[termHSS + 1]
-termStatusArray[termUE] = false
-termStatusArray[termENB] = false
-termStatusArray[termSPGW] = false
-termStatusArray[termMME] = false
-termStatusArray[termHSS] = false
-
-// Global Parameters. Normally they should be populated when the master job
-// triggers the slave job with parameters
-def eNB_Repository
-def eNB_Branch
-def eNB_CommitID
-def eNB_AllowMergeRequestProcess = false
-def eNB_TargetBranch
-
-def flexricOption = ""
-
-pipeline {
- agent {
- label pythonExecutor
- }
- options {
- ansiColor('xterm')
- lock(extra: lockResources)
- }
- stages {
- stage("Build Init") {
- steps {
- // update the build name and description
- buildName "${params.eNB_MR}"
- buildDescription "Branch : ${params.eNB_Branch}"
- }
- }
- stage ("Verify Parameters") {
- steps {
- script {
- echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
- def allParametersPresent = true
-
- // It is already to late to check it
- if (params.pythonExecutor != null) {
- echo "eNB CI executor node : ${pythonExecutor}"
- }
- // If not present picking a default Stage Name
- if (params.pipelineTestStageName == null) {
- // picking default
- testStageName = 'Template Test Stage'
- }
-
- if (params.LockResources == null) {
- echo "no LockResources given"
- allParametersPresent = false
- }
- if (params.eNB_SourceCodePath == null) {
- allParametersPresent = false
- }
- // the following 4 parameters should be pushed by the master trigger
- // if not present, take the job GIT variables (used for developing)
- if (params.eNB_Repository == null) {
- eNB_Repository = env.GIT_URL
- } else {
- eNB_Repository = params.eNB_Repository
- }
- echo "eNB_Repository : ${eNB_Repository}"
- if (params.eNB_Branch == null) {
- eNB_Branch = env.GIT_BRANCH
- } else {
- eNB_Branch = params.eNB_Branch
- }
- echo "eNB_Branch : ${eNB_Branch}"
- if (params.eNB_CommitID == null) {
- eNB_CommitID = env.GIT_COMMIT
- } else {
- eNB_CommitID = params.eNB_CommitID
- }
- echo "eNB_CommitID : ${eNB_CommitID}"
- if (params.eNB_mergeRequest != null) {
- eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
- if (eNB_AllowMergeRequestProcess) {
- if (params.eNB_TargetBranch != null) {
- eNB_TargetBranch = params.eNB_TargetBranch
- } else {
- eNB_TargetBranch = 'develop'
- }
- echo "eNB_TargetBranch : ${eNB_TargetBranch}"
- }
- }
-
- if (params.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}"
- }
-
- if (allParametersPresent) {
- echo "All parameters are present"
- if (eNB_AllowMergeRequestProcess) {
- sh "git fetch"
- sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
- } else if (eNB_CommitID != 'develop') {
- sh "git fetch"
- sh "git checkout -f ${eNB_CommitID}"
- }
- } else {
- error "Some parameters are missing"
- }
- }
- }
- }
- stage ("Build and Test") {
- steps {
- script {
- dir ('ci-scripts') {
- echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
- // If not present picking a default XML file
- if (params.pythonTestXmlFile == null) {
- // picking default
- testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
- echo "Test XML file(default): ${testXMLFile}"
- mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
- } else {
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
- echo "Test XML file : ${xmlFile}"
- } else {
- echo "Test XML file ${xmlFile}: no such file"
- }
- }
- }
- sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${flexricOption} ${mainPythonAllXmlFiles}"
- String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
- for (xmlFile in myXmlTestSuite) {
- if (fileExists(xmlFile)) {
- try {
- timeout (time: 60, unit: 'MINUTES') {
- sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${flexricOption} --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile}"
- }
- } catch (Exception e) {
- currentBuild.result = 'FAILURE'
- buildStageStatus = false
- }
- }
- }
- sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}"
- }
- }
- }
- }
- stage ("Terminate") {
- parallel {
- stage('Terminate eNB') {
- steps {
- echo '\u2705 \u001B[32mTerminate eNB\u001B[0m'
- sh "python3 ci-scripts/main.py --mode=TerminateeNB"
- }
- post {
- success {
- script {
- termStatusArray[termENB] = true
- }
- }
- }
- }
- }
- }
- stage('Log Collection') {
- parallel {
- stage('Log Collection (eNB - Run)') {
- steps {
- echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
- sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}"
- script {
- if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
- archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
- }
- if(fileExists("ci-scripts/test_results.html")) {
- sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
- sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
- archiveArtifacts "test_results-${JOB_NAME}.html"
- }
- }
- }
- }
- }
- }
- }
-
- post {
- always {
- script {
- if (params.pipelineZipsConsoleLog != null) {
- if (params.pipelineZipsConsoleLog) {
- echo "Archiving Jenkins console log"
- sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
- sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
- if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
- archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
- }
- }
- }
- }
- }
- // Making sure that we really shutdown every thing before leaving
- failure {
- script {
- if (!termStatusArray[termENB]) {
- sh "python3 ci-scripts/main.py --mode=TerminateeNB"
- }
- }
- }
- }
-}
diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py
index 71e437676c..be42790a5c 100644
--- a/ci-scripts/cls_containerize.py
+++ b/ci-scripts/cls_containerize.py
@@ -209,7 +209,7 @@ def CheckLogs(self, filename, HTML, RAN):
elif 'nv-cubb' in name:
msg = 'Undeploy PNF/Nvidia CUBB'
HTML.CreateHtmlTestRow(msg, 'OK', CONST.ALL_PROCESSES_OK)
- elif (any(sub in name for sub in ['enb','rru','rcc','cu','du','gnb'])):
+ elif (any(sub in name for sub in ['enb','rru','rcc','cu','du','gnb','vnf'])):
logging.debug(f'\u001B[1m Analyzing XnB logfile {filename}\u001B[0m')
logStatus = RAN.AnalyzeLogFile_eNB(filename, HTML, self.ran_checkers)
opt = f"xNB log analysis ({name})"
diff --git a/cmake_targets/snap_environment.sh b/cmake_targets/snap_environment.sh
deleted file mode 100755
index 1c0725d8b5..0000000000
--- a/cmake_targets/snap_environment.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-export UHD_IMAGES_DIR=$SNAP/uhd_images
-exec $@
diff --git a/cmake_targets/tools/Kbuild.cmake b/cmake_targets/tools/Kbuild.cmake
deleted file mode 100755
index 7403cd04df..0000000000
--- a/cmake_targets/tools/Kbuild.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-src=${dir}
-obj-m += ${name}.o
-${name}-y += ${objs}
-ccflags-y += ${module_cc_opt}
diff --git a/cmake_targets/tools/MODULES/CMakeParseArguments.cmake b/cmake_targets/tools/MODULES/CMakeParseArguments.cmake
deleted file mode 100755
index ab53b112fa..0000000000
--- a/cmake_targets/tools/MODULES/CMakeParseArguments.cmake
+++ /dev/null
@@ -1,66 +0,0 @@
-# Analogue for standard CMake module with same name, appeared in CMake 2.8.3.
-#
-# Used for compatibility with older versions of cmake.
-
-function(cmake_parse_arguments prefix options one_value_keywords multi_value_keywords)
- set(all_keywords ${options} ${one_value_keywords} ${multi_value_keywords})
- # Clear variables before parsing.
- foreach(arg ${one_value_keywords} ${multie_value_keywords})
- set(cpa_${arg})
- endforeach()
-
- foreach(arg ${options})
- set(cpa_${arg} FALSE)
- endforeach()
-
- set(cpa_UNPARSED_ARGUMENTS)
-
- set(current_keyword)
- # Classification for current_keyword:
- # 'ONE' or 'MULTY'.
- set(current_keyword_type)
-
- # now iterate over all arguments and fill the result variables
- foreach(arg ${ARGN})
- list(FIND all_keywords ${arg} keyword_index)
-
- if(keyword_index EQUAL -1)
- if(current_keyword)
- if(current_keyword_type STREQUAL "ONE")
- set(cpa_${current_keyword} ${arg})
- set(current_keyword)
- else(current_keyword_type STREQUAL "ONE")
- list(APPEND cpa_${current_keyword} ${arg})
- endif(current_keyword_type STREQUAL "ONE")
- else(current_keyword)
- list(APPEND cpa_UNPARSED_ARGUMENTS ${arg})
- endif(current_keyword)
- else(keyword_index EQUAL -1)
- if(current_keyword AND current_keyword_type STREQUAL "ONE")
- message(SEND_ERROR "Value is expected for one-value-keyword ${current_keyword}")
- endif(current_keyword AND current_keyword_type STREQUAL "ONE")
- list(FIND options ${arg} option_index)
- if(option_index EQUAL -1)
- set(current_keyword ${arg})
- list(FIND one_value_keywords ${arg} one_value_index)
- if(one_value_index EQUAL -1)
- set(current_keyword_type "MULTI")
- else(one_value_index EQUAL -1)
- set(current_keyword_type "ONE")
- endif(one_value_index EQUAL -1)
- else(option_index EQUAL -1)
- set(current_keyword)
- set(cpa_${arg} TRUE)
- endif(option_index EQUAL -1)
- endif(keyword_index EQUAL -1)
- endforeach(arg ${ARGN})
-
- if(current_keyword AND current_keyword_type STREQUAL "ONE")
- message(SEND_ERROR "Value is expected for one-value-keyword ${current_keyword}")
- endif(current_keyword AND current_keyword_type STREQUAL "ONE")
-
- # propagate the result variables to the caller:
- foreach(keyword ${all_keywords} UNPARSED_ARGUMENTS)
- set(${prefix}_${keyword} ${cpa_${keyword}} PARENT_SCOPE)
- endforeach(keyword ${all_keywords})
-endfunction(cmake_parse_arguments prefix options one_value_keywords multi_value_keywords)
diff --git a/cmake_targets/tools/MODULES/CMakeUserFindMySQL.cmake b/cmake_targets/tools/MODULES/CMakeUserFindMySQL.cmake
deleted file mode 100755
index 1b5de7e3ac..0000000000
--- a/cmake_targets/tools/MODULES/CMakeUserFindMySQL.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-# - Find mysqlclient
-# Find the native MySQL includes and library
-#
-# MYSQL_INCLUDE_DIR - where to find mysql.h, etc.
-# MYSQL_LIBRARIES - List of libraries when using MySQL.
-# MYSQL_FOUND - True if MySQL found.
-
-IF (MYSQL_INCLUDE_DIR)
- # Already in cache, be silent
- SET(MYSQL_FIND_QUIETLY TRUE)
-ENDIF (MYSQL_INCLUDE_DIR)
-
-FIND_PATH(MYSQL_INCLUDE_DIR mysql.h
- /usr/local/include/mysql
- /usr/include/mysql
-)
-
-SET(MYSQL_NAMES mysqlclient mysqlclient_r)
-FIND_LIBRARY(MYSQL_LIBRARY
- NAMES ${MYSQL_NAMES}
- PATHS /usr/lib /usr/local/lib
- PATH_SUFFIXES mysql
-)
-
-IF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY)
- SET(MYSQL_FOUND TRUE)
- SET( MYSQL_LIBRARIES ${MYSQL_LIBRARY} )
-ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY)
- SET(MYSQL_FOUND FALSE)
- SET( MYSQL_LIBRARIES )
-ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY)
-
-IF (MYSQL_FOUND)
- IF (NOT MYSQL_FIND_QUIETLY)
- MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARY}")
- ENDIF (NOT MYSQL_FIND_QUIETLY)
-ELSE (MYSQL_FOUND)
- IF (MYSQL_FIND_REQUIRED)
- MESSAGE(STATUS "Looked for MySQL libraries named ${MYSQL_NAMES}.")
- MESSAGE(FATAL_ERROR "Could NOT find MySQL library")
- ENDIF (MYSQL_FIND_REQUIRED)
-ENDIF (MYSQL_FOUND)
-
-MARK_AS_ADVANCED(
- MYSQL_LIBRARY
- MYSQL_INCLUDE_DIR
- )
-
diff --git a/cmake_targets/tools/MODULES/CMakeUserUseBison.cmake b/cmake_targets/tools/MODULES/CMakeUserUseBison.cmake
deleted file mode 100755
index 5295a1ba39..0000000000
--- a/cmake_targets/tools/MODULES/CMakeUserUseBison.cmake
+++ /dev/null
@@ -1,71 +0,0 @@
-# - Look for GNU Bison, the parser generator
-# Based off a news post from Andy Cedilnik at Kitware
-# Defines the following:
-# BISON_EXECUTABLE - path to the bison executable
-# BISON_FILE - parse a file with bison
-# BISON_PREFIX_OUTPUTS - Set to true to make BISON_FILE produce prefixed
-# symbols in the generated output based on filename.
-# So for ${filename}.y, you'll get ${filename}parse(), etc.
-# instead of yyparse().
-# BISON_GENERATE_DEFINES - Set to true to make BISON_FILE output the matching
-# .h file for a .c file. You want this if you're using
-# flex.
-
-IF(NOT DEFINED BISON_PREFIX_OUTPUTS)
- SET(BISON_PREFIX_OUTPUTS FALSE)
-ENDIF(NOT DEFINED BISON_PREFIX_OUTPUTS)
-
-IF(NOT DEFINED BISON_GENERATE_DEFINES)
- SET(BISON_GENERATE_DEFINES FALSE)
-ENDIF(NOT DEFINED BISON_GENERATE_DEFINES)
-
-IF(NOT BISON_EXECUTABLE)
- MESSAGE(STATUS "Looking for bison")
- FIND_PROGRAM(BISON_EXECUTABLE bison)
- IF(BISON_EXECUTABLE)
- MESSAGE(STATUS "Looking for bison -- ${BISON_EXECUTABLE}")
- ENDIF(BISON_EXECUTABLE)
-ENDIF(NOT BISON_EXECUTABLE)
-
-IF(BISON_EXECUTABLE)
- MACRO(BISON_FILE FILENAME)
- GET_FILENAME_COMPONENT(PATH "${FILENAME}" PATH)
- IF("${PATH}" STREQUAL "")
- SET(PATH_OPT "")
- ELSE("${PATH}" STREQUAL "")
- SET(PATH_OPT "/${PATH}")
- ENDIF("${PATH}" STREQUAL "")
- GET_FILENAME_COMPONENT(HEAD "${FILENAME}" NAME_WE)
- IF(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
- FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
- ENDIF(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
- IF(BISON_PREFIX_OUTPUTS)
- SET(PREFIX "${HEAD}")
- ELSE(BISON_PREFIX_OUTPUTS)
- SET(PREFIX "yy")
- ENDIF(BISON_PREFIX_OUTPUTS)
- SET(OUTFILE "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}/${HEAD}.tab.c")
- IF(BISON_GENERATE_DEFINES)
- SET(HEADER "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}/${HEAD}.tab.h")
- ADD_CUSTOM_COMMAND(
- OUTPUT "${OUTFILE}" "${HEADER}"
- COMMAND "${BISON_EXECUTABLE}"
- ARGS "--name-prefix=${PREFIX}"
- "--defines"
- "--output-file=${OUTFILE}"
- "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}"
- DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}")
- SET_SOURCE_FILES_PROPERTIES("${OUTFILE}" "${HEADER}" PROPERTIES GENERATED TRUE)
- SET_SOURCE_FILES_PROPERTIES("${HEADER}" PROPERTIES HEADER_FILE_ONLY TRUE)
- ELSE(BISON_GENERATE_DEFINES)
- ADD_CUSTOM_COMMAND(
- OUTPUT "${OUTFILE}"
- COMMAND "${BISON_EXECUTABLE}"
- ARGS "--name-prefix=${PREFIX}"
- "--output-file=${OUTFILE}"
- "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}"
- DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}")
- SET_SOURCE_FILES_PROPERTIES("${OUTFILE}" PROPERTIES GENERATED TRUE)
- ENDIF(BISON_GENERATE_DEFINES)
- ENDMACRO(BISON_FILE)
-ENDIF(BISON_EXECUTABLE)
diff --git a/cmake_targets/tools/MODULES/CMakeUserUseFlex.cmake b/cmake_targets/tools/MODULES/CMakeUserUseFlex.cmake
deleted file mode 100755
index 09a3e71e6d..0000000000
--- a/cmake_targets/tools/MODULES/CMakeUserUseFlex.cmake
+++ /dev/null
@@ -1,46 +0,0 @@
-# - Look for GNU flex, the lexer generator.
-# Defines the following:
-# FLEX_EXECUTABLE - path to the flex executable
-# FLEX_FILE - parse a file with flex
-# FLEX_PREFIX_OUTPUTS - Set to true to make FLEX_FILE produce outputs of
-# lex.${filename}.c, not lex.yy.c . Passes -P to flex.
-
-IF(NOT DEFINED FLEX_PREFIX_OUTPUTS)
- SET(FLEX_PREFIX_OUTPUTS FALSE)
-ENDIF(NOT DEFINED FLEX_PREFIX_OUTPUTS)
-
-IF(NOT FLEX_EXECUTABLE)
- MESSAGE(STATUS "Looking for flex")
- FIND_PROGRAM(FLEX_EXECUTABLE flex)
- IF(FLEX_EXECUTABLE)
- MESSAGE(STATUS "Looking for flex -- ${FLEX_EXECUTABLE}")
- ENDIF(FLEX_EXECUTABLE)
-ENDIF(NOT FLEX_EXECUTABLE)
-
-IF(FLEX_EXECUTABLE)
- MACRO(FLEX_FILE FILENAME)
- GET_FILENAME_COMPONENT(PATH "${FILENAME}" PATH)
- IF("${PATH}" STREQUAL "")
- SET(PATH_OPT "")
- ELSE("${PATH}" STREQUAL "")
- SET(PATH_OPT "/${PATH}")
- ENDIF("${PATH}" STREQUAL "")
- IF(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
- FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
- ENDIF(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}")
- IF(FLEX_PREFIX_OUTPUTS)
- GET_FILENAME_COMPONENT(PREFIX "${FILENAME}" NAME_WE)
- ELSE(FLEX_PREFIX_OUTPUTS)
- SET(PREFIX "yy")
- ENDIF(FLEX_PREFIX_OUTPUTS)
- SET(OUTFILE "${CMAKE_CURRENT_BINARY_DIR}${PATH_OPT}/lex.${PREFIX}.c")
- ADD_CUSTOM_COMMAND(
- OUTPUT "${OUTFILE}"
- COMMAND "${FLEX_EXECUTABLE}"
- ARGS "--prefix=${PREFIX}"
- "--outfile=${OUTFILE}"
- "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}"
- DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}")
- SET_SOURCE_FILES_PROPERTIES("${OUTFILE}" PROPERTIES GENERATED TRUE)
- ENDMACRO(FLEX_FILE)
-ENDIF(FLEX_EXECUTABLE)
diff --git a/cmake_targets/tools/MODULES/FindGCCXML.cmake b/cmake_targets/tools/MODULES/FindGCCXML.cmake
deleted file mode 100755
index 6a4daa084d..0000000000
--- a/cmake_targets/tools/MODULES/FindGCCXML.cmake
+++ /dev/null
@@ -1,8 +0,0 @@
-# FindGCCXML
-# ----------
-find_program(GCCXML
-NAMES gccxml
-PATHS "/usr/bin"
-"usr/local/bin"
-)
-mark_as_advanced(GCCXML)
diff --git a/cmake_targets/tools/MODULES/FindKbuild.cmake b/cmake_targets/tools/MODULES/FindKbuild.cmake
deleted file mode 100755
index 08accb8551..0000000000
--- a/cmake_targets/tools/MODULES/FindKbuild.cmake
+++ /dev/null
@@ -1,105 +0,0 @@
-# - Support for building kernel modules
-
-# This module defines several variables which may be used when build
-# kernel modules.
-#
-# The following variables are set here:
-# Kbuild_VERSION_STRING - kernel version.
-# Kbuild_ARCH - architecture.
-# Kbuild_BUILD_DIR - directory for build kernel and/or its components.
-# Kbuild_VERSION_{MAJOR|MINOR|TWEAK} - kernel version components
-# Kbuild_VERSION_STRING_CLASSIC - classic representation of version,
-# where parts are delimited by dots.
-#
-# Cache variables which affect on this package:
-# CMAKE_SYSTEM_VERSION - change Kbuild_VERSION_STRING
-# Also, setting CMAKE_SYSTEM_VERSION will be interpreted by cmake as crosscompile.
-#
-# Cache variables(ADVANCED) which affect on this package:
-# ARCH - if not empty, change Kbuild_ARCH
-# KBUILD_DIR - change Kbuild_BUILD_DIR
-
-set(Kbuild_VERSION_STRING ${CMAKE_SYSTEM_VERSION})
-
-# Form classic version view.
-string(REGEX MATCH "([0-9]+)\\.([0-9]+)[.-]([0-9]+)"
- _kernel_version_match
- "${Kbuild_VERSION_STRING}"
-)
-
-if(NOT _kernel_version_match)
- message(FATAL_ERROR "Kernel version has unexpected format: ${Kbuild_VERSION_STRING}")
-endif(NOT _kernel_version_match)
-
-set(Kbuild_VERSION_MAJOR ${CMAKE_MATCH_1})
-set(Kbuild_VERSION_MINOR ${CMAKE_MATCH_2})
-set(Kbuild_VERSION_TWEAK ${CMAKE_MATCH_3})
-# Version string for compare
-set(Kbuild_VERSION_STRING_CLASSIC "${Kbuild_VERSION_MAJOR}.${Kbuild_VERSION_MINOR}.${Kbuild_VERSION_TWEAK}")
-
-set(KBUILD_DIR "/lib/modules/${Kbuild_VERSION_STRING}/build" CACHE PATH
- "Directory for build linux kernel and/or its components."
-)
-mark_as_advanced(KBUILD_DIR)
-
-set(Kbuild_BUILD_DIR "${KBUILD_DIR}")
-
-set(ARCH "" CACHE STRING
- "Architecture for build linux kernel components for, empty string means autodetect."
-)
-mark_as_advanced(ARCH)
-
-if(NOT ARCH)
- # Autodetect arch.
- execute_process(COMMAND uname -m
- RESULT_VARIABLE uname_m_result
- OUTPUT_VARIABLE ARCH_DEFAULT
- )
- if(NOT uname_m_result EQUAL 0)
- message("'uname -m' failed:")
- message("${ARCH_DEFAULT}")
- message(FATAL_ERROR "Failed to determine system architecture.")
- endif(NOT uname_m_result EQUAL 0)
-
- string(REGEX REPLACE "\n$" "" ARCH_DEFAULT "${ARCH_DEFAULT}")
-
- # Pairs of pattern-replace for postprocess architecture string from
- # 'uname -m'.
- # Taken from ./Makefile of the kernel build.
- set(_kbuild_arch_replacers
- "i.86" "x86"
- "x86_64" "x86"
- "sun4u" "sparc64"
- "arm.*" "arm"
- "sa110" "arm"
- "s390x" "s390"
- "parisc64" "parisc"
- "ppc.*" "powerpc"
- "mips.*" "mips"
- "sh[234].*" "sh"
- "aarch64.*" "arm64"
- )
-
- set(_current_pattern)
- foreach(p ${_kbuild_arch_replacers})
- if(_current_pattern)
- string(REGEX REPLACE "${_current_pattern}" "${p}" ARCH_DEFAULT "${ARCH_DEFAULT}")
- set(_current_pattern)
- else(_current_pattern)
- set(_current_pattern "${p}")
- endif(_current_pattern)
- endforeach(p ${_kbuild_arch_replacers})
-
- set(Kbuild_ARCH "${ARCH_DEFAULT}")
-else(NOT ARCH)
- # User-provided value is used.
- set(Kbuild_ARCH "${ARCH}")
-endif(NOT ARCH)
-
-
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Kbuild
- REQUIRED_VARS Kbuild_BUILD_DIR
- VERSION_VAR KBuild_VERSION_STRING_CLASSIC
-)
diff --git a/cmake_targets/tools/MODULES/Kbuild.cmake b/cmake_targets/tools/MODULES/Kbuild.cmake
deleted file mode 100755
index 7403cd04df..0000000000
--- a/cmake_targets/tools/MODULES/Kbuild.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-src=${dir}
-obj-m += ${name}.o
-${name}-y += ${objs}
-ccflags-y += ${module_cc_opt}
diff --git a/cmake_targets/tools/MODULES/cmake_useful.cmake b/cmake_targets/tools/MODULES/cmake_useful.cmake
deleted file mode 100755
index af6bbb56c7..0000000000
--- a/cmake_targets/tools/MODULES/cmake_useful.cmake
+++ /dev/null
@@ -1,229 +0,0 @@
-# Create rule for obtain one file by copying another one
-function(rule_copy_file target_file source_file)
- add_custom_command(OUTPUT ${target_file}
- COMMAND cp -p ${source_file} ${target_file}
- DEPENDS ${source_file}
- )
-endfunction(rule_copy_file target_file source_file)
-
-# rule_copy_source([source_dir] file ...)
-#
-# Create rule for obtain file(s) in binary tree by copiing it from source tree.
-#
-# Files are given relative to ${source_dir}, if it is set, or
-# relative to ${CMAKE_CURRENT_SOURCE_DIR}.
-#
-# Files will be copied into ${CMAKE_CURRENT_BINARY_DIR} with same
-# relative paths.
-#
-# ${source_dir} should be absolute path(that is, starts from '/').
-# Otherwise first argument is treated as first file to copy.
-function(rule_copy_source file)
- string(REGEX MATCH "^/" is_abs_path ${file})
- if(is_abs_path)
- set(source_dir ${file})
- set(files ${ARGN})
- else(is_abs_path)
- set(source_dir ${CMAKE_CURRENT_SOURCE_DIR})
- set(files ${file} ${ARGN})
- endif(is_abs_path)
-
- foreach(file_real ${files})
- rule_copy_file("${CMAKE_CURRENT_BINARY_DIR}/${file_real}"
- ${source_dir}/${file_real})
- endforeach(file_real ${files})
-endfunction(rule_copy_source file)
-
-# to_abs_path(output_var path [...])
-#
-# Convert relative path of file to absolute path:
-# use path in source tree, if file already exist there.
-# otherwise use path in binary tree.
-# If initial path already absolute, return it.
-function(to_abs_path output_var)
- set(result)
- foreach(path ${ARGN})
- string(REGEX MATCH "^/" _is_abs_path ${path})
- if(_is_abs_path)
- list(APPEND result ${path})
- else(_is_abs_path)
- file(GLOB to_abs_path_file
- "${CMAKE_CURRENT_SOURCE_DIR}/${path}"
- )
- if(NOT to_abs_path_file)
- set (to_abs_path_file "${CMAKE_CURRENT_BINARY_DIR}/${path}")
- endif(NOT to_abs_path_file)
- list(APPEND result ${to_abs_path_file})
- endif(_is_abs_path)
- endforeach(path ${ARGN})
- set("${output_var}" ${result} PARENT_SCOPE)
-endfunction(to_abs_path output_var path)
-
-# is_path_inside_dir(output_var dir path)
-#
-# Set output_var to true if path is absolute path inside given directory.
-# NOTE: Path should be absolute.
-macro(is_path_inside_dir output_var dir path)
- file(RELATIVE_PATH _rel_path ${dir} ${path})
- string(REGEX MATCH "^\\.\\." _is_not_inside_dir ${_rel_path})
- if(_is_not_inside_dir)
- set(${output_var} "FALSE")
- else(_is_not_inside_dir)
- set(${output_var} "TRUE")
- endif(_is_not_inside_dir)
-endmacro(is_path_inside_dir output_var dir path)
-
-
-# Write given content to the file.
-#
-# If file is already exists and its content is same as written one, file
-# is not rewritten, so its write timestamp remains unchanged.
-function(file_update filename content)
- if(EXISTS "${filename}")
- file(READ "${filename}" old_content)
- if(old_content STREQUAL "${content}")
- return()
- endif(old_content STREQUAL "${content}")
- endif(EXISTS "${filename}")
- # File doesn't exists or its content differ.
- file(WRITE "${filename}" "${content}")
-endfunction(file_update filename content)
-
-
-# Write given content to the file in APPEND mode.
-#
-# For append we use position variable which should be initialized
-# to 0 for every new build process and which is updated every time when
-# this function is called.
-# If file is already exists and its content at given is same as
-# written one, file is not rewritten, so its write timestamp remains unchanged.
-#
-# Note, that file will not be rewritten if new build process issues less
-# APPEND actions than one which create file.
-# But similar problem exists for file_update() and even for built-in
-# configure_file() command: file will not be removed if new build process
-# do not call configure_file() for it.
-function(file_update_append filename content POS)
- set(pos "${${POS}}")
- string(LENGTH "${content}" len)
- # Update output variable first.
- # This allows to use return() when need not to do anything
- math(EXPR pos_new "${pos}+${len}")
- set(${POS} "${pos_new}" PARENT_SCOPE)
- if(EXISTS "${filename}")
- file(READ "${filename}" old_content LIMIT "${len}" OFFSET "${pos}")
- if(old_content STREQUAL "${content}")
- return()
- elseif(old_content STREQUAL "")
- file(APPEND "${filename}" "${content}")
- return()
- endif(old_content STREQUAL "${content}")
- else(EXISTS "${filename}")
- if(NOT pos EQUAL 0)
- message(FATAL_ERROR "Appending to non-zero position to non-existent file.")
- endif(NOT pos EQUAL 0)
- endif(EXISTS "${filename}")
- # File doesn't exists or its content differ.
- if(NOT pos EQUAL 0)
- file(READ "${filename}" prefix LIMIT "${pos}")
- else(NOT pos EQUAL 0)
- set(prefix)
- endif(NOT pos EQUAL 0)
- file(WRITE "${filename}" "${prefix}${content}")
-endfunction(file_update_append filename content POS)
-
-
-# Common mechanism for output status message
-# when checking different aspects.
-#
-# Normal using:
-#
-# check_begin("Checking <...>")
-# if(NOT )
-# check_try() # Here message is printed
-# # Perform check(try_compile(), etc.)
-# endif(NOT )
-# check_end("") # Here message is printed with result.
-
-# Should be called (unconditionally) when new cheking is issued.
-# Note, that given @status_msg is not printed at that step.
-function(check_begin status_msg)
- set(_check_status_msg ${status_msg} PARENT_SCOPE)
- set(_check_has_tries PARENT_SCOPE)
-endfunction(check_begin status_msg)
-
-# Should be called before every real checking, that is which is not come
-# from cache variables comparision.
-#
-# First call of that function is trigger printing of @status_msg,
-# passed to check_begin().
-function(check_try)
- if(NOT _check_has_tries)
- message(STATUS "${_check_status_msg}")
- set(_check_has_tries "1" PARENT_SCOPE)
- endif(NOT _check_has_tries)
-endfunction(check_try)
-
-# Should be called when cheking is end, and @result_msg should be short
-# description of check result.
-# If any check_try() has been issued before,
-# "@status_msg - @result_msg"
-# will be printed.
-# Otherwise,
-# "@status_msg - [cached] @result_msg"
-# will be printed, at it will be the only message for that check.
-function(check_end result_msg)
- if(NOT _check_has_tries)
- message(STATUS "${_check_status_msg} [cached] - ${result_msg}")
- else(NOT _check_has_tries)
- message(STATUS "${_check_status_msg} - ${result_msg}")
- endif(NOT _check_has_tries)
- set(_check_status_msg PARENT_SCOPE)
- set(_check_has_tries PARENT_SCOPE)
-endfunction(check_end result_msg)
-
-# set_bool_string(var true_string false_string value [CACHE ... | PARENT_SCOPE])
-#
-# Set variable to one of two string according to true property of some value.
-#
-# If 'value' is true-evaluated, 'var' will be set to 'true_string',
-# otherwise to 'var' will be set to 'false_string'.
-# Like standard set(), macro accept CACHE and PARENT_SCOPE modifiers.
-#
-# Useful for form meaningful value for cache variables, contained result
-# of some operation.
-# Also may be used for form message for check_end().
-macro(set_bool_string var true_string false_string value)
- # Macro parameters are not a variables, so them cannot be tested
- # using 'if(value)'.
- # Usage 'if(${value})' leads to warnings since 2.6.4 when ${val}
- # is boolean constant
- # (because until 2.6.4 'if(value)' always dereference val).
- # So copy 'value' to local variable for test it.
- set(_set_bool_string_value ${value})
- if(_set_bool_string_value)
- set(${var} "${true_string}" ${ARGN})
- else()
- set(${var} "${false_string}" ${ARGN})
- endif()
-endmacro(set_bool_string)
-
-# set_zero_string(var true_string false_string value [CACHE ... | PARENT_SCOPE])
-#
-# Set variable to one of two string according to zero property of some value.
-#
-# If 'value' is '0' (presizely), 'var' will be set to 'zero_string',
-# otherwise to 'var' will be set to 'nonzero_string'.
-# Like standard set(), macro accept CACHE and PARENT_SCOPE modifiers.
-#
-# Useful for form meaningful value for cache variables, contained result
-# of execute_process().
-# Also may be used for form message for check_end().
-macro(set_zero_string var zero_string nonzero_string value)
- set(_set_zero_string_value ${value})
- if(_set_zero_string_value EQUAL "0")
- set(${var} ${zero_string} ${ARGN})
- else()
- set(${var} ${nonzero_string} ${ARGN})
- endif()
-endmacro(set_zero_string)
\ No newline at end of file
diff --git a/cmake_targets/tools/MODULES/kbuild_system.cmake b/cmake_targets/tools/MODULES/kbuild_system.cmake
deleted file mode 100755
index 42a1a2d42b..0000000000
--- a/cmake_targets/tools/MODULES/kbuild_system.cmake
+++ /dev/null
@@ -1,1131 +0,0 @@
-# Provide way for create kernel modules, and perform other actions on them
-# in a way similar to standard cmake executables and libraries processing.
-#
-# NB: At the end of the whole configuration stage
-# kbuild_finalize_linking()
-# should be executed.
-#
-# Should be included after:
-# find_package(Kbuild)
-#
-# Cached variables(ADVANCED), which affects on definitions below:
-# CROSS_COMPILE - corresponded parameter for 'make' to build kernel objects.
-# KBUILD_C_FLAGS - Additional kbuild flags for all builds
-# KBUILD_C_FLAGS{DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL} - per-configuration flags.
-
-include(cmake_useful)
-
-# Compute path to the auxiliary files.
-get_filename_component(kbuild_this_module_dir ${CMAKE_CURRENT_LIST_FILE} PATH)
-set(kbuild_aux_dir "${kbuild_this_module_dir}/kbuild_system_files")
-
-# _declare_per_build_vars( )
-#
-# [INTERNAL] Per-build type definitions for given .
-#
-# Create CACHE STRING variables _{DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL}
-# with documentation string where %build% is replaced
-# with corresponded build type description.
-#
-# Default value for variable _ is taken from __INIT.
-macro(_declare_per_build_vars variable doc_pattern)
- set(_build_type)
- foreach(t
- RELEASE "release"
- DEBUG "debug"
- RELWITHDEBINFO "Release With Debug Info"
- MINSIZEREL "release minsize"
- )
- if(_build_type)
- string(REPLACE "%build%" "${t}" _docstring ${doc_pattern})
- set("${variable}_${_build_type}" "${${variable}_${_build_type}_INIT}"
- CACHE STRING "${_docstring}")
- set(_build_type)
- else(_build_type)
- set(_build_type "${t}")
- endif(_build_type)
- endforeach(t)
-endmacro(_declare_per_build_vars variable doc_pattern)
-
-
-# Default compiler flags.
-#
-# These flags are used directly when configuring 'Kbuild', so them should be
-# expressed as single-string, where different flags are joinged using ' '.
-set(KBUILD_C_FLAGS "" CACHE STRING
- "Compiler flags used by Kbuild system during all builds."
-)
-
-# Additional default compiler flags per build type.
-set(KBUILD_C_FLAGS_DEBUG_INIT "-g")
-set(KBUILD_C_FLAGS_RELWITHDEBINFO_INIT "-g")
-
-_declare_per_build_vars(KBUILD_C_FLAGS
- "Compiler flags used by Kbuild system during %build% builds."
-)
-mark_as_advanced(
- KBUILD_C_FLAGS
- KBUILD_C_FLAGS_DEBUG
- KBUILD_C_FLAGS_RELEASE
- KBUILD_C_FLAGS_RELWITHDEBINFO
- KBUILD_C_FLAGS_MINSIZEREL
-)
-
-
-# Additional definitions which are passed directly to 'make' for
-# kbuild process.
-#
-# Unlike to compiler flags, these ones are expressed using cmake list.
-set(KBUILD_MAKE_FLAGS "" CACHE STRING
- "Make flags used by Kbuild system during all builds."
-)
-
-_declare_per_build_vars(KBUILD_MAKE_FLAGS
- "Make flags used by Kbuild system during %build% builds."
-)
-
-mark_as_advanced(
- KBUILD_MAKE_FLAGS
- KBUILD_MAKE_FLAGS_DEBUG
- KBUILD_MAKE_FLAGS_RELEASE
- KBUILD_MAKE_FLAGS_RELWITHDEBINFO
- KBUILD_MAKE_FLAGS_MINSIZEREL
-)
-
-set(CROSS_COMPILE "" CACHE STRING "Cross compilation prefix for build linux kernel objects.")
-mark_as_advanced(CROSS_COMPILE)
-
-# Property prefixed with 'KMODULE_' is readonly for outer use,
-# unless explicitely noted in its description.
-
-# Property is set for every target described kernel module.
-# Concrete property's value currently has no special meaning.
-define_property(TARGET PROPERTY KMODULE_TYPE
- BRIEF_DOCS "Whether given target describes kernel module."
- FULL_DOCS "Whether given target describes kernel module."
-)
-
-# Absolute filename of .ko file which is built.
-# NOTE: Imported targets use
-# KMODULE_IMPORTED_MODULE_LOCATION
-# property instead.
-define_property(TARGET PROPERTY KMODULE_MODULE_LOCATION
- BRIEF_DOCS "Location of the built kernel module."
- FULL_DOCS "Location of the built kernel module."
-)
-
-# Name of the given module, like "ext4" or "kedr".
-define_property(TARGET PROPERTY KMODULE_MODULE_NAME
- BRIEF_DOCS "Name of the kernel module."
- FULL_DOCS "Name of the kernel module."
-)
-
-
-# Absolute filename of Module.symvers file which is built.
-# NOTE: Imported targets use
-# KMODULE_IMPORTED_SYMVERS_LOCATION
-# property instead.
-define_property(TARGET PROPERTY KMODULE_SYMVERS_LOCATION
- BRIEF_DOCS "Location of the symvers file of the kernel module."
- FULL_DOCS "Location of the symvers file of the kernel module."
-)
-
-# Property is "TRUE" for every target described imported kernel module,
-# "FALSE" for other targets described kernel module.
-define_property(TARGET PROPERTY KMODULE_IMPORTED
- BRIEF_DOCS "Whether given target describes imported kernel module."
- FULL_DOCS "Whether given target describes imported kernel module."
-)
-
-# Absolute filename of .ko file which is imported.
-# Property may be set after
-# kbuild_add_module(... IMPORTED)
-# for allow loading of given module or perform other actions required
-# kernel module itself.
-#
-# Analogue for KMODULE_MODULE_LOCATION property of normal(non-exported)
-# kernel module target.
-define_property(TARGET PROPERTY KMODULE_IMPORTED_MODULE_LOCATION
- BRIEF_DOCS "Location of the imported kernel module."
- FULL_DOCS "Location of the imported kernel module."
-)
-
-# Absolute filename of Module.symvers file for imported kernel module.
-# Property may be set after
-# kbuild_add_module(... IMPORTED)
-# for allow linking with given module or perform other actions required
-# its symbols.
-#
-# Analogue for KMODULE_MODULE_SYMVERS_LOCATION property of normal(non-exported)
-# kernel module target.
-define_property(TARGET PROPERTY KMODULE_IMPORTED_SYMVERS_LOCATION
- BRIEF_DOCS "Location of the symvers file for imported kernel module."
- FULL_DOCS "Location of the symvers file for imported kernel module."
-)
-
-# Helpers for simple extract some kernel module properties.
-
-# kbuild_get_module_location(RESULT_VAR name)
-#
-# Return location of the module, determined by the property
-# KMODULE_MODULE_LOCATION or KMODULE_IMPORTED_MODULE_LOCATION for
-# imported target. In the last case the property is checked for being set.
-function(kbuild_get_module_location RESULT_VAR name)
- if(NOT TARGET ${name})
- message(FATAL_ERROR "\"${name}\" is not really a target.")
- endif(NOT TARGET ${name})
- get_property(kmodule_type TARGET ${name} PROPERTY KMODULE_TYPE)
- if(NOT kmodule_type)
- message(FATAL_ERROR "\"${name}\" is not really a target for kernel module.")
- endif(NOT kmodule_type)
- get_property(kmodule_imported TARGET ${name} PROPERTY KMODULE_IMPORTED)
- if(kmodule_imported)
- get_property(module_location TARGET ${name} PROPERTY KMODULE_IMPORTED_MODULE_LOCATION)
- if(NOT module_location)
- message(FATAL_ERROR "target \"${name}\" for imported module has no property KMODULE_IMPORTED_MODULE_LOCATION set.")
- endif(NOT module_location)
- else(kmodule_imported)
- get_property(module_location TARGET ${name} PROPERTY KMODULE_MODULE_LOCATION)
- endif(kmodule_imported)
- set(${RESULT_VAR} ${module_location} PARENT_SCOPE)
-endfunction(kbuild_get_module_location RESULT_VAR module)
-
-# kbuild_get_symvers_location(RESULT_VAR name)
-#
-# Return location of the symvers file for the module, determined by the
-# property KMODULE_SYMVERS_LOCATION or KMODULE_IMPORTED_SYMVERS_LOCATION
-# for imported target. In the last case the property is checked for being set.
-function(kbuild_get_symvers_location RESULT_VAR name)
- if(NOT TARGET ${name})
- message(FATAL_ERROR "\"${name}\" is not really a target.")
- endif(NOT TARGET ${name})
- get_property(kmodule_type TARGET ${name} PROPERTY KMODULE_TYPE)
- if(NOT kmodule_type)
- message(FATAL_ERROR "\"${name}\" is not really a target for kernel module.")
- endif(NOT kmodule_type)
- get_property(kmodule_imported TARGET ${name} PROPERTY KMODULE_IMPORTED)
- if(kmodule_imported)
- get_property(symvers_location TARGET ${name} PROPERTY KMODULE_IMPORTED_SYMVERS_LOCATION)
- if(NOT symvers_location)
- message(FATAL_ERROR "target \"${name}\" for imported module has no property KMODULE_IMPORTED_SYMVERS_LOCATION set.")
- endif(NOT symvers_location)
- else(kmodule_imported)
- get_property(symvers_location TARGET ${name} PROPERTY KMODULE_SYMVERS_LOCATION)
- endif(kmodule_imported)
- set(${RESULT_VAR} ${symvers_location} PARENT_SCOPE)
-endfunction(kbuild_get_symvers_location RESULT_VAR module)
-
-# kbuild_add_module( [EXCLUDE_FROM_ALL] [MODULE_NAME ] [ ...])
-#
-# Build kernel module from , analogue of add_library().
-#
-# Source files are divided into two categories:
-# -Object sources
-# -Other sourses
-#
-# Object sources are those sources, which may be used in building kernel
-# module externally.
-# Follow types of object sources are supported now:
-# .c: a file with the code in C language;
-# .S: a file with the code in assembly language;
-# .o_shipped: shipped file in binary format,
-# does not require additional preprocessing.
-#
-# Other sources are treated as only prerequisite of building process.
-#
-#
-# kbuild_add_module( [MODULE_NAME ] IMPORTED)
-#
-# Create target, corresponded to the imported kernel module.
-# In that case KMODULE_IMPORTED_* properties should be set manually if needed.
-#
-# In either case, if MODULE_NAME option is given, it determine name
-# of the kernel module. Otherwise itself is used.
-function(kbuild_add_module name)
- cmake_parse_arguments(kbuild_add_module "IMPORTED;EXCLUDE_FROM_ALL" "MODULE_NAME" "" ${ARGN})
- if(kbuild_add_module_MODULE_NAME)
- set(module_name "${kbuild_add_module_MODULE_NAME}")
- else(kbuild_add_module_MODULE_NAME)
- set(module_name "${name}")
- endif(kbuild_add_module_MODULE_NAME)
-
- string(LENGTH ${module_name} module_name_len)
- if(module_name_len GREATER 55)
- # Name of the kernel module should fit into array of size (64-sizeof(unsigned long)).
- # On 64-bit systems(most restricted) this is 56.
- # Even 56 length is not good, as it is not include null character.
- # Without it, old versions of rmmod failed to unload module.
- message(SEND_ERROR "Kernel module name exceeds 55 characters: '${module_name}'")
- endif(module_name_len GREATER 55)
-
- if(kbuild_add_module_IMPORTED)
- # Creation of IMPORTED target is simple.
- add_custom_target(${name})
- set_property(TARGET ${name} PROPERTY KMODULE_TYPE "kmodule")
- set_property(TARGET ${name} PROPERTY KMODULE_IMPORTED "TRUE")
- set_property(TARGET ${name} PROPERTY KMODULE_MODULE_NAME "${module_name}")
- return()
- endif(kbuild_add_module_IMPORTED)
-
- if(kbuild_add_module_EXCLUDE_FROM_ALL)
- set(all_arg)
- else(kbuild_add_module_EXCLUDE_FROM_ALL)
- set(all_arg "ALL")
- endif(kbuild_add_module_EXCLUDE_FROM_ALL)
-
- # List of all source files, which are given.
- set(sources ${kbuild_add_module_UNPARSED_ARGUMENTS})
-
- # Sources with absolute paths
- to_abs_path(sources_abs ${sources})
- # list of files from which module building is depended
- set(depend_files)
- # Sources of "c" type, but without extension.
- # Used for clean files, and for out-of-source builds do not create
- # files in source tree.
- set(c_sources_noext_abs)
- # The sources with the code in assembly
- set(asm_sources_noext_abs)
- # Sources of "o_shipped" type, but without extension
- set(shipped_sources_noext_abs)
- # Categorize sources
- foreach(source_abs ${sources_abs})
- get_filename_component(ext ${source_abs} EXT)
- if(ext STREQUAL ".c" OR ext STREQUAL ".S" OR ext STREQUAL ".o_shipped")
- # Real sources
- # Move source into binary tree, if needed
- copy_source_to_binary_dir("${source_abs}" source_abs)
-
- get_filename_component(source_noext "${source_abs}" NAME_WE)
- get_filename_component(source_dir "${source_abs}" PATH)
- set(source_noext_abs "${source_dir}/${source_noext}")
- if(ext STREQUAL ".c")
- # c-source
- list(APPEND c_sources_noext_abs ${source_noext_abs})
- elseif(ext STREQUAL ".S")
- # asm source
- list(APPEND asm_sources_noext_abs ${source_noext_abs})
- elseif(ext STREQUAL ".o_shipped")
- # shipped-source
- list(APPEND shipped_sources_noext_abs ${source_noext_abs})
- endif(ext STREQUAL ".c")
- endif(ext STREQUAL ".c" OR ext STREQUAL ".S" OR ext STREQUAL ".o_shipped")
- # In any case, add file to depend list
- list(APPEND depend_files ${source_abs})
- endforeach(source_abs ${sources_abs})
-
- # Object sources relative to current binary dir
- # (for $(module)-y :=)
- set(obj_sources_noext_rel)
- foreach(obj_sources_noext_abs
- ${c_sources_noext_abs} ${asm_sources_noext_abs} ${shipped_sources_noext_abs})
- file(RELATIVE_PATH obj_source_noext_rel
- ${CMAKE_CURRENT_BINARY_DIR} ${obj_sources_noext_abs})
- list(APPEND obj_sources_noext_rel ${obj_source_noext_rel})
- endforeach(obj_sources_noext_abs)
-
- if(NOT obj_sources_noext_rel)
- message(FATAL_ERROR "List of object files for building kernel module ${name} is empty.")
- endif(NOT obj_sources_noext_rel)
-
- set(obj_sources_rel)
- # Detect, if build simple - source object name coincide with module name
-
- if(NOT obj_sources_noext_rel STREQUAL ${name})
- # Check, whether only one of source object names coincide with module name.
- # This situation is incorrect for kbuild system.
- list(FIND obj_sources_noext_rel ${name} is_objects_contain_name)
- if(is_objects_contain_name GREATER -1)
- message(FATAL_ERROR "Module should be built "
- "either from only one object with same name, "
- "or from objects with names different from the name of the module")
- endif(is_objects_contain_name GREATER -1)
-
- foreach(obj_source_noext_rel ${obj_sources_noext_rel})
- list(APPEND obj_sources_rel "${obj_source_noext_rel}.o")
- endforeach(obj_source_noext_rel ${obj_sources_noext_rel})
- endif(NOT obj_sources_noext_rel STREQUAL ${name})
-
- _get_directory_property_chained(ccflags KBUILD_COMPILE_DEFINITIONS " ")
- _get_directory_property_chained(include_dirs KBUILD_INCLUDE_DIRECTORIES)
-
- # Target for create module.
- add_custom_target(${name} ALL
- DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.ko"
- "${CMAKE_CURRENT_BINARY_DIR}/${_kbuild_symvers}"
- )
-
- # Create .cmd files for 'shipped' sources.
- # Gcc does not create them automatically for some reason.
- set(cmd_create_command)
- if(shipped_sources_noext_abs)
- foreach(shipped_source_noext_abs ${shipped_source_noext_abs})
- get_filename_component(shipped_dir ${shipped_source_noext_abs} PATH)
- get_filename_component(shipped_name ${shipped_source_noext_abs} NAME)
- list(APPEND cmd_create_command
- COMMAND printf "cmd_%s.o := cp -p %s.o_shipped %s.o\\n"
- "${shipped_source_noext_abs}"
- "${shipped_source_noext_abs}"
- "${shipped_source_noext_abs}"
- > "${shipped_dir}/.${shipped_name}.o.cmd")
- endforeach(shipped_source_noext_abs ${shipped_source_noext_abs})
- endif(shipped_sources_noext_abs)
-
- # User-defined parameters for 'make'
- set(make_flags ${KBUILD_MAKE_FLAGS})
- _get_per_build_var(make_flags_per_build KBUILD_MAKE_FLAGS)
- list(APPEND make_flags ${make_flags_per_build})
-
- # Rule for create module(and symvers file).
- add_custom_command(
- OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.ko"
- "${CMAKE_CURRENT_BINARY_DIR}/${_kbuild_symvers}"
- ${cmd_create_command}
- COMMAND $(MAKE) ${make_flags} ${kbuild_additional_make_flags}
- -C ${Kbuild_BUILD_DIR} M=${CMAKE_CURRENT_BINARY_DIR} modules
-# Update timestamps for targets.
-# In some cases Kbuild system may decide do not update resulted files
-# even in case when depencies newer.
-# Updating timestamps prevent command to be executed every make call.
- COMMAND touch "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.ko"
- "${CMAKE_CURRENT_BINARY_DIR}/${_kbuild_symvers}"
- DEPENDS ${depend_files}
- "${CMAKE_CURRENT_BINARY_DIR}/Kbuild"
- COMMENT "Building kernel module ${name}"
- )
-
- # Fill properties for the target.
- set_property(TARGET ${name} PROPERTY KMODULE_TYPE "kmodule")
- set_property(TARGET ${name} PROPERTY KMODULE_IMPORTED "FALSE")
- set_property(TARGET ${name} PROPERTY KMODULE_MODULE_NAME "${module_name}")
-
- set_property(TARGET ${name} PROPERTY KMODULE_MODULE_LOCATION
- "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.ko"
- )
- set_property(TARGET ${name} PROPERTY KMODULE_SYMVERS_LOCATION
- "${CMAKE_CURRENT_BINARY_DIR}/${_kbuild_symvers}"
- )
-
- # Internal properties
- set_property(TARGET ${name} PROPERTY KMODULE_BINARY_DIR
- "${CMAKE_CURRENT_BINARY_DIR}"
- )
- set_property(TARGET ${name} PROPERTY KMODULE_OBJ_SOURCES ${obj_sources_rel})
- set_property(TARGET ${name} PROPERTY KMODULE_COMPILE_FLAGS ${ccflags})
- set_property(TARGET ${name} PROPERTY KMODULE_INCLUDE_DIRECTORIES ${include_dirs})
-
-
- # Add target to the list of modules for built.
- set_property(GLOBAL APPEND PROPERTY KMODULE_TARGETS "${name}")
-
- # The rule to clean files
- _kbuild_module_clean_files(${name}
- C_SOURCE ${c_sources_noext_abs}
- ASM_SOURCE ${asm_sources_noext_abs}
- SHIPPED_SOURCE ${shipped_sources_noext_abs})
-endfunction(kbuild_add_module name)
-
-# kbuild_include_directories(dirs ...)
-#
-# Add include directories for Kbuild process.
-macro(kbuild_include_directories)
- set_property(DIRECTORY APPEND PROPERTY KBUILD_INCLUDE_DIRECTORIES ${ARGN})
-endmacro(kbuild_include_directories)
-
-# kbuild_add_definitions (flags)
-#
-# Specify additional flags for compile kernel module.
-#
-# Note that multiple flags should be specified as single string,
-# delimited with ' '.
-function(kbuild_add_definitions flags)
- get_property(current_flags DIRECTORY PROPERTY KBUILD_COMPILE_DEFINITIONS)
- _string_join(" " current_flags "${current_flags}" "${flags}")
- set_property(DIRECTORY PROPERTY KBUILD_COMPILE_DEFINITIONS "${current_flags}")
-endfunction(kbuild_add_definitions flags)
-
-# There is no control for kbuild make flags except default values.
-# Support for kbuild_add_make_definitions may be added if needed.
-
-
-# kbuild_link_module( [ ...])
-#
-# Link kernel module with other modules, that allows to use symbols from
-# other modules.
-#
-# may be:
-# 1) target name for other kernel module intended for build
-# 2) target name for imported kernel module with
-# KMODULE_IMPORTED_SYMVERS_LOCATION property set
-# 3) absolute path to symvers file of other kernel module.
-#
-# In any case, file-level dependency will be created for symvers file to link with.
-# In the first case, also target-level dependency will be added
-#
-# Analogue for target_link_library().
-#
-# May be used only from the same directory, where module target is created.
-function(kbuild_link_module name)
- # Check that @name corresponds to kernel module target for build.
- get_property(is_module TARGET ${name} PROPERTY KMODULE_TYPE SET)
- if(NOT is_module)
- message(FATAL_ERROR "kbuild_module_link: passed \n\t\"${name}\"\n which is not kernel module target.")
- endif(NOT is_module)
- get_property(module_imported TARGET ${name} PROPERTY KMODULE_IMPORTED)
- if(kmodule_imported)
- message(FATAL_ERROR "Imported kernel module target \"${name}\" may not be linked.")
- endif(kmodule_imported)
-
- get_property(module_name TARGET ${name} PROPERTY KMODULE_MODULE_NAME)
-
- foreach(l ${ARGN})
- string(REGEX MATCH "/" link_is_file ${l})
- if(link_is_file)
- string(REGEX MATCH "^/" file_is_absolute ${l})
- if(NOT file_is_absolute)
- message(FATAL_ERROR "kbuild_module_link: passed filename\n\t\"${link}\"\nwhich is not absolute as .")
- endif(NOT file_is_absolute)
- set(symvers_location "${l}")
- # Do not require symvers file to be already existed.
- else(link_is_file)
- if(NOT TARGET ${l})
- message(FATAL_ERROR "kbuild_module_link: passed link\n\t\"${l}\"\n which is neither an absolute path to symvers file nor a target.")
- endif(NOT TARGET ${l})
- get_property(kmodule_type TARGET ${l} PROPERTY KMODULE_TYPE)
- if(NOT kmodule_type)
- message(FATAL_ERROR "kbuild_module_link: passed target\n\t\"${l}\"\n which is not a target for kernel module as link.")
- endif(NOT kmodule_type)
- get_property(kmodule_imported TARGET ${l} PROPERTY KMODULE_IMPORTED)
- if(kmodule_imported)
- get_property(symvers_location TARGET ${l} PROPERTY KMODULE_IMPORTED_SYMVERS_LOCATION)
- if(NOT symvers_location)
- message(FATAL_ERROR "kbuild_module_link: passed imported target\n\t\"${l}\"\n without \"KMODULE_IMPORTED_SYMVERS_LOCATION\" property set as link.")
- endif(NOT symvers_location)
- else(kmodule_imported)
- get_property(symvers_location TARGET ${l} PROPERTY KMODULE_SYMVERS_LOCATION)
- # Target dependency is added only for non-imported target.
- add_dependencies(${name} ${l})
- endif(kmodule_imported)
- endif(link_is_file)
- add_custom_command(OUTPUT
- "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.ko"
- "${CMAKE_CURRENT_BINARY_DIR}/${_kbuild_symvers}"
- DEPENDS ${symvers_location}
- APPEND
- )
- set_property(TARGET ${name} APPEND PROPERTY KMODULE_DEPEND_SYMVERS ${symvers_location})
- endforeach(l ${ARGN})
-endfunction(kbuild_link_module name)
-
-# kbuild_finalize_linking()
-#
-# Should be called after all kernel modules and their links defined.
-# Usually this is the end of main CMakeLists.txt file.
-function(kbuild_finalize_linking)
- _get_per_build_var(ccflags_per_build KBUILD_C_FLAGS)
-
- get_property(kmodule_targets GLOBAL PROPERTY KMODULE_TARGETS)
- foreach(m ${kmodule_targets})
- get_property(module_binary_dir TARGET ${m} PROPERTY KMODULE_BINARY_DIR)
- get_property(module_name TARGET ${m} PROPERTY KMODULE_MODULE_NAME)
- get_property(module_symvers_cmake TARGET ${m} PROPERTY KMODULE_DEPEND_SYMVERS)
-
- get_property(obj_sources TARGET ${m} PROPERTY KMODULE_OBJ_SOURCES)
- get_property(ccflags_local TARGET ${m} PROPERTY KMODULE_COMPILE_FLAGS)
- get_property(include_dirs TARGET ${m} PROPERTY KMODULE_INCLUDE_DIRECTORIES)
-
- # Combine all compiler flags together
- _string_join(" " ccflags "${KBUILD_C_FLAGS}" "${ccflags_local}")
- foreach(dir ${include_dirs})
- _string_join(" " ccflags "${ccflags}" "-I${dir}")
- endforeach(dir ${include_dirs})
- _string_join(" " ccflags "${ccflags}" "${ccflags_per_build}")
-
- string(REPLACE ";" " " module_symvers "${module_symvers_cmake}")
-
- if(obj_sources)
- set(obj_src_string "${module_name}-y := ")
- foreach(obj ${obj_sources})
- set(obj_src_string "${obj_src_string} ${obj}")
- endforeach(obj ${obj_sources})
- else(obj_sources)
- # Simple building process - module name is same as the name
- # of the only source.
- set(obj_src_string "")
- endif(obj_sources)
- # Configure kbuild file
- configure_file(${kbuild_this_module_dir}/kbuild_system_files/Kbuild.in
- ${module_binary_dir}/Kbuild
- )
- endforeach(m ${kmodule_targets})
-endfunction(kbuild_finalize_linking)
-
-# kbuild_install(TARGETS ...
-# [[MODULE|SYMVERS]
-# DESTINATION
-# [CONFIGURATIONS [...]]
-# [COMPONENT ]
-# ]+)
-#
-# Install kernel module(s) and/or symvers file(s) into given directory.
-#
-# Almost all options means same as for install() cmake command.
-# 'MODULE' refers to kernel module itself, SYMVERS refers symvers file.
-#
-# Unlike to standard install() command, there is no default destination
-# directory neither for modules nor for symvers files.
-# So, at least one rule should be defined, and 'DESTINATION' option
-# should be set for every rule.
-#
-# TODO: support for 'EXPORT' mode.
-function(kbuild_install type)
- if(NOT type STREQUAL "TARGETS")
- message(FATAL_ERROR "Only 'TARGETS' mode is currently supported")
- endif(NOT type STREQUAL "TARGETS")
-
- parse_install_arguments(kbuild_install
- "MODULE;SYMVERS" # Section types
- "" "DESTINATION;COMPONENT" "CONFIGURATIONS" # Section keywords classification.
- ${ARGN}
- )
-
- set(kbuild_install_TARGETS ${kbuild_install_GLOBAL_ARGUMENTS})
- if(NOT kbuild_install_TARGETS)
- message(FATAL_ERROR "No targets given for kbuild_install() command")
- endif(NOT kbuild_install_TARGETS)
-
- if(NOT kbuild_install_sections)
- message(FATAL_ERROR "There is no default destination for install kernel module components, but no section described it is given.")
- endif(NOT kbuild_install_sections)
-
- foreach(section_type ${kbuild_install_sections})
- if(NOT kbuild_install_${section_type}_DESTINATION)
- message(FATAL_ERROR "DESTINATION is not defined for section ${section_type}")
- endif(NOT kbuild_install_${section_type}_DESTINATION)
- # All additional arguments for given section.
- set(install_args_${section_type}
- DESTINATION "${kbuild_install_${section_type}_DESTINATION}")
- if(kbuild_install_${section_type}_CONFIGURATION)
- list(APPEND install_args_${section_type}
- CONFIGURATION "${kbuild_install_${section_type}_CONFIGURATION}"
- )
- endif(kbuild_install_${section_type}_CONFIGURATION)
- if(kbuild_install_${section_type}_COMPONENT)
- list(APPEND install_args_${section_type}
- COMPONENT "${kbuild_install_${section_type}_COMPONENT}"
- )
- endif(kbuild_install_${section_type}_COMPONENT)
- # Module installation.
- if(section_type STREQUAL "MODULE" OR section_type STREQUAL "ALL")
- # Combine locations for all modules in one list.
- set(module_locations)
- foreach(t ${kbuild_install_TARGETS})
- kbuild_get_module_location(module_location ${t})
- list(APPEND module_locations ${module_location})
- endforeach(t ${kbuild_install_TARGETS})
- # .. and install them at once.
- install(FILES ${module_locations} ${install_args_${section_type}})
- endif(section_type STREQUAL "MODULE" OR section_type STREQUAL "ALL")
- # Symvers installation.
- if(section_type STREQUAL "SYMVERS" OR section_type STREQUAL "ALL")
- # Because of renaming, symvers files should be installed separately.
- foreach(t ${kbuild_install_TARGETS})
- kbuild_get_symvers_location(symvers_location ${t})
- get_property(module_name TARGET ${t} PROPERTY KMODULE_MODULE_NAME)
- install(FILES ${symvers_location}
- RENAME "${module_name}.symvers"
- ${install_args_${section_type}}
- )
- endforeach(t ${kbuild_install_TARGETS})
- endif(section_type STREQUAL "SYMVERS" OR section_type STREQUAL "ALL")
- endforeach(section_type ${kbuild_install_sections})
-endfunction(kbuild_install type)
-
-
-# kbuild_try_compile(RESULT_VAR bindir srcfile|SOURCES src ...
-# [CMAKE_FLAGS ]
-# [KBUILD_COMPILE_DEFINITIONS flags ...]
-# [OUTPUT_VARIABLE var])
-#
-# Similar to try_module in simplified form, but compile srcfile as
-# kernel module, instead of user space program.
-#
-# KBUILD_COMPILE_DEFINITIONS contains compiler definition flags for
-# build kernel module.
-#
-# Possible CMAKE_FLAGS which has special semantic:
-# KBUILD_INCLUDE_DIRECTORIES - include directories for build kernel module
-# KBUILD_LINK_MODULE - symvers file(s) for link module with other modules.
-function(kbuild_try_compile RESULT_VAR bindir srcfile)
- cmake_parse_arguments(kbuild_try_compile "" "OUTPUT_VARIABLE" "CMAKE_FLAGS;KBUILD_COMPILE_DEFINITIONS" ${ARGN})
- if(srcfile STREQUAL "SOURCES")
- set(srcfiles ${kbuild_try_compile_UNPARSED_ARGUMENTS})
- else(srcfile STREQUAL "SOURCES")
- set(srcfiles ${srcfile})
- endif(srcfile STREQUAL "SOURCES")
-
- # Inside try_compile project values of variables
- # CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR
- # differs from ones in current project.
- #
- # So make all paths absolute before pass them into try_compile project.
- # Note, that copiing files into binary dir is nevertheless performed
- # in the try_compile project, because it bases on real current binary dir.
- to_abs_path(srcfiles_abs ${srcfiles})
-
- # Collect parameters to try_compile() function
- set(cmake_flags
- "-DSOURCES:STRING=${srcfiles_abs}" # Source file(s)
- "-DCMAKE_MODULE_PATH:PATH=${CMAKE_MODULE_PATH}" # Path for search include files.
- ${kbuild_try_compile_CMAKE_FLAGS}
- )
-
- # Parameters for compiler
- if(kbuild_try_compile_KBUILD_COMPILE_DEFINITIONS)
- list(APPEND cmake_flags
- "-DKBUILD_COMPILE_DEFINITIONS:STRING=${kbuild_try_compile_KBUILD_COMPILE_DEFINITIONS}"
- )
- endif(kbuild_try_compile_KBUILD_COMPILE_DEFINITIONS)
-
- # Other user-defined cmake flags
- if(kbuild_try_compile_CMAKE_FLAGS)
-
- endif(kbuild_try_compile_CMAKE_FLAGS)
-
- # Possible definition of output variable.
- if(kbuild_try_compile_OUTPUT_VARIABLE)
- set(output_variable_def "OUTPUT_VARIABLE" "output_tmp")
- else(build_try_compile_OUTPUT_VARIABLE)
- set(output_variable_def)
- endif(kbuild_try_compile_OUTPUT_VARIABLE)
-
-
- try_compile(result_tmp # Result variable(temporary)
- "${bindir}" # Binary directory
- "${kbuild_aux_dir}/try_compile_project" # Source directory
- "kmodule" # Project name
- CMAKE_FLAGS # Flags to CMake:
- ${cmake_flags}
- ${kbuild_try_compile_flags}
- ${output_variable_def}
- )
-
- if(kbuild_try_compile_OUTPUT_VARIABLE)
- # Set output variable for the caller
- set("${kbuild_try_compile_OUTPUT_VARIABLE}" "${output_tmp}" PARENT_SCOPE)
- endif(kbuild_try_compile_OUTPUT_VARIABLE)
- # Set result variable for the caller
- set("${RESULT_VAR}" "${result_tmp}" PARENT_SCOPE)
-endfunction(kbuild_try_compile RESULT_VAR bindir srcfile)
-
-########### Auxiliary functions for internal use #######################
-# Per-directory tracking for kbuild compiler flags.
-#
-# Unlike to standard COMPILE_FLAGS, these flags do not include values
-# set for parent directories.
-# (There is no generic "fill-with-parent's values" mechanism exists
-# in cmake).
-#
-# So, this property has a little sence for the user.
-# It exists only for make effect of kbuild_add_definitions() to
-# cross "function" scope.
-define_property(DIRECTORY PROPERTY KBUILD_COMPILE_FLAGS
- BRIEF_DOCS "Compiler flags used by Kbuild system added in this directory."
- FULL_DOCS "Compiler flags used by Kbuild system added in this directory."
-)
-
-# Per-directory tracking for kbuild include directories.
-#
-# Unlike to standard INCLUDE_DIRECTORIES, these ones do not include values
-# set for parent directories.
-# (There is no generic "fill-with-parent's values" mechanism exists
-# in cmake).
-#
-# So, this property has a little sence for the user.
-# It exists only for make effect of kbuild_include_directories() to
-# cross "function" scope.
-define_property(DIRECTORY PROPERTY KBUILD_INCLUDE_DIRECTORIES
- BRIEF_DOCS "Include directories used by Kbuild system; added in this directory."
- FULL_DOCS "Include directories used by Kbuild system; added in this directory."
-)
-
-
-# Parameters below are set externally only in try_compile() for subproject,
-# which include this file.
-# No need to cache them as try_compile() project is not configured by the user.
-
-# Real top-level source directory.
-if(NOT KBUILD_REAL_SOURCE_DIR)
- set(KBUILD_REAL_SOURCE_DIR ${CMAKE_SOURCE_DIR})
-endif(NOT KBUILD_REAL_SOURCE_DIR)
-# Real top-level binary directory.
-if(NOT KBUILD_REAL_BINARY_DIR)
- set(KBUILD_REAL_BINARY_DIR ${CMAKE_BINARY_DIR})
-endif(NOT KBUILD_REAL_BINARY_DIR)
-
-# These flags are passed to the 'make' when compile kernel module.
-set(kbuild_additional_make_flags)
-# These CMake flags will be passed to try_compile() subproject.
-set(kbuild_try_compile_flags
- "-DKBUILD_REAL_SOURCE_DIR=${KBUILD_REAL_SOURCE_DIR}"
- "-DKBUILD_REAL_BINARY_DIR=${KBUILD_REAL_BINARY_DIR}"
-)
-
-# ARCH and CROSS_COMPILE are passed to submake only when non-empty.
-if(ARCH)
- list(APPEND kbuild_additional_make_flags "ARCH=${ARCH}")
- list(APPEND kbuild_try_compile_flags "-DARCH=${ARCH}")
-endif(ARCH)
-if(CROSS_COMPILE)
- list(APPEND kbuild_additional_make_flags "CROSS_COMPILE=${CROSS_COMPILE}")
- list(APPEND kbuild_try_compile_flags "-DCROSS_COMPILE=${CROSS_COMPILE}")
-endif(CROSS_COMPILE)
-
-# List of targets created with kmodule_add_module() without
-# 'IMPORTED' option.
-#
-# This list is traversed in kmodule_finalize_linking() for
-# create 'Kbuild' files.
-#
-# Note, that this list does not contain all defined kernel modules,
-# so property normally shouldn't be used by outer code.
-define_property(GLOBAL PROPERTY KMODULE_TARGETS
- BRIEF_DOCS "List of kernel module targets configured for build"
- FULL_DOCS "List of kernel module targets configured for build"
-)
-
-# CMAKE_CURRENT_BINARY_DIR at the moment, when kbuild_add_module() is issued.
-define_property(TARGET PROPERTY KMODULE_BINARY_DIR
- BRIEF_DOCS "CMAKE_CURRENT_BINARY_DIR where module is built."
- FULL_DOCS "CMAKE_CURRENT_BINARY_DIR where module is built."
-)
-
-# List of object files, used for build kernel module.
-#
-# List may be empty in case of simple build, when target module has same
-# name as its only source.
-#
-# This is internal property for configure 'Kbuild' file.
-define_property(TARGET PROPERTY KMODULE_OBJ_SOURCES
- BRIEF_DOCS "Object source files for build kernel module."
- FULL_DOCS "Object source files for build kernel module."
-)
-
-# Compiler flags, added with kbuild_add_definitions()
-#
-# Note, that KBUILD_C_FLAGS* are not included here.
-#
-# This is internal property for configure 'Kbuild' file.
-define_property(TARGET PROPERTY KMODULE_COMPILE_FLAGS
- BRIEF_DOCS "Additional compile flags for build kernel module."
- FULL_DOCS "Additional compile flags for build kernel module."
-)
-
-# Include directories, added with kbuild_include_directories().
-#
-# This is internal property for configure 'Kbuild' file.
-define_property(TARGET PROPERTY KMODULE_COMPILE_FLAGS
- BRIEF_DOCS "Additional compile flags for build kernel module."
- FULL_DOCS "Additional compile flags for build kernel module."
-)
-
-
-# List of symvers files, added by kbuild_link_module().
-#
-# This is internal property for configure 'Kbuild' file.
-define_property(TARGET PROPERTY KMODULE_DEPEND_SYMVERS
- BRIEF_DOCS "Symvers files this module depends on."
- FULL_DOCS "Symvers files this module depends on."
-)
-
-# Constants for internal filenames.
-set(_kbuild_symvers "Module.symvers")
-
-# copy_source_to_binary_dir( )
-#
-# Helper for the building kernel module.
-#
-# Make sure that given source file is inside current binary dir.
-# That place is writable and has some "uniqeness" garantee for generate
-# auxiliary files during build process.
-#
-# If already inside current binary dir, do nothing and
-# set variable to itself.
-#
-# Otherwise create rule for copy source into "nice" place inside
-# current binary dir and set pointed to that place.
-function(copy_source_to_binary_dir source new_source_var)
- is_path_inside_dir(is_in_current_binary ${CMAKE_CURRENT_BINARY_DIR} "${source}")
- if(is_in_current_binary)
- # Source is already placed where we want.
- set(${new_source_var} "${source}" PARENT_SCOPE)
- else(is_in_current_binary)
- # Base directory from which count relative source path.
- # By default, it is root directory.
- set(base_dir "/")
- # Try "nicer" base directories.
- foreach(d
- ${KBUILD_REAL_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${KBUILD_REAL_SOURCE_DIR}
- )
- is_path_inside_dir(is_in_d ${d} "${source}")
- if(is_in_d)
- set(base_dir ${d})
- break()
- endif(is_in_d)
- endforeach(d)
- # Copy source into same relativ dir, but inside current binary one.
- file(RELATIVE_PATH source_rel "${base_dir}" "${source}")
- set(new_source "${CMAKE_CURRENT_BINARY_DIR}/${source_rel}")
- get_filename_component(new_source_dir ${new_source} PATH)
- file(MAKE_DIRECTORY "${new_source_dir}")
- rule_copy_file("${new_source}" "${source}")
- # Return path to the new source.
- set(${new_source_var} "${new_source}" PARENT_SCOPE)
- endif(is_in_current_binary)
-endfunction(copy_source_to_binary_dir source new_source_var)
-
-# _get_per_build_var(RESULT_VAR variable)
-#
-# Return value of per-build variable.
-macro(_get_per_build_var RESULT_VAR variable)
- if(CMAKE_BUILD_TYPE)
- string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type_uppercase)
- set(${RESULT_VAR} "${${variable}_${_build_type_uppercase}}")
- else(CMAKE_BUILD_TYPE)
- set(${RESULT_VAR})
- endif(CMAKE_BUILD_TYPE)
-endmacro(_get_per_build_var RESULT_VAR variable)
-
-# _string_join(sep RESULT_VAR str1 str2)
-#
-# Join strings and using as glue.
-#
-# Note, that precisely 2 string are joined, not a list of strings.
-# This prevents automatic replacing of ';' inside strings while parsing arguments.
-macro(_string_join sep RESULT_VAR str1 str2)
- if("${str1}" STREQUAL "")
- set("${RESULT_VAR}" "${str2}")
- elseif("${str2}" STREQUAL "")
- set("${RESULT_VAR}" "${str1}")
- else("${str1}" STREQUAL "")
- set("${RESULT_VAR}" "${str1}${sep}${str2}")
- endif("${str1}" STREQUAL "")
-endmacro(_string_join sep RESULT_VAR str1 str2)
-# _build_get_directory_property_chained(RESULT_VAR [])
-#
-# Return list of all values for given property in the current directory
-# and all parent directories.
-#
-# If is given, it is used as glue for join values.
-# By default, cmake list separator (';') is used.
-function(_get_directory_property_chained RESULT_VAR property_name)
- set(sep ";")
- foreach(arg ${ARGN})
- set(sep "${arg}")
- endforeach(arg ${ARGN})
- set(result "")
- set(d "${CMAKE_CURRENT_SOURCE_DIR}")
- while(NOT "${d}" STREQUAL "")
- get_property(p DIRECTORY "${d}" PROPERTY "${property_name}")
- # debug
- # message("Property ${property_name} for directory ${d}: '${p}'")
- _string_join("${sep}" result "${p}" "${result}")
- # message("Intermediate result: '${result}'")
- get_property(d DIRECTORY "${d}" PROPERTY PARENT_DIRECTORY)
- endwhile(NOT "${d}" STREQUAL "")
- set("${RESULT_VAR}" "${result}" PARENT_SCOPE)
-endfunction(_get_directory_property_chained RESULT_VAR property_name)
-
-# _kbuild_module_clean_files(module_name
-# [C_SOURCE c_source_noext_abs ...]
-# [ASM_SOURCE asm_source_noext_abs ...]
-# [SHIPPED_SOURCE shipped_source_noext_abs ...])
-#
-# Tell CMake that intermediate files, created by kbuild system,
-# should be cleaned with 'make clean'.
-function(_kbuild_module_clean_files module_name)
- cmake_parse_arguments(kbuild_module_clean "" "" "C_SOURCE;ASM_SOURCE;SHIPPED_SOURCE" ${ARGN})
- if(kbuild_module_clean_UNPARSED_ARGUMENTS)
- message(FATAL_ERROR "Unparsed arguments")
- endif(kbuild_module_clean_UNPARSED_ARGUMENTS)
-
- # List common files (names only) for cleaning
- set(common_files_names
- ".tmp_versions" # Directory
- "modules.order"
- "Module.markers"
- )
- # List module name-depending files (extensions only) for cleaning
- set(name_files_ext
- ".o"
- ".mod.c"
- ".mod.o"
- )
- # Same but for the files with names starting with a dot ('.').
- set(name_files_dot_ext
- ".ko.cmd"
- ".mod.o.cmd"
- ".o.cmd"
- )
- # List source name-depending files (extensions only) for cleaning
- set(source_name_files_ext
- ".o"
- )
- # Same but for the files with names starting with a dot ('.')
- set(source_name_files_dot_ext
- ".o.cmd"
- ".o.d" # This file is created in case of unsuccessfull build
- )
-
- # Now collect all sort of files into list
- set(files_list)
-
- foreach(name ${common_files_names})
- list(APPEND files_list "${CMAKE_CURRENT_BINARY_DIR}/${name}")
- endforeach(name ${common_files_names})
-
- foreach(ext ${name_files_ext})
- list(APPEND files_list
- "${CMAKE_CURRENT_BINARY_DIR}/${module_name}${ext}")
- endforeach(ext ${name_files_ext})
-
- foreach(ext ${name_files_dot_ext})
- list(APPEND files_list
- "${CMAKE_CURRENT_BINARY_DIR}/.${module_name}${ext}")
- endforeach(ext ${name_files_ext})
-
- # All the types of sources are processed in a similar way
- foreach(obj_source_noext_abs ${kbuild_module_clean_C_SOURCE}
- ${kbuild_module_clean_ASM_SOURCE} ${kbuild_module_clean_SHIPPED_SOURCE})
-
- get_filename_component(dir ${obj_source_noext_abs} PATH)
- get_filename_component(name ${obj_source_noext_abs} NAME)
- foreach(ext ${source_name_files_ext})
- list(APPEND files_list "${dir}/${name}${ext}")
- endforeach(ext ${source_name_files_ext})
- foreach(ext ${source_name_files_dot_ext})
- list(APPEND files_list "${dir}/.${name}${ext}")
- endforeach(ext ${source_name_files_ext})
- endforeach(obj_source_noext_abs)
- # Tell CMake that given files should be cleaned.
- set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${files_list}")
-endfunction(_kbuild_module_clean_files module_name)
-
-# parse_install_arguments(prefix args..)
-#
-# Helper for parse arguments for install-like command.
-#
-# All arguments before the first keyword are classified as GLOBAL_ARGUMENTS
-# and stored into list ${prefix}_GLOBAL_ARGUMENTS.
-#
-# describe possible keywords denoting section type.
-# At most one section may exist for every type.
-# Special type ALL means generic section.
-#
-# , and describe
-# all keywords inside section.
-# Values corresponded to these keywords are stored under
-# __*.
-# Note, that unlike to cmake_parse_arguments(), all arguments inside
-# section definition should be either keyword or its value(s).
-# Additionally, _ is set to TRUE for every
-# encountered section and _sections contains list of such sections.
-#
-# If non section is currently active, the first section keyword starts
-# special generic section. Definitions for this section are stored as
-# for section of type ALL.
-# If such section exists, it should be the only section.
-#
-# Function is generic, but currently is used only there.
-function(parse_install_arguments prefix section_types options one_value_keywords multiple_value_keywords)
- set(all_keywords ${section_types} ${options} ${one_value_keywords} ${multiple_value_keywords})
- # Type of the currently parsed section('ALL' for ALL section).
- set(current_section_type)
- # Active section-related keyword for current section.
- set(current_section_keyword)
- # Classification for @_current_section_keyword:
- # 'OPTION', 'ONE' or 'MULTY'.
- set(current_section_keyword_type)
-
- # Clean all previous keyword values.
- set("pia_GLOBAL_ARGUMENTS")
- foreach(section_type "ALL" ${section_types})
- set(pia_${section_type} "FALSE")
- foreach(opt ${options})
- set("pia_${section_type}_${opt}" "FALSE")
- endforeach(opt ${options})
- foreach(keyword ${one_value_keywords} ${multiple_value_keywords})
- set("pia_${section_type}_${keyword}")
- endforeach(keyword ${one_value_keywords} ${multiple_value_keywords})
- endforeach(section_type "ALL" ${section_types})
- set("pia_sections")
-
- foreach(arg ${ARGN})
- list(FIND all_keywords ${arg} keyword_index)
- if(keyword_index EQUAL "-1")
- if(current_section_type)
- if(NOT current_section_keyword)
- message(FATAL_ERROR "In section ${current_section_type} argument ${arg} does not belong to any keyword.")
- endif(NOT current_section_keyword)
- if(current_section_keyword_type STREQUAL "ONE")
- set("pia_${current_section_type}_${current_section_keyword}" "${arg}")
- set(current_section_keyword "")
- else(current_section_keyword_type STREQUAL "ONE")
- list(APPEND "pia_${current_section_type}_${current_section_keyword}" "${arg}")
- endif(current_section_keyword_type STREQUAL "ONE")
- else(current_section_type)
- list(APPEND "pia_GLOBAL_ARGUMENTS" "${arg}")
- endif(current_section_type)
- else(keyword_index EQUAL "-1")
- if(current_section_type AND current_section_keyword AND current_section_keyword_type STREQUAL "ONE")
- message(FATAL_ERROR "Keyword ${arg} found while value for one-value-option ${current_section_keyword} expected.")
- endif(current_section_type AND current_section_keyword AND current_section_keyword_type STREQUAL "ONE")
- list(FIND section_types "${arg}" section_type_index)
- if(section_type_index EQUAL "-1")
- if(NOT current_section_type)
- set(current_section_type "ALL")
- set("pia_${current_section_type}" "TRUE")
- list(APPEND "pia_sections" "${current_section_type}")
- endif(NOT current_section_type)
- list(FIND options ${arg} option_index)
- if(option_index EQUAL "-1")
- set(current_section_keyword ${arg})
- list(FIND one_value_keywords ${current_section_keyword} one_index)
- if(one_index EQUAL "-1")
- set(current_section_keyword_type "MULTY")
- else(one_index EQUAL "-1")
- set(current_section_keyword_type "ONE")
- endif(one_index EQUAL "-1")
- set("pia_${current_section_type}_${current_section_keyword}")
- else(option_index EQUAL "-1")
- set("${prefix}_${current_section_type}_${current_section_keyword}" "TRUE")
- set(current_section_keyword_type)
- endif(option_index EQUAL "-1")
- else(section_type_index EQUAL "-1")
- if("pia_ALL")
- message(FATAL_ERROR "Generic section should be the only section defined")
- endif("pia_ALL")
- set(current_section_type "${arg}")
- if("pia_${current_section_type}")
- message(FATAL_ERROR "Section ${current_section_type} is defined twice.")
- endif("pia_${current_section_type}")
- set("pia_${current_section_type}" "TRUE")
- list(APPEND "pia_sections" "${current_section_type}")
- # Current keyword is initially undefined for such section.
- set(current_section_keyword)
- endif(section_type_index EQUAL "-1")
- endif(keyword_index EQUAL "-1")
- endforeach(arg ${ARGN})
-
- # propagate the result variables to the caller
- set("${prefix}_GLOBAL_ARGUMENTS" ${pia_GLOBAL_ARGUMENTS} PARENT_SCOPE)
- foreach(section_type "ALL" ${section_types})
- set(${prefix}_${section_type} ${pia_${section_type}} PARENT_SCOPE)
- foreach(keyword ${options} ${one_value_keywords} ${multiple_value_keywords})
- set("${prefix}_${section_type}_${keyword}" ${pia_${section_type}_${keyword}} PARENT_SCOPE)
- endforeach(keyword ${options} ${one_value_keywords} ${multiple_value_keywords})
- endforeach(section_type "ALL" ${section_types})
- set("${prefix}_sections" ${pia_sections} PARENT_SCOPE)
-endfunction(parse_install_arguments prefix section_types options one_value_keywords multiple_value_keywords)
diff --git a/cmake_targets/tools/MODULES/kmodule.cmake b/cmake_targets/tools/MODULES/kmodule.cmake
deleted file mode 100755
index 2912ac115a..0000000000
--- a/cmake_targets/tools/MODULES/kmodule.cmake
+++ /dev/null
@@ -1,539 +0,0 @@
-set(kmodule_this_module_dir "${CMAKE_SOURCE_DIR}/cmake/modules/")
-set(kmodule_test_sources_dir "${CMAKE_SOURCE_DIR}/cmake/kmodule_sources")
-
-set(kmodule_function_map_file "")
-if (CMAKE_CROSSCOMPILING)
- if (KEDR_SYSTEM_MAP_FILE)
- set (kmodule_function_map_file "${KEDR_SYSTEM_MAP_FILE}")
- else (KEDR_SYSTEM_MAP_FILE)
-# KEDR_SYSTEM_MAP_FILE is not specified, construct the default path
-# to the symbol map file.
- set (kmodule_function_map_file
- "${KEDR_ROOT_DIR}/boot/System.map-${KBUILD_VERSION_STRING}"
- )
- endif (KEDR_SYSTEM_MAP_FILE)
-endif (CMAKE_CROSSCOMPILING)
-
-# List of unreliable functions, that is, the functions that may be
-# be exported and mentioned in System.map but still cannot be used
-# because no header provides their declarations.
-set(unreliable_functions_list
- "__kmalloc_node"
- "kmem_cache_alloc_node"
- "kmem_cache_alloc_node_notrace"
- "kmem_cache_alloc_node_trace"
-)
-
-# kmodule_is_function_exist(function_name RESULT_VAR)
-# Verify, whether given function exist in the kernel space on the current system.
-# RESULT_VAR is TRUE, if function_name exist in the kernel space, FALSE otherwise.
-# RESULT_VAR is cached.
-
-function(kmodule_is_function_exist function_name RESULT_VAR)
- check_begin("Looking for ${function_name} in the kernel")
- if(NOT DEFINED ${RESULT_VAR})
- check_try()
- execute_process(
- COMMAND sh "${kmodule_this_module_dir}/kmodule_files/scripts/lookup_kernel_function.sh"
- ${function_name} ${kmodule_function_map_file}
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
- RESULT_VARIABLE kmodule_is_function_exist_result
- OUTPUT_QUIET)
-
- if (kmodule_is_function_exist_result EQUAL 0)
- list(FIND unreliable_functions_list ${function_name} unreliable_function_index)
- if(unreliable_function_index GREATER -1)
- # Additional verification for unreliable function
- kbuild_try_compile(kmodule_function_is_exist_reliable
- "${CMAKE_BINARY_DIR}/check_unreliable_functions/${function_name}"
- "${kmodule_test_sources_dir}/check_unreliable_functions/${function_name}.c"
- )
- if(NOT kmodule_function_is_exist_reliable)
- set(kmodule_is_function_exist_result 1)
- endif(NOT kmodule_function_is_exist_reliable)
- endif(unreliable_function_index GREATER -1)
- endif(kmodule_is_function_exist_result EQUAL 0)
-
- if (kmodule_is_function_exist_result EQUAL 0)
- set(${RESULT_VAR} "TRUE" CACHE INTERNAL "Does ${function_name} exist in the kernel?")
- elseif(kmodule_is_function_exist_result EQUAL 1)
- set(${RESULT_VAR} "FALSE" CACHE INTERNAL "Does ${function_name} exist in the kernel?")
- else(kmodule_is_function_exist_result EQUAL 0)
- message(FATAL_ERROR
-"Cannot determine whether function '${function_name}' exists in the kernel"
- )
- endif(kmodule_is_function_exist_result EQUAL 0)
- endif(NOT DEFINED ${RESULT_VAR})
- set_bool_string(check_result "found" "not found" ${${RESULT_VAR}})
- check_end(${check_result})
-endfunction(kmodule_is_function_exist function_name RESULT_VAR)
-
-# Creates the list of functions that actually exist on the
-# current system.
-#
-# kmodule_configure_kernel_functions(output_list
-# {[REQUIRED | OPTIONAL] {func | ONE_OF_LIST}} ...)
-#
-# ONE_OF_LIST := ONE_OF_BEGIN {func ...} ONE_OF_END
-#
-# There are 2 modes of function lookup:
-# OPTIONAL - if the function doesn't exist, it is silently ignored.
-# REQUIRED - if the function doesn't exist, FATAL_ERROR message is printed.
-#
-# Initial mode is REQUIRED, and it can be changed at any time by REQUIRED
-# and OPTIONAL keywords.
-#
-# ONE_OF_BEGIN/ONE_OF_END determine a section for which no more than one
-# function among all listed there should exist. FATAL_ERROR message is
-# printed otherwise. When mode is REQUIRED, precisely one function must
-# exist.
-# Inside this section other keywords must not be used (even another
-# ONE_OF_BEGIN).
-
-function(kmodule_configure_kernel_functions output_list)
- set(kmodule_configure_kernel_functions_mode "REQUIRED")
- set(kmodule_configure_kernel_functions_one_of_section "FALSE")
- set(output_list_tmp)
- set(${output_list})
- foreach(arg ${ARGN})
- if(arg STREQUAL "REQUIRED" OR arg STREQUAL "OPTIONAL")
- if(kmodule_configure_kernel_functions_one_of_section)
- message(FATAL_ERROR
-"Inside ONE_OF_BEGIN/ONE_OF_END section, other keywords are not allowed."
- )
- endif(kmodule_configure_kernel_functions_one_of_section)
- set(kmodule_configure_kernel_functions_mode ${arg})
- elseif(arg STREQUAL "ONE_OF_BEGIN")
- if(kmodule_configure_kernel_functions_one_of_section)
- message(FATAL_ERROR "Nested ONE_OF_BEGIN/ONE_OF_END sections are not allowed.")
- endif(kmodule_configure_kernel_functions_one_of_section)
- set(kmodule_configure_kernel_functions_one_of_section "TRUE")
- set(kmodule_configure_kernel_functions_one_of_section_function)
- elseif(arg STREQUAL "ONE_OF_END")
- if(NOT kmodule_configure_kernel_functions_one_of_section)
- message(FATAL_ERROR "ONE_OF_END without ONE_OF_BEGIN is not allowed.")
- endif(NOT kmodule_configure_kernel_functions_one_of_section)
- if(kmodule_configure_kernel_functions_one_of_section_function)
- list(APPEND output_list_tmp ${kmodule_configure_kernel_functions_one_of_section_function})
- else(kmodule_configure_kernel_functions_one_of_section_function)
- if(kmodule_configure_kernel_functions_mode STREQUAL "REQUIRED")
- message(FATAL_ERROR
-"None of the functions listed in ONE_OF section exist in the kernel but it is required."
- )
- endif(kmodule_configure_kernel_functions_mode STREQUAL "REQUIRED")
- endif(kmodule_configure_kernel_functions_one_of_section_function)
- set(kmodule_configure_kernel_functions_one_of_section "FALSE")
- else(arg STREQUAL "REQUIRED" OR arg STREQUAL "OPTIONAL")
- set(kmodule_func_varname _KMODULE_IS_${arg}_EXIST)
- kedr_find_function(${arg} ${kmodule_func_varname})
- if(kmodule_configure_kernel_functions_one_of_section)
- if(${kmodule_func_varname})
- if(kmodule_configure_kernel_functions_one_of_section_function)
- message(FATAL_ERROR "Two functions from ONE_OF sections exist in the kernel.")
- else(kmodule_configure_kernel_functions_one_of_section_function)
- set(kmodule_configure_kernel_functions_one_of_section_function ${arg})
- endif(kmodule_configure_kernel_functions_one_of_section_function)
- endif(${kmodule_func_varname})
- else(kmodule_configure_kernel_functions_one_of_section)
- if(${kmodule_func_varname})
- list(APPEND output_list_tmp ${arg})
- else(${kmodule_func_varname})
- if(kmodule_configure_kernel_functions_mode STREQUAL "REQUIRED")
- message(FATAL_ERROR "Function ${arg} is not found in the kernel but it is required.")
- endif(kmodule_configure_kernel_functions_mode STREQUAL "REQUIRED")
- endif(${kmodule_func_varname})
- endif(kmodule_configure_kernel_functions_one_of_section)
- endif(arg STREQUAL "REQUIRED" OR arg STREQUAL "OPTIONAL")
- endforeach(arg ${ARGN})
- if(kmodule_configure_kernel_functions_one_of_section)
- message(FATAL_ERROR "Found ONE_OF_BEGIN without ONE_OF_END")
- endif(kmodule_configure_kernel_functions_one_of_section)
- set(${output_list} ${output_list_tmp} PARENT_SCOPE)
-endfunction(kmodule_configure_kernel_functions output_list)
-
-############################################################################
-# Utility macros to check for particular features. If the particular feature
-# is supported, the macros will set the corresponding variable to TRUE,
-# otherwise - to FALSE (the name of variable is mentioned in the comments
-# for the macro).
-############################################################################
-
-# Check if the system has everything necessary to build at least simple
-# kernel modules.
-# The macro sets variable 'MODULE_BUILD_SUPPORTED'.
-macro(check_module_build)
- check_begin("Checking if kernel modules can be built on this system")
- if (NOT MODULE_BUILD_SUPPORTED)
- check_try()
- kbuild_try_compile(module_build_supported_impl
- "${CMAKE_BINARY_DIR}/check_module_build"
- "${kmodule_test_sources_dir}/check_module_build/module.c"
- )
- set_bool_string(MODULE_BUILD_SUPPORTED "yes" "no" ${module_build_supported_impl}
- CACHE INTERNAL "Can kernel modules be built on this system?"
- )
- endif (NOT MODULE_BUILD_SUPPORTED)
-
- check_end("${MODULE_BUILD_SUPPORTED}")
-
- if (NOT MODULE_BUILD_SUPPORTED)
- message(FATAL_ERROR
-"There are problems with building kernel modules on this system. "
-"Please check that the appropriate kernel headers and build tools "
-"are installed."
- )
- endif (NOT MODULE_BUILD_SUPPORTED)
-endmacro(check_module_build)
-
-# Check if reliable stack trace information can be obtained.
-# This is the case, for example, if the kernel is compiled with support
-# for frame pointers and/or stack unwind on.
-# The macro sets variable 'STACK_TRACE_RELIABLE'.
-macro(check_stack_trace)
- check_begin("Checking if stack trace information is reliable")
- if (NOT DEFINED STACK_TRACE_RELIABLE)
- check_try()
- kbuild_try_compile(stack_trace_reliable_impl
- "${CMAKE_BINARY_DIR}/check_stack_trace"
- "${kmodule_test_sources_dir}/check_stack_trace/module.c"
- )
- set_bool_string(STACK_TRACE_RELIABLE "yes" "no" ${stack_trace_reliable_impl}
- CACHE INTERNAL "Are stack traces reliable on this system?")
- endif (NOT DEFINED STACK_TRACE_RELIABLE)
- check_end("${STACK_TRACE_RELIABLE}")
-
- if (NOT STACK_TRACE_RELIABLE)
- message ("\n[WARNING]\n"
- "It looks like reliable stack traces cannot be obtained on this system.\n"
- "The output of KEDR-based tools like LeakCheck will be less detailed\n"
- "(each stack trace shown will contain only one frame).\n"
- "If this is not acceptable, you could rebuild the kernel with\n"
- "CONFIG_FRAME_POINTER or CONFIG_STACK_UNWIND (if available) set to \"y\"\n"
- "and then reconfigure and rebuild KEDR.\n")
- endif (NOT STACK_TRACE_RELIABLE)
-endmacro(check_stack_trace)
-
-# Check whether ring buffer is implemented by the kernel.
-# Set cache variable RING_BUFFER_IMPLEMENTED according to this checking.
-function(check_ring_buffer)
- check_begin("Checking if ring buffer is implemented in the kernel")
-
- if (NOT DEFINED RING_BUFFER_IMPLEMENTED)
- check_try()
- kbuild_try_compile(ring_buffer_implemented_impl
- "${CMAKE_BINARY_DIR}/check_ring_buffer"
- "${kmodule_test_sources_dir}/check_ring_buffer/module.c"
- )
-
- set_bool_string(RING_BUFFER_IMPLEMENTED "yes" "no" "${ring_buffer_implemented_impl}"
- CACHE INTERNAL "Whether ring buffer is implemented in the kernel"
- )
- endif (NOT DEFINED RING_BUFFER_IMPLEMENTED)
- check_end(${RING_BUFFER_IMPLEMENTED})
-
- if (NOT RING_BUFFER_IMPLEMENTED)
- message("\n[WARNING]\nRing buffer is not supported by the system.\n"
- "The tracing facilities as well as call monitoring plugins will not be built.\n"
- "If this is not acceptable, you could rebuild the kernel with\n"
- "CONFIG_RING_BUFFER set to \"y\" and then reconfigure and rebuild KEDR.\n")
- endif (NOT RING_BUFFER_IMPLEMENTED)
-endfunction(check_ring_buffer)
-
-# Check which memory allocator is used by the kernel.
-# Set KERNEL_MEMORY_ALLOCATOR to 'slab', 'slub', 'slob' or 'other'.
-#
-# Some functions in that allocators may have same names, but different signatures.
-function(check_allocator)
- check_begin("Checking which memory allocator is used by the kernel")
- if(NOT DEFINED KERNEL_MEMORY_ALLOCATOR)
- check_try()
- # Use local variable for detect allocator,
- # Cache one will be set at the end
- set(allocator "")
- if(allocator STREQUAL "")
- kbuild_try_compile(is_allocator_slab
- "${CMAKE_BINARY_DIR}/check_allocator_slab"
- "${kmodule_test_sources_dir}/check_allocator/module.c"
- KBUILD_COMPILE_DEFINITIONS "-DIS_ALLOCATOR_SLAB"
- )
- if (is_allocator_slab)
- set(allocator "slab")
- endif (is_allocator_slab)
- endif(allocator STREQUAL "")
-
- if(allocator STREQUAL "")
- kbuild_try_compile(is_allocator_slub
- "${CMAKE_BINARY_DIR}/check_allocator_slub"
- "${kmodule_test_sources_dir}/check_allocator/module.c"
- KBUILD_COMPILE_DEFINITIONS "-DIS_ALLOCATOR_SLUB"
- )
- if (is_allocator_slub)
- set(allocator "slub")
- endif (is_allocator_slub)
- endif(allocator STREQUAL "")
-
- if(allocator STREQUAL "")
- kbuild_try_compile(is_allocator_slob
- "${CMAKE_BINARY_DIR}/check_allocator_slob"
- "${kmodule_test_sources_dir}/check_allocator/module.c"
- KBUILD_COMPILE_DEFINITIONS "-DIS_ALLOCATOR_SLOB"
- )
- if (is_allocator_slob)
- set(allocator "slob")
- endif (is_allocator_slub)
- endif(allocator STREQUAL "")
-
- if(allocator STREQUAL "")
- set(allocator "other")
- endif(allocator STREQUAL "")
-
- set(KERNEL_MEMORY_ALLOCATOR "${allocator}" CACHE INTERNAL
- "Memory allocator which is used by the kernel"
- )
- endif (NOT DEFINED KERNEL_MEMORY_ALLOCATOR)
- check_end("${KERNEL_MEMORY_ALLOCATOR}")
-endfunction(check_allocator)
-
-# Check if 'kfree_rcu' is available in the kernel (it is likely to be
-# a macro or an inline). If it is available, we should handle it as
-# 'free' in LeakCheck. As KEDR cannot normally intercept kfree_rcu()
-# itself, it needs to intercept call_rcu/call_rcu_sched and check their
-# arguments.
-# The macro sets variable 'HAVE_KFREE_RCU'.
-macro(check_kfree_rcu)
- check_begin("Checking if kfree_rcu() is available")
-
- if (NOT DEFINED HAVE_KFREE_RCU)
- check_try()
- kbuild_try_compile(have_kfree_rcu_impl
- "${CMAKE_BINARY_DIR}/check_kfree_rcu"
- "${kmodule_test_sources_dir}/check_kfree_rcu/module.c"
- )
-
- set_bool_string(HAVE_KFREE_RCU "yes" "no" ${have_kfree_rcu_impl}
- CACHE INTERNAL "Is kfree_rcu() available?"
- )
- endif ()
- check_end("${HAVE_KFREE_RCU}")
-endmacro(check_kfree_rcu)
-############################################################################
-
-# Check if posix_acl_from_xattr() accepts struct user_namespace as the
-# first argument.
-# The macro sets variable 'POSIX_ACL_XATTR_HAS_USER_NS'.
-macro(check_xattr_user_ns)
- check_begin("Checking if posix_acl_from_xattr() has struct user_namespace * argument")
- if (NOT DEFINED POSIX_ACL_XATTR_HAS_USER_NS)
- check_try()
- kbuild_try_compile(have_xattr_user_ns_impl
- "${CMAKE_BINARY_DIR}/check_xattr_user_ns"
- "${kmodule_test_sources_dir}/check_xattr_user_ns/module.c"
- )
-
- set_bool_string(POSIX_ACL_XATTR_HAS_USER_NS "yes" "no" ${have_xattr_user_ns_impl}
- CACHE INTERNAL "Does posix_acl_from_xattr() have struct user_namespace argument?"
- )
- endif ()
- check_end("${POSIX_ACL_XATTR_HAS_USER_NS}")
-endmacro(check_xattr_user_ns)
-############################################################################
-
-# Check if hlist_for_each_entry*() macros accept only 'type *pos' argument
-# rather than both 'type *tpos' and 'hlist_node *pos' as the loop cursors.
-# The macro sets variable 'HLIST_FOR_EACH_ENTRY_POS_ONLY'.
-macro(check_hlist_for_each_entry)
- check_begin("Checking the signatures of hlist_for_each_entry*() macros")
- if (NOT DEFINED HLIST_FOR_EACH_ENTRY_POS_ONLY)
- check_try()
- kbuild_try_compile(pos_only_impl
- "${CMAKE_BINARY_DIR}/check_hlist_for_each_entry"
- "${kmodule_test_sources_dir}/check_hlist_for_each_entry/module.c"
- )
- set_bool_string(HLIST_FOR_EACH_ENTRY_POS_ONLY "yes" "no" ${pos_only_impl}
- CACHE INTERNAL
- "Do hlist_for_each_entry*() macros have only 'type *pos' to use as a loop cursor?"
- )
- endif ()
- set_bool_string(check_result "do not use additional loop cursor" "use additional loop cursor"
- ${HLIST_FOR_EACH_ENTRY_POS_ONLY})
- check_end(${check_result})
-endmacro(check_hlist_for_each_entry)
-############################################################################
-
-# Check if 'random32' is available in the kernel.
-# The macro sets variable 'KEDR_HAVE_RANDOM32'.
-macro(check_random32)
- check_begin("Checking if random32() is available")
- if (NOT DEFINED KEDR_HAVE_RANDOM32)
- check_try()
- kbuild_try_compile(have_random32_impl
- "${CMAKE_BINARY_DIR}/check_random32"
- "${kmodule_test_sources_dir}/check_random32/module.c"
- )
- set_bool_string(KEDR_HAVE_RANDOM32 "yes" "no" "${have_random32_impl}"
- CACHE INTERNAL "Is random32() available?"
- )
- endif ()
- check_end("${KEDR_HAVE_RANDOM32}")
-endmacro(check_random32)
-############################################################################
-
-# The payload modules should call kedr_find_function() for each kernel
-# function they would like to process. If the function is not known
-# to KEDR (absent from the "function database", see "functions/" directory),
-# kedr_find_function() issues a fatal error.
-#
-# 'func_name' is the name of the function,
-# 'found_var' is the name of the output variable (the variable will evaluate
-# as "true" if found, as "false" otherwise).
-function (kedr_find_function func_name found_var)
- if (NOT DEFINED KEDR_DATA_FILE_${func_name})
- message(FATAL_ERROR "Unsupported function: ${func_name}")
- endif (NOT DEFINED KEDR_DATA_FILE_${func_name})
-
- # OK, known function.
- kmodule_is_function_exist(${func_name} ${found_var})
- if (${found_var})
- # Mark the function as used by at least one payload module.
- # This can be used when preparing the tests for call interception.
- # The actual value does not matter, it only matters that this
- # variable is defined.
- set(KEDR_FUNC_USED_${func_name} "yes" CACHE INTERNAL
- "Is kernel function ${func_name} used by any payload module?")
- set(${found_var} "${${found_var}}" PARENT_SCOPE)
- else ()
- set(${found_var} "NO" PARENT_SCOPE)
- endif (${found_var})
-endfunction (kedr_find_function func_name found_var)
-
-# Returns (in ${path_var}) the path to the .data file for the function
-# ${func_name}. The function must be present in the system and
-# kedr_find_function() must be called for it before kedr_get_data_for_func().
-function (kedr_get_data_for_func func_name path_var)
- if (NOT DEFINED KEDR_FUNC_USED_${func_name})
- message(FATAL_ERROR
-"Attempt to lookup data for a function that is not marked as used: "
- "${func_name}")
- endif (NOT DEFINED KEDR_FUNC_USED_${func_name})
-
- set(${path_var} "${KEDR_DATA_FILE_${func_name}}" PARENT_SCOPE)
-endfunction (kedr_get_data_for_func func_name path_var)
-
-# kedr_get_header_data_list(list_var func1 [func2 func3 ...])
-# Get the list of paths to the 'header.data' files for the given functions.
-# The functions must be present in the system and # kedr_find_function()
-# must be called for each of them before kedr_get_header_data_list() is
-# called.
-# The resulting list is returned in ${list_var}. It will contain at least
-# one item. It will not contain duplicates.
-function (kedr_get_header_data_list list_var)
- set(hdata_list)
- foreach (func ${ARGN})
- if (NOT DEFINED KEDR_FUNC_USED_${func})
- message(FATAL_ERROR
-"Attempt to lookup header data for a function that is not marked as used: "
- "${func}")
- endif (NOT DEFINED KEDR_FUNC_USED_${func})
- list(APPEND hdata_list "${KEDR_HEADER_DATA_FILE_${func}}")
- endforeach ()
- list(REMOVE_DUPLICATES hdata_list)
-
- list(LENGTH hdata_list hdata_list_len)
- if (NOT hdata_list_len)
- message(FATAL_ERROR
- "kedr_get_header_data_list(): BUG: the output list is empty.")
- endif (NOT hdata_list_len)
-
- set(${list_var} ${hdata_list} PARENT_SCOPE)
-endfunction (kedr_get_header_data_list list_var)
-
-# kedr_create_header_rules(
-# header_impl_file header_data_file func1 [func2 ...])
-# Create the rules to generate ${header_impl_file} from
-# ${header_data_file} and the specific header files for the given
-# functions.
-function(kedr_create_header_rules header_impl_file header_data_file
- functions)
- set(hlist_data)
- kedr_get_header_data_list(hlist_data ${functions} ${ARGN})
- to_abs_path(hdata_files_abs ${header_data_file} ${hlist_data})
- add_custom_command(OUTPUT ${header_impl_file}
- COMMAND cat ${hdata_files_abs} > ${header_impl_file}
- DEPENDS ${hdata_files_abs}
- )
-endfunction(kedr_create_header_rules header_impl_file header_data_file
- functions)
-
-# kedr_create_data_rules(func)
-# Create the rules to generate ${func}_impl.data from
-# ${func}.data (contains processing instructions specific to the current
-# payload) and the .data file from "func_db" (contains function signature).
-function(kedr_create_data_rules func)
- set(func_db_data_file)
- kedr_get_data_for_func(${func} func_db_data_file)
-
- set(func_proc_data_file)
- to_abs_path(func_proc_data_file ${func}.data)
-
- add_custom_command(OUTPUT "${func}_impl.data"
- COMMAND printf "\"[group]\\n\"" > "${func}_impl.data"
- COMMAND grep -E -v '\\[group\\]'
- "${func_db_data_file}" >> "${func}_impl.data"
- COMMAND printf "\"\\n\"" >> "${func}_impl.data"
- COMMAND grep -E -v '\\[group\\]'
- "${func_proc_data_file}" >> "${func}_impl.data"
- DEPENDS
- "${func_proc_data_file}"
- "${func_db_data_file}"
- )
-endfunction(kedr_create_data_rules func)
-
-# kedr_create_payload_module(module_name payload_data_file template_dir)
-# Create the rules to build a payload module with the given name.
-# 'payload_data_file' defines how the kernel functions are to be processed
-# by this payload module.
-# 'template_dir' - path to the direcotry containing the templates to be used
-# to prepare the source code of the module from 'payload_data_file'.
-function(kedr_create_payload_module module_name payload_data_file
- template_dir)
-
- # Rules to build the module
- kbuild_add_module(${module_name}
- "payload.c"
- "functions_support.c"
- )
- kbuild_link_module(${module_name} kedr)
-
- # Rules to obtain the source files of the module
- kedr_generate("payload.c" ${payload_data_file} "${template_dir}")
- kedr_generate("functions_support.c" ${payload_data_file} "${KEDR_GEN_TEMPLATES_DIR}/functions_support.c")
-endfunction(kedr_create_payload_module module_name payload_data_file
- template_dir)
-
-# kedr_create_payload_data(payload_data_file func1 [func2 ...])
-# Create .data files and the header data files for the functions and prepare
-# the main .data file (${payload_data_file}) for the payload module.
-function(kedr_create_payload_data header_data_file payload_data_file
- functions)
- set(header_impl_file "header_impl.data")
- set(functions_data)
-
- foreach(func ${functions} ${ARGN})
- list(APPEND functions_data "${func}_impl.data")
- kedr_create_data_rules(${func})
- endforeach(func ${functions} ${ARGN})
-
- kedr_create_header_rules(${header_impl_file} ${header_data_file}
- ${functions} ${ARGN})
-
- to_abs_path(payload_data_file_abs ${payload_data_file})
- to_abs_path(source_files_abs ${header_impl_file} ${functions_data})
-
- set(payload_data_file_abs "${CMAKE_CURRENT_BINARY_DIR}/${payload_data_file}")
- add_custom_command(OUTPUT ${payload_data_file_abs}
- COMMAND cat ${source_files_abs} > ${payload_data_file_abs}
- DEPENDS ${source_files_abs}
- )
-endfunction(kedr_create_payload_data header_data_file payload_data_file
- functions)
-############################################################################
diff --git a/cmake_targets/tools/example_oaisim_enb_ue_mme_virtual.txt b/cmake_targets/tools/example_oaisim_enb_ue_mme_virtual.txt
deleted file mode 100755
index 805d121e6d..0000000000
--- a/cmake_targets/tools/example_oaisim_enb_ue_mme_virtual.txt
+++ /dev/null
@@ -1,98 +0,0 @@
-#/*
-# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
-# * contributor license agreements. See the NOTICE file distributed with
-# * this work for additional information regarding copyright ownership.
-# * The OpenAirInterface Software Alliance licenses this file to You under
-# * the OAI Public License, Version 1.1 (the "License"); you may not use this file
-# * except in compliance with the License.
-# * You may obtain a copy of the License at
-# *
-# * http://www.openairinterface.org/?page_id=698
-# *
-# * Unless required by applicable law or agreed to in writing, software
-# * distributed under the License is distributed on an "AS IS" BASIS,
-# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# * See the License for the specific language governing permissions and
-# * limitations under the License.
-# *-------------------------------------------------------------------------------
-# * For more information about the OpenAirInterface (OAI) Software Alliance:
-# * contact@openairinterface.org
-# */
-
-# file example_oaisim_enb_ue_mme_virtual.txt
-# brief
-# author Lionel Gauthier
-
-TODO: a document file, PDF for example, with nice pictures, etc
-This example shows how to generate and launch enb, 1 ue (NAS still not virtualized in UE) in virtualised mode, mme_gw, hss executables on the same host:
-
-################
-Configuration
-################
-freediameter 1.2.0 (not 1.1.5, 1.1.6,...) has to be installed and patched (done by check_install_oai_software() calling install_freediameter_from_source() in script build_helper)
-
-Config File:
-/etc/hosts must contain the fqdn of the MME and HSS (same since both run on the same host):
-(assuming the realm is openair4G.eur)
-127.0.0.1 localhost
-127.0.1.1 yang.openair4G.eur yang
-...
-
-################
-BUILDING, RUNNING
-################
-
-Building HSS:
-yang@yang:~/openair4G/trunk/cmake_targets$ tools/build_hss -c --connect-to-mme yang.openair4G.eur -t -T --realm openair4G.eur
-
-Configuring the HSS:
-In oai_db (easier for newbies to access HSS database through http://127.0.0.1/phpmyadmin)
- In table mmeidentity, enter the record corresponding to your MME:
- (idmmeidentity, mmehost, mmerealm)
- In table pdn, enter the record allowing an IMSI to connect to an APN
- In table users, enter the record corresponding to your USIM card.
-
-Running the HSS:
-yang@yang:~/openair4G/trunk/cmake_targets$ sudo tools/run_hss -g
-
-
-
-Building the MME-GW:
-yang@yang:~/openair4G/trunk/cmake_targets/tools$ ./build_epc -c -d -t -T --s6a-server
-
-Configuring the MME-GW:
- You can configure in file openair4G/trunk/cmake_targets/tools/epc.local.enb.conf.in the following parameters:
- MCC/MNC of your network
- SGI interface (outgoing interface of the S/P-GW)
- Integrity algorithms, Ciphering algorithms
- Please note that DNS addresses are hardcoded in source code (TODO in list).
-
-Running the MME-GW:
-yang@yang:~/openair4G/trunk/cmake_targets/tools$ sudo ./run_epc -l -g -K
-
-
-
-Building eNB:
-yang@yang:~/openair4G/trunk/cmake_targets$ ./build_oai --oaisim
-
-Configuring the eNB:
- The default configuration file for the eNB is trunk/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_mme.conf
-
-Running eNB:
-yang@yang:~/openair4G/trunk/cmake_targets$ tools/run_enb_ue_virt_s1 -m /tmp -K /tmp/enb_ue_virt_s1_itti.log
-
-
-Putting some IP UL/DL traffic in the bearer:
-ping -s 1000 -m 1 192.168.12.100 -I oip1
-
-
-################
-Tools available:
-###############
-
-1) itti_analyser (list messages exchanged between protocol layers)
-2) xforms (Layer 1)
-3) vcd (timing mesurements)
-
-
-
diff --git a/cmake_targets/tools/make_agent_cache b/cmake_targets/tools/make_agent_cache
deleted file mode 100755
index d2eab20fc0..0000000000
--- a/cmake_targets/tools/make_agent_cache
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-
-CACHE_DIR=/mnt/oai_agent_cache
-
-if [ ! -d $CACHE_DIR ]; then
- echo "Creating cache dir in $CACHE_DIR"
- sudo mkdir $CACHE_DIR
-fi
-
-if grep -qs "$CACHE_DIR" /proc/mounts; then
- echo "Agent cache is already mounted"
-else
- echo "Agent cache was not mounted"
- echo "Mounting..."
- sudo mount -o size=100m -t tmpfs none "$CACHE_DIR"
- if [ $? -eq 0 ]; then
- echo "Mount success"
- else
- echo "Something went wrong with the mount"
- fi
-fi
diff --git a/cmake_targets/tools/setup_routes.sh b/cmake_targets/tools/setup_routes.sh
deleted file mode 100755
index 67fe250be7..0000000000
--- a/cmake_targets/tools/setup_routes.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-for i in $(seq 1 $1);
-do
- let table=1000+$i
- echo "sudo ip route add 10.0.1.0/24 dev oaitun_ue$i table $table"
- sudo ip route add 10.0.1.0/24 dev oaitun_ue$i table $table
- echo "sudo ip route add default via 10.0.1.1 dev oaitun_ue$i table $table"
- sudo ip route add default via 10.0.1.1 dev oaitun_ue$i table $table
- let octet=$i+1
- echo "sudo ip rule add from 10.0.1.$octet table $table"
- sudo ip rule add from 10.0.1.$octet table $table
-done
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index 2772fc5aae..f9740978cd 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -497,8 +497,6 @@ static uint64_t get_carrier_frequency(const int N_RB, const int mu, const uint32
return carrier_freq;
}
-static void apply_ntn_timing_advance_and_doppler(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx);
-
static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
{
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
@@ -735,175 +733,6 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
return rem_samples + next_slot_first_symbol;
}
-static void fix_ntn_epoch_hfn(PHY_VARS_NR_UE *UE, int hfn, int frame)
-{
- if (!UE->nrUE_config.ntn_config.is_targetcell)
- return;
- UE->nrUE_config.ntn_config.is_targetcell = false;
-
- const int epoch_frame = UE->nrUE_config.ntn_config.epoch_sfn;
- const int diff1 = (frame - epoch_frame + 1024) % 1024;
- const int diff2 = (epoch_frame - frame + 1024) % 1024;
-
- int *epoch_hfn = &UE->nrUE_config.ntn_config.epoch_hfn;
- if (diff1 < diff2) { // epoch_frame in the past
- LOG_I(PHY, "epoch is %d frames in the past\n", diff1);
- if (epoch_frame <= frame)
- *epoch_hfn = hfn;
- else
- *epoch_hfn = hfn - 1;
- } else { // epoch_frame in the future
- LOG_I(PHY, "epoch is %d frames in the future\n", diff2);
- if (epoch_frame >= frame)
- *epoch_hfn = hfn;
- else
- *epoch_hfn = hfn + 1;
- }
- LOG_I(PHY, "setting epoch_hfn = %d\n", *epoch_hfn);
-}
-
-#define SPEED_OF_LIGHT 299792458
-
-// calculate TA and Doppler based on the NTN-Config, if abs_subframe_tx < 0 then apply only Doppler
-static void apply_ntn_timing_advance_and_doppler(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx)
-{
- const fapi_nr_ntn_config_t *ntn_config_params = &UE->nrUE_config.ntn_config;
-
- // Handle terrestrial networks
- if (ntn_config_params->cell_specific_k_offset == 0) {
- if (abs_subframe_tx >= 0)
- UE->timing_advance_ntn = 0;
- UE->dl_Doppler_shift = 0;
- UE->ul_Doppler_shift = 0;
- return;
- }
-
- const int abs_subframe_epoch = ntn_config_params->epoch_subframe
- + ntn_config_params->epoch_sfn * 10
- + ntn_config_params->epoch_hfn * 10240;
- const int ms_since_epoch = abs_subframe_tx < 0 ? 0 : abs_subframe_tx - abs_subframe_epoch;
-
- const position_t pos_sat_0 = ntn_config_params->pos_sat_0;
- const position_t vel_sat_0 = ntn_config_params->vel_sat_0;
-
- position_t pos_sat;
- position_t vel_sat;
-
- const double omega = ntn_config_params->omega;
- if (omega) {
- const double cos_wt = cos(omega * ms_since_epoch);
- const double sin_wt = sin(omega * ms_since_epoch);
-
- const position_t pos_sat_90 = ntn_config_params->pos_sat_90;
- pos_sat = (position_t){pos_sat_0.X * cos_wt + pos_sat_90.X * sin_wt,
- pos_sat_0.Y * cos_wt + pos_sat_90.Y * sin_wt,
- pos_sat_0.Z * cos_wt + pos_sat_90.Z * sin_wt};
-
- const position_t vel_sat_90 = ntn_config_params->vel_sat_90;
- vel_sat = (position_t){vel_sat_0.X * cos_wt + vel_sat_90.X * sin_wt,
- vel_sat_0.Y * cos_wt + vel_sat_90.Y * sin_wt,
- vel_sat_0.Z * cos_wt + vel_sat_90.Z * sin_wt};
- } else {
- pos_sat = (position_t){pos_sat_0.X + vel_sat_0.X * ms_since_epoch / 1000,
- pos_sat_0.Y + vel_sat_0.Y * ms_since_epoch / 1000,
- pos_sat_0.Z + vel_sat_0.Z * ms_since_epoch / 1000};
- vel_sat = vel_sat_0;
- }
-
- position_t pos_ue = {0};
- get_position_coordinates(UE->Mod_id, &pos_ue);
-
- // calculate directional vector from SAT to UE
- const position_t dir_sat_ue = {pos_ue.X - pos_sat.X, pos_ue.Y - pos_sat.Y, pos_ue.Z - pos_sat.Z};
-
- // calculate distance between SAT and UE
- const double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z);
-
- // calculate projected velocity from SAT towards UE
- const double vel_sat_ue = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance;
-
- // calculate DL Doppler shift (moving source)
- const double dl_Doppler_shift = (vel_sat_ue / (SPEED_OF_LIGHT - vel_sat_ue)) * fp->dl_CarrierFreq;
-
- // calculate UL Doppler shift (moving target)
- const double ul_Doppler_shift = (vel_sat_ue / SPEED_OF_LIGHT) * fp->ul_CarrierFreq;
-
- // calculate round-trip-time (factor 2) between SAT and UE in ms (factor 1000)
- const double N_UE_TA_adj = 2000 * distance / SPEED_OF_LIGHT;
-
- const double N_common_ta_adj = ntn_config_params->N_common_ta_adj;
- const double N_common_ta_drift = ntn_config_params->N_common_ta_drift;
- const double N_common_ta_drift_variant = ntn_config_params->N_common_ta_drift_variant;
-
- if (abs_subframe_tx >= 0) {
- UE->timing_advance_ntn = (N_UE_TA_adj + N_common_ta_adj + N_common_ta_drift * ms_since_epoch / 1e6
- + N_common_ta_drift_variant * ((int64_t)ms_since_epoch * ms_since_epoch) / 1e9)
- * fp->samples_per_subframe;
- }
-
- UE->freq_offset -= dl_Doppler_shift - UE->dl_Doppler_shift;
- UE->dl_Doppler_shift = dl_Doppler_shift;
- UE->ul_Doppler_shift = ul_Doppler_shift;
-
- if (abs_subframe_tx < 0) {
- LOG_I(PHY,
- "satellite velocity towards UE = %f m/s, DL Doppler shift = %f kHz, UL Doppler shift = %f kHz\n",
- vel_sat_ue,
- dl_Doppler_shift / 1000,
- ul_Doppler_shift / 1000);
- }
-}
-
-// apply values based on the NTN-Config
-static void apply_ntn_config(PHY_VARS_NR_UE *UE,
- NR_DL_FRAME_PARMS *fp,
- int hfn_rx,
- int frame_rx,
- int slot_rx,
- int *duration_rx_to_tx,
- int *timing_advance,
- int *ntn_koffset,
- bool *ntn_targetcell)
-{
- // return if there is no pending update
- if (!UE->nrUE_config.ntn_config.params_changed)
- return;
-
- *ntn_targetcell = UE->nrUE_config.ntn_config.is_targetcell;
-
- // skip update if it is for the target cell
- if (UE->nrUE_config.ntn_config.is_targetcell)
- return;
-
- UE->nrUE_config.ntn_config.params_changed = false;
-
- const fapi_nr_ntn_config_t *ntn_config_params = &UE->nrUE_config.ntn_config;
-
- const int mu = fp->numerology_index;
- const int koffset = ntn_config_params->cell_specific_k_offset;
-
- *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
- if (koffset > *ntn_koffset)
- *timing_advance += get_samples_slot_duration(fp, slot_rx, (koffset - *ntn_koffset) << mu);
- else if (koffset < *ntn_koffset)
- *timing_advance -= get_samples_slot_duration(fp, slot_rx, (*ntn_koffset - koffset) << mu);
- *ntn_koffset = koffset;
-
- const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
- apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
-
- LOG_I(PHY,
- "k_offset: %dms, N_Common_Ta: %fms, drift: %fยตs/s, variant: %fยตs/sยฒ, "
- "timing_advance_ntn: %d samples, DL Doppler shift: %fkHz, UL Doppler shift: %fkHz\n",
- koffset << mu,
- ntn_config_params->N_common_ta_adj,
- ntn_config_params->N_common_ta_drift,
- ntn_config_params->N_common_ta_drift_variant,
- UE->timing_advance_ntn,
- UE->dl_Doppler_shift / 1000,
- UE->ul_Doppler_shift / 1000);
-}
-
void *UE_thread(void *arg)
{
//this thread should be over the processing thread to keep in real time
diff --git a/openair1/PHY/CODING/DOC/LDPCImplementation.md b/openair1/PHY/CODING/DOC/LDPCImplementation.md
index 0e4a630f4b..56e7570de4 100644
--- a/openair1/PHY/CODING/DOC/LDPCImplementation.md
+++ b/openair1/PHY/CODING/DOC/LDPCImplementation.md
@@ -40,7 +40,6 @@ Linking C shared module libldpc_aal.so
At runtime, to successfully use LDPC accelerators (e.g., Xilinx T2/Intel ACCs), you will need to install the corresponding drivers and tools.
Please refer to the dedicated documentation at [LDPC_OFFLOAD_SETUP.md](file://../../../../doc/LDPC_OFFLOAD_SETUP.md).
-<<<<<<< HEAD
```
./nr-softmodem -O libconfig:gnb.band78.sa.fr1.106PRB.usrpb210.conf:dbgl5 --rfsim --rfsimulator.serveraddr server --log_config.gtpu_log_level info --loader.ldpc.shlibversion _aal --nrLDPC_coding_aal.dpdk_dev 01:00.0 --nrLDPC_coding_aal.dpdk_core_list 0-1
```
diff --git a/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c b/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c
index 998b95d0d3..86a4b93ddd 100644
--- a/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c
+++ b/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c
@@ -12,11 +12,7 @@ data storage. */
#include
#include
#include
-#if defined RHEL_RELEASE_CODE
-#include
-#else
#include
-#endif
#include
#include
#include
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ntn_l1.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ntn_l1.c
new file mode 100644
index 0000000000..51031d5449
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ntn_l1.c
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ * contact@openairinterface.org
+ */
+
+#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
+
+void fix_ntn_epoch_hfn(PHY_VARS_NR_UE *UE, int hfn, int frame)
+{
+ if (!UE->nrUE_config.ntn_config.is_targetcell)
+ return;
+ UE->nrUE_config.ntn_config.is_targetcell = false;
+
+ const int epoch_frame = UE->nrUE_config.ntn_config.epoch_sfn;
+ const int diff1 = (frame - epoch_frame + 1024) % 1024;
+ const int diff2 = (epoch_frame - frame + 1024) % 1024;
+
+ int *epoch_hfn = &UE->nrUE_config.ntn_config.epoch_hfn;
+ if (diff1 < diff2) { // epoch_frame in the past
+ LOG_I(PHY, "epoch is %d frames in the past\n", diff1);
+ if (epoch_frame <= frame)
+ *epoch_hfn = hfn;
+ else
+ *epoch_hfn = hfn - 1;
+ } else { // epoch_frame in the future
+ LOG_I(PHY, "epoch is %d frames in the future\n", diff2);
+ if (epoch_frame >= frame)
+ *epoch_hfn = hfn;
+ else
+ *epoch_hfn = hfn + 1;
+ }
+ LOG_I(PHY, "setting epoch_hfn = %d\n", *epoch_hfn);
+}
+
+#define SPEED_OF_LIGHT 299792458
+
+// calculate TA and Doppler based on the NTN-Config, if abs_subframe_tx < 0 then apply only Doppler
+void apply_ntn_timing_advance_and_doppler(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx)
+{
+ const fapi_nr_ntn_config_t *ntn_config_params = &UE->nrUE_config.ntn_config;
+
+ // Handle terrestrial networks
+ if (ntn_config_params->cell_specific_k_offset == 0) {
+ if (abs_subframe_tx >= 0)
+ UE->timing_advance_ntn = 0;
+ UE->dl_Doppler_shift = 0;
+ UE->ul_Doppler_shift = 0;
+ return;
+ }
+
+ const int abs_subframe_epoch = ntn_config_params->epoch_subframe
+ + ntn_config_params->epoch_sfn * 10
+ + ntn_config_params->epoch_hfn * 10240;
+ const int ms_since_epoch = abs_subframe_tx < 0 ? 0 : abs_subframe_tx - abs_subframe_epoch;
+
+ const position_t pos_sat_0 = ntn_config_params->pos_sat_0;
+ const position_t vel_sat_0 = ntn_config_params->vel_sat_0;
+
+ position_t pos_sat;
+ position_t vel_sat;
+
+ const double omega = ntn_config_params->omega;
+ if (omega) {
+ const double cos_wt = cos(omega * ms_since_epoch);
+ const double sin_wt = sin(omega * ms_since_epoch);
+
+ const position_t pos_sat_90 = ntn_config_params->pos_sat_90;
+ pos_sat = (position_t){pos_sat_0.X * cos_wt + pos_sat_90.X * sin_wt,
+ pos_sat_0.Y * cos_wt + pos_sat_90.Y * sin_wt,
+ pos_sat_0.Z * cos_wt + pos_sat_90.Z * sin_wt};
+
+ const position_t vel_sat_90 = ntn_config_params->vel_sat_90;
+ vel_sat = (position_t){vel_sat_0.X * cos_wt + vel_sat_90.X * sin_wt,
+ vel_sat_0.Y * cos_wt + vel_sat_90.Y * sin_wt,
+ vel_sat_0.Z * cos_wt + vel_sat_90.Z * sin_wt};
+ } else {
+ pos_sat = (position_t){pos_sat_0.X + vel_sat_0.X * ms_since_epoch / 1000,
+ pos_sat_0.Y + vel_sat_0.Y * ms_since_epoch / 1000,
+ pos_sat_0.Z + vel_sat_0.Z * ms_since_epoch / 1000};
+ vel_sat = vel_sat_0;
+ }
+
+ position_t pos_ue = {0};
+ get_position_coordinates(UE->Mod_id, &pos_ue);
+
+ // calculate directional vector from SAT to UE
+ const position_t dir_sat_ue = {pos_ue.X - pos_sat.X, pos_ue.Y - pos_sat.Y, pos_ue.Z - pos_sat.Z};
+
+ // calculate distance between SAT and UE
+ const double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z);
+
+ // calculate projected velocity from SAT towards UE
+ const double vel_sat_ue = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance;
+
+ // calculate DL Doppler shift (moving source)
+ const double dl_Doppler_shift = (vel_sat_ue / (SPEED_OF_LIGHT - vel_sat_ue)) * fp->dl_CarrierFreq;
+
+ // calculate UL Doppler shift (moving target)
+ const double ul_Doppler_shift = (vel_sat_ue / SPEED_OF_LIGHT) * fp->ul_CarrierFreq;
+
+ // calculate round-trip-time (factor 2) between SAT and UE in ms (factor 1000)
+ const double N_UE_TA_adj = 2000 * distance / SPEED_OF_LIGHT;
+
+ const double N_common_ta_adj = ntn_config_params->N_common_ta_adj;
+ const double N_common_ta_drift = ntn_config_params->N_common_ta_drift;
+ const double N_common_ta_drift_variant = ntn_config_params->N_common_ta_drift_variant;
+
+ if (abs_subframe_tx >= 0) {
+ UE->timing_advance_ntn = (N_UE_TA_adj + N_common_ta_adj + N_common_ta_drift * ms_since_epoch / 1e6
+ + N_common_ta_drift_variant * ((int64_t)ms_since_epoch * ms_since_epoch) / 1e9)
+ * fp->samples_per_subframe;
+ }
+
+ UE->freq_offset -= dl_Doppler_shift - UE->dl_Doppler_shift;
+ UE->dl_Doppler_shift = dl_Doppler_shift;
+ UE->ul_Doppler_shift = ul_Doppler_shift;
+
+ if (abs_subframe_tx < 0) {
+ LOG_I(PHY,
+ "satellite velocity towards UE = %f m/s, DL Doppler shift = %f kHz, UL Doppler shift = %f kHz\n",
+ vel_sat_ue,
+ dl_Doppler_shift / 1000,
+ ul_Doppler_shift / 1000);
+ }
+}
+
+// apply values based on the NTN-Config
+void apply_ntn_config(PHY_VARS_NR_UE *UE,
+ NR_DL_FRAME_PARMS *fp,
+ int hfn_rx,
+ int frame_rx,
+ int slot_rx,
+ int *duration_rx_to_tx,
+ int *timing_advance,
+ int *ntn_koffset,
+ bool *ntn_targetcell)
+{
+ // return if there is no pending update
+ if (!UE->nrUE_config.ntn_config.params_changed)
+ return;
+
+ *ntn_targetcell = UE->nrUE_config.ntn_config.is_targetcell;
+
+ // skip update if it is for the target cell
+ if (UE->nrUE_config.ntn_config.is_targetcell)
+ return;
+
+ UE->nrUE_config.ntn_config.params_changed = false;
+
+ const fapi_nr_ntn_config_t *ntn_config_params = &UE->nrUE_config.ntn_config;
+
+ const int mu = fp->numerology_index;
+ const int koffset = ntn_config_params->cell_specific_k_offset;
+
+ *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
+ if (koffset > *ntn_koffset)
+ *timing_advance += get_samples_slot_duration(fp, slot_rx, (koffset - *ntn_koffset) << mu);
+ else if (koffset < *ntn_koffset)
+ *timing_advance -= get_samples_slot_duration(fp, slot_rx, (*ntn_koffset - koffset) << mu);
+ *ntn_koffset = koffset;
+
+ const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
+ apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
+
+ LOG_I(PHY,
+ "k_offset: %dms, N_Common_Ta: %fms, drift: %fยตs/s, variant: %fยตs/sยฒ, "
+ "timing_advance_ntn: %d samples, DL Doppler shift: %fkHz, UL Doppler shift: %fkHz\n",
+ koffset << mu,
+ ntn_config_params->N_common_ta_adj,
+ ntn_config_params->N_common_ta_drift,
+ ntn_config_params->N_common_ta_drift_variant,
+ UE->timing_advance_ntn,
+ UE->dl_Doppler_shift / 1000,
+ UE->ul_Doppler_shift / 1000);
+}
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
index ed348986e8..2a24902295 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
@@ -330,7 +330,17 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
pdsch_scope_req_t *scope_req);
int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t slot, c16_t **txData);
-
+void apply_ntn_config(PHY_VARS_NR_UE *UE,
+ NR_DL_FRAME_PARMS *fp,
+ int hfn_rx,
+ int frame_rx,
+ int slot_rx,
+ int *duration_rx_to_tx,
+ int *timing_advance,
+ int *ntn_koffset,
+ bool *ntn_targetcell);
+void fix_ntn_epoch_hfn(PHY_VARS_NR_UE *UE, int hfn, int frame);
+void apply_ntn_timing_advance_and_doppler(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx);
void dump_nrdlsch(PHY_VARS_NR_UE *ue,uint8_t gNB_id,uint8_t nr_slot_rx,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid);
void nr_a_sum_b(c16_t *input_x, c16_t *input_y, unsigned short nb_rb);
diff --git a/openair1/PHY/TOOLS/calibration_test.c b/openair1/PHY/TOOLS/calibration_test.c
index 4d88ab542a..8007040499 100644
--- a/openair1/PHY/TOOLS/calibration_test.c
+++ b/openair1/PHY/TOOLS/calibration_test.c
@@ -108,10 +108,6 @@ int main(int argc, char **argv) {
.sdr_addrs=usrp_addrs,
//! Auto calibration flag
.autocal={0},
- //! rf devices work with x bits iqs when oai have its own iq format
- //! the two following parameters are used to convert iqs
- .iq_txshift=0,
- .iq_rxrescale=0,
//! Configuration file for LMS7002M
.configFilename="",
//! remote IP/MAC addr for Ethernet interface
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index f2452221d6..18f6f3f605 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -1742,7 +1742,7 @@ int main(int argc, char *argv[])
printStatIndent2(&gNB->rx_pusch_symbol_processing_stats, "RX PUSCH Symbol Processing time");
printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time");
printStatIndent2(&gNB->ts_deinterleave, "ULSCH segment deinterleaving time");
- printStatIndent2(&gNB->ts_rate_unmatch, "ULSCH segment rate recovery time");
+ printStatIndent2(&gNB->ts_rate_unmatch, "ULSCH segment rate matching time");
printStatIndent2(&gNB->ts_ldpc_decode, "ULSCH segments decoding time");
printStatIndent(&gNB->rx_srs_stats,"RX SRS time");
printStatIndent2(&gNB->generate_srs_stats,"Generate SRS sequence time");
diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h
index ed93cdaadf..3bfd2e20a2 100644
--- a/openair2/COMMON/ngap_messages_types.h
+++ b/openair2/COMMON/ngap_messages_types.h
@@ -473,8 +473,8 @@ typedef struct {
cell_id_t id;
// Cell type
uint8_t type;
- // Time UE Stayed in Cell
- long time_in_cell;
+ // Time UE Stayed in Cell (seconds)
+ uint16_t time_in_cell;
// Cause
ngap_cause_t *cause;
} last_visited_ngran_cell_info_t;
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
index af6bf37aff..477e39a60a 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
@@ -38,7 +38,7 @@
#include "executables/softmodem-common.h"
#include
-void fill_dci_search_candidates(const NR_SearchSpace_t *ss, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, const uint32_t Y)
+static void fill_dci_search_candidates(const NR_SearchSpace_t *ss, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, const uint32_t Y)
{
LOG_T(NR_MAC_DCI, "Filling search candidates for DCI\n");
@@ -89,7 +89,7 @@ void fill_dci_search_candidates(const NR_SearchSpace_t *ss, fapi_nr_dl_config_dc
rel15->number_of_candidates = i;
}
-NR_ControlResourceSet_t *ue_get_coreset(const NR_BWP_PDCCH_t *config, const int coreset_id)
+static NR_ControlResourceSet_t *ue_get_coreset(const NR_BWP_PDCCH_t *config, const int coreset_id)
{
if (config->commonControlResourceSet && coreset_id == config->commonControlResourceSet->controlResourceSetId)
return config->commonControlResourceSet;
@@ -362,12 +362,12 @@ bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per
return monitor;
}
-bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac,
- const NR_SearchSpace_t *ss,
- const int abs_slot,
- const int frame,
- const int slot,
- const int slots_per_frame)
+static bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac,
+ const NR_SearchSpace_t *ss,
+ const int abs_slot,
+ const int frame,
+ const int slot,
+ const int slots_per_frame)
{
const int duration = ss->duration ? *ss->duration : 1;
int period, offset;
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c
index 860089165f..a409cbe653 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c
@@ -58,13 +58,6 @@ static const int nb_symbols_excluding_dmrs[11][2][2]
/* 14 */ {{ 12 , 12 } , { 10 , 10 }},
};
-static int get_deltatf(uint16_t nb_of_prbs,
- uint8_t N_symb_PUCCH,
- uint8_t freq_hop_flag,
- uint8_t add_dmrs_flag,
- int N_sc_ctrl_RB,
- int O_UCI);
-
// โMPR according to Table 6.2.2-3 38.101-1
static float get_delta_mpr(uint16_t nr_band, frame_type_t frame_type, int scs, int channel_bandwidth, int n_prbs, int start_prb, int power_class)
{
@@ -256,6 +249,28 @@ int get_sum_delta_pucch(NR_UE_MAC_INST_t *mac, int slot, frame_t frame)
return delta_tpc_sum;
}
+static int get_deltatf(uint16_t nb_of_prbs,
+ uint8_t N_symb_PUCCH,
+ uint8_t freq_hop_flag,
+ uint8_t add_dmrs_flag,
+ int N_sc_ctrl_RB,
+ int O_UCI)
+{
+ int DELTA_TF;
+ int O_CRC = compute_pucch_crc_size(O_UCI);
+ int N_symb = N_symb_PUCCH < 4 ? N_symb_PUCCH : nb_symbols_excluding_dmrs[N_symb_PUCCH - 4][add_dmrs_flag][freq_hop_flag];
+ float N_RE = nb_of_prbs * N_sc_ctrl_RB * N_symb;
+ float K1 = 6;
+ if (O_UCI + O_CRC < 12)
+ DELTA_TF = 10 * log10((double)(((K1 * (O_UCI)) / N_RE)));
+ else {
+ float K2 = 2.4;
+ float BPRE = (O_UCI + O_CRC) / N_RE;
+ DELTA_TF = 10 * log10((double)(pow(2, (K2 * BPRE)) - 1));
+ }
+ return DELTA_TF;
+}
+
// PUCCH Power control according to 38.213 section 7.2.1
int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
int scs,
@@ -399,28 +414,6 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
return pucch_power;
}
-static int get_deltatf(uint16_t nb_of_prbs,
- uint8_t N_symb_PUCCH,
- uint8_t freq_hop_flag,
- uint8_t add_dmrs_flag,
- int N_sc_ctrl_RB,
- int O_UCI)
-{
- int DELTA_TF;
- int O_CRC = compute_pucch_crc_size(O_UCI);
- int N_symb = N_symb_PUCCH < 4 ? N_symb_PUCCH : nb_symbols_excluding_dmrs[N_symb_PUCCH - 4][add_dmrs_flag][freq_hop_flag];
- float N_RE = nb_of_prbs * N_sc_ctrl_RB * N_symb;
- float K1 = 6;
- if (O_UCI + O_CRC < 12)
- DELTA_TF = 10 * log10((double)(((K1 * (O_UCI)) / N_RE)));
- else {
- float K2 = 2.4;
- float BPRE = (O_UCI + O_CRC) / N_RE;
- DELTA_TF = 10 * log10((double)(pow(2, (K2 * BPRE)) - 1));
- }
- return DELTA_TF;
-}
-
// Returns the pathloss in dB for the active UL BWP on the selected carrier based on the DL RS associated with the PRACH transmission
// computation according to clause 7.4 (Physical random access channel) of 3GPP TS 38.213 version 16.3.0 Release 16
// Assumptions:
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 241a56b180..3ba221386f 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -104,58 +104,7 @@ static const int sequence_cyclic_shift_2_harq_ack_bits[4]
/* HARQ-ACK Value (0,0) (0,1) (1,0) (1,1) */
/* Sequence cyclic shift */ = { 0, 3, 9, 6 };
-/* \brief Function called by PHY to process the received RAR and check that the preamble matches what was sent by the gNB. It
-provides the timing advance and t-CRNTI.
-@param Mod_id Index of UE instance
-@param CC_id Index to a component carrier
-@param frame Frame index
-@param ra_rnti RA_RNTI value
-@param dlsch_buffer Pointer to dlsch_buffer containing RAR PDU
-@param t_crnti Pointer to PHY variable containing the T_CRNTI
-@param preamble_index Preamble Index used by PHY to transmit the PRACH. This should match the received RAR to trigger the rest of
-random-access procedure
-@param selected_rar_buffer the output buffer for storing the selected RAR header and RAR payload
-@returns timing advance or 0xffff if preamble doesn't match
-*/
-static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id);
-
-/*! \fn int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id);
- \brief This function schedules a positive or negative SR for schedulingRequestID sr_id
- depending on the presence of any active SR and the prohibit timer.
- If the max number of retransmissions is reached, it triggers a new RA */
-static int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id);
-
-static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
- struct NR_CSI_ReportConfig *csi_reportconfig,
- NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
- NR_CSI_MeasConfig_t *csi_MeasConfig);
-
-static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac,
- struct NR_CSI_ReportConfig *csi_reportconfig,
- NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
- NR_CSI_MeasConfig_t *csi_MeasConfig,
- CSI_mapping_t mapping_type);
-static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac,
- struct NR_CSI_ReportConfig *csi_reportconfig,
- NR_CSI_ResourceConfigId_t csi_ResourceConfigId,
- const NR_CSI_MeasConfig_t *csi_MeasConfig);
-
-static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp);
-
-static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id);
-
-static void set_harq_status(NR_UE_MAC_INST_t *mac,
- uint8_t pucch_id,
- uint8_t harq_id,
- int8_t delta_pucch,
- uint16_t data_toul_fb,
- uint8_t dai,
- int n_CCE,
- int N_CCE,
- frame_t frame,
- int slot);
-
-int get_pucch0_mcs(const int O_ACK, const int O_SR, const int ack_payload, const int sr_payload)
+static int get_pucch0_mcs(const int O_ACK, const int O_SR, const int ack_payload, const int sr_payload)
{
int mcs = 0;
if (O_SR == 0 || sr_payload == 0) { /* only ack is transmitted TS 36.213 9.2.3 UE procedure for reporting HARQ-ACK */
@@ -197,14 +146,6 @@ const initial_pucch_resource_t initial_pucch_resource[16] = {
/* 15 */ { 1, 0, 14, 0, 4, { 0, 3, 6, 9 } },
};
-static nr_dci_format_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
- const nfapi_nr_dci_formats_e dci_format,
- const uint8_t dci_size,
- const uint16_t rnti,
- const int ss_type,
- const uint8_t *dci_pdu,
- const int slot);
-
int get_rnti_type(const NR_UE_MAC_INST_t *mac, const uint16_t rnti)
{
const RA_config_t *ra = &mac->ra;
@@ -523,6 +464,71 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p
return 0;
}
+static void set_harq_status(NR_UE_MAC_INST_t *mac,
+ uint8_t pucch_id,
+ uint8_t harq_id,
+ int8_t delta_pucch,
+ uint16_t data_toul_fb,
+ uint8_t dai,
+ int n_CCE,
+ int N_CCE,
+ frame_t frame,
+ int slot)
+{
+ NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id];
+ current_harq->active = true;
+ current_harq->ack_received = false;
+ current_harq->pucch_resource_indicator = pucch_id;
+ current_harq->n_CCE = n_CCE;
+ current_harq->N_CCE = N_CCE;
+ current_harq->dai_cumul = 0;
+ current_harq->delta_pucch = delta_pucch;
+ // FIXME k0 != 0 currently not taken into consideration
+ int slots_per_frame = mac->frame_structure.numb_slots_frame;
+ current_harq->ul_frame = frame;
+ current_harq->ul_slot = slot + data_toul_fb;
+ if (current_harq->ul_slot >= slots_per_frame) {
+ current_harq->ul_frame = (frame + current_harq->ul_slot / slots_per_frame) % MAX_FRAME_NUMBER;
+ current_harq->ul_slot %= slots_per_frame;
+ }
+ // counter DAI in DCI ranges from 0 to 3
+ // we might have more than 4 HARQ processes to report per PUCCH
+ // we need to keep track of how many DAI we received in a slot (dai_cumul) despite the modulo operation
+ int highest_dai = -1;
+ int temp_dai = dai;
+ const int num_dl_harq = get_nrofHARQ_ProcessesForPDSCH(&mac->sc_info);
+ for (int i = 0; i < num_dl_harq; i++) {
+ // looking for other active HARQ processes with feedback in the same frame/slot
+ if (i == harq_id)
+ continue;
+ NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i];
+ if (harq->active &&
+ harq->ul_frame == current_harq->ul_frame &&
+ harq->ul_slot == current_harq->ul_slot) {
+ // highest_dai is the largest cumulative dai in the set of HARQ allocations for a given slot
+ if (harq->dai_cumul > highest_dai)
+ highest_dai = harq->dai_cumul - 1;
+ }
+ }
+
+ current_harq->dai_cumul = temp_dai + 1; // DAI = 0 (temp_dai) corresponds to 1st assignment and so on
+ // if temp_dai is less or equal than cumulative highest dai for given slot
+ // it's an indication dai was reset due to modulo 4 operation
+ if (temp_dai <= highest_dai) {
+ int mod4_count = (highest_dai + 1) / 4; // to take into account how many times dai wrapped up (modulo 4)
+ current_harq->dai_cumul += (mod4_count * 4);
+ }
+ LOG_D(NR_MAC,
+ "Setting harq_status for harq_id %d, dl %d.%d, sched ul %d.%d fb time %d total dai %d\n",
+ harq_id,
+ frame,
+ slot,
+ current_harq->ul_frame,
+ current_harq->ul_slot,
+ data_toul_fb,
+ current_harq->dai_cumul);
+}
+
static int nr_ue_process_dci_ul_00(NR_UE_MAC_INST_t *mac,
frame_t frame,
int slot,
@@ -1486,27 +1492,6 @@ static int8_t nr_ue_process_dci(NR_UE_MAC_INST_t *mac,
return -1;
}
-nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci)
-{
- LOG_D(NR_MAC,
- "Received dci indication (rnti %x, dci format %d, n_CCE %d, payloadSize %d, payload %llx)\n",
- dci->rnti,
- dci->dci_format,
- dci->n_CCE,
- dci->payloadSize,
- *(unsigned long long *)dci->payloadBits);
- const nr_dci_format_t format =
- nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, dci->payloadBits, slot);
- if (format == NR_DCI_NONE)
- return NR_DCI_NONE;
- int ret = nr_ue_process_dci(mac, frame, slot, mac->def_dci_pdu_rel15[slot] + format, dci, format);
- if (ret < 0) {
- mac->stats.bad_dci++;
- return NR_DCI_NONE;
- }
- return format;
-}
-
void nr_ue_process_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_l1_measurements_t *l1_measurements)
{
LOG_D(NR_MAC, "(%d.%d) Received measurements from L1\n", frame, slot);
@@ -1530,71 +1515,6 @@ void nr_ue_process_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slo
l1_measurements->rsrp_dBm);
}
-static void set_harq_status(NR_UE_MAC_INST_t *mac,
- uint8_t pucch_id,
- uint8_t harq_id,
- int8_t delta_pucch,
- uint16_t data_toul_fb,
- uint8_t dai,
- int n_CCE,
- int N_CCE,
- frame_t frame,
- int slot)
-{
- NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id];
- current_harq->active = true;
- current_harq->ack_received = false;
- current_harq->pucch_resource_indicator = pucch_id;
- current_harq->n_CCE = n_CCE;
- current_harq->N_CCE = N_CCE;
- current_harq->dai_cumul = 0;
- current_harq->delta_pucch = delta_pucch;
- // FIXME k0 != 0 currently not taken into consideration
- int slots_per_frame = mac->frame_structure.numb_slots_frame;
- current_harq->ul_frame = frame;
- current_harq->ul_slot = slot + data_toul_fb;
- if (current_harq->ul_slot >= slots_per_frame) {
- current_harq->ul_frame = (frame + current_harq->ul_slot / slots_per_frame) % MAX_FRAME_NUMBER;
- current_harq->ul_slot %= slots_per_frame;
- }
- // counter DAI in DCI ranges from 0 to 3
- // we might have more than 4 HARQ processes to report per PUCCH
- // we need to keep track of how many DAI we received in a slot (dai_cumul) despite the modulo operation
- int highest_dai = -1;
- int temp_dai = dai;
- const int num_dl_harq = get_nrofHARQ_ProcessesForPDSCH(&mac->sc_info);
- for (int i = 0; i < num_dl_harq; i++) {
- // looking for other active HARQ processes with feedback in the same frame/slot
- if (i == harq_id)
- continue;
- NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i];
- if (harq->active &&
- harq->ul_frame == current_harq->ul_frame &&
- harq->ul_slot == current_harq->ul_slot) {
- // highest_dai is the largest cumulative dai in the set of HARQ allocations for a given slot
- if (harq->dai_cumul > highest_dai)
- highest_dai = harq->dai_cumul - 1;
- }
- }
-
- current_harq->dai_cumul = temp_dai + 1; // DAI = 0 (temp_dai) corresponds to 1st assignment and so on
- // if temp_dai is less or equal than cumulative highest dai for given slot
- // it's an indication dai was reset due to modulo 4 operation
- if (temp_dai <= highest_dai) {
- int mod4_count = (highest_dai + 1) / 4; // to take into account how many times dai wrapped up (modulo 4)
- current_harq->dai_cumul += (mod4_count * 4);
- }
- LOG_D(NR_MAC,
- "Setting harq_status for harq_id %d, dl %d.%d, sched ul %d.%d fb time %d total dai %d\n",
- harq_id,
- frame,
- slot,
- current_harq->ul_frame,
- current_harq->ul_slot,
- data_toul_fb,
- current_harq->dai_cumul);
-}
-
initial_pucch_resource_t get_initial_pucch_resource(const int idx)
{
return initial_pucch_resource[idx];
@@ -2566,51 +2486,11 @@ bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sche
return (number_harq_feedback > 0);
}
-bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch, frame_t frame, int slot)
-{
- NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
- NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL;
-
- if(!pucch_Config ||
- !pucch_Config->schedulingRequestResourceToAddModList ||
- pucch_Config->schedulingRequestResourceToAddModList->list.count == 0)
- return false; // SR not configured
-
- int sr_count = 0;
- for (int id = 0; id < pucch_Config->schedulingRequestResourceToAddModList->list.count; id++) {
- NR_SchedulingRequestResourceConfig_t *sr_Config = pucch_Config->schedulingRequestResourceToAddModList->list.array[id];
- int SR_period; int SR_offset;
-
- find_period_offset_SR(sr_Config, &SR_period, &SR_offset);
- const int n_slots_frame = mac->frame_structure.numb_slots_frame;
- int sfn_sf = frame * n_slots_frame + slot;
-
- if ((sfn_sf - SR_offset) % SR_period == 0) {
- LOG_D(MAC, "Scheduling Request active in frame %d slot %d \n", frame, slot);
- if (!sr_Config->resource) {
- LOG_E(MAC, "No resource associated with SR. SR not scheduled\n");
- break;
- }
- NR_PUCCH_Resource_t *sr_pucch =
- find_pucch_resource_from_list(pucch_Config->resourceToAddModList, *sr_Config->resource);
- AssertFatal(sr_pucch != NULL, "Couldn't find PUCCH Resource ID for SR in PUCCH resource list\n");
- pucch->pucch_resource = sr_pucch;
- pucch->n_sr = 1;
- /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */
- int ret = nr_ue_get_SR(mac, frame, slot, sr_Config->schedulingRequestID);
- if (ret < 0) {
- memset(pucch, 0, sizeof(*pucch));
- return false;
- }
- pucch->sr_payload = ret;
- sr_count++;
- AssertFatal(sr_count < 2, "Cannot handle more than 1 SR per slot yet\n");
- }
- }
- return sr_count > 0;
-}
-
-static int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id)
+/*! \fn int nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id);
+ \brief This function schedules a positive or negative SR for schedulingRequestID sr_id
+ depending on the presence of any active SR and the prohibit timer.
+ If the max number of retransmissions is reached, it triggers a new RA */
+static int nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id)
{
// no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti
NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info;
@@ -2660,6 +2540,50 @@ static int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR
return -1;
}
+bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch, frame_t frame, int slot)
+{
+ NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
+ NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL;
+
+ if(!pucch_Config ||
+ !pucch_Config->schedulingRequestResourceToAddModList ||
+ pucch_Config->schedulingRequestResourceToAddModList->list.count == 0)
+ return false; // SR not configured
+
+ int sr_count = 0;
+ for (int id = 0; id < pucch_Config->schedulingRequestResourceToAddModList->list.count; id++) {
+ NR_SchedulingRequestResourceConfig_t *sr_Config = pucch_Config->schedulingRequestResourceToAddModList->list.array[id];
+ int SR_period; int SR_offset;
+
+ find_period_offset_SR(sr_Config, &SR_period, &SR_offset);
+ const int n_slots_frame = mac->frame_structure.numb_slots_frame;
+ int sfn_sf = frame * n_slots_frame + slot;
+
+ if ((sfn_sf - SR_offset) % SR_period == 0) {
+ LOG_D(MAC, "Scheduling Request active in frame %d slot %d \n", frame, slot);
+ if (!sr_Config->resource) {
+ LOG_E(MAC, "No resource associated with SR. SR not scheduled\n");
+ break;
+ }
+ NR_PUCCH_Resource_t *sr_pucch =
+ find_pucch_resource_from_list(pucch_Config->resourceToAddModList, *sr_Config->resource);
+ AssertFatal(sr_pucch != NULL, "Couldn't find PUCCH Resource ID for SR in PUCCH resource list\n");
+ pucch->pucch_resource = sr_pucch;
+ pucch->n_sr = 1;
+ /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */
+ int ret = nr_ue_get_SR(mac, frame, slot, sr_Config->schedulingRequestID);
+ if (ret < 0) {
+ memset(pucch, 0, sizeof(*pucch));
+ return false;
+ }
+ pucch->sr_payload = ret;
+ sr_count++;
+ AssertFatal(sr_count < 2, "Cannot handle more than 1 SR per slot yet\n");
+ }
+ }
+ return sr_count > 0;
+}
+
// section 5.2.5 of 38.214
int compute_csi_priority(NR_UE_MAC_INST_t *mac, NR_CSI_ReportConfig_t *csirep)
{
@@ -2855,52 +2779,6 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac,
return csi;
}
-csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
- int csi_report_id,
- CSI_mapping_t mapping_type,
- NR_CSI_MeasConfig_t *csi_MeasConfig)
-{
- AssertFatal(csi_MeasConfig->csi_ReportConfigToAddModList->list.count > 0,"No CSI Report configuration available\n");
- csi_payload_t csi = {0};
- struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
- NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement;
- if (csi_reportconfig->ext2 && csi_reportconfig->ext2->reportQuantity_r16) {
- switch (csi_reportconfig->ext2->reportQuantity_r16->present) {
- case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16:
- csi = get_ssb_sinr_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
- break;
- case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_cri_SINR_r16:
- LOG_E(NR_MAC, "CSI Reporting of CSI-RS based SINR not yet available\n");
- break;
- default:
- AssertFatal(1 == 0, "Invalid CSI report quantity r16 type %d\n", csi_reportconfig->ext2->reportQuantity_r16->present);
- }
- } else {
- switch (csi_reportconfig->reportQuantity.present) {
- case NR_CSI_ReportConfig__reportQuantity_PR_none:
- break;
- case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
- csi = get_ssb_rsrp_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
- break;
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
- csi = get_csirs_RI_PMI_CQI_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig, mapping_type);
- break;
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
- csi = get_csirs_RSRP_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
- break;
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1:
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI:
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
- LOG_E(NR_MAC, "Measurement report %d based on CSI-RS is not available\n", csi_reportconfig->reportQuantity.present);
- break;
- default:
- AssertFatal(1 == 0, "Invalid CSI report quantity type %d\n", csi_reportconfig->reportQuantity.present);
- }
- }
- return csi;
-}
-
// Comparison function for sorting SSB RSRP measurements in descending order
static int compare_ssb_rsrp(const void *a, const void *b)
{
@@ -2909,6 +2787,16 @@ static int compare_ssb_rsrp(const void *a, const void *b)
return mb->ssb_rsrp_dBm - ma->ssb_rsrp_dBm;
}
+// returns index from differential RSRP
+// according to Table 10.1.6.1-2 in 38.133
+static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp)
+{
+ int diff = best_rsrp-current_rsrp;
+ if (diff>30)
+ return 15;
+ else
+ return (diff>>1);
+}
static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac,
struct NR_CSI_ReportConfig *csi_reportconfig,
@@ -3121,49 +3009,300 @@ static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac,
return csi;
}
-// returns index from differential RSRP
-// according to Table 10.1.6.1-2 in 38.133
-static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp)
+csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac,
+ int csi_report_id,
+ CSI_mapping_t mapping_type,
+ NR_CSI_MeasConfig_t *csi_MeasConfig)
{
- int diff = best_rsrp-current_rsrp;
- if (diff>30)
- return 15;
- else
- return (diff>>1);
+ AssertFatal(csi_MeasConfig->csi_ReportConfigToAddModList->list.count > 0,"No CSI Report configuration available\n");
+ csi_payload_t csi = {0};
+ struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
+ NR_CSI_ResourceConfigId_t csi_ResourceConfigId = csi_reportconfig->resourcesForChannelMeasurement;
+ if (csi_reportconfig->ext2 && csi_reportconfig->ext2->reportQuantity_r16) {
+ switch (csi_reportconfig->ext2->reportQuantity_r16->present) {
+ case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16:
+ csi = get_ssb_sinr_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
+ break;
+ case NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_cri_SINR_r16:
+ LOG_E(NR_MAC, "CSI Reporting of CSI-RS based SINR not yet available\n");
+ break;
+ default:
+ AssertFatal(1 == 0, "Invalid CSI report quantity r16 type %d\n", csi_reportconfig->ext2->reportQuantity_r16->present);
+ }
+ } else {
+ switch (csi_reportconfig->reportQuantity.present) {
+ case NR_CSI_ReportConfig__reportQuantity_PR_none:
+ break;
+ case NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP:
+ csi = get_ssb_rsrp_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
+ break;
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
+ csi = get_csirs_RI_PMI_CQI_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig, mapping_type);
+ break;
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
+ csi = get_csirs_RSRP_payload(mac, csi_reportconfig, csi_ResourceConfigId, csi_MeasConfig);
+ break;
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1:
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI:
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
+ LOG_E(NR_MAC, "Measurement report %d based on CSI-RS is not available\n", csi_reportconfig->reportQuantity.present);
+ break;
+ default:
+ AssertFatal(1 == 0, "Invalid CSI report quantity type %d\n", csi_reportconfig->reportQuantity.present);
+ }
+ }
+ return csi;
}
-void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id)
+static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, int frame, int slot)
{
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
+ NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
+ ul_time_alignment->ta_command = ta;
+ ul_time_alignment->ta_apply = type;
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
+ const int n_slots_frame = mac->frame_structure.numb_slots_frame;
+ ul_time_alignment->frame = (frame + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER;
+ ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame;
+ // start or restart the timeAlignmentTimer associated with the indicated TAG
+ nr_timer_start(&mac->time_alignment_timer);
+}
- LOG_D(NR_MAC,
- "In [%d.%d] Handling DLSCH PDU type %d\n",
- dl_info->frame,
- dl_info->slot,
- dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type);
+static void handle_rar_reception(NR_UE_MAC_INST_t *mac, NR_MAC_RAR *rar, frame_t frame, int slot)
+{
+ RAR_grant_t rar_grant;
+ RA_config_t *ra = &mac->ra;
+#ifdef DEBUG_RAR
+ // CSI
+ unsigned char csi_req = (unsigned char)(rar->UL_GRANT_4 & 0x01);
+#endif
- // Processing MAC PDU
- // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs
- switch (dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type) {
- case FAPI_NR_RX_PDU_TYPE_DLSCH :
- // start or restart dataInactivityTimer if any MAC entity receives a MAC SDU for DTCH logical channel,
- // DCCH logical channel, or CCCH logical channel
- if (mac->data_inactivity_timer)
- nr_timer_start(mac->data_inactivity_timer);
- // DL data arrival during RRC_CONNECTED when UL synchronisation status is "non-synchronised"
- if (!nr_timer_is_active(&mac->time_alignment_timer) && mac->state == UE_CONNECTED && !get_softmodem_params()->phy_test) {
- trigger_MAC_UE_RA(mac, NULL);
+ // TPC
+ unsigned char tpc_command = (unsigned char)((rar->UL_GRANT_4 >> 1) & 0x07);
+ ra->Msg3_TPC = (tpc_command << 1) - 6;
+
+ // MCS
+ rar_grant.mcs = (unsigned char)(rar->UL_GRANT_4 >> 4);
+ // time alloc
+ rar_grant.Msg3_t_alloc = (unsigned char)(rar->UL_GRANT_3 & 0x0f);
+ // frequency alloc
+ rar_grant.Msg3_f_alloc = (uint16_t)((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12));
+ // frequency hopping
+ rar_grant.freq_hopping = (unsigned char)(rar->UL_GRANT_1 >> 2);
+
+ // Schedule Msg3
+ const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
+ const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
+ const NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[current_DL_BWP->bwp_id];
+ const NR_SearchSpace_t *ra_SS = get_common_search_space(mac, pdcch_config->ra_SS_id);
+ NR_tda_info_t tda_info = get_ul_tda_info(current_UL_BWP,
+ *ra_SS->controlResourceSetId,
+ ra_SS->searchSpaceType->present,
+ TYPE_RA_RNTI_,
+ rar_grant.Msg3_t_alloc);
+ if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0) {
+ LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n");
+ // resume RAR response window timer if MSG2 decoding failed
+ nr_timer_suspension(&mac->ra.response_window_timer);
+ return;
+ }
+ frame_t frame_tx = 0;
+ int slot_tx = 0;
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
+ int ret = nr_ue_pusch_scheduler(mac, 1, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset);
+
+ // TA command
+ // if the timeAlignmentTimer associated with this TAG is not running
+ if (!nr_timer_is_active(&mac->time_alignment_timer)) {
+ const int ta = rar->TA2 + (rar->TA1 << 5);
+ set_time_alignment(mac, ta, rar_ta, frame_tx, slot_tx);
+ LOG_W(MAC, "received TA command %d\n", 31 + ta);
+ }
+ // else ignore the received Timing Advance Command
+
+#ifdef DEBUG_RAR
+ LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E);
+ LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T);
+ LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID);
+
+ LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R);
+ LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1);
+
+ LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2);
+ LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1);
+
+ LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2);
+ LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3);
+ LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4);
+
+ LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1);
+ LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2);
+
+ LOG_I(NR_MAC,
+ "[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d\n",
+ frame,
+ slot,
+ mac->ue_id,
+ rar_grant.Msg3_t_alloc,
+ rar_grant.Msg3_f_alloc,
+ ta_command,
+ rar_grant.mcs,
+ rar_grant.freq_hopping,
+ tpc_command);
+#endif
+
+ if (ret != -1) {
+ uint16_t rnti = mac->crnti;
+ // Upon successful reception, set the T-CRNTI to the RAR value
+ // if the RA preamble is selected among the contention-based RA Preambles
+ if (!ra->cfra) {
+ ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
+ rnti = ra->t_crnti;
+ if (!mac->msg3_C_RNTI)
+ nr_mac_rrc_msg3_ind(mac->ue_id, rnti, false);
+ }
+ fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
+ if (!pdu)
+ return;
+ // Config Msg3 PDU
+ int ret = nr_config_pusch_pdu(mac,
+ &tda_info,
+ &pdu->pusch_config_pdu,
+ NULL,
+ NULL,
+ &rar_grant,
+ rnti,
+ NR_SearchSpace__searchSpaceType_PR_common,
+ NR_DCI_NONE);
+ if (ret != 0)
+ remove_ul_config_last_item(pdu);
+ release_ul_config(pdu, false);
+ }
+}
+
+/////////////////////////////////////
+// Random Access Response PDU //
+// TS 38.213 ch 8.2 //
+// TS 38.321 ch 6.2.3 //
+/////////////////////////////////////
+//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
+//| E | T | R A P I D |//
+//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |//
+//| R | T A |//
+//| T A | UL grant |//
+//| UL grant |//
+//| UL grant |//
+//| UL grant |//
+//| T C - R N T I |//
+//| T C - R N T I |//
+/////////////////////////////////////
+// UL grant (27 bits) //
+/////////////////////////////////////
+//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
+//|-------------------|FHF|F_alloc|//
+//| Freq allocation |//
+//| F_alloc |Time allocation|//
+//| MCS | TPC |CSI|//
+/////////////////////////////////////
+// TbD WIP Msg3 development ongoing
+// - apply UL grant freq alloc & time alloc as per 8.2 TS 38.213
+// - apply tpc command
+// WIP fix:
+// - time domain indication hardcoded to 0 for k2 offset
+// - extend TS 38.213 ch 8.3 Msg3 PUSCH
+// - b buffer
+// - ulsch power offset
+// - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures
+static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id)
+{
+ frame_t frame = dl_info->frame;
+ int slot = dl_info->slot;
+
+ if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack == 0) {
+ LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] CRC check failed on RAR (NAK)\n", mac->ue_id, frame, slot);
+ return;
+ }
+
+ RA_config_t *ra = &mac->ra;
+ ra->t_crnti = 0;
+ uint8_t n_subPDUs = 0; // number of RAR payloads
+ uint8_t n_subheaders = 0; // number of MAC RAR subheaders
+ uint8_t *dlsch_buffer = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu;
+ NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer
+ NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer
+ uint8_t preamble_index = ra->ra_PreambleIndex;
+ uint16_t rnti = mac->ra.ra_rnti;
+
+ T(T_NRUE_MAC_DL_RAR_PDU_WITH_DATA, T_INT(rnti), T_INT(frame), T_INT(slot),
+ T_BUFFER(dlsch_buffer, dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu_length));
+
+ ra->RA_backoff_limit = 0;
+ LOG_D(NR_MAC, "[%d.%d]: [UE %d][RAPROC] MAC received RAR (current preamble %d)\n", frame, slot, mac->ue_id, preamble_index);
+
+ while (1) {
+ n_subheaders++;
+ if (rarh->T == 1) {
+ n_subPDUs++;
+ LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got RAPID RAR subPDU\n", mac->ue_id, rnti);
+ } else {
+ int bi_ms = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI] * ra->scaling_factor_bi;
+ int slots_per_ms = mac->frame_structure.numb_slots_frame / 10;
+ ra->RA_backoff_limit = bi_ms * slots_per_ms;
+ LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got BI RAR subPDU %d ms\n", mac->ue_id, rnti, bi_ms);
+ if (((NR_RA_HEADER_BI *)rarh)->E == 1) {
+ rarh += sizeof(NR_RA_HEADER_BI);
+ continue;
+ } else {
break;
}
- nr_ue_process_mac_pdu(mac, dl_info, pdu_id);
+ }
+ if (rarh->RAPID == preamble_index) {
+ // The MAC entity may stop ra-ResponseWindow (and hence monitoring for Random Access Response(s)) after
+ // successful reception of a Random Access Response containing Random Access Preamble identifiers
+ // that matches the transmitted PREAMBLE_INDEX.
+ nr_timer_stop(&ra->response_window_timer);
+ LOG_A(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mac->ue_id, frame, slot, rarh->RAPID);
+ rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR));
+ handle_rar_reception(mac, rar, frame, slot);
+ if (ra->cfra)
+ nr_ra_succeeded(mac, dl_info->gNB_index, frame, slot);
break;
- case FAPI_NR_RX_PDU_TYPE_RAR :
- nr_ue_process_rar(mac, dl_info, pdu_id);
+ }
+ if (rarh->E == 0) {
+ LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] Received RAR preamble (%d) doesn't match the intended RAPID (%d)\n",
+ mac->ue_id,
+ frame,
+ slot,
+ rarh->RAPID,
+ preamble_index);
+ // resume RAR response window timer if MSG2 decoding failed
+ nr_timer_suspension(&mac->ra.response_window_timer);
break;
- default :
- AssertFatal(false, "Invalid DLSCH PDU type\n");
+ } else {
+ rarh += sizeof(NR_MAC_RAR) + 1;
+ }
}
- VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
+
+#ifdef DEBUG_RAR
+ LOG_D(NR_MAC,
+ "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n",
+ frame,
+ slot,
+ n_subheaders,
+ n_subPDUs);
+ LOG_D(NR_MAC,
+ "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n",
+ *(uint8_t *) rarh,
+ rar[0],
+ rar[1],
+ rar[2],
+ rar[3],
+ rar[4],
+ rar[5],
+ rarh->RAPID,
+ preamble_index);
+#endif
+ return;
}
// #define EXTRACT_DCI_ITEM(val,size) val= readBits(dci_pdu, &pos, size);
@@ -3615,17 +3754,25 @@ static nr_dci_format_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
return format;
}
-static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, int frame, int slot)
+nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci)
{
- NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
- ul_time_alignment->ta_command = ta;
- ul_time_alignment->ta_apply = type;
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
- const int n_slots_frame = mac->frame_structure.numb_slots_frame;
- ul_time_alignment->frame = (frame + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER;
- ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame;
- // start or restart the timeAlignmentTimer associated with the indicated TAG
- nr_timer_start(&mac->time_alignment_timer);
+ LOG_D(NR_MAC,
+ "Received dci indication (rnti %x, dci format %d, n_CCE %d, payloadSize %d, payload %llx)\n",
+ dci->rnti,
+ dci->dci_format,
+ dci->n_CCE,
+ dci->payloadSize,
+ *(unsigned long long *)dci->payloadBits);
+ const nr_dci_format_t format =
+ nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, dci->payloadBits, slot);
+ if (format == NR_DCI_NONE)
+ return NR_DCI_NONE;
+ int ret = nr_ue_process_dci(mac, frame, slot, mac->def_dci_pdu_rel15[slot] + format, dci, format);
+ if (ret < 0) {
+ mac->stats.bad_dci++;
+ return NR_DCI_NONE;
+ }
+ return format;
}
static bool check_ra_contention_resolution(const uint8_t *pdu, const uint8_t *cont_res)
@@ -4055,240 +4202,36 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
return mac_ce - pdu;
}
-static void handle_rar_reception(NR_UE_MAC_INST_t *mac, NR_MAC_RAR *rar, frame_t frame, int slot)
+void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id)
{
- RAR_grant_t rar_grant;
- RA_config_t *ra = &mac->ra;
-#ifdef DEBUG_RAR
- // CSI
- unsigned char csi_req = (unsigned char)(rar->UL_GRANT_4 & 0x01);
-#endif
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
- // TPC
- unsigned char tpc_command = (unsigned char)((rar->UL_GRANT_4 >> 1) & 0x07);
- ra->Msg3_TPC = (tpc_command << 1) - 6;
+ LOG_D(NR_MAC,
+ "In [%d.%d] Handling DLSCH PDU type %d\n",
+ dl_info->frame,
+ dl_info->slot,
+ dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type);
- // MCS
- rar_grant.mcs = (unsigned char)(rar->UL_GRANT_4 >> 4);
- // time alloc
- rar_grant.Msg3_t_alloc = (unsigned char)(rar->UL_GRANT_3 & 0x0f);
- // frequency alloc
- rar_grant.Msg3_f_alloc = (uint16_t)((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12));
- // frequency hopping
- rar_grant.freq_hopping = (unsigned char)(rar->UL_GRANT_1 >> 2);
-
- // Schedule Msg3
- const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
- const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
- const NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[current_DL_BWP->bwp_id];
- const NR_SearchSpace_t *ra_SS = get_common_search_space(mac, pdcch_config->ra_SS_id);
- NR_tda_info_t tda_info = get_ul_tda_info(current_UL_BWP,
- *ra_SS->controlResourceSetId,
- ra_SS->searchSpaceType->present,
- TYPE_RA_RNTI_,
- rar_grant.Msg3_t_alloc);
- if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0) {
- LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n");
- // resume RAR response window timer if MSG2 decoding failed
- nr_timer_suspension(&mac->ra.response_window_timer);
- return;
- }
- frame_t frame_tx = 0;
- int slot_tx = 0;
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
- int ret = nr_ue_pusch_scheduler(mac, 1, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset);
-
- // TA command
- // if the timeAlignmentTimer associated with this TAG is not running
- if (!nr_timer_is_active(&mac->time_alignment_timer)) {
- const int ta = rar->TA2 + (rar->TA1 << 5);
- set_time_alignment(mac, ta, rar_ta, frame_tx, slot_tx);
- LOG_W(MAC, "received TA command %d\n", 31 + ta);
- }
- // else ignore the received Timing Advance Command
-
-#ifdef DEBUG_RAR
- LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E);
- LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T);
- LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID);
-
- LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R);
- LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1);
-
- LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2);
- LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1);
-
- LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2);
- LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3);
- LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4);
-
- LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1);
- LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2);
-
- LOG_I(NR_MAC,
- "[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d\n",
- frame,
- slot,
- mac->ue_id,
- rar_grant.Msg3_t_alloc,
- rar_grant.Msg3_f_alloc,
- ta_command,
- rar_grant.mcs,
- rar_grant.freq_hopping,
- tpc_command);
-#endif
-
- if (ret != -1) {
- uint16_t rnti = mac->crnti;
- // Upon successful reception, set the T-CRNTI to the RAR value
- // if the RA preamble is selected among the contention-based RA Preambles
- if (!ra->cfra) {
- ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
- rnti = ra->t_crnti;
- if (!mac->msg3_C_RNTI)
- nr_mac_rrc_msg3_ind(mac->ue_id, rnti, false);
- }
- fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
- if (!pdu)
- return;
- // Config Msg3 PDU
- int ret = nr_config_pusch_pdu(mac,
- &tda_info,
- &pdu->pusch_config_pdu,
- NULL,
- NULL,
- &rar_grant,
- rnti,
- NR_SearchSpace__searchSpaceType_PR_common,
- NR_DCI_NONE);
- if (ret != 0)
- remove_ul_config_last_item(pdu);
- release_ul_config(pdu, false);
- }
-}
-
-/////////////////////////////////////
-// Random Access Response PDU //
-// TS 38.213 ch 8.2 //
-// TS 38.321 ch 6.2.3 //
-/////////////////////////////////////
-//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
-//| E | T | R A P I D |//
-//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |//
-//| R | T A |//
-//| T A | UL grant |//
-//| UL grant |//
-//| UL grant |//
-//| UL grant |//
-//| T C - R N T I |//
-//| T C - R N T I |//
-/////////////////////////////////////
-// UL grant (27 bits) //
-/////////////////////////////////////
-//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
-//|-------------------|FHF|F_alloc|//
-//| Freq allocation |//
-//| F_alloc |Time allocation|//
-//| MCS | TPC |CSI|//
-/////////////////////////////////////
-// TbD WIP Msg3 development ongoing
-// - apply UL grant freq alloc & time alloc as per 8.2 TS 38.213
-// - apply tpc command
-// WIP fix:
-// - time domain indication hardcoded to 0 for k2 offset
-// - extend TS 38.213 ch 8.3 Msg3 PUSCH
-// - b buffer
-// - ulsch power offset
-// - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures
-static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id)
-{
- frame_t frame = dl_info->frame;
- int slot = dl_info->slot;
-
- if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack == 0) {
- LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] CRC check failed on RAR (NAK)\n", mac->ue_id, frame, slot);
- return;
- }
-
- RA_config_t *ra = &mac->ra;
- ra->t_crnti = 0;
- uint8_t n_subPDUs = 0; // number of RAR payloads
- uint8_t n_subheaders = 0; // number of MAC RAR subheaders
- uint8_t *dlsch_buffer = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu;
- NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer
- NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer
- uint8_t preamble_index = ra->ra_PreambleIndex;
- uint16_t rnti = mac->ra.ra_rnti;
-
- T(T_NRUE_MAC_DL_RAR_PDU_WITH_DATA, T_INT(rnti), T_INT(frame), T_INT(slot),
- T_BUFFER(dlsch_buffer, dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu_length));
-
- ra->RA_backoff_limit = 0;
- LOG_D(NR_MAC, "[%d.%d]: [UE %d][RAPROC] MAC received RAR (current preamble %d)\n", frame, slot, mac->ue_id, preamble_index);
-
- while (1) {
- n_subheaders++;
- if (rarh->T == 1) {
- n_subPDUs++;
- LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got RAPID RAR subPDU\n", mac->ue_id, rnti);
- } else {
- int bi_ms = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI] * ra->scaling_factor_bi;
- int slots_per_ms = mac->frame_structure.numb_slots_frame / 10;
- ra->RA_backoff_limit = bi_ms * slots_per_ms;
- LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got BI RAR subPDU %d ms\n", mac->ue_id, rnti, bi_ms);
- if (((NR_RA_HEADER_BI *)rarh)->E == 1) {
- rarh += sizeof(NR_RA_HEADER_BI);
- continue;
- } else {
+ // Processing MAC PDU
+ // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs
+ switch (dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type) {
+ case FAPI_NR_RX_PDU_TYPE_DLSCH :
+ // start or restart dataInactivityTimer if any MAC entity receives a MAC SDU for DTCH logical channel,
+ // DCCH logical channel, or CCCH logical channel
+ if (mac->data_inactivity_timer)
+ nr_timer_start(mac->data_inactivity_timer);
+ // DL data arrival during RRC_CONNECTED when UL synchronisation status is "non-synchronised"
+ if (!nr_timer_is_active(&mac->time_alignment_timer) && mac->state == UE_CONNECTED && !get_softmodem_params()->phy_test) {
+ trigger_MAC_UE_RA(mac, NULL);
break;
}
- }
- if (rarh->RAPID == preamble_index) {
- // The MAC entity may stop ra-ResponseWindow (and hence monitoring for Random Access Response(s)) after
- // successful reception of a Random Access Response containing Random Access Preamble identifiers
- // that matches the transmitted PREAMBLE_INDEX.
- nr_timer_stop(&ra->response_window_timer);
- LOG_A(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mac->ue_id, frame, slot, rarh->RAPID);
- rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR));
- handle_rar_reception(mac, rar, frame, slot);
- if (ra->cfra)
- nr_ra_succeeded(mac, dl_info->gNB_index, frame, slot);
+ nr_ue_process_mac_pdu(mac, dl_info, pdu_id);
break;
- }
- if (rarh->E == 0) {
- LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] Received RAR preamble (%d) doesn't match the intended RAPID (%d)\n",
- mac->ue_id,
- frame,
- slot,
- rarh->RAPID,
- preamble_index);
- // resume RAR response window timer if MSG2 decoding failed
- nr_timer_suspension(&mac->ra.response_window_timer);
+ case FAPI_NR_RX_PDU_TYPE_RAR :
+ nr_ue_process_rar(mac, dl_info, pdu_id);
break;
- } else {
- rarh += sizeof(NR_MAC_RAR) + 1;
- }
+ default :
+ AssertFatal(false, "Invalid DLSCH PDU type\n");
}
-
-#ifdef DEBUG_RAR
- LOG_D(NR_MAC,
- "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n",
- frame,
- slot,
- n_subheaders,
- n_subPDUs);
- LOG_D(NR_MAC,
- "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n",
- *(uint8_t *) rarh,
- rar[0],
- rar[1],
- rar[2],
- rar[3],
- rar[4],
- rar[5],
- rarh->RAPID,
- preamble_index);
-#endif
- return;
+ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
}
-
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index c21a0ce3bd..2818c20c37 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -57,30 +57,6 @@
AssertFatal(ret == 0, "Failure in mutex management ret=%d\n", a); \
}
-static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP);
-static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac);
-
-static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac,
- NR_SINGLE_ENTRY_PHR_MAC_CE *phr,
- float P_CMAX,
- float tx_power,
- frame_t frame,
- slot_t slot);
-static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
- int cc_id,
- frame_t frame,
- slot_t slot,
- uint8_t gNB_index,
- uint8_t *ulsch_buffer,
- const uint32_t buflen,
- int tx_power,
- int P_MAX,
- bool *BSRsent);
-
-static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP);
-static void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot);
-static void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot);
-
static void clear_ul_config_request(NR_UE_MAC_INST_t *mac)
{
int slots = mac->frame_structure.numb_slots_frame;
@@ -1131,6 +1107,205 @@ static bool nr_ue_periodic_srs_scheduling(NR_UE_MAC_INST_t *mac, frame_t frame,
return srs_scheduled;
}
+static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac)
+{
+ NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
+ fapi_nr_ta_command_pdu *ta = &dl_config->dl_config_list[dl_config->number_pdus].ta_command_pdu;
+ ta->ta_frame = ul_time_alignment->frame;
+ ta->ta_slot = ul_time_alignment->slot;
+ ta->is_rar = ul_time_alignment->ta_apply == rar_ta;
+ ta->ta_command = ul_time_alignment->ta_command;
+ dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_CONFIG_TA_COMMAND;
+ dl_config->number_pdus += 1;
+ ul_time_alignment->ta_apply = no_ta;
+}
+
+static NR_CSI_ResourceConfigId_t find_CSI_resourceconfig(NR_CSI_MeasConfig_t *csi_measconfig,
+ NR_BWP_Id_t dl_bwp_id,
+ NR_NZP_CSI_RS_ResourceId_t csi_id)
+{
+ bool found = false;
+ for (int csi_list = 0; csi_list < csi_measconfig->csi_ResourceConfigToAddModList->list.count; csi_list++) {
+ NR_CSI_ResourceConfig_t *csires = csi_measconfig->csi_ResourceConfigToAddModList->list.array[csi_list];
+ if(csires->bwp_Id != dl_bwp_id)
+ continue;
+ struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList *resset = &csires->csi_RS_ResourceSetList;
+ if(resset->present != NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB)
+ continue;
+ if(!resset->choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)
+ continue;
+ for(int i = 0; i < resset->choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count; i++) {
+ NR_NZP_CSI_RS_ResourceSetId_t *res_id = resset->choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[i];
+ AssertFatal(res_id, "NR_NZP_CSI_RS_ResourceSetId shouldn't be NULL\n");
+ struct NR_CSI_MeasConfig__nzp_CSI_RS_ResourceSetToAddModList *res_list = csi_measconfig->nzp_CSI_RS_ResourceSetToAddModList;
+ AssertFatal(res_list, "nzp_CSI_RS_ResourceSetToAddModList shouldn't be NULL\n");
+ for (int j = 0; j < res_list->list.count; j++) {
+ NR_NZP_CSI_RS_ResourceSet_t *csi_res = res_list->list.array[j];
+ if (*res_id != csi_res->nzp_CSI_ResourceSetId)
+ continue;
+ for (int k = 0; k < csi_res->nzp_CSI_RS_Resources.list.count; k++) {
+ AssertFatal(csi_res->nzp_CSI_RS_Resources.list.array[k], "NZP_CSI_RS_ResourceId shoulan't be NULL\n");
+ if (csi_id == *csi_res->nzp_CSI_RS_Resources.list.array[k]) {
+ found = true;
+ break;
+ }
+ }
+ if (found && csi_res->trs_Info)
+ // CRI-RS for Tracking (not implemented yet)
+ // in this case we there is no associated CSI report
+ // therefore to signal this we return a value higher than
+ // maxNrofCSI-ResourceConfigurations
+ return NR_maxNrofCSI_ResourceConfigurations + 1;
+ else if (found)
+ return csires->csi_ResourceConfigId;
+ }
+ }
+ }
+ return -1; // not found any CSI-resource in current DL BWP associated with this CSI-RS ID
+}
+
+static uint8_t set_csirs_measurement_bitmap(NR_CSI_MeasConfig_t *csi_measconfig, NR_CSI_ResourceConfigId_t csi_res_id)
+{
+ uint8_t meas_bitmap = 0;
+ if (csi_res_id > NR_maxNrofCSI_ResourceConfigurations)
+ return meas_bitmap; // CSI-RS for tracking
+ for(int i = 0; i < csi_measconfig->csi_ReportConfigToAddModList->list.count; i++) {
+ NR_CSI_ReportConfig_t *report_config = csi_measconfig->csi_ReportConfigToAddModList->list.array[i];
+ if(report_config->resourcesForChannelMeasurement != csi_res_id)
+ continue;
+ // bit 0 RSRP bit 1 RI bit 2 LI bit 3 PMI bit 4 CQI bit 5 i1
+ switch (report_config->reportQuantity.present) {
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
+ meas_bitmap += (1 << 1) + (1 << 3) + (1 << 4);
+ break;
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1:
+ meas_bitmap += (1 << 1) + (1 << 5);
+ break;
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI:
+ meas_bitmap += (1 << 1) + (1 << 4) + (1 << 5);
+ break;
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
+ meas_bitmap += (1 << 1) + (1 << 4);
+ break;
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
+ meas_bitmap += 1;
+ break;
+ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
+ meas_bitmap += (1 << 1) + (1 << 2) + (1 << 3) + (1 << 4);
+ break;
+ default:
+ AssertFatal(false, "Unexpected measurement report type %d\n", report_config->reportQuantity.present);
+ }
+ }
+ return meas_bitmap;
+}
+
+static void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot)
+{
+ if (!mac->sc_info.csi_MeasConfig)
+ return;
+
+ NR_CSI_MeasConfig_t *csi_measconfig = mac->sc_info.csi_MeasConfig;
+
+ if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList == NULL)
+ return;
+
+ fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot);
+ NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
+ NR_BWP_Id_t dl_bwp_id = current_DL_BWP->bwp_id;
+
+ int mu = current_DL_BWP->scs;
+ uint16_t bwp_size = current_DL_BWP->BWPSize;
+ uint16_t bwp_start = current_DL_BWP->BWPStart;
+
+ for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++) {
+ NR_NZP_CSI_RS_Resource_t *nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id];
+ int period, offset;
+ csi_period_offset(NULL, nzpcsi->periodicityAndOffset, &period, &offset);
+ if((frame * mac->frame_structure.numb_slots_frame + slot-offset) % period != 0)
+ continue;
+ NR_CSI_ResourceConfigId_t csi_res_id = find_CSI_resourceconfig(csi_measconfig, dl_bwp_id, nzpcsi->nzp_CSI_RS_ResourceId);
+ // do not schedule reseption of this CSI-RS if not associated with current BWP
+ if(csi_res_id < 0)
+ continue;
+ LOG_D(MAC,"Scheduling reception of CSI-RS in frame %d slot %d\n", frame, slot);
+ fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = &dl_config->dl_config_list[dl_config->number_pdus].csirs_config_pdu.csirs_config_rel15;
+ csirs_config_pdu->measurement_bitmap = set_csirs_measurement_bitmap(csi_measconfig, csi_res_id);
+ csirs_config_pdu->subcarrier_spacing = mu;
+ csirs_config_pdu->cyclic_prefix = current_DL_BWP->cyclicprefix ? *current_DL_BWP->cyclicprefix : 0;
+
+ if (csi_res_id > NR_maxNrofCSI_ResourceConfigurations)
+ csirs_config_pdu->csi_type = 0; // TRS
+ else
+ csirs_config_pdu->csi_type = 1; // NZP-CSI-RS
+
+ csirs_config_pdu->scramb_id = nzpcsi->scramblingID;
+ csirs_config_pdu->power_control_offset = nzpcsi->powerControlOffset + 8;
+ if (nzpcsi->powerControlOffsetSS)
+ csirs_config_pdu->power_control_offset_ss = *nzpcsi->powerControlOffsetSS;
+ else
+ csirs_config_pdu->power_control_offset_ss = 1; // 0 dB
+
+ configure_csi_resource_mapping(csirs_config_pdu, &nzpcsi->resourceMapping, bwp_size, bwp_start);
+
+ dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_CSI_RS;
+ dl_config->number_pdus += 1;
+ }
+}
+
+static void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot)
+{
+ if (!mac->sc_info.csi_MeasConfig)
+ return;
+
+ NR_CSI_MeasConfig_t *csi_measconfig = mac->sc_info.csi_MeasConfig;
+
+ if (csi_measconfig->csi_IM_ResourceToAddModList == NULL)
+ return;
+
+ fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot);
+ NR_CSI_IM_Resource_t *imcsi;
+ int period, offset;
+
+ NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
+ int mu = current_DL_BWP->scs;
+ uint16_t bwp_size = current_DL_BWP->BWPSize;
+ uint16_t bwp_start = current_DL_BWP->BWPStart;
+
+ for (int id = 0; id < csi_measconfig->csi_IM_ResourceToAddModList->list.count; id++){
+ imcsi = csi_measconfig->csi_IM_ResourceToAddModList->list.array[id];
+ csi_period_offset(NULL,imcsi->periodicityAndOffset,&period,&offset);
+ if((frame * mac->frame_structure.numb_slots_frame + slot - offset ) %period != 0)
+ continue;
+ fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu = &dl_config->dl_config_list[dl_config->number_pdus].csiim_config_pdu.csiim_config_rel15;
+ csiim_config_pdu->bwp_size = bwp_size;
+ csiim_config_pdu->bwp_start = bwp_start;
+ csiim_config_pdu->subcarrier_spacing = mu;
+ csiim_config_pdu->start_rb = imcsi->freqBand->startingRB;
+ csiim_config_pdu->nr_of_rbs = imcsi->freqBand->nrofRBs;
+ // As specified in 5.2.2.4 of 38.214
+ switch (imcsi->csi_IM_ResourceElementPattern->present) {
+ case NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern0:
+ for (int i = 0; i < 4; i++) {
+ csiim_config_pdu->k_csiim[i] =
+ (imcsi->csi_IM_ResourceElementPattern->choice.pattern0->subcarrierLocation_p0 << 1) + (i >> 1);
+ csiim_config_pdu->l_csiim[i] = imcsi->csi_IM_ResourceElementPattern->choice.pattern0->symbolLocation_p0 + (i % 2);
+ }
+ break;
+ case NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern1:
+ for (int i = 0; i < 4; i++) {
+ csiim_config_pdu->k_csiim[i] = (imcsi->csi_IM_ResourceElementPattern->choice.pattern1->subcarrierLocation_p1 << 2) + i;
+ csiim_config_pdu->l_csiim[i] = imcsi->csi_IM_ResourceElementPattern->choice.pattern1->symbolLocation_p1;
+ }
+ break;
+ default:
+ AssertFatal(1 == 0, "Invalid CSI-IM pattern\n");
+ }
+ dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_CSI_IM;
+ dl_config->number_pdus += 1;
+ }
+}
+
// Performs :
// 1. TODO: Call RRC for link status return to PHY
// 2. TODO: Perform SR/BSR procedures for scheduling feedback
@@ -1341,260 +1516,179 @@ static void nr_update_bsr(NR_UE_MAC_INST_t *mac, uint32_t *LCG_bytes)
}
}
-void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
+static bool is_prach_frame(frame_t frame, prach_occasion_info_t *prach_occasion_info, int association_periods)
{
- int cc_id = ul_info->cc_id;
- frame_t frame_tx = ul_info->frame;
- slot_t slot_tx = ul_info->slot;
- uint32_t gNB_index = ul_info->gNB_index;
+ int config_period = prach_occasion_info->frame_info[0];
+ int frame_period = config_period * association_periods;
+ int frame_in_period = frame % frame_period;
+ if (association_periods > 1) {
+ int current_assoc_period = frame_in_period / config_period;
+ if (current_assoc_period != prach_occasion_info->association_period_idx)
+ return false;
+ frame_in_period %= config_period;
+ }
+ if (frame_in_period == prach_occasion_info->frame_info[1]) // SFN % x == y (see Tables in Table 6.3.3.2 of 38.211)
+ return true;
+ else
+ return false;
+}
+// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x
+// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
+// - todo:
+// - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config
+static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP)
+{
RA_config_t *ra = &mac->ra;
- if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_UE_IDLE) {
- init_RA(mac, frame_tx);
- // perform the Random Access Resource selection procedure (see clause 5.1.2 and .2a)
- ra_resource_selection(mac);
- }
+ // Get any valid PRACH occasion in the current slot for the selected SSB index
+ prach_occasion_info_t *prach_occasion_info = &ra->sched_ro_info;
- if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_GENERATE_PREAMBLE)
- nr_ue_prach_scheduler(mac, frame_tx, slot_tx);
-
- bool BSRsent = false;
- if (mac->state == UE_CONNECTED) {
- nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx);
- nr_update_rlc_buffers_status(mac, frame_tx, slot_tx, gNB_index);
- }
-
- // Schedule ULSCH only if the current frame and slot match those in ul_config_req
- // AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus)
- uint8_t ulsch_input_buffer_array[NFAPI_MAX_NUM_UL_PDU][MAX_ULSCH_PAYLOAD_BYTES];
- int number_of_pdus = 0;
-
- fapi_nr_ul_config_request_pdu_t *ulcfg_pdu = lockGet_ul_iterator(mac, frame_tx, slot_tx);
- if (!ulcfg_pdu)
+ if (!is_prach_frame(frameP, prach_occasion_info, ra->association_periods))
return;
- LOG_D(NR_MAC, "number of UL PDUs: %d with UL transmission in sfn [%d.%d]\n", *ulcfg_pdu->privateNBpdus, frame_tx, slot_tx);
- while (ulcfg_pdu->pdu_type != FAPI_NR_END) {
- uint8_t *ulsch_input_buffer = ulsch_input_buffer_array[number_of_pdus];
- if (ulcfg_pdu->pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) {
- nfapi_nr_ue_pusch_pdu_t *pdu = &ulcfg_pdu->pusch_config_pdu;
- uint32_t TBS_bytes = pdu->pusch_data.tb_size;
- LOG_D(NR_MAC,
- "harq_id %d, new_data_indicator %d, TBS_bytes %d (ra_state %d)\n",
- pdu->pusch_data.harq_process_id,
- pdu->pusch_data.new_data_indicator,
- TBS_bytes,
- ra->ra_state);
- pdu->tx_request_body.fapiTxPdu = NULL;
- if ((ra->ra_state == nrRA_WAIT_RAR || ra->ra_state == nrRA_WAIT_MSGB) && !ra->cfra) {
- nr_get_Msg3_MsgA_PUSCH_payload(mac, ulsch_input_buffer, TBS_bytes);
- for (int k = 0; k < TBS_bytes; k++) {
- LOG_D(NR_MAC, "(%i): 0x%x\n", k, ulsch_input_buffer[k]);
+ if (is_ul_slot(slotP, &mac->frame_structure)) {
+ if (slotP == prach_occasion_info->slot) {
+ fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH);
+ if (!pdu) {
+ LOG_E(NR_MAC, "Error in PRACH allocation\n");
+ return;
+ }
+
+ int format = prach_occasion_info->format;
+ fapi_nr_prach_config_t *prach_config = &mac->phy_config.config_req.prach_config;
+ pdu->prach_config_pdu = (fapi_nr_ul_config_prach_pdu){
+ .phys_cell_id = mac->physCellId,
+ .num_prach_ocas = 1,
+ .prach_slot = prach_occasion_info->slot,
+ .prach_start_symbol = prach_occasion_info->start_symbol,
+ .num_ra = prach_occasion_info->fdm,
+ .num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format, ra->restricted_set_config),
+ .root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].prach_root_sequence_index,
+ .restricted_set = prach_config->restricted_set_config,
+ .freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].k1};
+
+ LOG_I(NR_MAC,
+ "PRACH scheduler: Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n",
+ frameP,
+ pdu->prach_config_pdu.prach_slot,
+ pdu->prach_config_pdu.prach_start_symbol,
+ pdu->prach_config_pdu.num_ra);
+
+ switch (format) { // single PRACH format
+ case 0:
+ pdu->prach_config_pdu.prach_format = 0;
+ break;
+ case 1:
+ pdu->prach_config_pdu.prach_format = 1;
+ break;
+ case 2:
+ pdu->prach_config_pdu.prach_format = 2;
+ break;
+ case 3:
+ pdu->prach_config_pdu.prach_format = 3;
+ break;
+ case 0xa1:
+ pdu->prach_config_pdu.prach_format = 4;
+ break;
+ case 0xa2:
+ pdu->prach_config_pdu.prach_format = 5;
+ break;
+ case 0xa3:
+ pdu->prach_config_pdu.prach_format = 6;
+ break;
+ case 0xb1:
+ pdu->prach_config_pdu.prach_format = 7;
+ break;
+ case 0xb4:
+ pdu->prach_config_pdu.prach_format = 8;
+ break;
+ case 0xc0:
+ pdu->prach_config_pdu.prach_format = 9;
+ break;
+ case 0xc2:
+ pdu->prach_config_pdu.prach_format = 10;
+ break;
+ default:
+ AssertFatal(false, "Invalid PRACH format");
+ }
+
+ pdu->prach_config_pdu.ra_PreambleIndex = ra->ra_PreambleIndex;
+ pdu->prach_config_pdu.prach_tx_power = get_prach_tx_power(mac);
+ release_ul_config(pdu, false);
+ nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slotP,
+ .mac = mac,
+ .module_id = mac->ue_id,
+ .CC_id = 0 /*TBR fix*/};
+ if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
+ mac->if_module->scheduled_response(&scheduled_response);
+
+ T(T_UE_PHY_INITIATE_RA_PROCEDURE, T_INT(frameP), T_INT(pdu->prach_config_pdu.prach_slot),
+ T_INT(pdu->prach_config_pdu.ra_PreambleIndex), T_INT(pdu->prach_config_pdu.prach_tx_power));
+
+ const int n_slots_frame = mac->frame_structure.numb_slots_frame;
+ if (ra->ra_type == RA_4_STEP) {
+ ra->ra_state = nrRA_WAIT_RAR;
+ // we start to monitor DCI for RAR in the first valid occasion after transmitting RACH
+ // the response window timer should be started at that time
+ // but for processing reasons it is better to start it here and to add the slot difference
+ // that also takes into account the rx to tx slot offset
+ int next_slot = (slotP + 1) % n_slots_frame;
+ int next_frame = (frameP + (next_slot < slotP)) % MAX_FRAME_NUMBER;
+ int add_slots = 1;
+ NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[mac->current_DL_BWP->bwp_id];
+ const NR_SearchSpace_t *ra_SS = get_common_search_space(mac, pdcch_config->ra_SS_id);
+ while (!is_dl_slot(next_slot, &mac->frame_structure)
+ || !is_ss_monitor_occasion(next_frame, next_slot, n_slots_frame, ra_SS)) {
+ int temp_slot = (next_slot + 1) % n_slots_frame;
+ next_frame = (next_frame + (temp_slot < next_slot)) % MAX_FRAME_NUMBER;
+ next_slot = temp_slot;
+ add_slots++;
}
- pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer;
- pdu->tx_request_body.pdu_length = TBS_bytes;
- number_of_pdus++;
- T(T_NRUE_MAC_UL_PDU_WITH_DATA, T_INT(mac->crnti), T_INT(frame_tx), T_INT(slot_tx),
- T_INT(ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id), T_BUFFER(ulsch_input_buffer, TBS_bytes));
+ add_slots += GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mac->current_DL_BWP->scs);
+ nr_timer_setup(&ra->response_window_timer, ra->response_window_setup_time + add_slots, 1);
+ nr_timer_start(&ra->response_window_timer);
+ } else if (ra->ra_type == RA_2_STEP) {
+ NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource =
+ mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16;
+ slot_t msgA_pusch_slot = (slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) % n_slots_frame;
+ frame_t msgA_pusch_frame =
+ (frameP + ((slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) / n_slots_frame)) % 1024;
+
+ fapi_nr_ul_config_request_pdu_t *pdu =
+ lockGet_ul_config(mac, msgA_pusch_frame, msgA_pusch_slot, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
+ if (!pdu)
+ return;
+
+ // Config Msg3/MsgA-PUSCH PDU
+ NR_tda_info_t tda_info = {0};
+ AssertFatal(msgA_PUSCH_Resource->startSymbolAndLengthMsgA_PO_r16,
+ "Only SLIV based on startSymbolAndLengthMsgA_PO_r16 implemented\n");
+
+ int ret = nr_config_pusch_pdu(mac,
+ &tda_info,
+ &pdu->pusch_config_pdu,
+ NULL,
+ NULL,
+ NULL,
+ mac->ra.ra_rnti,
+ NR_SearchSpace__searchSpaceType_PR_common,
+ NR_DCI_NONE);
+
+ if (ret != 0)
+ remove_ul_config_last_item(pdu);
+ release_ul_config(pdu, false);
+
+ LOG_D(NR_MAC, "ra->ra_state %s\n", nrra_ue_text[ra->ra_state]);
+ ra->ra_state = nrRA_WAIT_MSGB;
+ ra->t_crnti = 0;
+ mac->crnti = 0;
+ ra->ra_rnti = 0;
} else {
- if (ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator
- && (mac->state == UE_CONNECTED || (ra->ra_state == nrRA_WAIT_RAR && ra->cfra))) {
- if (!nr_timer_is_active(&mac->time_alignment_timer) && mac->state == UE_CONNECTED && !get_softmodem_params()->phy_test) {
- // UL data arrival during RRC_CONNECTED when UL synchronisation status is "non-synchronised"
- trigger_MAC_UE_RA(mac, NULL);
- return;
- }
- // Getting IP traffic to be transmitted
- int tx_power = pdu->tx_power;
- int P_CMAX = nr_get_Pcmax(mac->p_Max,
- mac->nr_band,
- mac->frame_structure.frame_type,
- mac->frequency_range,
- mac->current_UL_BWP->channel_bandwidth,
- pdu->qam_mod_order,
- false,
- mac->current_UL_BWP->scs,
- mac->current_UL_BWP->BWPSize,
- pdu->transform_precoding,
- pdu->rb_size,
- pdu->rb_start);
-
- nr_ue_get_sdu(mac, cc_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes, tx_power, P_CMAX, &BSRsent);
- pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer;
- pdu->tx_request_body.pdu_length = TBS_bytes;
- number_of_pdus++;
- T(T_NRUE_MAC_UL_PDU_WITH_DATA, T_INT(mac->crnti), T_INT(frame_tx), T_INT(slot_tx),
- T_INT(ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id), T_BUFFER(ulsch_input_buffer, TBS_bytes));
- // start or restart dataInactivityTimer if any MAC entity transmits a MAC SDU for DTCH logical channel,
- // or DCCH logical channel
- if (mac->data_inactivity_timer)
- nr_timer_start(mac->data_inactivity_timer);
- }
+ AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type);
}
-
- if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION && !ra->cfra) {
- LOG_I(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 retransmitted\n", frame_tx, slot_tx);
- // 38.321 restart the ra-ContentionResolutionTimer at each HARQ retransmission in the first symbol after the end of the Msg3
- // transmission
- nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index);
- }
- if (ra->ra_state == nrRA_WAIT_RAR && !ra->cfra) {
- LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 transmitted\n", frame_tx, slot_tx);
- nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index);
- }
- if (ra->ra_state == nrRA_WAIT_MSGB && !ra->cfra) {
- LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-MsgA-PUSCH transmitted\n", frame_tx, slot_tx);
- }
- }
- ulcfg_pdu++;
- }
- release_ul_config(ulcfg_pdu, false);
-
- if(mac->state >= UE_PERFORMING_RA && mac->state < UE_DETACHING)
- nr_ue_pucch_scheduler(mac, frame_tx, slot_tx);
-
- if (mac->if_module != NULL && mac->if_module->scheduled_response != NULL) {
- LOG_D(NR_MAC, "3# scheduled_response transmitted,%d, %d\n", frame_tx, slot_tx);
- nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slot_tx,
- .mac = mac,
- .module_id = mac->ue_id,
- .CC_id = cc_id,
- .phy_data = ul_info->phy_data};
- mac->if_module->scheduled_response(&scheduled_response);
- }
-
- if(mac->state == UE_CONNECTED)
- nr_update_sr(mac, BSRsent);
- // Global variables implicit logic
- // far away, BSR_reporting_active is set
- mac->scheduling_info.BSR_reporting_active = NR_BSR_TRIGGER_NONE;
-
- // update Bj for all active lcids before LCP procedure
- if (mac->current_UL_BWP) {
- LOG_D(NR_MAC, "%4d.%2d Logical Channel Prioritization\n", frame_tx, slot_tx);
- for (int i = 0; i < mac->lc_ordered_list.count; i++) {
- nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
- int lcid = lc_info->lcid;
- // max amount of data that can be buffered/accumulated in a logical channel buffer
- uint32_t bucketSize_max = lc_info->bucket_size;
- // measure Bj increment the value of Bj by product PBR * T
- NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
- int32_t bj = sched_info->Bj;
- if (lc_info->pbr < UINT_MAX) {
- uint32_t slots_elapsed = nr_timer_elapsed_time(&sched_info->Bj_timer); // slots elapsed since Bj was last incremented
- // it is safe to divide by 1k since pbr in lc_info is computed multiplying by 1000 the RRC value to convert kB/s to B/s
- uint32_t pbr_ms = lc_info->pbr / 1000;
- bj += ((pbr_ms * slots_elapsed) >> mac->current_UL_BWP->scs); // each slot length is 1/scs ms
- }
- else
- bj = INT_MAX;
- // bj > max bucket size, set bj to max bucket size, as in ts38.321 5.4.3.1 Logical Channel Prioritization
- sched_info->Bj = min(bj, bucketSize_max);
- // reset bj timer
- nr_timer_start(&sched_info->Bj_timer);
- }
- }
-}
-
-static uint8_t nr_locate_BsrIndexByBufferSize(int size, int value)
-{
- if (value == 0) {
- return 0; //elseif (value > 150000) return 63;
- }
-
- uint32_t (*get_bsr_value)(int);
- if (size == NR_SHORT_BSR_TABLE_SIZE)
- get_bsr_value = &get_short_bsr_value;
- else
- get_bsr_value = &get_long_bsr_value;
-
- int jl = 0; // lower bound
- int ju = size - 1; // upper bound
- // determine the order of the the table: 1 if ascending order of table, 0 otherwise
- bool ascend = (*get_bsr_value)(ju) >= (*get_bsr_value)(jl) ? 1 : 0;
- while (ju - jl > 1) { //If we are not yet done,
- int jm = (ju + jl) / 2; // compute a midpoint,
- if ((value >= (*get_bsr_value)(jm)) == ascend) {
- jl = jm; // replace the lower limit
- } else {
- ju = jm; //replace the upper limit
- }
-
- LOG_T(NR_MAC,
- "[UE] searching BSR index %d for (BSR TABLE %d < value %d)\n",
- jm,
- (*get_bsr_value)(jm),
- value);
- }
-
- if (value == (*get_bsr_value)(jl)) {
- return jl;
- } else {
- return jl + 1; //equally ju
- }
-}
-
-// PUSCH scheduler:
-// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2,
-// - where K2 is the offset between the slot in which UL DCI is received and the slot
-// - in which ULSCH should be scheduled. K2 is configured in RRC configuration.
-// PUSCH Msg3 scheduler:
-// - scheduled by RAR UL grant according to 8.3 of TS 38.213
-// Note: Msg3 tx in the uplink symbols of mixed slot
-int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
- const uint8_t is_Msg3,
- const frame_t current_frame,
- const int current_slot,
- frame_t *frame_tx,
- int *slot_tx,
- const long k2)
-{
- int delta = 0;
- const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
-
- // Get the numerology to calculate the Tx frame and slot
- int mu = current_UL_BWP->scs;
- int slots_per_frame = mac->frame_structure.numb_slots_frame;
-
- // k2 as per 3GPP TS 38.214 version 15.9.0 Release 15 ch 6.1.2.1.1
- // PUSCH time domain resource allocation is higher layer configured from uschTimeDomainAllocationList in either pusch-ConfigCommon
-
- if (is_Msg3) {
-
- delta = get_delta_for_k2(mu);
-
- AssertFatal((k2 + delta) > GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
- "Slot offset (%ld) for Msg3 needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to "
- "%ld in gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
- k2,
- GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
- GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
- GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu));
-
- *slot_tx = (current_slot + k2 + delta) % slots_per_frame;
- *frame_tx = (current_frame + (current_slot + k2 + delta) / slots_per_frame) % MAX_FRAME_NUMBER;
- } else {
- AssertFatal(k2 >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
- "Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in "
- "gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
- k2,
- GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
- GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
- GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu));
-
- if (k2 < 0) { // This can happen when a false DCI is received
- LOG_W(PHY, "%d.%d. Received k2 %ld\n", current_frame, current_slot, k2);
- return -1;
- }
-
- // Calculate TX slot and frame
- *slot_tx = (current_slot + k2) % slots_per_frame;
- *frame_tx = (current_frame + (current_slot + k2) / slots_per_frame) % MAX_FRAME_NUMBER;
- }
-
- LOG_D(NR_MAC, "[%04d.%02d] UL transmission in [%04d.%02d] (k2 %ld delta %d)\n", current_frame, current_slot, *frame_tx, *slot_tx, k2, delta);
- return 0;
+ } // is_nr_prach_slot
+ } // if is_nr_UL_slot
}
static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac,
@@ -1782,472 +1876,43 @@ static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frame, int slot
}
}
-static void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot)
+static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac,
+ NR_SINGLE_ENTRY_PHR_MAC_CE *phr,
+ float P_CMAX,
+ float tx_power,
+ frame_t frame,
+ slot_t slot)
{
- if (!mac->sc_info.csi_MeasConfig)
- return;
-
- NR_CSI_MeasConfig_t *csi_measconfig = mac->sc_info.csi_MeasConfig;
-
- if (csi_measconfig->csi_IM_ResourceToAddModList == NULL)
- return;
-
- fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot);
- NR_CSI_IM_Resource_t *imcsi;
- int period, offset;
-
- NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
- int mu = current_DL_BWP->scs;
- uint16_t bwp_size = current_DL_BWP->BWPSize;
- uint16_t bwp_start = current_DL_BWP->BWPStart;
-
- for (int id = 0; id < csi_measconfig->csi_IM_ResourceToAddModList->list.count; id++){
- imcsi = csi_measconfig->csi_IM_ResourceToAddModList->list.array[id];
- csi_period_offset(NULL,imcsi->periodicityAndOffset,&period,&offset);
- if((frame * mac->frame_structure.numb_slots_frame + slot - offset ) %period != 0)
- continue;
- fapi_nr_dl_config_csiim_pdu_rel15_t *csiim_config_pdu = &dl_config->dl_config_list[dl_config->number_pdus].csiim_config_pdu.csiim_config_rel15;
- csiim_config_pdu->bwp_size = bwp_size;
- csiim_config_pdu->bwp_start = bwp_start;
- csiim_config_pdu->subcarrier_spacing = mu;
- csiim_config_pdu->start_rb = imcsi->freqBand->startingRB;
- csiim_config_pdu->nr_of_rbs = imcsi->freqBand->nrofRBs;
- // As specified in 5.2.2.4 of 38.214
- switch (imcsi->csi_IM_ResourceElementPattern->present) {
- case NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern0:
- for (int i = 0; i < 4; i++) {
- csiim_config_pdu->k_csiim[i] =
- (imcsi->csi_IM_ResourceElementPattern->choice.pattern0->subcarrierLocation_p0 << 1) + (i >> 1);
- csiim_config_pdu->l_csiim[i] = imcsi->csi_IM_ResourceElementPattern->choice.pattern0->symbolLocation_p0 + (i % 2);
- }
- break;
- case NR_CSI_IM_Resource__csi_IM_ResourceElementPattern_PR_pattern1:
- for (int i = 0; i < 4; i++) {
- csiim_config_pdu->k_csiim[i] = (imcsi->csi_IM_ResourceElementPattern->choice.pattern1->subcarrierLocation_p1 << 2) + i;
- csiim_config_pdu->l_csiim[i] = imcsi->csi_IM_ResourceElementPattern->choice.pattern1->symbolLocation_p1;
- }
- break;
- default:
- AssertFatal(1 == 0, "Invalid CSI-IM pattern\n");
- }
- dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_CSI_IM;
- dl_config->number_pdus += 1;
+ nr_phr_info_t *phr_info = &mac->scheduling_info.phr_info;
+ // Value mapping according to 38.133 10.1.18.1
+ const int PC_MAX_00 = -29;
+ *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE){.PCMAX = max(0, (int)P_CMAX - PC_MAX_00) & 0x3f};
+ // Value mapping according to 38.133 10.1.17.1.1
+ const int POWER_HEADROOM_55 = 22;
+ int headroom = P_CMAX - tx_power;
+ if (headroom < POWER_HEADROOM_55) {
+ const int POWER_HEADROOM_0 = -32;
+ phr->PH = max(0, headroom - POWER_HEADROOM_0);
+ } else {
+ phr->PH = min(0x3f, 55 + (headroom - POWER_HEADROOM_55) / 2);
}
-}
-NR_CSI_ResourceConfigId_t find_CSI_resourceconfig(NR_CSI_MeasConfig_t *csi_measconfig,
- NR_BWP_Id_t dl_bwp_id,
- NR_NZP_CSI_RS_ResourceId_t csi_id)
-{
- bool found = false;
- for (int csi_list = 0; csi_list < csi_measconfig->csi_ResourceConfigToAddModList->list.count; csi_list++) {
- NR_CSI_ResourceConfig_t *csires = csi_measconfig->csi_ResourceConfigToAddModList->list.array[csi_list];
- if(csires->bwp_Id != dl_bwp_id)
- continue;
- struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList *resset = &csires->csi_RS_ResourceSetList;
- if(resset->present != NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB)
- continue;
- if(!resset->choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList)
- continue;
- for(int i = 0; i < resset->choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count; i++) {
- NR_NZP_CSI_RS_ResourceSetId_t *res_id = resset->choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[i];
- AssertFatal(res_id, "NR_NZP_CSI_RS_ResourceSetId shouldn't be NULL\n");
- struct NR_CSI_MeasConfig__nzp_CSI_RS_ResourceSetToAddModList *res_list = csi_measconfig->nzp_CSI_RS_ResourceSetToAddModList;
- AssertFatal(res_list, "nzp_CSI_RS_ResourceSetToAddModList shouldn't be NULL\n");
- for (int j = 0; j < res_list->list.count; j++) {
- NR_NZP_CSI_RS_ResourceSet_t *csi_res = res_list->list.array[j];
- if (*res_id != csi_res->nzp_CSI_ResourceSetId)
- continue;
- for (int k = 0; k < csi_res->nzp_CSI_RS_Resources.list.count; k++) {
- AssertFatal(csi_res->nzp_CSI_RS_Resources.list.array[k], "NZP_CSI_RS_ResourceId shoulan't be NULL\n");
- if (csi_id == *csi_res->nzp_CSI_RS_Resources.list.array[k]) {
- found = true;
- break;
- }
- }
- if (found && csi_res->trs_Info)
- // CRI-RS for Tracking (not implemented yet)
- // in this case we there is no associated CSI report
- // therefore to signal this we return a value higher than
- // maxNrofCSI-ResourceConfigurations
- return NR_maxNrofCSI_ResourceConfigurations + 1;
- else if (found)
- return csires->csi_ResourceConfigId;
- }
- }
- }
- return -1; // not found any CSI-resource in current DL BWP associated with this CSI-RS ID
-}
+ LOG_D(NR_MAC,
+ "PHR Reporting sfn.slot %d.%d reason = %d, P_CMAX = %d (%5.2f dBm), headrom = %d (%d dB) tx_power = %5.2f dBm\n",
+ frame,
+ slot,
+ phr_info->phr_reporting,
+ phr->PCMAX,
+ P_CMAX,
+ phr->PH,
+ headroom,
+ tx_power);
-uint8_t set_csirs_measurement_bitmap(NR_CSI_MeasConfig_t *csi_measconfig, NR_CSI_ResourceConfigId_t csi_res_id)
-{
- uint8_t meas_bitmap = 0;
- if (csi_res_id > NR_maxNrofCSI_ResourceConfigurations)
- return meas_bitmap; // CSI-RS for tracking
- for(int i = 0; i < csi_measconfig->csi_ReportConfigToAddModList->list.count; i++) {
- NR_CSI_ReportConfig_t *report_config = csi_measconfig->csi_ReportConfigToAddModList->list.array[i];
- if(report_config->resourcesForChannelMeasurement != csi_res_id)
- continue;
- // bit 0 RSRP bit 1 RI bit 2 LI bit 3 PMI bit 4 CQI bit 5 i1
- switch (report_config->reportQuantity.present) {
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
- meas_bitmap += (1 << 1) + (1 << 3) + (1 << 4);
- break;
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1:
- meas_bitmap += (1 << 1) + (1 << 5);
- break;
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI:
- meas_bitmap += (1 << 1) + (1 << 4) + (1 << 5);
- break;
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI:
- meas_bitmap += (1 << 1) + (1 << 4);
- break;
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP:
- meas_bitmap += 1;
- break;
- case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
- meas_bitmap += (1 << 1) + (1 << 2) + (1 << 3) + (1 << 4);
- break;
- default:
- AssertFatal(false, "Unexpected measurement report type %d\n", report_config->reportQuantity.present);
- }
- }
- return meas_bitmap;
-}
-
-void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
- const NR_CSI_RS_ResourceMapping_t *resourceMapping,
- uint32_t bwp_size,
- uint32_t bwp_start)
-{
- // According to last paragraph of TS 38.214 5.2.2.3.1
- if (resourceMapping->freqBand.startingRB < bwp_start)
- csirs_config_pdu->start_rb = bwp_start;
- else
- csirs_config_pdu->start_rb = resourceMapping->freqBand.startingRB;
- if (resourceMapping->freqBand.nrofRBs > (bwp_start + bwp_size - csirs_config_pdu->start_rb))
- csirs_config_pdu->nr_of_rbs = bwp_start + bwp_size - csirs_config_pdu->start_rb;
- else
- csirs_config_pdu->nr_of_rbs = resourceMapping->freqBand.nrofRBs;
- AssertFatal(csirs_config_pdu->nr_of_rbs >= 24, "CSI-RS has %d RBs, but the minimum is 24\n", csirs_config_pdu->nr_of_rbs);
-
- csirs_config_pdu->symb_l0 = resourceMapping->firstOFDMSymbolInTimeDomain;
- if (resourceMapping->firstOFDMSymbolInTimeDomain2)
- csirs_config_pdu->symb_l1 = *resourceMapping->firstOFDMSymbolInTimeDomain2;
- csirs_config_pdu->cdm_type = resourceMapping->cdm_Type;
-
- csirs_config_pdu->freq_density = resourceMapping->density.present;
- if ((resourceMapping->density.present == NR_CSI_RS_ResourceMapping__density_PR_dot5)
- && (resourceMapping->density.choice.dot5 == NR_CSI_RS_ResourceMapping__density__dot5_evenPRBs))
- csirs_config_pdu->freq_density--;
-
- switch(resourceMapping->frequencyDomainAllocation.present){
- case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1:
- csirs_config_pdu->row = 1;
- csirs_config_pdu->freq_domain = ((resourceMapping->frequencyDomainAllocation.choice.row1.buf[0]) >> 4) & 0x0f;
- break;
- case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2:
- csirs_config_pdu->row = 2;
- csirs_config_pdu->freq_domain = (((resourceMapping->frequencyDomainAllocation.choice.row2.buf[1] >> 4) & 0x0f)
- | ((resourceMapping->frequencyDomainAllocation.choice.row2.buf[0] << 4) & 0xff0));
- break;
- case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4:
- csirs_config_pdu->row = 4;
- csirs_config_pdu->freq_domain = ((resourceMapping->frequencyDomainAllocation.choice.row4.buf[0]) >> 5) & 0x07;
- break;
- case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other:
- csirs_config_pdu->freq_domain = ((resourceMapping->frequencyDomainAllocation.choice.other.buf[0]) >> 2) & 0x3f;
- // determining the row of table 7.4.1.5.3-1 in 38.211
- switch (resourceMapping->nrofPorts) {
- case NR_CSI_RS_ResourceMapping__nrofPorts_p1:
- AssertFatal(1 == 0, "Resource with 1 CSI port shouldn't be within other rows\n");
- break;
- case NR_CSI_RS_ResourceMapping__nrofPorts_p2:
- csirs_config_pdu->row = 3;
- break;
- case NR_CSI_RS_ResourceMapping__nrofPorts_p4:
- csirs_config_pdu->row = 5;
- break;
- case NR_CSI_RS_ResourceMapping__nrofPorts_p8:
- if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
- csirs_config_pdu->row = 8;
- else {
- int num_k = 0;
- for (int k = 0; k < 6; k++)
- num_k += (((csirs_config_pdu->freq_domain) >> k) & 0x01);
- if (num_k == 4)
- csirs_config_pdu->row = 6;
- else
- csirs_config_pdu->row = 7;
- }
- break;
- case NR_CSI_RS_ResourceMapping__nrofPorts_p12:
- if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
- csirs_config_pdu->row = 10;
- else
- csirs_config_pdu->row = 9;
- break;
- case NR_CSI_RS_ResourceMapping__nrofPorts_p16:
- if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
- csirs_config_pdu->row = 12;
- else
- csirs_config_pdu->row = 11;
- break;
- case NR_CSI_RS_ResourceMapping__nrofPorts_p24:
- if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
- csirs_config_pdu->row = 14;
- else {
- if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4)
- csirs_config_pdu->row = 15;
- else
- csirs_config_pdu->row = 13;
- }
- break;
- case NR_CSI_RS_ResourceMapping__nrofPorts_p32:
- if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
- csirs_config_pdu->row = 17;
- else {
- if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4)
- csirs_config_pdu->row = 18;
- else
- csirs_config_pdu->row = 16;
- }
- break;
- default:
- AssertFatal(false, "Invalid number of ports in CSI-RS resource\n");
- }
- break;
- default:
- AssertFatal(false, "Invalid freqency domain allocation in CSI-RS resource\n");
- }
-}
-
-static void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot)
-{
- if (!mac->sc_info.csi_MeasConfig)
- return;
-
- NR_CSI_MeasConfig_t *csi_measconfig = mac->sc_info.csi_MeasConfig;
-
- if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList == NULL)
- return;
-
- fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot);
- NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP;
- NR_BWP_Id_t dl_bwp_id = current_DL_BWP->bwp_id;
-
- int mu = current_DL_BWP->scs;
- uint16_t bwp_size = current_DL_BWP->BWPSize;
- uint16_t bwp_start = current_DL_BWP->BWPStart;
-
- for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++) {
- NR_NZP_CSI_RS_Resource_t *nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id];
- int period, offset;
- csi_period_offset(NULL, nzpcsi->periodicityAndOffset, &period, &offset);
- if((frame * mac->frame_structure.numb_slots_frame + slot-offset) % period != 0)
- continue;
- NR_CSI_ResourceConfigId_t csi_res_id = find_CSI_resourceconfig(csi_measconfig, dl_bwp_id, nzpcsi->nzp_CSI_RS_ResourceId);
- // do not schedule reseption of this CSI-RS if not associated with current BWP
- if(csi_res_id < 0)
- continue;
- LOG_D(MAC,"Scheduling reception of CSI-RS in frame %d slot %d\n", frame, slot);
- fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu = &dl_config->dl_config_list[dl_config->number_pdus].csirs_config_pdu.csirs_config_rel15;
- csirs_config_pdu->measurement_bitmap = set_csirs_measurement_bitmap(csi_measconfig, csi_res_id);
- csirs_config_pdu->subcarrier_spacing = mu;
- csirs_config_pdu->cyclic_prefix = current_DL_BWP->cyclicprefix ? *current_DL_BWP->cyclicprefix : 0;
-
- if (csi_res_id > NR_maxNrofCSI_ResourceConfigurations)
- csirs_config_pdu->csi_type = 0; // TRS
- else
- csirs_config_pdu->csi_type = 1; // NZP-CSI-RS
-
- csirs_config_pdu->scramb_id = nzpcsi->scramblingID;
- csirs_config_pdu->power_control_offset = nzpcsi->powerControlOffset + 8;
- if (nzpcsi->powerControlOffsetSS)
- csirs_config_pdu->power_control_offset_ss = *nzpcsi->powerControlOffsetSS;
- else
- csirs_config_pdu->power_control_offset_ss = 1; // 0 dB
-
- configure_csi_resource_mapping(csirs_config_pdu, &nzpcsi->resourceMapping, bwp_size, bwp_start);
-
- dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_CSI_RS;
- dl_config->number_pdus += 1;
- }
-}
-
-static bool is_prach_frame(frame_t frame, prach_occasion_info_t *prach_occasion_info, int association_periods)
-{
- int config_period = prach_occasion_info->frame_info[0];
- int frame_period = config_period * association_periods;
- int frame_in_period = frame % frame_period;
- if (association_periods > 1) {
- int current_assoc_period = frame_in_period / config_period;
- if (current_assoc_period != prach_occasion_info->association_period_idx)
- return false;
- frame_in_period %= config_period;
- }
- if (frame_in_period == prach_occasion_info->frame_info[1]) // SFN % x == y (see Tables in Table 6.3.3.2 of 38.211)
- return true;
- else
- return false;
-}
-
-// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x
-// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
-// - todo:
-// - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config
-static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP)
-{
- RA_config_t *ra = &mac->ra;
-
- // Get any valid PRACH occasion in the current slot for the selected SSB index
- prach_occasion_info_t *prach_occasion_info = &ra->sched_ro_info;
-
- if (!is_prach_frame(frameP, prach_occasion_info, ra->association_periods))
- return;
-
- if (is_ul_slot(slotP, &mac->frame_structure)) {
- if (slotP == prach_occasion_info->slot) {
- fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH);
- if (!pdu) {
- LOG_E(NR_MAC, "Error in PRACH allocation\n");
- return;
- }
-
- int format = prach_occasion_info->format;
- fapi_nr_prach_config_t *prach_config = &mac->phy_config.config_req.prach_config;
- pdu->prach_config_pdu = (fapi_nr_ul_config_prach_pdu){
- .phys_cell_id = mac->physCellId,
- .num_prach_ocas = 1,
- .prach_slot = prach_occasion_info->slot,
- .prach_start_symbol = prach_occasion_info->start_symbol,
- .num_ra = prach_occasion_info->fdm,
- .num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format, ra->restricted_set_config),
- .root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].prach_root_sequence_index,
- .restricted_set = prach_config->restricted_set_config,
- .freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].k1};
-
- LOG_I(NR_MAC,
- "PRACH scheduler: Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n",
- frameP,
- pdu->prach_config_pdu.prach_slot,
- pdu->prach_config_pdu.prach_start_symbol,
- pdu->prach_config_pdu.num_ra);
-
- switch (format) { // single PRACH format
- case 0:
- pdu->prach_config_pdu.prach_format = 0;
- break;
- case 1:
- pdu->prach_config_pdu.prach_format = 1;
- break;
- case 2:
- pdu->prach_config_pdu.prach_format = 2;
- break;
- case 3:
- pdu->prach_config_pdu.prach_format = 3;
- break;
- case 0xa1:
- pdu->prach_config_pdu.prach_format = 4;
- break;
- case 0xa2:
- pdu->prach_config_pdu.prach_format = 5;
- break;
- case 0xa3:
- pdu->prach_config_pdu.prach_format = 6;
- break;
- case 0xb1:
- pdu->prach_config_pdu.prach_format = 7;
- break;
- case 0xb4:
- pdu->prach_config_pdu.prach_format = 8;
- break;
- case 0xc0:
- pdu->prach_config_pdu.prach_format = 9;
- break;
- case 0xc2:
- pdu->prach_config_pdu.prach_format = 10;
- break;
- default:
- AssertFatal(false, "Invalid PRACH format");
- }
-
- pdu->prach_config_pdu.ra_PreambleIndex = ra->ra_PreambleIndex;
- pdu->prach_config_pdu.prach_tx_power = get_prach_tx_power(mac);
- release_ul_config(pdu, false);
- nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slotP,
- .mac = mac,
- .module_id = mac->ue_id,
- .CC_id = 0 /*TBR fix*/};
- if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
- mac->if_module->scheduled_response(&scheduled_response);
-
- T(T_UE_PHY_INITIATE_RA_PROCEDURE, T_INT(frameP), T_INT(pdu->prach_config_pdu.prach_slot),
- T_INT(pdu->prach_config_pdu.ra_PreambleIndex), T_INT(pdu->prach_config_pdu.prach_tx_power));
-
- const int n_slots_frame = mac->frame_structure.numb_slots_frame;
- if (ra->ra_type == RA_4_STEP) {
- ra->ra_state = nrRA_WAIT_RAR;
- // we start to monitor DCI for RAR in the first valid occasion after transmitting RACH
- // the response window timer should be started at that time
- // but for processing reasons it is better to start it here and to add the slot difference
- // that also takes into account the rx to tx slot offset
- int next_slot = (slotP + 1) % n_slots_frame;
- int next_frame = (frameP + (next_slot < slotP)) % MAX_FRAME_NUMBER;
- int add_slots = 1;
- NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[mac->current_DL_BWP->bwp_id];
- const NR_SearchSpace_t *ra_SS = get_common_search_space(mac, pdcch_config->ra_SS_id);
- while (!is_dl_slot(next_slot, &mac->frame_structure)
- || !is_ss_monitor_occasion(next_frame, next_slot, n_slots_frame, ra_SS)) {
- int temp_slot = (next_slot + 1) % n_slots_frame;
- next_frame = (next_frame + (temp_slot < next_slot)) % MAX_FRAME_NUMBER;
- next_slot = temp_slot;
- add_slots++;
- }
- add_slots += GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mac->current_DL_BWP->scs);
- nr_timer_setup(&ra->response_window_timer, ra->response_window_setup_time + add_slots, 1);
- nr_timer_start(&ra->response_window_timer);
- } else if (ra->ra_type == RA_2_STEP) {
- NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource =
- mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16;
- slot_t msgA_pusch_slot = (slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) % n_slots_frame;
- frame_t msgA_pusch_frame =
- (frameP + ((slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) / n_slots_frame)) % 1024;
-
- fapi_nr_ul_config_request_pdu_t *pdu =
- lockGet_ul_config(mac, msgA_pusch_frame, msgA_pusch_slot, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
- if (!pdu)
- return;
-
- // Config Msg3/MsgA-PUSCH PDU
- NR_tda_info_t tda_info = {0};
- AssertFatal(msgA_PUSCH_Resource->startSymbolAndLengthMsgA_PO_r16,
- "Only SLIV based on startSymbolAndLengthMsgA_PO_r16 implemented\n");
-
- int ret = nr_config_pusch_pdu(mac,
- &tda_info,
- &pdu->pusch_config_pdu,
- NULL,
- NULL,
- NULL,
- mac->ra.ra_rnti,
- NR_SearchSpace__searchSpaceType_PR_common,
- NR_DCI_NONE);
-
- if (ret != 0)
- remove_ul_config_last_item(pdu);
- release_ul_config(pdu, false);
-
- LOG_D(NR_MAC, "ra->ra_state %s\n", nrra_ue_text[ra->ra_state]);
- ra->ra_state = nrRA_WAIT_MSGB;
- ra->t_crnti = 0;
- mac->crnti = 0;
- ra->ra_rnti = 0;
- } else {
- AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type);
- }
- } // is_nr_prach_slot
- } // if is_nr_UL_slot
+ phr_info->PathlossLastValue = compute_nr_SSB_PL(mac);
+ // Restart both timers according to 38.321
+ nr_timer_start(&phr_info->periodicPHR_Timer);
+ nr_timer_start(&phr_info->prohibitPHR_Timer);
+ phr_info->phr_reporting = 0;
}
typedef struct {
@@ -2265,6 +1930,44 @@ typedef struct {
uint32_t lcp_allocation_counter;
} NR_UE_MAC_CE_INFO;
+static uint8_t nr_locate_BsrIndexByBufferSize(int size, int value)
+{
+ if (value == 0) {
+ return 0; //elseif (value > 150000) return 63;
+ }
+
+ uint32_t (*get_bsr_value)(int);
+ if (size == NR_SHORT_BSR_TABLE_SIZE)
+ get_bsr_value = &get_short_bsr_value;
+ else
+ get_bsr_value = &get_long_bsr_value;
+
+ int jl = 0; // lower bound
+ int ju = size - 1; // upper bound
+ // determine the order of the the table: 1 if ascending order of table, 0 otherwise
+ bool ascend = (*get_bsr_value)(ju) >= (*get_bsr_value)(jl) ? 1 : 0;
+ while (ju - jl > 1) { //If we are not yet done,
+ int jm = (ju + jl) / 2; // compute a midpoint,
+ if ((value >= (*get_bsr_value)(jm)) == ascend) {
+ jl = jm; // replace the lower limit
+ } else {
+ ju = jm; //replace the upper limit
+ }
+
+ LOG_T(NR_MAC,
+ "[UE] searching BSR index %d for (BSR TABLE %d < value %d)\n",
+ jm,
+ (*get_bsr_value)(jm),
+ value);
+ }
+
+ if (value == (*get_bsr_value)(jl)) {
+ return jl;
+ } else {
+ return jl + 1; //equally ju
+ }
+}
+
static void nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
int CC_id,
frame_t frame,
@@ -2837,54 +2540,329 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
return mac_ce_info.num_sdus > 0; // success if we got at least one sdu
}
-static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac)
+void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
{
- NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
- fapi_nr_ta_command_pdu *ta = &dl_config->dl_config_list[dl_config->number_pdus].ta_command_pdu;
- ta->ta_frame = ul_time_alignment->frame;
- ta->ta_slot = ul_time_alignment->slot;
- ta->is_rar = ul_time_alignment->ta_apply == rar_ta;
- ta->ta_command = ul_time_alignment->ta_command;
- dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_CONFIG_TA_COMMAND;
- dl_config->number_pdus += 1;
- ul_time_alignment->ta_apply = no_ta;
-}
+ int cc_id = ul_info->cc_id;
+ frame_t frame_tx = ul_info->frame;
+ slot_t slot_tx = ul_info->slot;
+ uint32_t gNB_index = ul_info->gNB_index;
-static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac,
- NR_SINGLE_ENTRY_PHR_MAC_CE *phr,
- float P_CMAX,
- float tx_power,
- frame_t frame,
- slot_t slot)
-{
- nr_phr_info_t *phr_info = &mac->scheduling_info.phr_info;
- // Value mapping according to 38.133 10.1.18.1
- const int PC_MAX_00 = -29;
- *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE){.PCMAX = max(0, (int)P_CMAX - PC_MAX_00) & 0x3f};
- // Value mapping according to 38.133 10.1.17.1.1
- const int POWER_HEADROOM_55 = 22;
- int headroom = P_CMAX - tx_power;
- if (headroom < POWER_HEADROOM_55) {
- const int POWER_HEADROOM_0 = -32;
- phr->PH = max(0, headroom - POWER_HEADROOM_0);
- } else {
- phr->PH = min(0x3f, 55 + (headroom - POWER_HEADROOM_55) / 2);
+ RA_config_t *ra = &mac->ra;
+
+ if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_UE_IDLE) {
+ init_RA(mac, frame_tx);
+ // perform the Random Access Resource selection procedure (see clause 5.1.2 and .2a)
+ ra_resource_selection(mac);
}
- LOG_D(NR_MAC,
- "PHR Reporting sfn.slot %d.%d reason = %d, P_CMAX = %d (%5.2f dBm), headrom = %d (%d dB) tx_power = %5.2f dBm\n",
- frame,
- slot,
- phr_info->phr_reporting,
- phr->PCMAX,
- P_CMAX,
- phr->PH,
- headroom,
- tx_power);
+ if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_GENERATE_PREAMBLE)
+ nr_ue_prach_scheduler(mac, frame_tx, slot_tx);
- phr_info->PathlossLastValue = compute_nr_SSB_PL(mac);
- // Restart both timers according to 38.321
- nr_timer_start(&phr_info->periodicPHR_Timer);
- nr_timer_start(&phr_info->prohibitPHR_Timer);
- phr_info->phr_reporting = 0;
+ bool BSRsent = false;
+ if (mac->state == UE_CONNECTED) {
+ nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx);
+ nr_update_rlc_buffers_status(mac, frame_tx, slot_tx, gNB_index);
+ }
+
+ // Schedule ULSCH only if the current frame and slot match those in ul_config_req
+ // AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus)
+ uint8_t ulsch_input_buffer_array[NFAPI_MAX_NUM_UL_PDU][MAX_ULSCH_PAYLOAD_BYTES];
+ int number_of_pdus = 0;
+
+ fapi_nr_ul_config_request_pdu_t *ulcfg_pdu = lockGet_ul_iterator(mac, frame_tx, slot_tx);
+ if (!ulcfg_pdu)
+ return;
+ LOG_D(NR_MAC, "number of UL PDUs: %d with UL transmission in sfn [%d.%d]\n", *ulcfg_pdu->privateNBpdus, frame_tx, slot_tx);
+
+ while (ulcfg_pdu->pdu_type != FAPI_NR_END) {
+ uint8_t *ulsch_input_buffer = ulsch_input_buffer_array[number_of_pdus];
+ if (ulcfg_pdu->pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) {
+ nfapi_nr_ue_pusch_pdu_t *pdu = &ulcfg_pdu->pusch_config_pdu;
+ uint32_t TBS_bytes = pdu->pusch_data.tb_size;
+ LOG_D(NR_MAC,
+ "harq_id %d, new_data_indicator %d, TBS_bytes %d (ra_state %d)\n",
+ pdu->pusch_data.harq_process_id,
+ pdu->pusch_data.new_data_indicator,
+ TBS_bytes,
+ ra->ra_state);
+ pdu->tx_request_body.fapiTxPdu = NULL;
+ if ((ra->ra_state == nrRA_WAIT_RAR || ra->ra_state == nrRA_WAIT_MSGB) && !ra->cfra) {
+ nr_get_Msg3_MsgA_PUSCH_payload(mac, ulsch_input_buffer, TBS_bytes);
+ for (int k = 0; k < TBS_bytes; k++) {
+ LOG_D(NR_MAC, "(%i): 0x%x\n", k, ulsch_input_buffer[k]);
+ }
+ pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer;
+ pdu->tx_request_body.pdu_length = TBS_bytes;
+ number_of_pdus++;
+ T(T_NRUE_MAC_UL_PDU_WITH_DATA, T_INT(mac->crnti), T_INT(frame_tx), T_INT(slot_tx),
+ T_INT(ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id), T_BUFFER(ulsch_input_buffer, TBS_bytes));
+ } else {
+ if (ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator
+ && (mac->state == UE_CONNECTED || (ra->ra_state == nrRA_WAIT_RAR && ra->cfra))) {
+ if (!nr_timer_is_active(&mac->time_alignment_timer) && mac->state == UE_CONNECTED && !get_softmodem_params()->phy_test) {
+ // UL data arrival during RRC_CONNECTED when UL synchronisation status is "non-synchronised"
+ trigger_MAC_UE_RA(mac, NULL);
+ return;
+ }
+ // Getting IP traffic to be transmitted
+ int tx_power = pdu->tx_power;
+ int P_CMAX = nr_get_Pcmax(mac->p_Max,
+ mac->nr_band,
+ mac->frame_structure.frame_type,
+ mac->frequency_range,
+ mac->current_UL_BWP->channel_bandwidth,
+ pdu->qam_mod_order,
+ false,
+ mac->current_UL_BWP->scs,
+ mac->current_UL_BWP->BWPSize,
+ pdu->transform_precoding,
+ pdu->rb_size,
+ pdu->rb_start);
+
+ nr_ue_get_sdu(mac, cc_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes, tx_power, P_CMAX, &BSRsent);
+ pdu->tx_request_body.fapiTxPdu = ulsch_input_buffer;
+ pdu->tx_request_body.pdu_length = TBS_bytes;
+ number_of_pdus++;
+ T(T_NRUE_MAC_UL_PDU_WITH_DATA, T_INT(mac->crnti), T_INT(frame_tx), T_INT(slot_tx),
+ T_INT(ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id), T_BUFFER(ulsch_input_buffer, TBS_bytes));
+ // start or restart dataInactivityTimer if any MAC entity transmits a MAC SDU for DTCH logical channel,
+ // or DCCH logical channel
+ if (mac->data_inactivity_timer)
+ nr_timer_start(mac->data_inactivity_timer);
+ }
+ }
+
+ if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION && !ra->cfra) {
+ LOG_I(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 retransmitted\n", frame_tx, slot_tx);
+ // 38.321 restart the ra-ContentionResolutionTimer at each HARQ retransmission in the first symbol after the end of the Msg3
+ // transmission
+ nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index);
+ }
+ if (ra->ra_state == nrRA_WAIT_RAR && !ra->cfra) {
+ LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 transmitted\n", frame_tx, slot_tx);
+ nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index);
+ }
+ if (ra->ra_state == nrRA_WAIT_MSGB && !ra->cfra) {
+ LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-MsgA-PUSCH transmitted\n", frame_tx, slot_tx);
+ }
+ }
+ ulcfg_pdu++;
+ }
+ release_ul_config(ulcfg_pdu, false);
+
+ if(mac->state >= UE_PERFORMING_RA && mac->state < UE_DETACHING)
+ nr_ue_pucch_scheduler(mac, frame_tx, slot_tx);
+
+ if (mac->if_module != NULL && mac->if_module->scheduled_response != NULL) {
+ LOG_D(NR_MAC, "3# scheduled_response transmitted,%d, %d\n", frame_tx, slot_tx);
+ nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slot_tx,
+ .mac = mac,
+ .module_id = mac->ue_id,
+ .CC_id = cc_id,
+ .phy_data = ul_info->phy_data};
+ mac->if_module->scheduled_response(&scheduled_response);
+ }
+
+ if(mac->state == UE_CONNECTED)
+ nr_update_sr(mac, BSRsent);
+ // Global variables implicit logic
+ // far away, BSR_reporting_active is set
+ mac->scheduling_info.BSR_reporting_active = NR_BSR_TRIGGER_NONE;
+
+ // update Bj for all active lcids before LCP procedure
+ if (mac->current_UL_BWP) {
+ LOG_D(NR_MAC, "%4d.%2d Logical Channel Prioritization\n", frame_tx, slot_tx);
+ for (int i = 0; i < mac->lc_ordered_list.count; i++) {
+ nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
+ int lcid = lc_info->lcid;
+ // max amount of data that can be buffered/accumulated in a logical channel buffer
+ uint32_t bucketSize_max = lc_info->bucket_size;
+ // measure Bj increment the value of Bj by product PBR * T
+ NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
+ int32_t bj = sched_info->Bj;
+ if (lc_info->pbr < UINT_MAX) {
+ uint32_t slots_elapsed = nr_timer_elapsed_time(&sched_info->Bj_timer); // slots elapsed since Bj was last incremented
+ // it is safe to divide by 1k since pbr in lc_info is computed multiplying by 1000 the RRC value to convert kB/s to B/s
+ uint32_t pbr_ms = lc_info->pbr / 1000;
+ bj += ((pbr_ms * slots_elapsed) >> mac->current_UL_BWP->scs); // each slot length is 1/scs ms
+ }
+ else
+ bj = INT_MAX;
+ // bj > max bucket size, set bj to max bucket size, as in ts38.321 5.4.3.1 Logical Channel Prioritization
+ sched_info->Bj = min(bj, bucketSize_max);
+ // reset bj timer
+ nr_timer_start(&sched_info->Bj_timer);
+ }
+ }
+}
+
+// PUSCH scheduler:
+// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2,
+// - where K2 is the offset between the slot in which UL DCI is received and the slot
+// - in which ULSCH should be scheduled. K2 is configured in RRC configuration.
+// PUSCH Msg3 scheduler:
+// - scheduled by RAR UL grant according to 8.3 of TS 38.213
+// Note: Msg3 tx in the uplink symbols of mixed slot
+int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
+ const uint8_t is_Msg3,
+ const frame_t current_frame,
+ const int current_slot,
+ frame_t *frame_tx,
+ int *slot_tx,
+ const long k2)
+{
+ int delta = 0;
+ const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
+
+ // Get the numerology to calculate the Tx frame and slot
+ int mu = current_UL_BWP->scs;
+ int slots_per_frame = mac->frame_structure.numb_slots_frame;
+
+ // k2 as per 3GPP TS 38.214 version 15.9.0 Release 15 ch 6.1.2.1.1
+ // PUSCH time domain resource allocation is higher layer configured from uschTimeDomainAllocationList in either pusch-ConfigCommon
+
+ if (is_Msg3) {
+
+ delta = get_delta_for_k2(mu);
+
+ AssertFatal((k2 + delta) > GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ "Slot offset (%ld) for Msg3 needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to "
+ "%ld in gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
+ k2,
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu));
+
+
+ *slot_tx = (current_slot + k2 + delta) % slots_per_frame;
+ *frame_tx = (current_frame + (current_slot + k2 + delta) / slots_per_frame) % MAX_FRAME_NUMBER;
+ } else {
+ AssertFatal(k2 >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ "Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in "
+ "gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
+ k2,
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu));
+
+
+ if (k2 < 0) { // This can happen when a false DCI is received
+ LOG_W(PHY, "%d.%d. Received k2 %ld\n", current_frame, current_slot, k2);
+ return -1;
+ }
+
+ // Calculate TX slot and frame
+ *slot_tx = (current_slot + k2) % slots_per_frame;
+ *frame_tx = (current_frame + (current_slot + k2) / slots_per_frame) % MAX_FRAME_NUMBER;
+ }
+
+ LOG_D(NR_MAC, "[%04d.%02d] UL transmission in [%04d.%02d] (k2 %ld delta %d)\n", current_frame, current_slot, *frame_tx, *slot_tx, k2, delta);
+ return 0;
+}
+
+void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
+ const NR_CSI_RS_ResourceMapping_t *resourceMapping,
+ uint32_t bwp_size,
+ uint32_t bwp_start)
+{
+ // According to last paragraph of TS 38.214 5.2.2.3.1
+ if (resourceMapping->freqBand.startingRB < bwp_start)
+ csirs_config_pdu->start_rb = bwp_start;
+ else
+ csirs_config_pdu->start_rb = resourceMapping->freqBand.startingRB;
+ if (resourceMapping->freqBand.nrofRBs > (bwp_start + bwp_size - csirs_config_pdu->start_rb))
+ csirs_config_pdu->nr_of_rbs = bwp_start + bwp_size - csirs_config_pdu->start_rb;
+ else
+ csirs_config_pdu->nr_of_rbs = resourceMapping->freqBand.nrofRBs;
+ AssertFatal(csirs_config_pdu->nr_of_rbs >= 24, "CSI-RS has %d RBs, but the minimum is 24\n", csirs_config_pdu->nr_of_rbs);
+
+ csirs_config_pdu->symb_l0 = resourceMapping->firstOFDMSymbolInTimeDomain;
+ if (resourceMapping->firstOFDMSymbolInTimeDomain2)
+ csirs_config_pdu->symb_l1 = *resourceMapping->firstOFDMSymbolInTimeDomain2;
+ csirs_config_pdu->cdm_type = resourceMapping->cdm_Type;
+
+ csirs_config_pdu->freq_density = resourceMapping->density.present;
+ if ((resourceMapping->density.present == NR_CSI_RS_ResourceMapping__density_PR_dot5)
+ && (resourceMapping->density.choice.dot5 == NR_CSI_RS_ResourceMapping__density__dot5_evenPRBs))
+ csirs_config_pdu->freq_density--;
+
+ switch(resourceMapping->frequencyDomainAllocation.present){
+ case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row1:
+ csirs_config_pdu->row = 1;
+ csirs_config_pdu->freq_domain = ((resourceMapping->frequencyDomainAllocation.choice.row1.buf[0]) >> 4) & 0x0f;
+ break;
+ case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row2:
+ csirs_config_pdu->row = 2;
+ csirs_config_pdu->freq_domain = (((resourceMapping->frequencyDomainAllocation.choice.row2.buf[1] >> 4) & 0x0f)
+ | ((resourceMapping->frequencyDomainAllocation.choice.row2.buf[0] << 4) & 0xff0));
+ break;
+ case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_row4:
+ csirs_config_pdu->row = 4;
+ csirs_config_pdu->freq_domain = ((resourceMapping->frequencyDomainAllocation.choice.row4.buf[0]) >> 5) & 0x07;
+ break;
+ case NR_CSI_RS_ResourceMapping__frequencyDomainAllocation_PR_other:
+ csirs_config_pdu->freq_domain = ((resourceMapping->frequencyDomainAllocation.choice.other.buf[0]) >> 2) & 0x3f;
+ // determining the row of table 7.4.1.5.3-1 in 38.211
+ switch (resourceMapping->nrofPorts) {
+ case NR_CSI_RS_ResourceMapping__nrofPorts_p1:
+ AssertFatal(1 == 0, "Resource with 1 CSI port shouldn't be within other rows\n");
+ break;
+ case NR_CSI_RS_ResourceMapping__nrofPorts_p2:
+ csirs_config_pdu->row = 3;
+ break;
+ case NR_CSI_RS_ResourceMapping__nrofPorts_p4:
+ csirs_config_pdu->row = 5;
+ break;
+ case NR_CSI_RS_ResourceMapping__nrofPorts_p8:
+ if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
+ csirs_config_pdu->row = 8;
+ else {
+ int num_k = 0;
+ for (int k = 0; k < 6; k++)
+ num_k += (((csirs_config_pdu->freq_domain) >> k) & 0x01);
+ if (num_k == 4)
+ csirs_config_pdu->row = 6;
+ else
+ csirs_config_pdu->row = 7;
+ }
+ break;
+ case NR_CSI_RS_ResourceMapping__nrofPorts_p12:
+ if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
+ csirs_config_pdu->row = 10;
+ else
+ csirs_config_pdu->row = 9;
+ break;
+ case NR_CSI_RS_ResourceMapping__nrofPorts_p16:
+ if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
+ csirs_config_pdu->row = 12;
+ else
+ csirs_config_pdu->row = 11;
+ break;
+ case NR_CSI_RS_ResourceMapping__nrofPorts_p24:
+ if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
+ csirs_config_pdu->row = 14;
+ else {
+ if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4)
+ csirs_config_pdu->row = 15;
+ else
+ csirs_config_pdu->row = 13;
+ }
+ break;
+ case NR_CSI_RS_ResourceMapping__nrofPorts_p32:
+ if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm4_FD2_TD2)
+ csirs_config_pdu->row = 17;
+ else {
+ if (resourceMapping->cdm_Type == NR_CSI_RS_ResourceMapping__cdm_Type_cdm8_FD2_TD4)
+ csirs_config_pdu->row = 18;
+ else
+ csirs_config_pdu->row = 16;
+ }
+ break;
+ default:
+ AssertFatal(false, "Invalid number of ports in CSI-RS resource\n");
+ }
+ break;
+ default:
+ AssertFatal(false, "Invalid freqency domain allocation in CSI-RS resource\n");
+ }
}
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
index dd5558d546..6dd4886911 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
@@ -490,16 +490,16 @@ static bool check_sib1_tda(gNB_MAC_INST *gNB_mac,
// the UE may assume that this PDSCH resource allocation is not applied (Table 5.1.2.1.1-4 and 5 in 38.214)
int row = tda + 1;
if (table_type == defaultB && (row == 12 || row == 13 || row == 14))
- false;
+ return false;
if (table_type == defaultC && (row == 1 || row == 6 || row == 7 ||row > 12))
- false;
+ return false;
// assuming normal CP
NR_tda_info_t tda_info = get_info_from_tda_tables(table_type, tda, scc->dmrs_TypeA_Position, true);
// SIB1 TDA going to the last symbol would cause overlap with CSI-RS
if (!tda_info.valid_tda || tda_info.startSymbolIndex + tda_info.nrOfSymbols == 14)
- false;
+ return false;
if (tda_info.startSymbolIndex < type0_PDCCH_CSS_config->first_symbol_index + type0_PDCCH_CSS_config->num_symbols)
- false;
+ return false;
NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, &tda_info, 1);
// Configure sched_ctrlCommon for SIB1
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 4d28d66b69..3b8476f9a4 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -1092,7 +1092,13 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context
const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
uint32_t ssb_arfcn = get_ssb_arfcn(du);
LOG_I(NR_RRC, "Reestablishment update key pci=%d, earfcn_dl=%u\n", cell_info->nr_pci, ssb_arfcn);
- nr_derive_key_ng_ran_star(cell_info->nr_pci, ssb_arfcn, ue_p->nh_ncc > 0 ? ue_p->nh : ue_p->kgnb, ue_p->kgnb);
+
+ /* Per TS 33.501 6.9.2.3.4: When sending RRCReestablishment with nextHopChainingCount,
+ * we're staying at the same NCC level (not advancing), so use horizontal derivation
+ * from the currently active KgNB. Vertical derivation (from NH) is only used when
+ * advancing to a new NCC level, which happens during handover or masterKeyUpdate. */
+ const uint8_t *base_key = ue_p->kgnb;
+ nr_derive_key_ng_ran_star(cell_info->nr_pci, ssb_arfcn, base_key, ue_p->kgnb);
int size = do_RRCReestablishment(ue_context_pP->ue_context.nh_ncc, buffer, NR_RRC_BUF_SIZE, xid);
LOG_A(NR_RRC, "Send RRCReestablishment [%d bytes] to RNTI %04x\n", size, ue_p->rnti);
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c
index 5c212438e1..65991f714d 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.c
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.c
@@ -1649,7 +1649,7 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc,
msg.source2target->ue_history_info.cause->type = NGAP_CAUSE_RADIO_NETWORK;
msg.source2target->ue_history_info.cause->value = NGAP_CAUSE_RADIO_NETWORK_HANDOVER_DESIRABLE_FOR_RADIO_REASON;
msg.source2target->ue_history_info.type = NGAP_CellSize_small;
- msg.source2target->ue_history_info.time_in_cell = 500; // dummy number for now
+ msg.source2target->ue_history_info.time_in_cell = min(time(NULL) - UE->last_seen, 4095);
msg.source2target->ue_history_info.id = target_cell;
/* Fill both PDU Session Resource List IE (M) in Handover Required
diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c
index 384be2a7b1..424118fa4c 100644
--- a/openair2/RRC/NR_UE/rrc_UE.c
+++ b/openair2/RRC/NR_UE/rrc_UE.c
@@ -527,13 +527,141 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf
nr_rrc_send_msg_to_mac(rrc, &rrc_msg);
}
-static void nr_rrc_nh_update(NR_UE_RRC_INST_t *rrc, uint8_t *kamf, uint8_t *sync_input)
+/** @brief Synchronize NH chain based on nextHopChainingCount
+ *
+ * This function synchronizes the NH parameter chain as specified in 3GPP TS 33.501 Annex A.10.
+ * Use cases: Master Key Update, RRC Reestablishment: The UE receives an NCC value that is
+ * different from the NCC associated with the currently active KgNB. The NH chain is synchronized
+ * by computing the function defined in Annex A.10 iteratively (and increasing the NCC value until
+ * it matches the NCC value received from the source ng-gNB).
+ *
+ * @param kamf K_AMF key from NAS
+ * @param kgnb Current KgNB key (input/output)
+ * @param nh Current NH parameter (input/output)
+ * @param nhcc Pointer to current nextHopChainingCount (input/output)
+ * @param target_ncc Target nextHopChainingCount value to synchronize to */
+static void nr_sync_nh_chain(const uint8_t kamf[SECURITY_KEY_LEN],
+ uint8_t kgnb[SECURITY_KEY_LEN],
+ uint8_t nh[SECURITY_KEY_LEN],
+ uint64_t *nhcc,
+ const int8_t target_ncc)
{
- uint8_t nh[SECURITY_KEY_LEN] = {0};
- nr_derive_nh(kamf, sync_input, nh);
- log_hex_buffer("Sync input = stored NH", rrc->nh, SECURITY_KEY_LEN);
- memcpy(rrc->nh, nh, SECURITY_KEY_LEN);
- rrc->nhcc++; // Increase stored nextHopChainingCount
+ // If the UE received an NCC value that was different from the NCC associated with the
+ // currently active KgNB, the UE shall first synchronize the locally kept NH
+ // parameter by computing the function defined in Annex A.10 iteratively (and increasing
+ // the NCC value until it matches the NCC value received from the source ng-gNB).
+ if (target_ncc <= *nhcc) {
+ LOG_W(NR_RRC, "Received NCC=%d is less than or equal to current nhcc=%ld (nothing to sync)\n", target_ncc, *nhcc);
+ return;
+ }
+ if (target_ncc > *nhcc) {
+ LOG_I(NR_RRC, "Synchronizing NH chain: current nhcc=%ld, target ncc=%d\n", *nhcc, target_ncc);
+ if (*nhcc == 0) {
+ // First derivation: derive KgNB from KAMF, then derive NH from KgNB (per TS 33.501 A.10)
+ // Note: For the first NH derivation, we use UL NAS COUNT = 0 to match the AMF's derivation
+ // during handover. The AMF derives the first NH using the UL NAS COUNT from the last
+ // successful NAS SMC, which is 0 for the initial derivation.
+ derive_kgnb(kamf, 0, kgnb);
+ nr_derive_nh(kamf, kgnb, nh);
+ *nhcc = 1;
+ }
+ // Following derivations: iterate from current nhcc to target_ncc
+ for (uint8_t i = *nhcc; i < target_ncc; i++) {
+ LOG_D(NR_RRC, "Derive keys for ChainingCount = %d\n", i);
+ nr_derive_nh(kamf, nh, nh);
+ }
+ *nhcc = target_ncc;
+ }
+}
+
+/** @brief Derive KNG-RAN* (KgNB*) using horizontal derivation
+ *
+ * This function derives KNG-RAN* from the currently active KgNB (horizontal derivation)
+ * as specified in 3GPP TS 33.501 Annex A.11 and A.12.
+ * Used when NCC values match (no NH synchronization needed).
+ *
+ * @param pci Physical Cell ID
+ * @param nr_arfcn_dl NR ARFCN-DL
+ * @param kgnb Current KgNB key (input/output)
+ */
+static void nr_derive_kgnb_horizontal(const uint16_t pci, const uint64_t nr_arfcn_dl, uint8_t kgnb[SECURITY_KEY_LEN])
+{
+ // When the NCC values match, the UE shall derive the KNG-RAN* from the currently active
+ // KgNB and the target PCI and its frequency ARFCN-DL using the function defined in Annex A.11 and A.12.
+ LOG_D(NR_RRC, "Deriving KNG-RAN* using horizontal derivation (from current KgNB)\n");
+ nr_derive_key_ng_ran_star(pci, nr_arfcn_dl, kgnb, kgnb);
+}
+
+/** @brief Derive KNG-RAN* (KgNB*) using vertical derivation
+ *
+ * This function derives KNG-RAN* from the synchronized NH parameter (vertical derivation)
+ * as specified in 3GPP TS 33.501 Annex A.11 and A.12.
+ * Used after NH chain synchronization when NCC values differ.
+ *
+ * @param pci Physical Cell ID
+ * @param nr_arfcn_dl NR ARFCN-DL
+ * @param kgnb Current KgNB key (input/output)
+ * @param nh Synchronized NH parameter (input)
+ */
+static void nr_derive_kgnb_vertical(const uint16_t pci,
+ const uint64_t nr_arfcn_dl,
+ uint8_t kgnb[SECURITY_KEY_LEN],
+ const uint8_t nh[SECURITY_KEY_LEN])
+{
+ // When the NCC values match (after synchronization), the UE shall compute the K NG-RAN *
+ // from the synchronized NH parameter and the target PCI and its frequency ARFCN-DL
+ // using the function defined in Annex A.11 and A.12.
+ LOG_D(NR_RRC, "Deriving KNG-RAN* using vertical derivation (from synchronized NH)\n");
+ nr_derive_key_ng_ran_star(pci, nr_arfcn_dl, nh, kgnb);
+}
+
+/** @brief Update KgNB based on received nextHopChainingCount
+ *
+ * This function implements the common logic for updating KgNB based on received NCC value,
+ * as specified in 3GPP TS 33.501 6.9.2.3.4.
+ *
+ * Per 33.501 6.9.2.3.4 and Fig 6.9.2.1.1-1:
+ * - If NCC received == current NCC: use horizontal derivation (from currently active KgNB)
+ * This applies regardless of whether NCC is 0 or >0. For a fixed NCC level, multiple
+ * horizontal derivations can be done within that level.
+ * - If NCC received > current NCC: synchronize NH chain (Annex A.10), then use vertical
+ * derivation (from NH) to enter the new NCC level.
+ *
+ * Horizontal derivation = derive KNG-RAN* from currently active KgNB + (PCI, ARFCN-DL)
+ * Vertical derivation = derive KNG-RAN* from NH + (PCI, ARFCN-DL)
+ *
+ * @param rrc RRC instance pointer
+ * @param kamf K_AMF key from NAS
+ * @param received_ncc Received nextHopChainingCount value */
+static void nr_update_kgnb_from_ncc(NR_UE_RRC_INST_t *rrc, const uint8_t kamf[SECURITY_KEY_LEN], int8_t received_ncc)
+{
+ const uint64_t original_nhcc = rrc->nhcc;
+
+ if (received_ncc == original_nhcc) {
+ // NCC values match: use horizontal derivation from currently active KgNB
+ // Per TS 33.501 6.9.2.3.4: "derive the KNG-RAN* from the currently active KgNB"
+ // This applies regardless of NCC being 0 or >0. For a fixed NCC level, we stay
+ // within that level using horizontal derivations.
+ LOG_D(NR_RRC, "NCC values match (%d), using horizontal derivation\n", received_ncc);
+ nr_derive_kgnb_horizontal(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb);
+ } else if (received_ncc < original_nhcc) {
+ // Note: According to spec, NCC should only increase. If received_ncc < original_nhcc,
+ // this is an error condition, but we handle it gracefully.
+ LOG_W(NR_RRC,
+ "Received NCC=%d is less than current nhcc=%ld (unexpected per spec, NH chain should only increase)\n",
+ received_ncc,
+ original_nhcc);
+ } else {
+ // received_ncc > original_nhcc: synchronize NH chain first (per 33.501 A.10)
+ nr_sync_nh_chain(kamf, rrc->kgnb, rrc->nh, &rrc->nhcc, received_ncc);
+ // Store the received nextHopChainingCount value (per 38.331 5.3.7.5)
+ LOG_D(NR_RRC, "Synchronizing NH chain to target NCC %d\n", received_ncc);
+ rrc->nhcc = received_ncc;
+ // After synchronization, derive KNG-RAN* from synchronized NH (vertical derivation)
+ // per 33.501 6.9.2.3.4: "When the NCC values match, the UE shall compute the K NG-RAN *
+ // from the synchronized NH parameter"
+ nr_derive_kgnb_vertical(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->nh);
+ }
}
/** @brief AS security key update procedure (5.3.5.7 3GPP TS 38.331) */
@@ -545,40 +673,17 @@ void as_security_key_update(NR_UE_RRC_INST_t *rrc, NR_MasterKeyUpdate_t *mku)
if (mku->keySetChangeIndicator) {
LOG_E(NR_RRC, "derive or update the K gNB key based on the K AMF key, as specified in TS 33.501: not implemented yet\n");
} else {
- /* derive or update the K gNB key based on the current K gNB key or the NH, using the nextHopChainingCount
- value indicated in the received masterKeyUpdate, as specified in 6.9.2.3.3 3GPP TS 33.501 */
- if (mku->nextHopChainingCount != rrc->nhcc) {
- // - If the UE received an NCC value that was different from the NCC associated with the currently active
- // K gNB/K eNB, the UE shall first synchronize the locally kept NH parameter by computing the function defined in
- // Annex A.10 iteratively (and increasing the NCC value until it matches the NCC value received from the source
- // ng-eNB/gNB via the HO command message.
- LOG_A(NR_RRC, "Received masterKeyUpdate (nextHopChainingCount %ld): update security keys\n", mku->nextHopChainingCount);
- /** @todo: The KAMF should be obtained from NAS. This exchange over ITTI must be synchronized
- * with the rest of the RRCReconfiguration procedure, in particular, the RadioBearerConfig
- * processing that triggers bearer modifications. Security configueration of bearers must
- * complete using the newly derived keys. As a workaround NAS is directly accessed here. */
- nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id);
- uint8_t *kamf = nas->security.kamf;
- log_hex_buffer("Stored kamf", kamf, SECURITY_KEY_LEN);
- if (rrc->nhcc == 0) { // First derivation
- derive_kgnb(kamf, 0, rrc->kgnb);
- log_hex_buffer("Sync input = derived kgnb", rrc->kgnb, SECURITY_KEY_LEN);
- nr_rrc_nh_update(rrc, kamf, rrc->kgnb);
- }
- for (int i = rrc->nhcc; i < mku->nextHopChainingCount; i++) { // Following derivations
- LOG_D(NR_RRC, "Derive keys for ChainingCount = %d\n", i);
- nr_rrc_nh_update(rrc, kamf, rrc->nh);
- }
- nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->nh, rrc->kgnb);
- // When the NCC values match, the UE shall compute the K NG-RAN *
- // from the synchronized NH parameter and the target PCI and its frequency ARFCN-DL/EARFCN-DL using the
- // function defined in Annex A.11 and A.12.
- // The UE shall use the KNG-RAN * as the K gNB when communicating with the target gNB and as the KeNB when
- // communicating with the target ng-eNB.
- } else {
- nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb);
- }
- log_hex_buffer("Derived kgnb", rrc->kgnb, SECURITY_KEY_LEN);
+ LOG_I(NR_RRC, "Received masterKeyUpdate (nextHopChainingCount %ld): update security keys\n", mku->nextHopChainingCount);
+ /** @todo: The KAMF should be obtained from NAS. This exchange over ITTI must be synchronized
+ * with the rest of the RRCReconfiguration procedure, in particular, the RadioBearerConfig
+ * processing that triggers bearer modifications. Security configueration of bearers must
+ * complete using the newly derived keys. As a workaround NAS is directly accessed here. */
+ nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id);
+ const uint8_t *kamf = nas->security.kamf;
+ // KgNB update (TS 33.501 ยง6.9.2.3.3):
+ // If received NCC != local NCC, iteratively derive NH (Annex A.10) until NCC matches.
+ // Then derive the new KgNB from the synchronized NH.
+ nr_update_kgnb_from_ncc(rrc, kamf, mku->nextHopChainingCount);
}
}
@@ -2246,6 +2351,9 @@ static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t
nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
}
+/** @brief Process RRCReestablishment message
+ * This function processes the RRCReestablishment message received from the gNB,
+ * implementing procedures as described in 38.331 section 5.3.7.5 */
static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
const int gNB_index,
const NR_RRCReestablishment_t *rrcReestablishment,
@@ -2254,18 +2362,19 @@ static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
int msg_size,
const nr_pdcp_integrity_data_t *msg_integrity)
{
- // implementign procedues as described in 38.331 section 5.3.7.5
// stop timer T301
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
nr_timer_stop(&timers->T301);
- // store the nextHopChainingCount value
NR_RRCReestablishment_IEs_t *ies = rrcReestablishment->criticalExtensions.choice.rrcReestablishment;
AssertFatal(ies, "Not expecting RRCReestablishment_IEs to be NULL\n");
- // TODO need to understand how to use nextHopChainingCount
- // int nh = rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount;
- // update the K gNB key based on the current K gNB key or the NH, using the stored nextHopChainingCount value
- nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb);
+ // Update KgNB based on the current K gNB key or the NH,
+ // using the received nextHopChainingCount (per 33.501 6.9.2.3.4)
+ // received from RRCReestablishment and update the stored value in rrc->nhcc
+ int8_t received_ncc = ies->nextHopChainingCount;
+ nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id);
+ const uint8_t *kamf = nas->security.kamf;
+ nr_update_kgnb_from_ncc(rrc, kamf, received_ncc);
// derive the K_RRCenc key associated with the previously configured cipheringAlgorithm
// derive the K_RRCint key associated with the previously configured integrityProtAlgorithm
diff --git a/openair3/SECU/key_nas_deriver.c b/openair3/SECU/key_nas_deriver.c
index 3fb35adee2..a2948ab0b2 100644
--- a/openair3/SECU/key_nas_deriver.c
+++ b/openair3/SECU/key_nas_deriver.c
@@ -150,8 +150,23 @@ void nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t
* NOTE: knas is dynamically allocated by the KDF function
*/
-/** @brief KgNB derivation (A.9 3GPP TS 33.501) */
-void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb)
+/** @brief KgNB derivation function (Annex A.9 3GPP TS 33.501)
+ *
+ * Derives KgNB from K_AMF and the uplink NAS COUNT.
+ * This function is applied when cryptographically protected 5G radio bearers are
+ * established and when a key change on-the-fly is performed.
+ *
+ * KDF input S structure (per Annex A.9):
+ * - FC = 0x6E
+ * - P0 = Uplink NAS COUNT (count parameter)
+ * - L0 = length of uplink NAS COUNT (0x00 0x04)
+ * - P1 = Access type distinguisher (0x01 for 3GPP access)
+ * - L1 = length of Access type distinguisher (0x00 0x01)
+ *
+ * @param[in] kamf 256-bit K_AMF key (input key KEY to KDF)
+ * @param[in] count Uplink NAS COUNT value (P0 in KDF input S)
+ * @param[out] kgnb Derived 256-bit KgNB key */
+void derive_kgnb(const uint8_t kamf[32], const uint32_t count, uint8_t *kgnb)
{
/* Compute the KDF input parameter
* S = FC(0x6E) || UL NAS Count || 0x00 0x04 || 0x01 || 0x00 0x01
diff --git a/openair3/SECU/key_nas_deriver.h b/openair3/SECU/key_nas_deriver.h
index eff72c68bb..100d554aa2 100644
--- a/openair3/SECU/key_nas_deriver.h
+++ b/openair3/SECU/key_nas_deriver.h
@@ -16,7 +16,7 @@ typedef enum {
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
-void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb);
+void derive_kgnb(const uint8_t kamf[32], const uint32_t count, uint8_t *kgnb);
void derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
diff --git a/radio/BLADERF/bladerf_lib.c b/radio/BLADERF/bladerf_lib.c
index 178fc2fff2..bff12bee8e 100644
--- a/radio/BLADERF/bladerf_lib.c
+++ b/radio/BLADERF/bladerf_lib.c
@@ -957,8 +957,6 @@ int device_init(openair0_device *device,
/* device specific */
//openair0_cfg->txlaunch_wait = 1;//manage when TX processing is triggered
//openair0_cfg->txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
- openair0_cfg->iq_txshift = 0;// shift
- openair0_cfg->iq_rxrescale = 15;//rescale iqs
// init required params
switch ((int)openair0_cfg->sample_rate) {
@@ -983,8 +981,6 @@ int device_init(openair0_device *device,
exit(-1);
break;
}
- openair0_cfg->iq_txshift= 0;
- openair0_cfg->iq_rxrescale = 15; /*not sure*/
openair0_cfg->rx_gain_calib_table = calib_table_fx4;
// The number of buffers to use in the underlying data stream
diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h
index 5812e63aa4..5877506ea2 100644
--- a/radio/COMMON/common_lib.h
+++ b/radio/COMMON/common_lib.h
@@ -276,10 +276,6 @@ typedef struct openair0_config {
char *sdr_addrs;
//! Auto calibration flag
int autocal[8];
- //! rf devices work with x bits iqs when oai have its own iq format
- //! the two following parameters are used to convert iqs
- int iq_txshift;
- int iq_rxrescale;
//! Configuration file for LMS7002M
char *configFilename;
//! remote IP/MAC addr for Ethernet interface
diff --git a/radio/ETHERNET/ethernet_lib.c b/radio/ETHERNET/ethernet_lib.c
index 2a4d021afc..038246c998 100644
--- a/radio/ETHERNET/ethernet_lib.c
+++ b/radio/ETHERNET/ethernet_lib.c
@@ -540,40 +540,6 @@ int transport_init(openair0_device *device,
eth->if_name = eth_params->local_if_name;
device->priv = eth;
-
-
- /* device specific */
- // openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
- // openair0_cfg[0].iq_txshift = eth_params->iq_txshift;// shift
- // openair0_cfg[0].tx_sample_advance = eth_params->tx_sample_advance;
-
- /* RRU does not have any information to make this configuration atm */
- /*
- if (device->host_type == RAU_HOST) {
-
- switch ((int)openair0_cfg[0].sample_rate) {
- case 30720000:
- openair0_cfg[0].samples_per_packet = 3840;
- break;
- case 23040000:
- openair0_cfg[0].samples_per_packet = 2880;
- break;
- case 15360000:
- openair0_cfg[0].samples_per_packet = 1920;
- break;
- case 7680000:
- openair0_cfg[0].samples_per_packet = 960;
- break;
- case 1920000:
- openair0_cfg[0].samples_per_packet = 240;
- break;
- default:
- printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
- exit(-1);
- break;
- }
- }*/
-
device->openair0_cfg=&openair0_cfg[0];
return 0;
}
diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp
index 923e938869..dabc6f8947 100644
--- a/radio/USRP/usrp_lib.cpp
+++ b/radio/USRP/usrp_lib.cpp
@@ -478,14 +478,15 @@ static int trx_usrp_write(openair0_device *device,
nsamps2 = (nsamps+7)>>3;
simde__m256i buff_tx[cc < 2 ? 2 : cc][nsamps2];
- // bring RX data into 12 LSBs for softmodem RX
+ // bring TX data into 16 MSBs, assuming it is on the 12 LSB after OAI computation
+ const int shift = 4;
for (int i = 0; i < cc; i++) {
for (int j = 0; j < nsamps2; j++) {
if ((((uintptr_t)buff[i]) & 0x1F) == 0) {
- buff_tx[i][j] = simde_mm256_slli_epi16(((simde__m256i *)buff[i])[j], 4);
+ buff_tx[i][j] = simde_mm256_slli_epi16(((simde__m256i *)buff[i])[j], shift);
} else {
simde__m256i tmp = simde_mm256_loadu_si256(((simde__m256i *)buff[i]) + j);
- buff_tx[i][j] = simde_mm256_slli_epi16(tmp, 4);
+ buff_tx[i][j] = simde_mm256_slli_epi16(tmp, shift);
}
}
}
@@ -605,17 +606,17 @@ void *trx_usrp_write_thread(void * arg){
nsamps2 = (nsamps+7)>>3;
simde__m256i buff_tx[cc < 2 ? 2 : cc][nsamps2];
-
- // bring RX data into 12 LSBs for softmodem RX
+ // bring TX data into 16 MSBs, assuming it is on the 12 LSB after OAI computation
+ const int shift = 4;
for (int i = 0; i < cc; i++) {
for (int j = 0; j < nsamps2; j++) {
if ((((uintptr_t) buff[i])&0x1F)==0) {
- buff_tx[i][j] = simde_mm256_slli_epi16(((simde__m256i *)buff[i])[j], 4);
+ buff_tx[i][j] = simde_mm256_slli_epi16(((simde__m256i *)buff[i])[j], shift);
}
else
{
simde__m256i tmp = simde_mm256_loadu_si256(((simde__m256i *)buff[i]) + j);
- buff_tx[i][j] = simde_mm256_slli_epi16(tmp,4);
+ buff_tx[i][j] = simde_mm256_slli_epi16(tmp, shift);
}
}
}
@@ -752,11 +753,13 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
// bring RX data into 12 LSBs for softmodem RX
for (int i=0; iru_conf;
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology;
@@ -190,7 +193,7 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot)
LOG_W(HW, "we get rach data from ru, but it is not scheduled %d.%d\n", frame, slot);
return -1;
}
- for (sym_idx = 0; sym_idx < prach_info.N_dur; sym_idx++) {
+ for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) {
for (int aa = 0; aa < ru->nb_rx; aa++) {
int16_t *dst, *src;
int idx = 0;
@@ -200,7 +203,7 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot)
src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData;
/* convert Network order to host order */
if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) {
- if (sym_idx == 0) {
+ if (sym_idx == prach_start_sym) {
for (idx = 0; idx < 139 * 2; idx++) {
dst[idx] = ((int16_t)ntohs(src[idx + g_kbar]));
}
@@ -233,7 +236,7 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot)
AssertFatal(1 == 0, "BFP decompression not supported on this architecture");
#endif
// note: this is hardwired for 139 point PRACH sequence, kbar=2
- if (sym_idx == 0) //
+ if (sym_idx == prach_start_sym)
for (idx = 0; idx < (139 * 2); idx++)
dst[idx] = local_dst[idx + g_kbar];
else
diff --git a/radio/rfsimulator/simulator.cpp b/radio/rfsimulator/simulator.cpp
index a29001e0bf..65e32216c4 100644
--- a/radio/rfsimulator/simulator.cpp
+++ b/radio/rfsimulator/simulator.cpp
@@ -54,6 +54,10 @@ extern "C" {
#include
#include
#include "rfsimulator.h"
+extern int get_currentchannels_type(const char *buf,
+ int debug,
+ webdatadef_t *tdata,
+ telnet_printfunc_t prnt); // in random_channel.c
}
#include
#include
@@ -112,10 +116,6 @@ typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole;
};
// clang-format on
static void getset_currentchannels_type(char *buf, int debug, webdatadef_t *tdata, telnet_printfunc_t prnt);
-extern int get_currentchannels_type(const char *buf,
- int debug,
- webdatadef_t *tdata,
- telnet_printfunc_t prnt); // in random_channel.c
static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
static int rfsimu_getdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
diff --git a/radio/rfsimulator/stored_node.c b/radio/rfsimulator/stored_node.c
index 51db5bfea1..5792304671 100644
--- a/radio/rfsimulator/stored_node.c
+++ b/radio/rfsimulator/stored_node.c
@@ -177,6 +177,7 @@ int main(int argc, char *argv[]) {
timestamp+=blockSize;
header.option_value=0;
header.option_flag=0;
+ header.beam_map = 1;
} else {
AssertFatal(read(fd,&header,sizeof(header)), "");
}