diff --git a/.clang-format b/.clang-format index a7248821a9..3b0be979ba 100644 --- a/.clang-format +++ b/.clang-format @@ -62,6 +62,7 @@ ForEachMacros: - BOOST_FOREACH - RB_FOREACH - UE_iterator + - FOR_EACH_SEQ_ARR IncludeBlocks: Preserve IncludeCategories: - Regex: '^' diff --git a/CHANGELOG.md b/CHANGELOG.md index 5df218b36d..a9b355d079 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,51 @@ # RELEASE NOTES: # +## [v2.3.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.3.0) -> July 2025. ## + +General new features and improvements (both RAN and UE): +- Preliminary support for RedCap UEs +- Support for NTN LEO scenarios including SIB19 and channel emulation (see + doc/RUNMODEM.md) +- VRTSIM: new shared memory realtime radio (see develop/radio/vrtsim/README.md) +- Support for TDD pattern 2 +- Support for long PRACH +- Support for SIB2 +- Add unit tests using ctest (see doc/UnitTests.md) + +Stability and bug fixes: +- Improve various procedures (e.g., RRC reestablishment, RRC Reject, ...) +- Add improvements for ImScope +- Bugfixes in the entire stack (e.g., #803, #805, #810, #812, #818, #852, #878, + #884, #890, #895, #901, #907, #932, #939 ...) +- Documentation updates +- And many other small fixes, like memory leaks, crashes, ... + +RAN changes (gNB/CU/CU-CP/CU-UP/DU/DU-high/DU-low): +- Stability and performance improvements when running with 4-layer DL MIMO +- Stability and performance improvements when running with 2-layer UL MIMO +- Interoperability testing with Metanoia Jura and Foxconn RUs +- Support of O-RAN 7.2 M-plane (Start-up procedure including configuration + management, see also doc/ORAN_FHI7.2_Tutorial.md) +- Upgrade OSC FHI (xran) from E to F release +- Refactoring of LDPC interface and performance improvements +- Support for nFAPI in all scenarios for FR1 (see doc/nfapi.md) +- Support at least 32 UEs concurrently +- Improve robustness when running in split modes (F1, E1) +- Add basic support for beam management in FR2 +- Add support for O1 on DU (see also https://gitlab.eurecom.fr/oai/o1-adapter) +- E2 agent: Support for multiple E2SM-RC report service styles + +nrUE changes: +- Refactoring of threading towards better code and performance +- Add or rework various procedures (e.g., RA with C-RNTI, Going to Idle, RA, ...) +- Refactor and extend NAS implementation (e.g., Service Request, Registration + Request, Service Acept, Service Reject, ...) +- Support for continuous frequency offset compensation +- Reduce minimum RX-to-TX time to 3 + +Regression: +- Multiple BWPs do not work reliably on gNB; use tag 2025.w17 + ## [v2.2.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.2.0) -> November 2024. ## General 5G improvements (both gNB and UE): diff --git a/CMakeLists.txt b/CMakeLists.txt index 57d165ea05..8f8a6006bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -652,7 +652,6 @@ add_library(SCHED_LIB ${SCHED_SRC}) target_link_libraries(SCHED_LIB PRIVATE asn1_lte_rrc_hdrs) set(SCHED_NR_SRC - ${OPENAIR1_DIR}/SCHED_NR/fapi_nr_l1.c ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_gNB.c ${OPENAIR1_DIR}/SCHED_NR/nr_prach_procedures.c ${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c @@ -939,7 +938,6 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch.c - ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c @@ -1215,7 +1213,6 @@ set (MAC_SRC set (MAC_NR_SRC ${NR_PHY_INTERFACE_DIR}/NR_IF_Module.c - ${NR_PHY_INTERFACE_DIR}/nr_sched_response.c ${NR_GNB_MAC_DIR}/main.c ${NR_GNB_MAC_DIR}/config.c ${NR_GNB_MAC_DIR}/gNB_scheduler.c @@ -1283,12 +1280,6 @@ set (MISC_NFAPI_LTE add_library(MISC_NFAPI_LTE_LIB ${MISC_NFAPI_LTE}) -set (MISC_NFAPI_NR - ${OPENAIR1_DIR}/SCHED/nfapi_nr_dummy.c - ) - -add_library(MISC_NFAPI_NR_LIB ${MISC_NFAPI_NR}) - add_library(L2 ${L2_SRC} ${MAC_SRC} @@ -2091,7 +2082,7 @@ if (${T_TRACER}) oai_eth_transpro HASHTABLE UTIL SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB - MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB + MISC_NFAPI_LTE_LIB PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_UE_NR ngap GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE SIMU diff --git a/ci-scripts/Jenkinsfile b/ci-scripts/Jenkinsfile new file mode 100644 index 0000000000..abb2e3942c --- /dev/null +++ b/ci-scripts/Jenkinsfile @@ -0,0 +1,233 @@ +#!/bin/groovy +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +def pythonExecutor = params.pythonExecutor +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true +def JOB_TIMESTAMP + +// Choose test stage name or fallback default +def testStageName = params.pipelineTestStageName != null ? params.pipelineTestStageName : 'Template Test Stage' + +// Name of the resource +def lockResources = [] +if (params.LockResources != null && params.LockResources.trim().length() > 0) + params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]} + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters + +def sourceRepository = params.eNB_Repository ?: env.GIT_URL +def sourceBranch = params.eNB_Branch ?: env.GIT_BRANCH +def targetRepository = params.Target_Repository ?: sourceRepository +def targetBranch = params.eNB_TargetBranch ?: 'develop' +def commitID = params.eNB_CommitID ?: env.GIT_COMMIT +def is_MR = params.eNB_mergeRequest ?: false + +def flexricOption = "" +def runWithOC = false + +//------------------------------------------------------------------------------- +// Pipeline start +pipeline { + agent { + label pythonExecutor + } + options { + timestamps() + ansiColor('xterm') + lock(extra: lockResources) + } + + stages { + stage("Build Init") { + steps { + script { + echo '\u2705 \u001B[94mBuild Init\u001B[0m' + JOB_TIMESTAMP = sh(returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"').trim() + } + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Branch : ${sourceBranch}" + } + } + stage ('Verify Parameters') { + steps { + script { + echo '\u2705 \u001B[94mVerify Parameters\u001B[0m' + def allParametersPresent = true + + if (params.LockResources == null) { + echo "no LockResources given" + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + echo "no eNB_SourceCodePath given" + allParametersPresent = false + } + if (params.OC_Credentials != null) { + echo "This pipeline is configured to run with Opensift Cluster." + runWithOC = true + if (params.OC_ProjectName == null) { + echo "no OC_ProjectName given" + allParametersPresent = false + } + } + if (params.Flexric_Tag != null) { + echo "This pipeline is configured to run with a FlexRIC deployment." + echo "Appending FlexRicTag option to the list of options" + flexricOption = "--FlexRicTag=${params.Flexric_Tag}" + echo "Using new Flexric option: ${flexricOption}" + } + + echo "CI executor node : ${pythonExecutor}" + echo "Source Repository : ${sourceRepository}" + echo "Source Branch : ${sourceBranch}" + echo "Target Repository : ${targetRepository}" + echo "Target Branch : ${targetBranch}" + echo "Commit ID : ${commitID}" + + if (allParametersPresent) { + echo '\u2705 \u001B[94m All parameters are present\u001B[0m' + if (is_MR) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${sourceBranch} --src-commit ${commitID} --target-branch ${targetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${commitID}" + } + } else { + echo "\u274C Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + stage ("Deploy and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[94m Deploy and Test: ${testStageName}\u001B[0m" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } else { + echo "Test XML file ${xmlFile}: no such file" + } + } + sh """ + python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + ${flexricOption} ${mainPythonAllXmlFiles} + """ + if (runWithOC) { + withCredentials([usernamePassword(credentialsId: "${params.OC_Credentials}", usernameVariable: 'OC_Username', passwordVariable: 'OC_Password')]) { + sh """ + python3 main.py --mode=InitiateHtml --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + ${flexricOption} ${mainPythonAllXmlFiles} + """ + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + timeout (time: 60, unit: 'MINUTES') { + sh """ + python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \ + --OCUserName=${OC_Username} --OCPassword=${OC_Password} --OCProjectName=${OC_ProjectName} \ + ${flexricOption} + """ + } + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + } + } else { + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + timeout (time: 60, unit: 'MINUTES') { + sh """ + python3 main.py --mode=TesteNB --ranRepository=${targetRepository} \ + --ranBranch=${sourceBranch} --ranCommitID=${commitID} \ + --ranAllowMerge=${is_MR} --ranTargetBranch=${targetBranch} \ + --eNBSourceCodePath=${params.eNB_SourceCodePath} --XMLTestFile=${xmlFile} \ + ${flexricOption} + """ + } + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus}" + } + } + } + } + stage ("Log Collection") { + steps { + script { + echo '\u2705 \u001B[94mLog Collection\u001B[0m' + dir ('ci-scripts') { + // Zipping all archived log files + sh "mkdir test_logs" + sh "mv *.log* test_logs || true" + // Zip all log files matching cmake_targets/{*.log*,log/*} into test_logs_XXXX.zip + if (fileExists('../cmake_targets/log')) { + sh "mv ../cmake_targets/log/* test_logs || true" + } + sh "zip -r -qq test_logs_${env.BUILD_ID}.zip *test_log*/" + sh "rm -rf *test_log*/" + if (fileExists("test_logs_${env.BUILD_ID}.zip")) { + archiveArtifacts artifacts: "test_logs_${env.BUILD_ID}.zip" + } + if (fileExists("test_results.html")) { + def reportName = "test_results-${env.JOB_NAME}.html" + sh "mv test_results.html ${reportName}" + sh """ + sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' \ + -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' \ + -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' \ + -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' \ + -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' ${reportName} + """ + archiveArtifacts artifacts: "${reportName}" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 3301c133ec..a2bb8112fc 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -271,14 +271,15 @@ pipeline { when { expression {doBuild && "PUSH".equals(env.gitlabActionType)} } steps { script { - triggerSlaveJob ('RAN-DockerHub-Push', 'DockerHub-Push') + catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + triggerSlaveJob ('RAN-DockerHub-Push', 'DockerHub-Push') + } } } post { failure { script { echo "Push to Docker-Hub KO" - currentBuild.result = 'FAILURE' failingStages += '\n * RAN-DockerHub-Push' } } diff --git a/ci-scripts/Jenkinsfile-push-registry b/ci-scripts/Jenkinsfile-push-registry index ccd91e28ff..60b8777ba9 100644 --- a/ci-scripts/Jenkinsfile-push-registry +++ b/ci-scripts/Jenkinsfile-push-registry @@ -84,9 +84,20 @@ pipeline { sh "docker login -u ${DH_Username} -p ${DH_Password} > /dev/null 2>&1" sh "docker login -u oaicicd -p oaicicd ${OAI_Registry} > /dev/null 2>&1" listOfImages.eachWithIndex { item, iindex -> - sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop || true" - sh "docker buildx imagetools create --tag ${DH_Account}/${item}:${WEEK_TAG} ${OAI_Registry}/${item}:armv8_develop-${WEEK_SHA} ${OAI_Registry}/${item}:develop-${WEEK_SHA}" - sh "docker buildx imagetools create --tag ${DH_Account}/${item}:develop ${OAI_Registry}/${item}:armv8_develop-${WEEK_SHA} ${OAI_Registry}/${item}:develop-${WEEK_SHA}" + if (["oai-gnb", "oai-nr-ue", "oai-nr-cuup"].contains(item)) { + // For images built on AMD64 and ARMv8 Jetson + echo "Pushing image '${item}' for both AMD64 and ARM64 architectures with tags: ${WEEK_TAG} and develop" + sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop || true" + sh "docker buildx imagetools create --tag ${DH_Account}/${item}:${WEEK_TAG} ${OAI_Registry}/${item}:armv8_develop-${WEEK_SHA} ${OAI_Registry}/${item}:develop-${WEEK_SHA}" + sh "docker buildx imagetools create --tag ${DH_Account}/${item}:develop ${OAI_Registry}/${item}:armv8_develop-${WEEK_SHA} ${OAI_Registry}/${item}:develop-${WEEK_SHA}" + } else { + sh "docker pull --quiet ${OAI_Registry}/${item}:develop-${WEEK_SHA}" + sh "docker image tag ${OAI_Registry}/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:develop" + sh "docker image tag ${OAI_Registry}/${item}:develop-${WEEK_SHA} ${DH_Account}/${item}:${WEEK_TAG}" + sh "docker push --quiet ${DH_Account}/${item}:develop" + sh "docker push --quiet ${DH_Account}/${item}:${WEEK_TAG}" + } + sh "docker rmi ${DH_Account}/${item}:${WEEK_TAG} ${DH_Account}/${item}:develop ${OAI_Registry}/${item}:develop-${WEEK_SHA} || true" } // Proxy is not following the same pattern. sh "docker image tag proxy:develop ${DH_Account}/proxy:develop" diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index 4953f049fb..3a3ea52fa0 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -43,10 +43,6 @@ import constants as CONST def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): - - py_param_file_present = False - py_params={} - force_local = False while len(argvs) > 1: myArgv = argvs.pop(1) # 0th is this file's name @@ -172,4 +168,4 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER): HELP.GenericHelp(CONST.Version) sys.exit('Invalid Parameter: ' + myArgv) - return py_param_file_present, py_params, mode, force_local + return mode, force_local diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 4e13cdf7b3..8a9919c700 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -397,9 +397,9 @@ class Cluster: # Analyze the logs collectInfo = {} for image, lf in log_files: - ret = cls_containerize.AnalyzeBuildLogs(image, lf) - imgStatus = ret['status'] - msg = f"size {imageSize[image]}, analysis of {os.path.basename(lf)}: {ret['errors']} errors, {ret['warnings']} warnings" + imgStatus, errors = cls_containerize.AnalyzeBuildLogs(image, lf) + info = f"Analysis of {os.path.basename(lf)}: {imgStatus=}, size {imageSize[image]}, {len(errors)} errors" + msg = "\n".join([info] + errors) HTML.CreateHtmlTestRowQueue(image, 'OK' if imgStatus else 'KO', [msg]) status = status and imgStatus diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index c97bb8d4d1..71e437676c 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -47,6 +47,7 @@ import helpreadme as HELP import constants as CONST import cls_oaicitest from cls_ci_helper import archiveArtifact +from collections import deque #----------------------------------------------------------- # Helper functions used here and in other classes @@ -85,9 +86,9 @@ def CreateTag(ranCommitID, ranBranch, ranAllowMerge): return tagToUse def AnalyzeBuildLogs(image, lf): - errorandwarnings = {} committed = False tagged = False + errors = [] with open(lf, mode='r') as inputfile: for line in inputfile: lineHasTag = re.search(f'Successfully tagged {image}:', str(line)) is not None @@ -96,11 +97,13 @@ def AnalyzeBuildLogs(image, lf): # the OpenShift Cluster builder prepends image registry URL lineHasCommit = re.search(r'COMMIT [a-zA-Z0-9\.:/\-]*' + image, str(line)) is not None committed = committed or lineHasCommit - errorandwarnings['errors'] = 0 if committed or tagged else 1 - errorandwarnings['warnings'] = 0 - errorandwarnings['status'] = committed or tagged - logging.info(f"Analyzing {image}, file {lf}: {errorandwarnings}") - return errorandwarnings + if re.search(r'error:|Errors|ERROR', line): + errors.append(f"=> {line.strip()}") + status = (committed or tagged) and len(errors) == 0 + logging.info(f"Analyzing {image}, file {lf}: {status=}, {len(errors)} errors") + for e in errors: + logging.info(e) + return status, errors def GetImageName(ssh, svcName, file): ret = ssh.run(f"docker compose -f {file} config --format json {svcName} | jq -r '.services.\"{svcName}\".image'", silent=True) @@ -119,7 +122,7 @@ def ExistEnvFilePrint(ssh, wd, prompt='env vars in existing'): def WriteEnvFile(ssh, services, wd, tag, flexric_tag): ret = ssh.run(f'cat {wd}/.env', silent=True, reportNonZero=False) - registry = "oai-ci" # pull_images() gives us this registry path + registry = "oai-ci/" # pull_images() gives us this registry path envs = {"REGISTRY":registry, "TAG": tag, "FLEXRIC_TAG": flexric_tag} if ret.returncode == 0: # it exists, we have to update # transforms env file to dictionary @@ -134,7 +137,8 @@ def WriteEnvFile(ssh, services, wd, tag, flexric_tag): # or -asan images. We need to detect which kind we did pull. fullImageName = GetImageName(ssh, svc, f"{wd}/docker-compose.y*ml") image = fullImageName.split("/")[-1].split(":")[0] - checkimg = f"{registry}/{image}-asan:{tag}" + # registry now includes the trailing slash ("oai-ci/") + checkimg = f"{registry}{image}-asan:{tag}" ret = ssh.run(f'docker image inspect {checkimg}', reportNonZero=False) if ret.returncode == 0: logging.info(f"detected pulled image {checkimg}") @@ -164,25 +168,26 @@ def CopyinServiceLog(ssh, lSourcePath, svcName, wd_yaml, ctx): ssh.run(f'docker compose -f {wd_yaml} logs {svcName} --no-log-prefix &> {remote_filename}') return archiveArtifact(ssh, ctx, remote_filename) -def GetRunningServices(ssh, file): +def GetDeployedServices(ssh, file): ret = ssh.run(f'docker compose -f {file} config --services') if ret.returncode != 0: + logging.error("could not get services") return None allServices = ret.stdout.splitlines() - running_services = [] + deployed_services = [] for s in allServices: - # outputs the hash if the container is running - ret = ssh.run(f'docker compose -f {file} ps --all --quiet -- {s}') + # outputs the hash if the container has been deployed (but might be stopped) + ret = ssh.run(f'docker compose -f {file} ps --all --quiet -- {s}', silent=True) if ret.returncode != 0: - logging.info(f"service {s}: {ret.stdout}") + # error: should not happen as we iterate over docker-provided service list + logging.error(f"service {s}: {ret.stdout}") elif ret.stdout == "": - logging.warning(f"could not retrieve information for service {s}") + logging.info(f"service {s} not deployed") else: c = ret.stdout - logging.debug(f'running service {s} with container id {c}') - running_services.append((s, c)) - logging.info(f'stopping services: {running_services}') - return running_services + logging.info(f'service {s} with container id {c}') + deployed_services.append(s) + return deployed_services def CheckLogs(self, filename, HTML, RAN): success = True @@ -214,6 +219,24 @@ def CheckLogs(self, filename, HTML, RAN): else: HTML.CreateHtmlTestRowQueue(opt, 'OK', [HTML.htmleNBFailureMsg]) HTML.htmleNBFailureMsg = "" + elif 'xapp' in name: + opt = f"Undeploy {name}" + with open(f'{filename}', "r") as f: + last_line = deque(f, maxlen=1).pop() + if ('Test xApp run SUCCESSFULLY' in last_line): + HTML.CreateHtmlTestRowQueue(opt, 'OK', ["xApp run successfully"]) + else: + HTML.CreateHtmlTestRowQueue(opt, 'KO', ["xApp didn't run successfully"]) + success = False + elif 'RIC' in name: + opt = f"Undeploy {name}" + with open(f'{filename}', 'r') as f: + last_line = deque(f, maxlen=1).pop() + if ('Removing E2 Node' in last_line): + HTML.CreateHtmlTestRowQueue(opt, 'OK', ["nearRT-RIC run successfully"]) + else: + HTML.CreateHtmlTestRowQueue(opt, 'KO', ["nearRT-RIC didn't run successfully"]) + success = False else: logging.info(f"Skipping analysis of log '{filename}': no submatch for xNB/UE") logging.debug(f"log check: file {filename} passed analysis {success}") @@ -439,9 +462,9 @@ class Containerize(): # Analyze the logs for name, lf in log_files: - ret = AnalyzeBuildLogs(name, lf) - imgStatus = ret['status'] - msg = f"size {allImagesSize[name]}, analysis of {os.path.basename(lf)}: {ret['errors']} errors, {ret['warnings']} warnings" + imgStatus, errors = AnalyzeBuildLogs(name, lf) + info = f"Analysis of {os.path.basename(lf)}: {imgStatus=}, size {allImagesSize[name]}, {len(errors)} errors" + msg = "\n".join([info] + errors) HTML.CreateHtmlTestRowQueue(name, 'OK' if imgStatus else 'KO', [msg]) status = status and imgStatus @@ -714,7 +737,6 @@ class Containerize(): def DeployObject(self, ctx, node, HTML): num_attempts = self.num_attempts lSourcePath = self.eNBSourceCodePath - logging.debug(f'Deploying OAI Object on server: {node}') yaml = self.yamlPath.strip('/') wd = f'{lSourcePath}/{yaml}' wd_yaml = f'{wd}/docker-compose.y*ml' @@ -725,6 +747,7 @@ class Containerize(): logging.error(msg) HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg]) return False + logging.info(f'\u001B[1mDeploying object(s) "{services}" on server {node}\u001B[0m') ExistEnvFilePrint(ssh, wd) WriteEnvFile(ssh, services, wd, self.deploymentTag, self.flexricTag) if num_attempts <= 0: @@ -749,36 +772,68 @@ class Containerize(): imagesInfo = info.stdout.splitlines()[1:] logging.debug(f'{info.stdout.splitlines()[1:]}') if deployed: - HTML.CreateHtmlTestRowQueue('N/A', 'OK', ['\n'.join(imagesInfo)]) + HTML.CreateHtmlTestRowQueue(self.services, 'OK', ['\n'.join(imagesInfo)]) + logging.info('\u001B[1m Deploying objects Pass\u001B[0m') else: - HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['\n'.join(imagesInfo)]) + HTML.CreateHtmlTestRowQueue(self.services, 'KO', ['\n'.join(imagesInfo)]) + logging.error('\u001B[1m Deploying objects Failed\u001B[0m') return deployed + def StopObject(self, ctx, node, HTML): + lSourcePath = self.eNBSourceCodePath + if not self.services: + raise ValueError(f'no services provided') + logging.info(f'\u001B[1m Stopping objects "{self.services}" from server: {node}\u001B[0m') + reqServices = self.services.split() + yaml = self.yamlPath.strip('/') + wd = f'{lSourcePath}/{yaml}' + wd_yaml = f'{wd}/docker-compose.y*ml' + with cls_cmd.getConnection(node) as ssh: + ExistEnvFilePrint(ssh, wd) + services = GetDeployedServices(ssh, wd_yaml) + success = [] + fail = [] + for s in reqServices: + if s in services: + ssh.run(f'docker compose -f {wd_yaml} stop -- {s}') + success.append(s) + else: + logging.error(f"no such service {s}") + fail.append(s) + if success == reqServices: + logging.info('\u001B[1m Stopping object Pass\u001B[0m') + HTML.CreateHtmlTestRowQueue(self.services, 'OK', [f'Stopped {self.services}']) + else: + logging.error('\u001B[1m Stopping object Failed\u001B[0m') + HTML.CreateHtmlTestRowQueue(self.services, 'KO', [f'Failed stopping {" ".join(fail)}, succeeded {" ".join(success)}']) + return success + def UndeployObject(self, ctx, node, HTML, RAN): lSourcePath = self.eNBSourceCodePath - logging.debug(f'\u001B[1m Undeploying OAI Object from server: {node}\u001B[0m') + logging.info(f'\u001B[1m Undeploying all objects from server {node}\u001B[0m') yaml = self.yamlPath.strip('/') wd = f'{lSourcePath}/{yaml}' + wd_yaml = f'{wd}/docker-compose.y*ml' with cls_cmd.getConnection(node) as ssh: ExistEnvFilePrint(ssh, wd) - services = GetRunningServices(ssh, f"{wd}/docker-compose.y*ml") + services = GetDeployedServices(ssh, wd_yaml) copyin_res = None + ssh.run(f'docker compose -f {wd_yaml} stop') if services is not None: - all_serv = " ".join([s for s, _ in services]) - ssh.run(f'docker compose -f {wd}/docker-compose.y*ml stop -- {all_serv}') - copyin_res = [CopyinServiceLog(ssh, lSourcePath, s, f"{wd}/docker-compose.y*ml", ctx) for s, _ in services] + copyin_res = [CopyinServiceLog(ssh, lSourcePath, s, wd_yaml, ctx) for s in services] else: logging.warning('could not identify services to stop => no log file') - ssh.run(f'docker compose -f {wd}/docker-compose.y*ml down -v') + ssh.run(f'docker compose -f {wd_yaml} down -v') ssh.run(f'rm {wd}/.env') if not copyin_res: HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['Could not copy logfile(s)']) - return False + logging.error(f"could not copy all files: {copyin_res=} {services=}") + success = False else: log_results = [CheckLogs(self, f, HTML, RAN) for f in copyin_res] success = all(log_results) if success: - logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m') + logging.info('\u001B[1m Undeploying objects Pass\u001B[0m') else: - logging.error('\u001B[1m Undeploying OAI Object Failed\u001B[0m') + logging.error('\u001B[1m Undeploying objects Failed\u001B[0m') return success diff --git a/ci-scripts/cls_module.py b/ci-scripts/cls_module.py index cfdd96477f..17d45828c8 100644 --- a/ci-scripts/cls_module.py +++ b/ci-scripts/cls_module.py @@ -111,10 +111,11 @@ class Module_UE: return self._collectTrace(ctx) return None - def attach(self, attach_tries = 4, attach_timeout = 60): + def attach(self, attach_tries = 3, attach_timeout = 0): ip = None while attach_tries > 0: self._command(self.cmd_dict["attach"]) + attach_timeout += 20 timeout = attach_timeout logging.debug("Waiting for IP address to be assigned") ip = self.getIP(silent=False, reportNonZero=True) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 2b31f41064..cf37e591c6 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -233,10 +233,10 @@ def Custom_Command(HTML, node, command): HTML.CreateHtmlTestRowQueue(command, status, message) return status == 'OK' or status == 'Warning' -def Custom_Script(HTML, node, script): +def Custom_Script(HTML, node, script, args): logging.info(f"Executing custom script on {node}") with cls_cmd.getConnection(node) as c: - ret = c.exec_script(script, 90) + ret = c.exec_script(script, 90, args) logging.debug(f"Custom_Script: {script} on node: {node} - return code {ret.returncode}, output:\n{ret.stdout}") status = 'OK' message = [ret.stdout] @@ -299,18 +299,16 @@ class OaiCiTest(): self.iperf_packetloss_threshold = '' self.iperf_bitrate_threshold = '' self.iperf_profile = '' - self.iperf_options = '' self.iperf_tcp_rate_target = '' self.finalStatus = False self.air_interface='' self.ue_ids = [] - self.nodes = [] self.svr_node = None self.svr_id = None self.cmd_prefix = '' # prefix before {lte,nr}-uesoftmodem - def InitializeUE(self, HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def InitializeUE(self, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] messages = [] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.initialize) for ue in ues] @@ -321,8 +319,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('N/A', 'OK', messages) return True - def AttachUE(self, HTML): - ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)] + def AttachUE(self, node, HTML): + ues = [cls_module.Module_UE(ue_id, node) for ue_id in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.attach) for ue in ues] attached = [f.result() for f in futures] @@ -337,8 +335,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not retrieve UE IP address(es) or MTU(s) wrong!"]) return success - def DetachUE(self, HTML): - ues = [cls_module.Module_UE(ue_id, server_name) for ue_id, server_name in zip(self.ue_ids, self.nodes)] + def DetachUE(self, node, HTML): + ues = [cls_module.Module_UE(ue_id, node) for ue_id in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.detach) for ue in ues] [f.result() for f in futures] @@ -346,8 +344,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('NA', 'OK', messages) return True - def DataDisableUE(self, HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def DataDisableUE(self, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.dataDisable) for ue in ues] status = [f.result() for f in futures] @@ -360,8 +358,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not disable UE data!"]) return success - def DataEnableUE(self, HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def DataEnableUE(self, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] logging.debug(f'disabling data for UEs {ues}') with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.dataEnable) for ue in ues] @@ -375,8 +373,8 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue('N/A', 'KO', ["Could not enable UE data!"]) return success - def CheckStatusUE(self,HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def CheckStatusUE(self, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] logging.debug(f'checking status of UEs {ues}') messages = [] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: @@ -446,10 +444,10 @@ class OaiCiTest(): return (True, message) - def Ping(self, ctx, HTML, infra_file="ci_infra.yaml"): + def Ping(self, ctx, node, HTML, infra_file="ci_infra.yaml"): if self.ue_ids == [] or self.svr_id == None: raise Exception("no module names in self.ue_ids or/and self.svr_id provided") - ues = [cls_module.Module_UE(ue_id, server_name, infra_file) for ue_id, server_name in zip(self.ue_ids, self.nodes)] + ues = [cls_module.Module_UE(ue_id, node, infra_file) for ue_id in self.ue_ids] cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file) with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(self.Ping_common, ctx, cn, ue) for ue in ues] @@ -503,6 +501,11 @@ class OaiCiTest(): t = iperf_time * 2.5 cmd_ue.run(f'rm {client_filename}', reportNonZero=False, silent=True) if cn.runIperf3Server(): + # Clean up any existing iperf3 server processes on this port. + ret = cmd_svr.run(f"{cn.getCmdPrefix()} pkill -f '.*iperf3.*{port}'", reportNonZero=False) + # If pkill succeeds, it means there was a leftover iperf3 server. + if ret.returncode == 0: + logging.warning(f'Iperf3 server on port {port} detected and terminated') cmd_svr.run(f'{cn.getCmdPrefix()} timeout -vk3 {t} iperf3 -s -B {svrIP} -p {port} -1 {jsonReport} >> /dev/null &', timeout=t) cmd_ue.run(f'{ue.getCmdPrefix()} timeout -vk3 {t} {iperf_ue} -B {ueIP} -c {svrIP} -p {port} {iperf_opt} {jsonReport} {serverReport} -O 5 >> {client_filename}', timeout=t) dest_filename = archiveArtifact(cmd_ue, ctx, client_filename) @@ -515,12 +518,12 @@ class OaiCiTest(): return (status, f'{ue_header}\n{msg}') - def Iperf(self, ctx, HTML, infra_file="ci_infra.yaml"): - logging.debug(f'Iperf: iperf_args "{self.iperf_args}" iperf_packetloss_threshold "{self.iperf_packetloss_threshold}" iperf_bitrate_threshold "{self.iperf_bitrate_threshold}" iperf_profile "{self.iperf_profile}" iperf_options "{self.iperf_options}"') + def Iperf(self, ctx, node, HTML, infra_file="ci_infra.yaml"): + logging.debug(f'Iperf: iperf_args "{self.iperf_args}" iperf_packetloss_threshold "{self.iperf_packetloss_threshold}" iperf_bitrate_threshold "{self.iperf_bitrate_threshold}" iperf_profile "{self.iperf_profile}"') if self.ue_ids == [] or self.svr_id == None: raise Exception("no module names in self.ue_ids or/and self.svr_id provided") - ues = [cls_module.Module_UE(ue_id, server_name, infra_file) for ue_id, server_name in zip(self.ue_ids, self.nodes)] + ues = [cls_module.Module_UE(ue_id, node, infra_file) for ue_id in self.ue_ids] cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file) with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(self.Iperf_Module, ctx, cn, ue, i, len(ues)) for i, ue in enumerate(ues)] @@ -544,10 +547,10 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', messages) return success - def Iperf2_Unidir(self, ctx, HTML, infra_file="ci_infra.yaml"): + def Iperf2_Unidir(self, ctx, node, HTML, infra_file="ci_infra.yaml"): if self.ue_ids == [] or self.svr_id == None or len(self.ue_ids) != 1: raise Exception("no module names in self.ue_ids or/and self.svr_id provided, multi UE scenario not supported") - ue = cls_module.Module_UE(self.ue_ids[0].strip(),self.nodes[0].strip(), infra_file) + ue = cls_module.Module_UE(self.ue_ids[0].strip(), node, infra_file) cn = cls_corenetwork.CoreNetwork(self.svr_id, self.svr_node, filename=infra_file) ueIP = ue.getIP() if not ueIP: @@ -847,8 +850,8 @@ class OaiCiTest(): global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return global_status - def TerminateUE(self, ctx, HTML): - ues = [cls_module.Module_UE(n.strip()) for n in self.ue_ids] + def TerminateUE(self, ctx, node, HTML): + ues = [cls_module.Module_UE(n.strip(), node) for n in self.ue_ids] with concurrent.futures.ThreadPoolExecutor(max_workers=64) as executor: futures = [executor.submit(ue.terminate, ctx) for ue in ues] archives = [f.result() for f in futures] diff --git a/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf b/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf index f16a94b472..ca1d9de0d7 100644 --- a/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf +++ b/ci-scripts/conf_files/gnb-cu.sa.f1.ho.conf @@ -53,7 +53,7 @@ security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen # valid values: nea0, nea1, nea2, nea3 - ciphering_algorithms = ( "nea0" ); + ciphering_algorithms = ( "nea2", "nea0" ); # preferred integrity algorithms # the first one of the list that an UE supports in chosen @@ -63,7 +63,7 @@ security = { # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' drb_ciphering = "yes"; - drb_integrity = "no"; + drb_integrity = "yes"; }; log_config : diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index e4d9127284..4daf7c62fd 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -23,7 +23,6 @@ gNBs = ////////// Physical parameters: min_rxtxtime = 2; - do_CSIRS = 1; do_SRS = 1; servingCellConfigCommon = ( @@ -135,11 +134,11 @@ gNBs = # pattern1 # dl_UL_TransmissionPeriodicity # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 - dl_UL_TransmissionPeriodicity = 6; - nrofDownlinkSlots = 7; - nrofDownlinkSymbols = 6; - nrofUplinkSlots = 2; - nrofUplinkSymbols = 4; + dl_UL_TransmissionPeriodicity = 5; + nrofDownlinkSlots = 3; + nrofDownlinkSymbols = 10; + nrofUplinkSlots = 1; + nrofUplinkSymbols = 2; ssPBCH_BlockPower = -25; } diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf index f26891d8f2..9e95918e6f 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf @@ -32,7 +32,7 @@ gNBs = pdsch_AntennaPorts_N1 = 2; pusch_AntennaPorts = 2; do_CSIRS = 1; - do_SRS = 0; + do_SRS = 1; min_rxtxtime = 2; servingCellConfigCommon = ( @@ -155,7 +155,7 @@ gNBs = nrofUplinkSlots = 3; #1; nrofUplinkSymbols = 0; - ssPBCH_BlockPower = -25; + ssPBCH_BlockPower = -15; } ); @@ -176,8 +176,8 @@ gNBs = NETWORK_INTERFACES : { - GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.202"; - GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.202"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.53"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.53"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 }; @@ -195,7 +195,7 @@ MACRLCs = ( remote_s_portd = 50010; // pnf p7 port [!] tr_s_preference = "aerial"; tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 200; # 150; + pusch_TargetSNRx10 = 280; # 150; pucch_TargetSNRx10 = 200; #200; dl_max_mcs = 28; ul_max_mcs = 28; diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf index 90662226ed..3410875961 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf @@ -24,9 +24,9 @@ gNBs = pdsch_AntennaPorts_N1 = 2; pusch_AntennaPorts = 2; do_CSIRS = 1; - do_SRS = 0; + do_SRS = 1; min_rxtxtime = 2; - + force_UL256qam_off = 1; servingCellConfigCommon = ( { #spCellConfigCommon @@ -168,8 +168,8 @@ gNBs = NETWORK_INTERFACES : { - GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.202"; - GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.202"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.53"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.53"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 }; @@ -187,7 +187,7 @@ MACRLCs = ( remote_s_portd = 50010; // pnf p7 port [!] tr_s_preference = "aerial"; tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 220; # 150; + pusch_TargetSNRx10 = 260; # 150; pucch_TargetSNRx10 = 200; #200; dl_max_mcs = 28; ul_max_mcs = 28; diff --git a/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf b/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf index eb7c1e01e2..737ef0aadf 100644 --- a/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf +++ b/ci-scripts/conf_files/gnb.band78.106prb.rfsim.phytest-dora.conf @@ -195,6 +195,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 50; eNB_instances = [0]; + sl_ahead = 3; sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; } ); diff --git a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf index a7663ae811..b3884a3d31 100644 --- a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf @@ -16,7 +16,7 @@ gNBs = ////////// Physical parameters: - do_SINR = 1; + CSI_report_type = "ssb_sinr"; min_rxtxtime = 6; disable_harq = 1; cu_sibs = [2]; diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf index 4be45f6e19..41e9974caf 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf @@ -106,8 +106,7 @@ gNBs = pucchGroupHopping = 0; hoppingId = 40; p0_nominal = -90; -# ssb_PositionsInBurs_BitmapPR -# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_Bitmap = 1; # ssb_periodicityServingCell # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 diff --git a/ci-scripts/conf_files/gnb.sa.band77.51prb.usrpb200.n2-ho.conf b/ci-scripts/conf_files/gnb.sa.band77.51prb.usrpb200.n2-ho.conf new file mode 100644 index 0000000000..577e23a87d --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band77.51prb.usrpb200.n2-ho.conf @@ -0,0 +1,237 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 001; mnc = 03; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + + // Include neighbour configuration for N2 handover + @include "neighbour-config-ho.conf" + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3610.56 MHz + absoluteFrequencySSB = 679104; + dl_frequencyBand = 77; + # this is 3599.94 MHz + dl_absoluteFrequencyPointA = 678388; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 51; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13750; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 77; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 51; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13750; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "172.21.6.109"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.19.98"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.19.98"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + ul_prbblack_SNR_threshold = 10; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 100; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0; + att_rx = 0; + bands = [77]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + clock_src = "external"; + time_src = "external"; +} +); + + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea2", "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "yes"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf index 35542cba95..2550662fa6 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf @@ -1,4 +1,4 @@ -Active_gNBs = ( "gnb-rfsim"); +Active_gNBs = ("gnb-rfsim"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf index 6322d1463c..7bfceaf620 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf @@ -18,8 +18,6 @@ gNBs = ////////// Physical parameters: - do_CSIRS = 0; - do_SRS = 0; min_rxtxtime = 6; servingCellConfigCommon = ( diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.prs.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.prs.conf new file mode 100644 index 0000000000..3b6b591d85 --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.prs.conf @@ -0,0 +1,256 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 97; mnc_length = 2;}); + + ////////// Physical parameters: + + min_rxtxtime = 6; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 + absoluteFrequencySSB = 621312; + # this is 3300.60 MHz + dl_absoluteFrequencyPointA = 620040; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + +#uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -104; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spar e1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + +#tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "CI_MME_IP_ADDR"; }); + + NETWORK_INTERFACES : + { + + GNB_IPV4_ADDRESS_FOR_NG_AMF = "CI_GNB_IP_ADDR"; + GNB_IPV4_ADDRESS_FOR_NGU = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; +} +); + +prs_config = ( +{ + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [0]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [0]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + sf_extension = 0; + eNB_instances = [0]; +} +); + + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level = "info"; + hw_log_level = "info"; + phy_log_level = "info"; + mac_log_level = "info"; + rlc_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + f1ap_log_level = "debug"; +}; diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml index 7454c24a33..e493fab8ca 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml @@ -4,7 +4,7 @@ Active_gNBs: e2_agent: enabled: "yes" near_ric_ip_addr: 192.168.71.21 - near_ric_port: 36421 + e2ap_server_port: 36422 sm_dir: "/usr/local/lib/flexric/" # Asn1_verbosity, choice in: none, info, annoying @@ -152,7 +152,8 @@ MACRLCs: tr_n_preference: local_RRC pusch_TargetSNRx10: 200 pucch_TargetSNRx10: 200 - # min_grant_prb: 10 + min_grant_prb: 5 + stats_max_ue: 17 L1s: - num_cc: 1 diff --git a/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf index 4a3d2852c4..afe40c733c 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf @@ -196,6 +196,7 @@ RUs = ( att_tx = 0 att_rx = 0; bands = [78]; + sl_ahead=3; max_pdschReferenceSignalPower = -27; max_rxgain = 114; sf_extension = 0; diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf index e9f3089019..58571b839f 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf @@ -21,10 +21,6 @@ gNBs = nr_cellid = 12345678L ////////// Physical parameters: - pdsch_AntennaPorts_XP = 1; - pusch_AntennaPorts = 1; - do_CSIRS = 1; - do_SRS = 0; uess_agg_levels = [2, 2, 2, 0, 0]; servingCellConfigCommon = ( @@ -186,6 +182,7 @@ MACRLCs = ( tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 200; + stats_max_ue = 17; } ); diff --git a/ci-scripts/conf_files/nrue.band78.106prb.l2sim.conf b/ci-scripts/conf_files/nrue.band78.106prb.l2sim.conf index 45d192dc04..0dfd31a789 100644 --- a/ci-scripts/conf_files/nrue.band78.106prb.l2sim.conf +++ b/ci-scripts/conf_files/nrue.band78.106prb.l2sim.conf @@ -14,7 +14,6 @@ key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; dnn= "oai"; nssai_sst=1; -nssai_sd=16777215; } MACRLCs = ( diff --git a/ci-scripts/conf_files/nrue.band78.106prb.prs.conf b/ci-scripts/conf_files/nrue.band78.106prb.prs.conf new file mode 100644 index 0000000000..1bf92fd0d6 --- /dev/null +++ b/ci-scripts/conf_files/nrue.band78.106prb.prs.conf @@ -0,0 +1,89 @@ +PRSs = +( + { + Active_gNBs = 1; + prs_config0 = ( + { + gNB_id = 0; + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [0]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [0]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; + } + ); + + prs_config1 = ( + { + gNB_id = 1; + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [1]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [1]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; + } + ); + + prs_config2 = ( + { + gNB_id = 2; + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [2]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [2]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; + } + ); + + prs_config3 = ( + { + gNB_id = 3; + NumPRSResources = 1; + PRSResourceSetPeriod = [20, 2]; + SymbolStart = [7]; + NumPRSSymbols = [6]; + NumRB = 106; + RBOffset = 0; + CombSize = 4; + REOffset = [0]; + PRSResourceOffset = [3]; + PRSResourceRepetition = 1; + PRSResourceTimeGap = 1; + NPRS_ID = [3]; + MutingPattern1 = []; + MutingPattern2 = []; + MutingBitRepetition = 1; + } + ); + } +); diff --git a/ci-scripts/conf_files/ue.sa.conf b/ci-scripts/conf_files/ue.sa.conf index 9101c7e8e9..dc744fb732 100644 --- a/ci-scripts/conf_files/ue.sa.conf +++ b/ci-scripts/conf_files/ue.sa.conf @@ -4,7 +4,6 @@ uicc0 = { opc= "c42449363bbad02b66d16bc975d77cc1"; dnn= "oai"; nssai_sst=1; - nssai_sd=66051; } thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" diff --git a/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf b/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf index 7242b91190..7bdbe7127c 100644 --- a/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf +++ b/ci-scripts/conf_files/untested/gnb.sa.band78.fr1.51PRB.usrpb210.conf @@ -17,9 +17,6 @@ gNBs = ////////// Physical parameters: - do_CSIRS = 0; - do_SRS = 0; - servingCellConfigCommon = ( { #spCellConfigCommon diff --git a/ci-scripts/datalog_rt_stats.100.2x2.yaml b/ci-scripts/datalog_rt_stats.100.2x2.yaml index 7c5cb48add..360ba57402 100644 --- a/ci-scripts/datalog_rt_stats.100.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.100.2x2.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 200.0 L1 Rx processing : 530.0 PUSCH inner-receiver : 360.0 - Schedule Response : 1.0 DL & UL scheduling timing : 17.0 UL Indication : 1.0 Slot Indication : 13.0 @@ -31,7 +30,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.25 UL Indication : 1.00 Slot Indication : 0.50 diff --git a/ci-scripts/datalog_rt_stats.1x1.60.yaml b/ci-scripts/datalog_rt_stats.1x1.60.yaml index 5e0564977b..b418b74940 100644 --- a/ci-scripts/datalog_rt_stats.1x1.60.yaml +++ b/ci-scripts/datalog_rt_stats.1x1.60.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 110.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 150.0 - Schedule Response : 1.0 DL & UL scheduling timing : 5.0 UL Indication : 1.0 Slot Indication : 6.0 @@ -31,7 +30,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.50 UL Indication : 1.00 Slot Indication : 0.50 diff --git a/ci-scripts/datalog_rt_stats.2x2.yaml b/ci-scripts/datalog_rt_stats.2x2.yaml index 7d489c171e..25009bad10 100644 --- a/ci-scripts/datalog_rt_stats.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.2x2.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 230.0 L1 Rx processing : 175.0 PUSCH inner-receiver : 100.0 - Schedule Response : 3.0 DL & UL scheduling timing : 11.0 UL Indication : 3.0 Slot Indication : 14.0 @@ -28,7 +27,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.50 UL Indication : 1.00 Slot Indication : 0.25 diff --git a/ci-scripts/datalog_rt_stats.60.2x2.yaml b/ci-scripts/datalog_rt_stats.60.2x2.yaml index 7352136764..6df6fded54 100644 --- a/ci-scripts/datalog_rt_stats.60.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.60.2x2.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 140.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 155.0 - Schedule Response : 1.0 DL & UL scheduling timing : 8.0 UL Indication : 3.0 Slot Indication : 9.0 @@ -31,7 +30,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.35 UL Indication : 1.00 Slot Indication : 0.35 diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index be3f8b277e..65fd678b0f 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 90.0 L1 Rx processing : 290.0 PUSCH inner-receiver : 115.0 - Schedule Response : 1.0 DL & UL scheduling timing : 4.0 UL Indication : 2.0 Slot Indication : 5.0 @@ -31,7 +30,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.50 UL Indication : 1.00 Slot Indication : 0.50 diff --git a/ci-scripts/main.py b/ci-scripts/main.py index ac4ac2c3be..8aadad76bb 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -85,15 +85,7 @@ def CheckClassValidity(xml_class_list,action,id): resp=True return resp -#assigning parameters to object instance attributes (even if the attributes do not exist !!) -def AssignParams(params_dict): - - for key,value in params_dict.items(): - setattr(CiTestObj, key, value) - setattr(RAN, key, value) - setattr(HTML, key, value) - -def ExecuteActionWithParam(action, ctx): +def ExecuteActionWithParam(action, ctx, node): global RAN global HTML global CONTAINERS @@ -102,7 +94,6 @@ def ExecuteActionWithParam(action, ctx): if action == 'Build_eNB' or action == 'Build_Image' or action == 'Build_Proxy' or action == "Build_Cluster_Image" or action == "Build_Run_Tests": RAN.Build_eNB_args=test.findtext('Build_eNB_args') CONTAINERS.imageKind=test.findtext('kind') - node = test.findtext('node') proxy_commit = test.findtext('proxy_commit') if proxy_commit is not None: CONTAINERS.proxyCommit = proxy_commit @@ -118,7 +109,6 @@ def ExecuteActionWithParam(action, ctx): success = CONTAINERS.BuildRunTests(ctx, node, HTML) elif action == 'Initialize_eNB': - node = test.findtext('node') datalog_rt_stats_file=test.findtext('rt_stats_cfg') if datalog_rt_stats_file is None: RAN.datalog_rt_stats_file='datalog_rt_stats.default.yaml' @@ -139,7 +129,6 @@ def ExecuteActionWithParam(action, ctx): success = RAN.InitializeeNB(ctx, node, HTML) elif action == 'Terminate_eNB': - node = test.findtext('node') #retx checkers string_field = test.findtext('d_retx_th') if (string_field is not None): @@ -158,68 +147,35 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Terminate_UE' or action == 'CheckStatusUE' or action == 'DataEnable_UE' or action == 'DataDisable_UE': CiTestObj.ue_ids = test.findtext('id').split(' ') - if force_local: - # Change all execution targets to localhost - CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids) - else: - if test.findtext('nodes'): - CiTestObj.nodes = test.findtext('nodes').split(' ') - if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): - logging.error('Number of Nodes are not equal to the total number of UEs') - sys.exit("Mismatch in number of Nodes and UIs") - else: - CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) if action == 'Initialize_UE': - success = CiTestObj.InitializeUE(HTML) + success = CiTestObj.InitializeUE(node, HTML) elif action == 'Attach_UE': - success = CiTestObj.AttachUE(HTML) + success = CiTestObj.AttachUE(node, HTML) elif action == 'Detach_UE': - success = CiTestObj.DetachUE(HTML) + success = CiTestObj.DetachUE(node, HTML) elif action == 'Terminate_UE': - success = CiTestObj.TerminateUE(ctx, HTML) + success = CiTestObj.TerminateUE(ctx, node, HTML) elif action == 'CheckStatusUE': - success = CiTestObj.CheckStatusUE(HTML) + success = CiTestObj.CheckStatusUE(node, HTML) elif action == 'DataEnable_UE': - success = CiTestObj.DataEnableUE(HTML) + success = CiTestObj.DataEnableUE(node, HTML) elif action == 'DataDisable_UE': - success = CiTestObj.DataDisableUE(HTML) + success = CiTestObj.DataDisableUE(node, HTML) elif action == 'Ping': CiTestObj.ping_args = test.findtext('ping_args') CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') CiTestObj.ue_ids = test.findtext('id').split(' ') - CiTestObj.svr_id = test.findtext('svr_id') or None + CiTestObj.svr_id = test.findtext('svr_id') if test.findtext('svr_node'): CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost' - if force_local: - # Change all execution targets to localhost - CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids) - else: - if test.findtext('nodes'): - CiTestObj.nodes = test.findtext('nodes').split(' ') - if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): - logging.error('Number of Nodes are not equal to the total number of UEs') - sys.exit("Mismatch in number of Nodes and UIs") - else: - CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) ping_rttavg_threshold = test.findtext('ping_rttavg_threshold') or '' - success = CiTestObj.Ping(ctx, HTML) + success = CiTestObj.Ping(ctx, node, HTML) elif action == 'Iperf' or action == 'Iperf2_Unidir': CiTestObj.iperf_args = test.findtext('iperf_args') CiTestObj.ue_ids = test.findtext('id').split(' ') - CiTestObj.svr_id = test.findtext('svr_id') or None - if force_local: - # Change all execution targets to localhost - CiTestObj.nodes = ['localhost'] * len(CiTestObj.ue_ids) - else: - if test.findtext('nodes'): - CiTestObj.nodes = test.findtext('nodes').split(' ') - if len(CiTestObj.ue_ids) != len(CiTestObj.nodes): - logging.error('Number of Nodes are not equal to the total number of UEs') - sys.exit("Mismatch in number of Nodes and UIs") - else: - CiTestObj.nodes = [None] * len(CiTestObj.ue_ids) + CiTestObj.svr_id = test.findtext('svr_id') if test.findtext('svr_node'): CiTestObj.svr_node = test.findtext('svr_node') if not force_local else 'localhost' CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') @@ -229,14 +185,10 @@ def ExecuteActionWithParam(action, ctx): if CiTestObj.iperf_profile != 'balanced' and CiTestObj.iperf_profile != 'unbalanced' and CiTestObj.iperf_profile != 'single-ue': logging.error(f'test-case has wrong profile {CiTestObj.iperf_profile}, forcing balanced') CiTestObj.iperf_profile = 'balanced' - CiTestObj.iperf_options = test.findtext('iperf_options') or 'check' - if CiTestObj.iperf_options != 'check' and CiTestObj.iperf_options != 'sink': - logging.error('test-case has wrong option ' + CiTestObj.iperf_options) - CiTestObj.iperf_options = 'check' if action == 'Iperf': - success = CiTestObj.Iperf(ctx, HTML) + success = CiTestObj.Iperf(ctx, node, HTML) elif action == 'Iperf2_Unidir': - success = CiTestObj.Iperf2_Unidir(ctx, HTML) + success = CiTestObj.Iperf2_Unidir(ctx, node, HTML) elif action == 'IdleSleep': st = test.findtext('idle_sleep_time_in_sec') or "5" @@ -244,7 +196,6 @@ def ExecuteActionWithParam(action, ctx): elif action == 'Deploy_Run_OC_PhySim': oc_release = test.findtext('oc_release') - node = test.findtext('node') or None script = "scripts/oc-deploy-physims.sh" image_tag = cls_containerize.CreateTag(CLUSTER.ranCommitID, CLUSTER.ranBranch, CLUSTER.ranAllowMerge) options = f"oaicicd-core-for-ci-ran {oc_release} {image_tag} {CLUSTER.eNBSourceCodePath}" @@ -252,7 +203,6 @@ def ExecuteActionWithParam(action, ctx): success = cls_oaicitest.Deploy_Physim(ctx, HTML, node, workdir, script, options) elif action == 'Build_Deploy_Docker_PhySim' or action == 'Build_Deploy_Source_PhySim': - node = test.findtext('node') or None ctest_opt = test.findtext('ctest-opt') or '' script = "scripts/docker-build-and-deploy-physims.sh" if action == 'Build_Deploy_Docker_PhySim' else 'scripts/source-deploy-physims.sh' options = f"{CONTAINERS.eNBSourceCodePath} {ctest_opt}" @@ -264,8 +214,7 @@ def ExecuteActionWithParam(action, ctx): core_op = getattr(cls_oaicitest.OaiCiTest, action) success = core_op(cn_id, ctx, HTML) - elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace": - node = test.findtext('node') + elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace" or action == "Stop_Object": CONTAINERS.yamlPath = test.findtext('yaml_path') string_field=test.findtext('d_retx_th') if (string_field is not None): @@ -278,6 +227,8 @@ def ExecuteActionWithParam(action, ctx): CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge) if action == 'Deploy_Object': success = CONTAINERS.DeployObject(ctx, node, HTML) + elif action == 'Stop_Object': + success = CONTAINERS.StopObject(ctx, node, HTML) elif action == 'Undeploy_Object': success = CONTAINERS.UndeployObject(ctx, node, HTML, RAN) elif action == 'Create_Workspace': @@ -287,15 +238,12 @@ def ExecuteActionWithParam(action, ctx): success = CONTAINERS.Create_Workspace(node, HTML) elif action == 'LicenceAndFormattingCheck': - node = test.findtext('node') success = SCA.LicenceAndFormattingCheck(ctx, node, HTML) elif action == 'Cppcheck_Analysis': - node = test.findtext('node') success = SCA.CppCheckAnalysis(ctx, node, HTML) elif action == 'Push_Local_Registry': - node = test.findtext('node') tag_prefix = test.findtext('tag_prefix') or "" success = CONTAINERS.Push_Image_to_Local_Registry(node, HTML, tag_prefix) @@ -303,7 +251,6 @@ def ExecuteActionWithParam(action, ctx): if force_local: # Do not pull or remove images when running locally. User is supposed to handle image creation & cleanup return True - node = test.findtext('node') tag_prefix = test.findtext('tag_prefix') or "" images = test.findtext('images').split() # hack: for FlexRIC, we need to overwrite the tag to use @@ -316,26 +263,21 @@ def ExecuteActionWithParam(action, ctx): success = CONTAINERS.Clean_Test_Server_Images(HTML, node, images, tag=tag) elif action == 'Custom_Command': - node = test.findtext('node') - if force_local: - # Change all execution targets to localhost - node = 'localhost' command = test.findtext('command') # Allow referencing repository workspace path in XML via %%workspace%% command = command.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath) success = cls_oaicitest.Custom_Command(HTML, node, command) elif action == 'Custom_Script': - node = test.findtext('node') script = test.findtext('script') + args = test.findtext('args') # Allow referencing repository workspace path in XML via %%workspace%% script = script.replace("%%workspace%%", CONTAINERS.eNBSourceCodePath) - success = cls_oaicitest.Custom_Script(HTML, node, script) + success = cls_oaicitest.Custom_Script(HTML, node, script, args) elif action == 'Pull_Cluster_Image': tag_prefix = test.findtext('tag_prefix') or "" images = test.findtext('images').split() - node = test.findtext('node') success = CLUSTER.PullClusterImage(HTML, node, images, tag_prefix=tag_prefix) else: @@ -353,8 +295,16 @@ def test_in_list(test, list): return True return False +test_runner_abort = False def receive_signal(signum, frame): - sys.exit(1) + global test_runner_abort + if not test_runner_abort: + logging.warning("received signal, canceling steps") + logging.info("send signal again to exit immediately") + test_runner_abort = True + else: + logging.warning("received signal again, exiting") + sys.exit(1) def ShowTestID(ctx, desc): logging.info(f'\u001B[1m----------------------------------------\u001B[0m') @@ -399,16 +349,7 @@ CLUSTER = cls_cluster.Cluster() import args_parse # Force local execution, move all execution targets to localhost force_local = False -py_param_file_present, py_params, mode, force_local = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER) - - - -#----------------------------------------------------------- -# TEMPORARY params management (UNUSED) -#----------------------------------------------------------- -#temporary solution for testing: -if py_param_file_present == True: - AssignParams(py_params) +mode, force_local = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER) #----------------------------------------------------------- # mode amd XML class (action) analysis @@ -554,7 +495,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re #logging.info('test will be run: ' + test) todo_tests.append(test) - signal.signal(signal.SIGUSR1, receive_signal) + signal.signal(signal.SIGINT, receive_signal) HTML.CreateHtmlTabHeader() @@ -564,6 +505,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re i = 0 for test_case_id in todo_tests: for test in all_tests: + if test_runner_abort: + task_set_succeeded = False id = test.get('id') if test_case_id != id: continue @@ -572,6 +515,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re ctx = TestCaseCtx(i, int(id), logPath) HTML.testCase_id=CiTestObj.testCase_id desc = test.findtext('desc') + node = test.findtext('node') if not force_local else 'localhost' always_exec = test.findtext('always_exec') in ['True', 'true', 'Yes', 'yes'] may_fail = test.findtext('may_fail') in ['True', 'true', 'Yes', 'yes'] HTML.desc = desc @@ -586,7 +530,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re HTML.CreateHtmlTestRowQueue(msg, "SKIP", []) break try: - test_succeeded = ExecuteActionWithParam(action, ctx) + test_succeeded = ExecuteActionWithParam(action, ctx, node) if not test_succeeded and may_fail: logging.warning(f"test ID {test_case_id} action {action} may or may not fail, proceeding despite error") elif not test_succeeded: diff --git a/ci-scripts/scripts/set-and-verify-distance-prs.sh b/ci-scripts/scripts/set-and-verify-distance-prs.sh new file mode 100755 index 0000000000..73012a4484 --- /dev/null +++ b/ci-scripts/scripts/set-and-verify-distance-prs.sh @@ -0,0 +1,89 @@ +#!/bin/bash + +[[ $# -lt 1 ]] && { echo "Usage: $0 "; exit 1; } +DISTANCES=("$@") + +IP=192.168.71.150 +PORT=8091 +NCAT_TIMEOUT=1 #s +SLEEP_WAIT=4 #s +MAX_RETRIES=3 + +set_and_verify_distance() { + local distance=$1 + echo "Testing PRS ToA estimation for distance: $distance m" + + # it seems that grep returns immediately with this syntax, but not echo | ncat | grep + # so prefer this to receive new distance immediately. We use --idle to keep + # ncat open for some additional time + local setdist_resp="$(grep --max-count 1 new_offset <(echo rfsimu setdistance rfsimu_channel_enB0 $distance | ncat --idle ${NCAT_TIMEOUT} ${IP} ${PORT}))" + echo "> response: ${setdist_resp}" + + local gettoa_resp="$(echo "ciUE get_max_dl_toa" | ncat ${IP} ${PORT} | grep "UE max PRS DL ToA")" + echo "> response: ${gettoa_resp}" + + [[ -z "$setdist_resp" || -z "$gettoa_resp" ]] && return 1 + + # Extract ToA values + [[ "$setdist_resp" =~ new_offset\ ([0-9]+) ]] && local set_toa="${BASH_REMATCH[1]}" || { echo "> Set ToA extraction failed for distance: $distance m"; return 1; } + + [[ "$gettoa_resp" =~ UE\ max\ PRS\ DL\ ToA\ ([0-9]+) ]] && local est_toa="${BASH_REMATCH[1]}" || { echo "> Estimated ToA extraction failed for distance: $distance m"; return 1; } + + # Compare extracted ToA values + [[ $set_toa == $est_toa ]] && echo "PRS SUCCESS for distance: $distance m" || { echo "PRS FAILURE for distance: $distance m (Actual ToA=$set_toa, Estimated ToA=$est_toa)" ; return 1; } + +} + +test_distance() { + local distance=$1 retries=0 + + # retry loop incase we didn't receive the response + while (( retries < MAX_RETRIES )); do + echo " Attempt $((retries + 1))/$MAX_RETRIES" + + # Always reset to 0 m before testing target distance + if ! set_and_verify_distance 0; then + echo " Set distance 0 m failed during attempt $((retries + 1))" + else + sleep "$SLEEP_WAIT" + # Now test the actual target distance + if set_and_verify_distance "$distance"; then + return 0 + fi + fi + + ((retries++)) + if (( retries < MAX_RETRIES )); then + sleep "$SLEEP_WAIT" + else + echo " ERROR: No valid response after $MAX_RETRIES retries for distance: $distance m" + return 1 + fi + done +} + +num_success=0 +num_fail=0 + +for d in "${DISTANCES[@]}"; do + if test_distance "$d"; then + ((num_success++)) + else + ((num_fail++)) + fi + sleep "$SLEEP_WAIT" +done + +# ---- Summary ---- +echo +echo "==================== SUMMARY ====================" +echo "Total tests run : ${#DISTANCES[@]}" +echo "Successful tests: ${num_success}" +echo "Failed tests : ${num_fail}" +echo "=================================================" + +if [ $num_success -gt 0 ]; then + exit 0 +else + exit 1 +fi diff --git a/ci-scripts/tests/deployment.py b/ci-scripts/tests/deployment.py index e7efc707bf..10bd2c843f 100644 --- a/ci-scripts/tests/deployment.py +++ b/ci-scripts/tests/deployment.py @@ -60,6 +60,33 @@ class TestDeploymentMethods(unittest.TestCase): self.assertTrue(deploy) self.assertTrue(undeploy) + def test_stop_services(self): + self.cont.yamlPath = 'tests/simple-undep/' + self.cont.deploymentTag = "noble" + # should deploy both testA and testB + deploy = self.cont.DeployObject(self.ctx, self.node, self.html) + # should fail (no such service) + self.cont.services = "testC" + stopC = self.cont.StopObject(self.ctx, self.node, self.html) + # should stop testA + self.cont.services = "testA" + stopA = self.cont.StopObject(self.ctx, self.node, self.html) + # should (re-)stop testA (no-op) + self.cont.services = "testA" + stopA2 = self.cont.StopObject(self.ctx, self.node, self.html) + # should deploy testB + self.cont.services = "testB" + stopB = self.cont.StopObject(self.ctx, self.node, self.html) + # should not undeploy anything (everything already stopped) + self.cont.services = None + undeployAll = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) + self.assertTrue(deploy) + self.assertFalse(stopC) + self.assertTrue(stopA) + self.assertTrue(stopA2) + self.assertTrue(stopB) + self.assertTrue(undeployAll) + def test_deployfails(self): # fails reliably old = self.cont.yamlPath diff --git a/ci-scripts/tests/ping-iperf.py b/ci-scripts/tests/ping-iperf.py index bd30768a9f..3450a2b3e9 100644 --- a/ci-scripts/tests/ping-iperf.py +++ b/ci-scripts/tests/ping-iperf.py @@ -23,7 +23,7 @@ class TestPingIperf(unittest.TestCase): self.html.testCaseId = "000000" self.ci = cls_oaicitest.OaiCiTest() self.ci.ue_ids = ["test"] - self.ci.nodes = ["localhost"] + self.node = "localhost" self.ctx = TestCaseCtx.Default(tempfile.mkdtemp()) def tearDown(self): with cls_cmd.LocalCmd() as c: @@ -35,7 +35,7 @@ class TestPingIperf(unittest.TestCase): self.ci.svr_id = "test" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Ping(self.ctx, self.html, infra_file=infra_file) + success = self.ci.Ping(self.ctx, self.node, self.html, infra_file=infra_file) self.assertTrue(success) def test_iperf(self): @@ -50,7 +50,7 @@ class TestPingIperf(unittest.TestCase): self.ci.iperf_profile = "balanced" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Iperf(self.ctx, self.html, infra_file=infra_file) + success = self.ci.Iperf(self.ctx, self.node, self.html, infra_file=infra_file) self.assertTrue(success) def test_iperf2_unidir(self): @@ -62,7 +62,7 @@ class TestPingIperf(unittest.TestCase): self.ci.iperf_profile = "balanced" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Iperf2_Unidir(self.ctx, self.html, infra_file=infra_file) + success = self.ci.Iperf2_Unidir(self.ctx, self.node, self.html, infra_file=infra_file) self.assertTrue(success) def test_iperf_highrate(self): @@ -77,7 +77,7 @@ class TestPingIperf(unittest.TestCase): self.ci.iperf_profile = "balanced" infra_file = "tests/config/infra_ping_iperf.yaml" # TODO Should need nothing but options and UE(s) to use - success = self.ci.Iperf(self.ctx, self.html, infra_file=infra_file) + success = self.ci.Iperf(self.ctx, self.node, self.html, infra_file=infra_file) self.assertTrue(success) if __name__ == '__main__': diff --git a/ci-scripts/tests/simple-undep/docker-compose.yml b/ci-scripts/tests/simple-undep/docker-compose.yml new file mode 100644 index 0000000000..6f88826a9a --- /dev/null +++ b/ci-scripts/tests/simple-undep/docker-compose.yml @@ -0,0 +1,23 @@ +services: + testA: + image: ubuntu:${TAG:-jammy} + container_name: test_container_A + cap_drop: + - ALL + entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + test: /bin/bash -c "true" + interval: 1s + timeout: 1s + retries: 1 + testB: + image: ubuntu:${TAG:-jammy} + container_name: test_container_B + cap_drop: + - ALL + entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + test: /bin/bash -c "true" + interval: 1s + timeout: 1s + retries: 1 diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index 615454bbea..a20b78fc99 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -20,6 +20,7 @@ - Build_Image - Build_Run_Tests - Deploy_Object + - Stop_Object - Undeploy_Object - Cppcheck_Analysis - Deploy_Run_OC_PhySim diff --git a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml index eabece50cd..8a010b9308 100644 --- a/ci-scripts/xml_files/container_4g_l2sim_tdd.xml +++ b/ci-scripts/xml_files/container_4g_l2sim_tdd.xml @@ -44,7 +44,7 @@ Pull_Local_Registry Pull Images from Local Registry - obelix + localhost oai-enb oai-lte-ue @@ -88,16 +88,16 @@ Attach_UE Attach OAI UE l2sim4g_ue - obelix + localhost Ping Ping trf-gen from LTE-UE 1 l2sim4g_ue - obelix + localhost l2sim4g_ext_dn - obelix + localhost -c 20 0 @@ -106,9 +106,9 @@ Ping Ping LTE-UE 1 from trf-gen l2sim4g_ext_dn - obelix + localhost l2sim4g_ue - obelix + localhost -c 20 0 @@ -117,9 +117,9 @@ Iperf Iperf UDP Downlink l2sim4g_ue - obelix + localhost l2sim4g_ext_dn - obelix + localhost -u -t 30 -b 1M -R 25 80 @@ -129,9 +129,9 @@ Iperf Iperf UDP Uplink l2sim4g_ue - obelix + localhost l2sim4g_ext_dn - obelix + localhost -u -t 30 -b 3M 25 80 @@ -149,7 +149,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - obelix + localhost oai-enb oai-lte-ue diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml index 4b93c10fcd..3606957af6 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz.xml @@ -103,16 +103,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim4g_ue - acamas + localhost Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -c 20 5 @@ -121,9 +121,9 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - acamas + localhost rfsim4g_ue - acamas + localhost -c 20 5 @@ -136,8 +136,8 @@ -u -t 30 -b 2M -R 25 80 - acamas - acamas + localhost + localhost @@ -148,8 +148,8 @@ -u -t 30 -b 1M 25 80 - acamas - acamas + localhost + localhost diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml index 968e30071a..1d7194f44f 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_05MHz_noS1.xml @@ -83,9 +83,9 @@ Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - acamas + localhost rfsim4g_enb_nos1 - acamas + localhost -c 20 5 @@ -94,9 +94,9 @@ Ping Ping LTE-UE from eNB rfsim4g_enb_nos1 - acamas + localhost rfsim4g_ue - acamas + localhost -c 20 5 @@ -105,9 +105,9 @@ Iperf Iperf UDP DL rfsim4g_ue - acamas + localhost rfsim4g_enb_nos1 - acamas + localhost -u -t 30 -b 2M -R 25 80 @@ -117,9 +117,9 @@ Iperf Iperf UDP UL rfsim4g_ue - acamas + localhost rfsim4g_enb_nos1 - acamas + localhost -u -t 30 -b 1M 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml index 076ee6995b..a5b642ebe0 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_10MHz.xml @@ -103,16 +103,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim4g_ue - acamas + localhost Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -c 20 5 @@ -121,9 +121,9 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - acamas + localhost rfsim4g_ue - acamas + localhost -c 20 5 @@ -132,9 +132,9 @@ Iperf Iperf UDP DL rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -u -t 30 -b 2M -R 25 80 @@ -144,9 +144,9 @@ Iperf Iperf UDP UL rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -u -t 30 -b 1M 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml index 2e049e4efe..592c80de68 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fdd_20MHz.xml @@ -103,16 +103,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim4g_ue - acamas + localhost Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -c 20 5 @@ -121,9 +121,9 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - acamas + localhost rfsim4g_ue - acamas + localhost -c 20 5 @@ -132,9 +132,9 @@ Iperf Iperf UDP DL rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -u -t 30 -b 2M -R 25 80 @@ -144,9 +144,9 @@ Iperf Iperf UDP UL rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -u -t 30 -b 1M 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml index 7ab434c804..21d2acc4eb 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_fembms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_fembms.xml @@ -80,9 +80,9 @@ Iperf2_Unidir Iperf2 UDP DL rfsim4g_ue_fembms - acamas + localhost rfsim4g_enb_fembms - acamas + localhost -u -t 30 -b 2M 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml index e6a4cde19a..70d5db33cb 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_mbms.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_mbms.xml @@ -80,9 +80,9 @@ Iperf Iperf UDP DL rfsim4g_ue - acamas + localhost rfsim4g_enb_nos1 - acamas + localhost -u -t 30 -b 2M -R 25 80 diff --git a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml index 2e22577879..60054cb305 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_tdd_05MHz.xml @@ -103,9 +103,9 @@ Ping Ping Traffic-Gen from LTE-UE rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -c 20 5 @@ -114,9 +114,9 @@ Ping Ping LTE-UE from Traffic-Gen rfsim4g_ext_dn - acamas + localhost rfsim4g_ue - acamas + localhost -c 20 5 @@ -125,9 +125,9 @@ Iperf Iperf UDP DL rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -u -t 30 -b 2M -R 25 80 @@ -137,9 +137,9 @@ Iperf Iperf UDP UL rfsim4g_ue - acamas + localhost rfsim4g_ext_dn - acamas + localhost -u -t 30 -b 1M 25 80 diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml index d27091ac63..5c0fa2b99e 100644 --- a/ci-scripts/xml_files/container_5g_e1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -76,16 +76,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 - acamas acamas acamas + localhost Ping Ping ext-dn from all NR-UEs rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 - acamas acamas acamas + localhost rfsim5g_5gc_fixed_ip - acamas + localhost -c 20 -i0.25 5 diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index 50e794e4cb..f17be0215d 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -107,7 +107,7 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - acamas + localhost @@ -122,9 +122,9 @@ Ping Ping ext-dn from all NR-UEs rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i0.25 5 @@ -132,30 +132,30 @@ Custom_Command Simulate a DL radio channel with noise (3 dB) - acamas + localhost echo channelmod modify 0 noise_power_dB 3 | ncat --send-only 192.168.71.181 8091 Iperf - Iperf (DL/3Mbps/UDP)(30 sec) + Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 Iperf - Iperf (UL/3Mbps/UDP)(30 sec) + Iperf (UL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 @@ -163,7 +163,7 @@ Custom_Command Trigger Reestablishment - acamas + localhost echo ci force_reestab | ncat 192.168.71.171 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' @@ -171,9 +171,9 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i0.5 -w25 80 @@ -181,56 +181,56 @@ Custom_Command Verify Reestablishment - acamas + localhost echo ci get_reestab_count | ncat 192.168.71.150 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' Custom_Command Simulate a disruption of DL radio channel (ploss 55) - acamas + localhost echo channelmod modify 0 ploss 55 | ncat 192.168.71.181 8091 Custom_Command Get UE sync state (UE ID 0) - acamas + localhost echo ciUE sync_state 0 | ncat 192.168.71.181 8091 | grep -E UE_NOT_SYNC Custom_Command Restoration of the original DL channel conditions (ploss 20) - acamas + localhost echo channelmod modify 0 ploss 20 | ncat 192.168.71.181 8091 Custom_Command Get UE sync state (UE ID 0) - acamas + localhost echo ciUE sync_state 0 | ncat 192.168.71.181 8091 | grep -E UE_CONNECTED Custom_Command Trigger Handover - acamas + localhost echo ci trigger_f1_ho | ncat 192.168.71.150 9090 Custom_Command UE (1) connected to DU-PCI 0? - acamas + localhost echo ci fetch_du_by_ue_id 1 | ncat 192.168.71.150 9090 | grep "3584" Custom_Command UE (1) connected to DU-PCI 1? - acamas + localhost echo ci fetch_du_by_ue_id 1 | ncat 192.168.71.150 9090 | grep "3585" diff --git a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml index 6ce1e37b90..44ccb3a3d2 100644 --- a/ci-scripts/xml_files/container_5g_fdd_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_fdd_rfsim.xml @@ -70,16 +70,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - acamas + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -88,9 +88,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue - acamas + localhost -c 20 -i 0.25 5 @@ -100,9 +100,9 @@ Iperf (DL/3Mbps/UDP)(30 sec) -u -b 3M -t 30 -R rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 @@ -112,9 +112,9 @@ Iperf (UL/3Mbps/UDP)(30 sec) -u -b 3M -t 30 rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 diff --git a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml index 8ee9326b5e..135eab6b68 100644 --- a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml @@ -42,6 +42,13 @@ 002006 444444 100002 + 100003 + 100004 + 100005 + 100006 + 100007 + 100008 + 100009 100001 222221 222222 @@ -95,10 +102,10 @@ Deploy_Object - Deploy OAI FlexRIC + Deploy OAI nearRT-RIC localhost ci-scripts/yaml_files/5g_rfsimulator_flexric - oai-flexric + nearRT-RIC @@ -121,7 +128,7 @@ Ping Ping ext-dn from both UEs rfsim5g_ue rfsim5g_ue2 - carabe carabe + carabe oai_ext_dn carabe -c 20 @@ -132,14 +139,14 @@ Attach_UE Attach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - carabe carabe + carabe Detach_UE Detach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - carabe carabe + carabe @@ -151,16 +158,72 @@ + Stop_Object + Stop RC monitoring xApp + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + xapp-rc-moni + + + + Stop_Object + Stop KPM monitoring xApp + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + xapp-kpm-moni + + + + Stop_Object + Stop KPM monitoring and RC control xApp + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + xapp-kpm-rc + + + + Stop_Object + Stop custom SMs monitoring xApp + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + xapp-gtp-mac-rlc-pdcp-moni + + + + Stop_Object + Stop OAI UEs + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + oai-nr-ue oai-nr-ue2 + + + + Stop_Object + Stop OAI gNB + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + oai-gnb + + + + Stop_Object + Stop nearRT-RIC + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + nearRT-RIC + + + Undeploy_Object - Undeploy RAN and Flexric + Undeploy RAN and FlexRIC localhost ci-scripts/yaml_files/5g_rfsimulator_flexric true - + Deploy_Object - RC monitoring + Deploy RC monitoring localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-rc-moni @@ -168,7 +231,7 @@ Deploy_Object - KPM monitoring + Deploy KPM monitoring localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-kpm-moni @@ -176,7 +239,7 @@ Deploy_Object - KPM monitoring and RC control + Deploy KPM monitoring and RC control localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-kpm-rc @@ -184,7 +247,7 @@ Deploy_Object - Custom SMs monitoring + Deploy custom SMs monitoring localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-gtp-mac-rlc-pdcp-moni diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index d7fb38ef8f..43d2072040 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -125,16 +125,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 - acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -143,9 +143,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue - acamas + localhost -c 20 -i 0.25 5 @@ -154,9 +154,9 @@ Ping Ping ext-dn from Second NR-UE rfsim5g_ue2 - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -165,9 +165,9 @@ Ping Ping Second NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue2 - acamas + localhost -c 20 -i 0.25 5 @@ -176,9 +176,9 @@ Ping Ping ext-dn from both UEs rfsim5g_ue rfsim5g_ue2 - acamas acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -187,33 +187,33 @@ Ping Ping ext-dn from all UEs rfsim5g_ue rfsim5g_ue2 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 - acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 -s 1016 5 Iperf - Iperf (DL/3Mbps/UDP)(30 sec) + Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 Iperf - Iperf (UL/1Mbps/UDP)(30 sec) + Iperf (UL/1Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 @@ -222,21 +222,21 @@ Attach_UE Attach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - acamas acamas + localhost Detach_UE Detach OAI UE 1 and 2 rfsim5g_ue rfsim5g_ue2 - acamas acamas + localhost Detach_UE Detach OAI UE 3 to 10 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 - acamas acamas acamas acamas acamas acamas acamas acamas + localhost diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index 7db37d8e63..b8e01c7edc 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -88,7 +88,7 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - acamas + localhost @@ -101,9 +101,9 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i0.5 80 @@ -112,33 +112,33 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue - acamas + localhost -c 20 -i0.2 5 Iperf - Iperf (DL/3Mbps/UDP)(30 sec) + Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 Iperf - Iperf (UL/1Mbps/UDP)(30 sec) + Iperf (UL/1Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 @@ -146,14 +146,14 @@ Custom_Command Force Msg3 C-RNTI RA - acamas + localhost echo ciUE force_crnti_ra | ncat 192.168.71.150 8091 Custom_Command Force RRC_IDLE (UE ID 0) - acamas + localhost echo ciUE force_RRC_IDLE | ncat 192.168.71.150 8091 diff --git a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml index 75924e1ca2..236106d966 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_2x2.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_2x2.xml @@ -70,16 +70,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - acamas + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -88,33 +88,33 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue - acamas + localhost -c 20 -i 0.25 5 Iperf - Iperf (DL/10Mbps/UDP)(30 sec) + Iperf (DL/10Mbps/UDP)(20 sec) -u -b 10M -t 20 -R rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 Iperf - Iperf (UL/3Mbps/UDP)(30 sec) + Iperf (UL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml index b376df99f4..4b695063e7 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fdd_phytest.xml @@ -49,7 +49,7 @@ Custom_Command Clean-Up any residual volume - acamas + localhost docker volume rm 5g_rfsimulator_fdd_phytest_rrc.config -f @@ -77,9 +77,9 @@ Ping Ping gNB from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_gnb_nos1 - acamas + localhost -c20 -i0.2 0 @@ -88,33 +88,33 @@ Ping Ping NR-UE from gNB rfsim5g_gnb_nos1 - acamas + localhost rfsim5g_ue - acamas + localhost -c20 -i0.2 0 Iperf - Iperf (DL/30kbps/UDP)(30 sec) + Iperf (DL/30kbps/UDP)(20 sec) -u -b 0.03M -t 20 -R -c 10.0.1.1 rfsim5g_ue - acamas + localhost rfsim5g_gnb_nos1 - acamas + localhost 5 90 Iperf - Iperf (UL/30kbps/UDP)(30 sec) + Iperf (UL/30kbps/UDP)(20 sec) -u -b 0.03M -t 20 -c 10.0.1.1 rfsim5g_ue - acamas + localhost rfsim5g_gnb_nos1 - acamas + localhost 5 90 diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml index 6a47da0ff9..224a64c757 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml @@ -70,16 +70,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - acamas + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i0.2 0 @@ -88,9 +88,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue - acamas + localhost -c 20 -i0.2 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_multiue.xml b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml index 79d85e154c..8022741c6c 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_multiue.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_multiue.xml @@ -48,56 +48,52 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-ue Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_rfsimulator_multiue mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G gNB RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_multiue oai-gnb - 0 - 0 Deploy_Object Deploy OAI 5G NR-UE RF sim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_multiue oai-nr-ue - 0 - 0 Attach_UE Attach OAI UE (Wait for IP) rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 - acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas + localhost Ping Ping ext-dn from NR-UE rfsim5g_multiue1 - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -106,9 +102,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_multiue1 - acamas + localhost -c 20 -i 0.25 5 @@ -117,9 +113,9 @@ Ping Ping ext-dn from Second NR-UE rfsim5g_multiue2 - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -128,9 +124,9 @@ Ping Ping Second NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_multiue2 - acamas + localhost -c 20 -i 0.25 5 @@ -139,9 +135,9 @@ Ping Ping ext-dn from both UEs rfsim5g_multiue1 rfsim5g_multiue2 - acamas acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -150,33 +146,33 @@ Ping Ping ext-dn from all UEs rfsim5g_multiue1 rfsim5g_multiue2 rfsim5g_multiue3 rfsim5g_multiue4 rfsim5g_multiue5 rfsim5g_multiue6 rfsim5g_multiue7 rfsim5g_multiue8 rfsim5g_multiue9 rfsim5g_multiue10 - acamas acamas acamas acamas acamas acamas acamas acamas acamas acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 -s 1016 5 Iperf - Iperf (DL/3Mbps/UDP)(30 sec) + Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_multiue1 - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 Iperf - Iperf (UL/1Mbps/UDP)(30 sec) + Iperf (UL/1Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_multiue1 - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 @@ -185,7 +181,7 @@ Detach_UE Detach OAI UEs rfsim5g_multiue1 - acamas + localhost @@ -195,15 +191,14 @@ ci-scripts/yaml_files/5g_rfsimulator_multiue 1,0,0,0 1,0,0,0 - 0 - 0 + localhost Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-ue diff --git a/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml b/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml index feffaedf05..37cab0ddb5 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_n2_ho.xml @@ -55,58 +55,54 @@ Pull_Local_Registry Pull Images from Local Registry - 0 + localhost oai-gnb-asan oai-nr-cuup-asan oai-nr-ue-asan Create_Workspace Create new Workspace - 0 - 0 + localhost Deploy_Object Deploy OAI 5G CoreNetwork + localhost ci-scripts/yaml_files/5g_rfsimulator_n2_ho mysql oai-amf oai-smf oai-upf oai-ext-dn - 0 - 0 Deploy_Object Deploy OAI 5G CU-CP/CU-UP/DU 0 + UE RFsim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_n2_ho oai-cucp-0 oai-cuup-0 oai-du-0 oai-nr-ue - 0 - 0 Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - acamas + localhost Deploy_Object Deploy OAI 5G CU-CP/CU-UP/DU 1 RFsim SA + localhost ci-scripts/yaml_files/5g_rfsimulator_n2_ho oai-cucp-1 oai-cuup-1 oai-du-1 - 0 - 0 Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue - acamas + localhost -c 50 -i 0.25 5 @@ -115,33 +111,33 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 50 -i 0.25 10 Iperf - Iperf (DL/10Mbps/UDP)(30 sec) + Iperf (DL/10Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 Iperf - Iperf (UL/4Mbps/UDP)(30 sec) + Iperf (UL/4Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 @@ -155,7 +151,7 @@ Custom_Command Trigger N2 Handover - acamas + localhost echo ci trigger_n2_ho 1,1 | ncat 192.168.71.150 9090 yes @@ -163,14 +159,14 @@ Custom_Command UE (1) connected to DU-PCI 1? - acamas + localhost echo ci fetch_du_by_ue_id 1 | ncat 192.168.71.180 9090 | grep "1234" Custom_Command Trigger N2 Handover - acamas + localhost echo ci trigger_n2_ho 0,1 | ncat 192.168.71.180 9090 yes @@ -178,7 +174,7 @@ Custom_Command UE (1) connected to DU-PCI 0? - acamas + localhost echo ci fetch_du_by_ue_id 1 | ncat 192.168.71.150 9090 | grep "3584" @@ -186,9 +182,8 @@ Undeploy_Object true Undeploy all OAI 5G stack + localhost ci-scripts/yaml_files/5g_rfsimulator_n2_ho - 0 - 0 10,100,100,100 10,100,100,100 @@ -197,7 +192,7 @@ Clean_Test_Server_Images true Clean Test Images on Test Server - 0 + localhost oai-gnb-asan oai-nr-cuup-asan oai-nr-ue-asan diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml index 7107b7971b..66f725ca53 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_geo.xml @@ -74,16 +74,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - acamas + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -92,9 +92,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue - acamas + localhost -c 20 -i 0.25 5 @@ -102,7 +102,7 @@ Custom_Command Trigger Reestablishment - acamas + localhost echo ci force_reestab | ncat 192.168.71.140 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' yes @@ -111,9 +111,9 @@ Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i0.5 -w25 80 @@ -121,7 +121,7 @@ Custom_Command Verify Reestablishment - acamas + localhost echo ci get_reestab_count | ncat 192.168.71.140 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' yes diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml index 63897cfb8b..cde84b00e7 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml @@ -69,16 +69,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - acamas + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -87,9 +87,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue - acamas + localhost -c 20 -i 0.25 5 diff --git a/ci-scripts/xml_files/container_5g_rfsim_prs.xml b/ci-scripts/xml_files/container_5g_rfsim_prs.xml new file mode 100644 index 0000000000..bbc287ff76 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_prs.xml @@ -0,0 +1,100 @@ + + + rfsim-5gnr-prs + Monolithic gNB with PRS + wrench + + 111111 + 800813 + 000012 + 000013 + 040001 + 040023 + 100011 + 222222 + + + + + Pull_Local_Registry + Pull Images from Local Registry + localhost + oai-gnb-asan oai-nr-ue-asan + + + + Create_Workspace + Create new Workspace + localhost + + + + Deploy_Object + Deploy OAI 5G gNB+UE RF sim SA + localhost + ci-scripts/yaml_files/5g_rfsimulator_prs + oai-gnb oai-nr-ue + + + + Attach_UE + Attach OAI UE (Wait for IP) + rfsim5g_ue + localhost + + + + IdleSleep + Sleep + 2 + + + + Custom_Script + true + Set and verify distance at 50, 100, 150 m + localhost + + 50 100 150 + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + localhost + ci-scripts/yaml_files/5g_rfsimulator_prs + 30,100,100,100 + 30,100,100,100 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + localhost + oai-gnb-asan oai-nr-ue-asan + + + diff --git a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml index 58bff964d4..6ddd6d13b7 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml @@ -74,7 +74,7 @@ Custom_Command Check that UE synched - acamas + localhost docker logs rfsim5g-oai-nr-ue-2 | grep -m 1 "PSBCH RX:OK" diff --git a/ci-scripts/xml_files/container_5g_rfsim_simple.xml b/ci-scripts/xml_files/container_5g_rfsim_simple.xml index 738ce1a077..3dd5a560e0 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_simple.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_simple.xml @@ -63,14 +63,14 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - localhost + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - localhost + localhost rfsim5g_ext_dn localhost -c 20 -i 0.25 @@ -81,7 +81,7 @@ Detach_UE Detach OAI UE 1 rfsim5g_ue - localhost + localhost diff --git a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml index 97730bd233..6a09b8138d 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -49,7 +49,7 @@ Custom_Command Clean-Up any residual volume - acamas + localhost docker volume rm 5g_rfsimulator_tdd_dora_rrc.config -f @@ -83,9 +83,9 @@ Ping Ping gNB from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_gnb_nos1 - acamas + localhost -c20 -i0.2 0 @@ -94,9 +94,9 @@ Ping Ping NR-UE from gNB rfsim5g_gnb_nos1 - acamas + localhost rfsim5g_ue - acamas + localhost -c20 -i0.2 0 diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index c5c76124d3..3bb99de4ab 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -36,6 +36,11 @@ 020003 030001 030002 + 050001 + 050002 + 050003 + 020001 + 020002 100001 222222 @@ -72,16 +77,16 @@ Attach_UE Attach OAI UE (Wait for IP) rfsim5g_ue - acamas + localhost Ping Ping ext-dn from NR-UE rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 @@ -90,9 +95,9 @@ Ping Ping NR-UE from ext-dn rfsim5g_ext_dn - acamas + localhost rfsim5g_ue - acamas + localhost -c 20 -i 0.25 5 @@ -101,50 +106,70 @@ Attach_UE Verify 2nd PDU session is up rfsim5g_ue_pdu_2 - acamas + localhost Ping Ping ext-dn from NR-UE on PDU session ID 2 rfsim5g_ue_pdu_2 - acamas + localhost rfsim5g_ext_dn - acamas + localhost -c 20 -i 0.25 5 Iperf - Iperf (DL/3Mbps/UDP)(30 sec) + Iperf (DL/3Mbps/UDP)(20 sec) -u -b 3M -t 20 -R rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 Iperf - Iperf (UL/1Mbps/UDP)(30 sec) + Iperf (UL/1Mbps/UDP)(20 sec) -u -b 1M -t 20 rfsim5g_ue - acamas + localhost rfsim5g_ext_dn - acamas + localhost 5 90 + + Custom_Command + Trigger PDU Session Release via gNB telnet + acamas + echo ci pdu_session_release 2 | ncat 192.168.71.140 9090 + + + + Custom_Command + Add PDU Session via UE telnet + acamas + echo ci add_pdu_session 6,7 | ncat 192.168.71.150 8091 + + + + Custom_Command + Trigger PDU Session Release via gNB telnet + acamas + echo ci pdu_session_release 6 | ncat 192.168.71.140 9090 + + Undeploy_Object true Undeploy all OAI 5G stack localhost - oai-vnf oai-pnf ci-scripts/yaml_files/5g_rfsimulator_u0_25prb 1,0,0,0 1,0,0,0 diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml index 336211e558..c73c6dadca 100644 --- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml @@ -247,6 +247,7 @@ UndeployCoreNetwork Terminate EPC + true ltebox-nepes diff --git a/ci-scripts/xml_files/container_sa_aerial_quectel.xml b/ci-scripts/xml_files/container_sa_aerial_quectel.xml index 05d35d0171..bf3f702219 100644 --- a/ci-scripts/xml_files/container_sa_aerial_quectel.xml +++ b/ci-scripts/xml_files/container_sa_aerial_quectel.xml @@ -88,8 +88,8 @@ Iperf - iperf (DL/UDP/500M)(30 sec)(single-ue profile) - -u -b 500M -t 30 -R + iperf (DL/UDP/800M)(30 sec)(single-ue profile) + -u -b 800M -t 30 -R oc-cn5g-20897-aerial up2-aerial 25 @@ -98,8 +98,8 @@ Iperf - iperf (UL/UDP/40M)(30 sec)(single-ue profile) - -u -b 40M -t 30 -l 1428 + iperf (UL/UDP/150M)(30 sec)(single-ue profile) + -u -b 150M -t 30 -l 1428 oc-cn5g-20897-aerial up2-aerial 25 @@ -119,9 +119,9 @@ Iperf - Optional iperf (UL/UDP/90M)(30 sec)(single-ue profile) + Optional iperf (UL/UDP/200M)(30 sec)(single-ue profile) true - -u -b 90M -t 30 -l 1428 + -u -b 200M -t 30 -l 1428 oc-cn5g-20897-aerial up2-aerial 25 diff --git a/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml b/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml index ab38b72295..baf525f167 100644 --- a/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml +++ b/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml @@ -97,8 +97,8 @@ Iperf - iperf (UL/UDP/200M)(30 sec)(single-ue profile) - -u -b 200M -t 30 -l 1428 + iperf (UL/UDP/300M)(30 sec)(single-ue profile) + -u -b 300M -t 30 -l 1428 oc-cn5g-20897-aerial up2-aerial 10 @@ -107,9 +107,9 @@ Iperf - iperf (UL/UDP/220M)(30 sec)(single-ue profile) + iperf (UL/UDP/380M)(30 sec)(single-ue profile) true - -u -b 220M -t 30 -l 1428 + -u -b 380M -t 30 -l 1428 oc-cn5g-20897-aerial up2-aerial 10 diff --git a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml index 77b2312409..07a5c5f401 100644 --- a/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_ho_b210_quectel.xml @@ -93,7 +93,7 @@ Custom_Command Set attenuator to 0 for DU0 and 17 for DU1 rocket - python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 0 -r 3,4 17 -d 5 + python3 %%workspace%%/ci-scripts/attenuatorctl.py -s 1,2 0 -s 3,4 25 @@ -168,7 +168,7 @@ Custom_Command Attenuate DU1 by 17dB and remove attenuation on DU0 to trigger Handover rocket - python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 0 -r 3,4 17 -d 5 + python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 0 -r 3,4 25 -d 5 diff --git a/ci-scripts/xml_files/container_sa_n2_ho_b210_quectel.xml b/ci-scripts/xml_files/container_sa_n2_ho_b210_quectel.xml new file mode 100644 index 0000000000..46707f70b4 --- /dev/null +++ b/ci-scripts/xml_files/container_sa_n2_ho_b210_quectel.xml @@ -0,0 +1,230 @@ + + + TEST-MONO-N2-HO-B210 + Monolithic N2 Handover 20 MHz TDD SA + tasks + + 000001 + 000002 + 000023 + 000003 + 000004 + 000005 + 000006 + 000007 + 000008 + 000009 + 000010 + 000011 + 000012 + 000013 + 000014 + 000015 + 000017 + 000018 + 000019 + 000016 + 000020 + 000021 + 000022 + + + + + DeployCoreNetwork + Initialize 5G Core + oc-cn5g-00103-ho + + + + Pull_Local_Registry + Pull Images from Local Registry + oai-gnb + groot + + + + Pull_Local_Registry + Pull Images from Local Registry + oai-gnb + rocket + + + + Create_Workspace + Create new Workspace for groot + groot + + + + Create_Workspace + Create new Workspace on rocket + rocket + + + + Custom_Command + Set initial attenuation on target gNB + rocket + python3 %%workspace%%/ci-scripts/attenuatorctl.py -s 1,2 0 -s 3,4 25 + + + + Deploy_Object + Deploy Monolithic gNB-PCI0 (TDD/Band77/20MHz/B210) in a container + ci-scripts/yaml_files/5g_sa_n2_ho_b210 + groot + oai-gnb-pci0 + + + + Deploy_Object + Deploy Monolithic gNB-PCI1 (TDD/Band77/20MHz/B210) in a container + ci-scripts/yaml_files/5g_sa_n2_ho_b210 + rocket + oai-gnb-pci1 + + + + Attach_UE + Attach Quectel + raspix + + + + Ping + Ping: 100pings in 20sec + raspix + oc-cn5g-00103-ho + -c 100 -i 0.2 + 5 + + + + IdleSleep + Sleep + 5 + + + + Custom_Command + Gradually attenuate gNB-PCI0 (ch1-2=15dB) and gNB-PCI1 (ch3-4=0dB) over 5s to trigger N2 Handover to gNB-PCI1 + rocket + python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 15 -r 3,4 0 -d 5 + + + + Ping + Ping: 50pings in 10sec + raspix + oc-cn5g-00103-ho + -c 50 -i 0.2 + 5 + + + + Custom_Command + UE connected to gNB-PCI1? + rocket + echo ci fetch_du_by_ue_id 1 | ncat 127.0.0.1 9090 | grep "3585" + + + + Custom_Command + Gradually attenuate gNB-PCI0 (ch1-2=0dB) and gNB-PCI1 (ch3-4=15dB) over 5s to trigger N2 Handover back to gNB-PCI0 + rocket + python3 %%workspace%%/ci-scripts/attenuatorctl.py -r 1,2 0 -r 3,4 25 -d 5 + + + + Ping + Ping: 50pings in 10sec + raspix + oc-cn5g-00103-ho + -c 50 -i 0.2 + 5 + + + + Custom_Command + UE connected to gNB-PCI0? + groot + echo ci fetch_du_by_ue_id 1 | ncat 127.0.0.1 9090 | grep "3584" + + + + Custom_Command + true + Reset all attenuators to 0dB + rocket + python3 %%workspace%%/ci-scripts/attenuatorctl.py -s 1-4 0 + + + + Detach_UE + true + Detach Quectel + raspix + + + + Undeploy_Object + true + Undeploy Monolithic gNB-PCI0 + groot + ci-scripts/yaml_files/5g_sa_n2_ho_b210 + + + + Undeploy_Object + true + Undeploy Monolithic gNB-PCI1 + rocket + ci-scripts/yaml_files/5g_sa_n2_ho_b210 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + groot + oai-gnb + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + rocket + oai-gnb + + + + UndeployCoreNetwork + true + Terminate 5G Core + oc-cn5g-00103-ho + + + diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml index a4d72398e1..ad98afcd32 100644 --- a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml @@ -146,7 +146,6 @@ Undeploy gNB matix ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz - oai-gnb 10,100,100,100 10,100,100,100 diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml index ab7188c023..a809fafa2c 100644 --- a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml @@ -146,7 +146,6 @@ Undeploy gNB matix ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz - oai-gnb 15,100,100,100 20,100,100,100 diff --git a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml index d7cf992aa4..d4d0d51258 100644 --- a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml @@ -146,7 +146,6 @@ Undeploy VNF-PNF matix ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz - oai-vnf oai-pnf 10,100,100,100 10,100,100,100 diff --git a/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml b/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml index 0d810a1d4b..4ae1f78aa6 100644 --- a/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml @@ -178,7 +178,7 @@ services: retries: 5 oai_enb: - image: ${REGISTRY:-oaisoftwarealliance}/${ENB_IMG:-oai-enb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${ENB_IMG:-oai-enb}:${TAG:-develop} privileged: true container_name: l2sim4g-oai-enb network_mode: "host" @@ -210,7 +210,7 @@ services: retries: 5 oai_ue1: - image: ${REGISTRY:-oaisoftwarealliance}/${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} privileged: true container_name: l2sim4g-oai-lte-ue1 network_mode: "host" @@ -229,7 +229,7 @@ services: retries: 5 oai_ue2: - image: ${REGISTRY:-oaisoftwarealliance}/${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} privileged: true container_name: l2sim4g-oai-lte-ue2 network_mode: "host" diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml index 4b110abf74..5461f37a10 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml @@ -178,7 +178,7 @@ services: retries: 5 oai_enb0: - image: ${REGISTRY:-oaisoftwarealliance}/${ENB_IMG:-oai-enb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${ENB_IMG:-oai-enb}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-enb networks: @@ -197,7 +197,7 @@ services: retries: 5 oai_ue0: - image: ${REGISTRY:-oaisoftwarealliance}/${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-lte-ue0 networks: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml index 9de0f448c3..ab07314c91 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz_noS1/docker-compose.yml @@ -1,6 +1,6 @@ services: oai_enb0: - image: ${REGISTRY:-oaisoftwarealliance}/${ENB_IMG:-oai-enb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${ENB_IMG:-oai-enb}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-enb networks: @@ -19,7 +19,7 @@ services: retries: 5 oai_ue0: - image: ${REGISTRY:-oaisoftwarealliance}/${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-lte-ue0 networks: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml index 1cb0150465..856428f728 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml @@ -178,7 +178,7 @@ services: retries: 5 oai_enb0: - image: ${REGISTRY:-oaisoftwarealliance}/${ENB_IMG:-oai-enb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${ENB_IMG:-oai-enb}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-enb networks: @@ -197,7 +197,7 @@ services: retries: 5 oai_ue0: - image: ${REGISTRY:-oaisoftwarealliance}/${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-lte-ue0 networks: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml index a0e43a27d2..3458c4f11b 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml @@ -178,7 +178,7 @@ services: retries: 5 oai_enb0: - image: ${REGISTRY:-oaisoftwarealliance}/${ENB_IMG:-oai-enb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${ENB_IMG:-oai-enb}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-enb networks: @@ -197,7 +197,7 @@ services: retries: 5 oai_ue0: - image: ${REGISTRY:-oaisoftwarealliance}/${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-lte-ue0 networks: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml index 5c7f267074..cadb22236a 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_fembms/docker-compose.yml @@ -1,6 +1,6 @@ services: oai_enb0: - image: ${REGISTRY:-oaisoftwarealliance}/${ENB_IMG:-oai-enb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${ENB_IMG:-oai-enb}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-enb networks: @@ -19,7 +19,7 @@ services: retries: 5 oai_ue0: - image: ${REGISTRY:-oaisoftwarealliance}/${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-lte-ue0 networks: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml index af913ead24..027644d9a1 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_mbms/docker-compose.yml @@ -1,6 +1,6 @@ services: oai_enb0: - image: ${REGISTRY:-oaisoftwarealliance}/${ENB_IMG:-oai-enb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${ENB_IMG:-oai-enb}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-enb networks: @@ -19,7 +19,7 @@ services: retries: 5 oai_ue0: - image: ${REGISTRY:-oaisoftwarealliance}/${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-lte-ue0 networks: diff --git a/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml index 7ebbed861f..24acd9c676 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml @@ -178,7 +178,7 @@ services: retries: 5 oai_enb0: - image: ${REGISTRY:-oaisoftwarealliance}/${ENB_IMG:-oai-enb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${ENB_IMG:-oai-enb}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-enb networks: @@ -197,7 +197,7 @@ services: retries: 5 oai_ue0: - image: ${REGISTRY:-oaisoftwarealliance}/${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${LTEUE_IMG:-oai-lte-ue}:${TAG:-develop} privileged: true container_name: rfsim4g-oai-lte-ue0 networks: diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index 73d2505e92..49dcf0e450 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -92,7 +92,7 @@ services: retries: 5 oai-cu: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-cu cap_drop: - ALL @@ -121,7 +121,7 @@ services: retries: 5 oai-du-pci0: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-du-pci0 cap_drop: - ALL @@ -152,7 +152,7 @@ services: retries: 5 oai-du-pci1: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-du-pci1 cap_drop: - ALL @@ -187,7 +187,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml index 9eec82a98b..8bcb771967 100644 --- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml @@ -90,7 +90,7 @@ services: start_period: 10s start_interval: 500ms oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb cap_drop: - ALL @@ -113,7 +113,7 @@ services: retries: 5 ipc: host oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index 37353fb4b7..97dcce4d49 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -1,14 +1,13 @@ services: mysql: - container_name: "mysql" + container_name: "rfsim5g-mysql" image: mysql:8.0 init: true volumes: - - ./conf/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql - - ./conf/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh - - ./conf/sql.cnf:/etc/mysql/conf.d/custom.cnf + - ./oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ./mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh environment: - - TZ=Asia/Tokyo + - TZ=Europe/Paris - MYSQL_DATABASE=oai_db - MYSQL_USER=test - MYSQL_PASSWORD=test @@ -23,40 +22,38 @@ services: networks: public_net: ipv4_address: 192.168.71.131 - oai-amf: - container_name: "oai-amf" - image: oaisoftwarealliance/oai-amf:v2.1.9 + container_name: "rfsim5g-oai-amf" + image: oaisoftwarealliance/oai-amf:v2.1.10 environment: - - TZ=Asia/Tokyo + - TZ=Europe/paris volumes: - - ./conf/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml + - ./mini_nonrf_config.yaml:/openair-amf/etc/config.yaml depends_on: - mysql networks: public_net: ipv4_address: 192.168.71.132 - oai-smf: - container_name: "oai-smf" - image: oaisoftwarealliance/oai-smf:v2.1.9 + container_name: "rfsim5g-oai-smf" + image: oaisoftwarealliance/oai-smf:v2.1.10 environment: - - TZ=Asia/Tokyo + - TZ=Europe/Paris volumes: - - ./conf/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml + - ./mini_nonrf_config.yaml:/openair-smf/etc/config.yaml depends_on: - oai-amf networks: public_net: ipv4_address: 192.168.71.133 - oai-upf: - container_name: "oai-upf" - image: oaisoftwarealliance/oai-upf:v2.1.9 + container_name: "rfsim5g-oai-upf" + image: oaisoftwarealliance/oai-upf:v2.1.10 + init: true environment: - - TZ=Asia/Tokyo + - TZ=Europe/Paris volumes: - - ./conf/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml + - ./mini_nonrf_config.yaml:/openair-upf/etc/config.yaml depends_on: - oai-smf cap_add: @@ -72,10 +69,9 @@ services: traffic_net: ipv4_address: 192.168.72.134 interface_name: eth1 - oai-ext-dn: privileged: true - container_name: oai-ext-dn + container_name: rfsim5g-oai-ext-dn image: oaisoftwarealliance/trf-gen-cn5g:focal init: true entrypoint: /bin/bash -c \ @@ -93,22 +89,23 @@ services: interval: 10s timeout: 5s retries: 5 - oai-gnb: - image: nakaolab:oct29 - container_name: oai-gnb + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-gnb + cap_add: + - SYS_NICE cap_drop: - ALL + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 depends_on: - oai-ext-dn - command: ["-c", "/oai-ran/cmake_targets/ran_build/build/nr-softmodem -O /opt/oai-gnb/etc/gnb.yaml --rfsim --log_config.global_log_options level,nocolor,time"] networks: public_net: ipv4_address: 192.168.71.140 volumes: - # - ../../conf_files/gnb.sa.band78.273prb.rfsim.2x2.conf:/opt/oai-gnb/etc/gnb.conf - ../../conf_files/gnb.sa.band78.106prb.rfsim.yaml:/opt/oai-gnb/etc/gnb.yaml - # - ../../conf_files/gnb.sa.band78.106prb.rfsim.2x2.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" start_period: 10s @@ -116,59 +113,22 @@ services: interval: 10s timeout: 5s retries: 5 - - oai-flexric: - image: nakaolab:oct29 - container_name: oai-flexric - command: ["-c", "stdbuf -o0 /oai-ran/openair2/E2AP/flexric/build/examples/ric/nearRT-RIC"] - networks: - public_net: - ipv4_address: 192.168.71.21 - volumes: - - ./conf/flexric.conf:/oai-ran/openair2/E2AP/flexric/flexric.conf - - ./conf/flexric.conf:/usr/local/etc/flexric/flexric.conf - healthcheck: - test: /bin/bash -c "pgrep nearRT-RIC" - interval: 10s - timeout: 5s - - xapp-chatgpt: - image: nakaolab:oct29 - command: ["-c", "XAPP_DURATION=3600 /oai-ran/openair2/E2AP/flexric/build/examples/xApp/c/monitor/xapp_chatgpt"] - # command: ["-lc","ulimit -c unlimited; export XAPP_DURATION=3600; gdb -q -batch \ - # -ex 'set pagination off' \ - # -ex run \ - # -ex 'bt full' \ - # -ex 'thread apply all bt full' \ - # --args /oai-ran/openair2/E2AP/flexric/build/examples/xApp/c/monitor/xapp_chatgpt"] - container_name: xapp-chatgpt - environment: - - TZ=Asia/Tokyo - depends_on: - - oai-flexric - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.71.26 - healthcheck: - test: /bin/bash -c "pgrep -f xapp_chatgpt" - interval: 10s - timeout: 5s - - oai-nr-ue1: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3319680000 --ssb 516 --uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue1 + oai-nr-ue: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue cap_drop: - ALL cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: public_net: - ipv4_address: 192.168.71.151 + ipv4_address: 192.168.71.150 devices: - /dev/net/tun:/dev/net/tun volumes: @@ -180,16 +140,44 @@ services: interval: 10s timeout: 5s retries: 5 - oai-nr-ue2: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3319680000 --ssb 516 --uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue2 + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue2 cap_drop: - ALL cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001101 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.151 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + start_period: 10s + start_interval: 500ms + interval: 10s + timeout: 5s + retries: 5 + oai-nr-ue3: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue3 + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001102 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -206,16 +194,17 @@ services: interval: 10s timeout: 5s retries: 5 - - oai-nr-ue3: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001102 -C 3319680000 --ssb 516 --uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue3 + oai-nr-ue4: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue4 cap_drop: - ALL cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001103 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -232,16 +221,17 @@ services: interval: 10s timeout: 5s retries: 5 - - oai-nr-ue4: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001103 -C 3319680000 --ssb 516 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue4 + oai-nr-ue5: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue5 cap_drop: - ALL cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001104 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -258,16 +248,17 @@ services: interval: 10s timeout: 5s retries: 5 - - oai-nr-ue5: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001104 -C 3319680000 --ssb 516 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue5 + oai-nr-ue6: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue6 cap_drop: - ALL cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001105 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -284,16 +275,17 @@ services: interval: 10s timeout: 5s retries: 5 - - oai-nr-ue6: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001105 -C 3319680000 --ssb 516 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue6 + oai-nr-ue7: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue7 cap_drop: - ALL cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001106 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -310,16 +302,17 @@ services: interval: 10s timeout: 5s retries: 5 - - oai-nr-ue7: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001100 -C 3319680000 --ssb 516 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue7 + oai-nr-ue8: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue8 cap_drop: - ALL cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001107 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -336,16 +329,17 @@ services: interval: 10s timeout: 5s retries: 5 - - oai-nr-ue8: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001107 -C 3319680000 --ssb 516 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue8 + oai-nr-ue9: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue9 cap_drop: - ALL cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001108 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -362,16 +356,17 @@ services: interval: 10s timeout: 5s retries: 5 - - oai-nr-ue9: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001108 -C 3319680000 --ssb 516 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue9 + oai-nr-ue10: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue10 cap_drop: - ALL cap_add: - NET_ADMIN # for interface bringup - NET_RAW # for ping + - SYS_NICE + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001109 -C 3319680000 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time depends_on: - oai-gnb networks: @@ -389,71 +384,13 @@ services: timeout: 5s retries: 5 - oai-nr-ue10: - image: nakaolab:oct29 - command: ["-c", "stdbuf -oL /oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem --rfsim -r 106 --numerology 1 --uicc0.imsi 208990100001109 -C 3319680000 --ssb 516 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time"] - container_name: oai-nr-ue10 - cap_drop: - - ALL - cap_add: - - NET_ADMIN # for interface bringup - - NET_RAW # for ping - depends_on: - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.71.160 - devices: - - /dev/net/tun:/dev/net/tun - volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - healthcheck: - test: /bin/bash -c "pgrep nr-uesoftmodem" - interval: 10s - timeout: 5s - retries: 5 - - # iperf3: - # image: networkstatic/iperf3:latest - # container_name: iperf3 - # command: ["-c 'for p in $(seq 5201 5210); do iperf3 -s -p $$p & done;'"] - # ports: - # - "5201-5210:5201-5210/tcp" - # - "5201-5210:5201-5210/udp" - # networks: - # public_net: - # ipv4_address: 192.168.71.130 - # restart: unless-stopped - - iperf_udp: - image: mlabbe/iperf - container_name: iperf_udp - command: ["-u -s -p 5201"] - ports: - - "5201:5201/udp" - networks: - public_net: - ipv4_address: 192.168.71.129 - restart: unless-stopped - - iperf_tcp: - image: mlabbe/iperf - container_name: iperf_tcp - command: ["-s -p 5202"] - ports: - - "5202:5202/tcp" - networks: - public_net: - ipv4_address: 192.168.71.130 - restart: unless-stopped - networks: public_net: driver: bridge name: rfsim5g-oai-public-net ipam: config: - - subnet: 192.168.71.0/24 + - subnet: 192.168.71.128/26 driver_opts: com.docker.network.bridge.name: "rfsim5g-public" traffic_net: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index 9cab11ea9e..b5b9684626 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -90,7 +90,7 @@ services: timeout: 5s retries: 5 oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb cap_drop: - ALL @@ -112,7 +112,7 @@ services: timeout: 5s retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index 778754fd58..f3482280bd 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -90,7 +90,7 @@ services: timeout: 5s retries: 5 oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb cap_drop: - ALL @@ -115,7 +115,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index 9ccce2a8e1..200a1b6e3a 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -71,7 +71,7 @@ services: interface_name: eth1 oai-cucp: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-cucp cap_drop: - ALL @@ -100,7 +100,7 @@ services: retries: 5 oai-cuup: - image: ${REGISTRY:-oaisoftwarealliance}/${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} container_name: rfsim5g-oai-cuup cap_drop: - ALL @@ -131,7 +131,7 @@ services: retries: 5 oai-cuup2: - image: ${REGISTRY:-oaisoftwarealliance}/${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} container_name: rfsim5g-oai-cuup2 cap_drop: - ALL @@ -165,7 +165,7 @@ services: retries: 5 oai-cuup3: - image: ${REGISTRY:-oaisoftwarealliance}/${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} container_name: rfsim5g-oai-cuup3 cap_drop: - ALL @@ -199,7 +199,7 @@ services: retries: 5 oai-du: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-du cap_drop: - ALL @@ -230,7 +230,7 @@ services: retries: 5 oai-du2: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-du2 cap_drop: - ALL @@ -264,7 +264,7 @@ services: retries: 5 oai-du3: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-du3 cap_drop: - ALL @@ -298,7 +298,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL @@ -328,7 +328,7 @@ services: retries: 5 oai-nr-ue2: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue2 cap_drop: - ALL @@ -358,7 +358,7 @@ services: retries: 5 oai-nr-ue3: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue3 cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml index 1dec021ffc..533c5d576c 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fdd_phytest/docker-compose.yaml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb cap_drop: - ALL @@ -25,7 +25,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml b/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml index 2e4766e747..5bb8d0246d 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml @@ -1,7 +1,7 @@ services: - oai-flexric: - image: ${REGISTRY:-oaisoftwarealliance}/oai-flexric:${FLEXRIC_TAG:-develop} - container_name: oai-flexric + nearRT-RIC: + image: ${REGISTRY-oaisoftwarealliance/}oai-flexric:${FLEXRIC_TAG:-develop} + container_name: nearRT-RIC networks: public_net: ipv4_address: 192.168.70.150 @@ -13,11 +13,11 @@ services: timeout: 5s xapp-rc-moni: - image: ${REGISTRY:-oaisoftwarealliance}/oai-flexric:${FLEXRIC_TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-flexric:${FLEXRIC_TAG:-develop} command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_rc_moni" container_name: xapp-rc-moni depends_on: - - oai-flexric + - nearRT-RIC - oai-gnb networks: public_net: @@ -30,11 +30,11 @@ services: timeout: 5s xapp-kpm-moni: - image: ${REGISTRY:-oaisoftwarealliance}/oai-flexric:${FLEXRIC_TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-flexric:${FLEXRIC_TAG:-develop} command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_kpm_moni" container_name: xapp-kpm-moni depends_on: - - oai-flexric + - nearRT-RIC - oai-gnb networks: public_net: @@ -47,11 +47,11 @@ services: timeout: 5s xapp-kpm-rc: - image: ${REGISTRY:-oaisoftwarealliance}/oai-flexric:${FLEXRIC_TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-flexric:${FLEXRIC_TAG:-develop} command: "stdbuf -o0 /usr/local/flexric/xApp/c/kpm_rc/xapp_kpm_rc" container_name: xapp-kpm-rc depends_on: - - oai-flexric + - nearRT-RIC - oai-gnb networks: public_net: @@ -64,11 +64,11 @@ services: timeout: 5s xapp-gtp-mac-rlc-pdcp-moni: - image: ${REGISTRY:-oaisoftwarealliance}/oai-flexric:${FLEXRIC_TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-flexric:${FLEXRIC_TAG:-develop} command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni" container_name: xapp-gtp-mac-rlc-pdcp-moni depends_on: - - oai-flexric + - nearRT-RIC - oai-gnb networks: public_net: @@ -80,8 +80,28 @@ services: interval: 10s timeout: 5s - oai-nr-ue1: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + oai-gnb: + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} + privileged: true + container_name: rfsim5g-oai-gnb + environment: + USE_ADDITIONAL_OPTIONS: -E --rfsim --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0 + depends_on: + - nearRT-RIC + networks: + public_net: + ipv4_address: 192.168.70.151 + volumes: + - ../../conf_files/gnb.sa.band78.106prb.rfsim.flexric.conf:/opt/oai-gnb/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-nr-ue: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} privileged: true container_name: rfsim5g-oai-nr-ue environment: @@ -100,7 +120,7 @@ services: retries: 5 oai-nr-ue2: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} privileged: true container_name: rfsim5g-oai-nr-ue2 environment: @@ -118,154 +138,7 @@ services: timeout: 5s retries: 5 - oai-nr-ue3: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} - privileged: true - container_name: rfsim5g-oai-nr-ue3 - environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 001010000000004 --rfsimulator.serveraddr 192.168.70.151 --log_config.global_log_options level,nocolor,time - depends_on: - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.70.154 - volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - healthcheck: - test: /bin/bash -c "pgrep nr-uesoftmodem" - interval: 10s - timeout: 5s - retries: 5 - - oai-nr-ue4: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} - privileged: true - container_name: rfsim5g-oai-nr-ue4 - environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 001010000000004 --rfsimulator.serveraddr 192.168.70.151 --log_config.global_log_options level,nocolor,time - depends_on: - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.70.155 - volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - healthcheck: - test: /bin/bash -c "pgrep nr-uesoftmodem" - interval: 10s - timeout: 5s - retries: 5 - - oai-nr-ue5: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} - privileged: true - container_name: rfsim5g-oai-nr-ue5 - environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 001010000000004 --rfsimulator.serveraddr 192.168.70.151 --log_config.global_log_options level,nocolor,time - depends_on: - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.70.156 - volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - healthcheck: - test: /bin/bash -c "pgrep nr-uesoftmodem" - interval: 10s - timeout: 5s - retries: 5 - - oai-nr-ue6: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} - privileged: true - container_name: rfsim5g-oai-nr-ue6 - environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 001010000000004 --rfsimulator.serveraddr 192.168.70.151 --log_config.global_log_options level,nocolor,time - depends_on: - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.70.157 - volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - healthcheck: - test: /bin/bash -c "pgrep nr-uesoftmodem" - interval: 10s - timeout: 5s - retries: 5 - - oai-nr-ue7: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} - privileged: true - container_name: rfsim5g-oai-nr-ue7 - environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 001010000000004 --rfsimulator.serveraddr 192.168.70.151 --log_config.global_log_options level,nocolor,time - depends_on: - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.70.158 - volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - healthcheck: - test: /bin/bash -c "pgrep nr-uesoftmodem" - interval: 10s - timeout: 5s - retries: 5 - - oai-nr-ue8: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} - privileged: true - container_name: rfsim5g-oai-nr-ue8 - environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 001010000000004 --rfsimulator.serveraddr 192.168.70.151 --log_config.global_log_options level,nocolor,time - depends_on: - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.70.159 - volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - healthcheck: - test: /bin/bash -c "pgrep nr-uesoftmodem" - interval: 10s - timeout: 5s - retries: 5 - - oai-nr-ue9: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} - privileged: true - container_name: rfsim5g-oai-nr-ue9 - environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 001010000000004 --rfsimulator.serveraddr 192.168.70.151 --log_config.global_log_options level,nocolor,time - depends_on: - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.70.160 - volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - healthcheck: - test: /bin/bash -c "pgrep nr-uesoftmodem" - interval: 10s - timeout: 5s - retries: 5 - - oai-nr-ue10: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} - privileged: true - container_name: rfsim5g-oai-nr-ue10 - environment: - USE_ADDITIONAL_OPTIONS: -E --rfsim -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 001010000000004 --rfsimulator.serveraddr 192.168.70.151 --log_config.global_log_options level,nocolor,time - depends_on: - - oai-gnb - networks: - public_net: - ipv4_address: 192.168.70.161 - volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf - healthcheck: - test: /bin/bash -c "pgrep nr-uesoftmodem" - interval: 10s - timeout: 5s - retries: 5 +networks: + public_net: + name: oai-cn5g-public-net + external: true diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml index 13d91d9090..7ae33004f5 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml @@ -91,7 +91,7 @@ services: retries: 5 oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb cap_drop: - ALL @@ -112,7 +112,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml index 9d660e0c3b..b44178a3f5 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml @@ -83,7 +83,7 @@ services: timeout: 5s retries: 5 oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb cap_drop: - ALL @@ -103,7 +103,7 @@ services: timeout: 5s retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml index 6c03a02443..ad171109c7 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml @@ -84,7 +84,7 @@ services: retries: 5 oai-cucp-0: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-cucp-0 cap_drop: - ALL @@ -111,7 +111,7 @@ services: retries: 5 oai-cuup-0: - image: ${REGISTRY:-oaisoftwarealliance}/${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} container_name: rfsim5g-oai-cuup-0 cap_drop: - ALL @@ -139,7 +139,7 @@ services: oai-du-0: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-du-0 cap_drop: - ALL @@ -150,7 +150,6 @@ services: --telnetsrv --telnetsrv.listenaddr 192.168.71.171 --telnetsrv.shrmod ci --rfsimulator.serveraddr 192.168.71.190 - --gNBs.[0].servingCellConfigCommon.[0].ra_ResponseWindow 5 ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-cucp-0 @@ -169,7 +168,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL @@ -195,7 +194,7 @@ services: retries: 5 oai-cucp-1: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-cucp-1 cap_drop: - ALL @@ -227,7 +226,7 @@ services: retries: 5 oai-cuup-1: - image: ${REGISTRY:-oaisoftwarealliance}/${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} container_name: rfsim5g-oai-cuup-1 cap_drop: - ALL @@ -254,7 +253,7 @@ services: retries: 5 oai-du-1: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-du-1 cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml index c83060b713..731b833f08 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml @@ -90,7 +90,7 @@ services: timeout: 5s retries: 5 oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb cap_drop: - ALL @@ -115,7 +115,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml index 5469b0b247..4e209e09d1 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml @@ -87,7 +87,7 @@ services: timeout: 5s retries: 5 oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb cap_drop: - ALL @@ -110,7 +110,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_prs/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_prs/docker-compose.yaml new file mode 100644 index 0000000000..c6b6c338de --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_prs/docker-compose.yaml @@ -0,0 +1,71 @@ +services: + oai-gnb: + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-gnb + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: --phy-test --rfsim -E + --log_config.global_log_options level,nocolor,time + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 + networks: + public_net: + ipv4_address: 192.168.71.140 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/gnb.sa.band78.106prb.rfsim.prs.conf:/opt/oai-gnb/etc/gnb.conf + - rrc.config:/opt/oai-gnb/ + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-nr-ue: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue + cap_drop: + - ALL + cap_add: + - NET_ADMIN # for interface bringup + - NET_RAW # for ping + environment: + USE_ADDITIONAL_OPTIONS: --phy-test --rfsim -E + --reconfig-file etc/rrc/reconfig.raw --rbconfig-file etc/rrc/rbconfig.raw + --rfsimulator.serveraddr 192.168.71.140 + --log_config.global_log_options level,nocolor,time + --telnetsrv --telnetsrv.listenaddr 192.168.71.150 --telnetsrv.listenport 8091 + --telnetsrv.shrmod ciUE + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.band78.106prb.prs.conf:/opt/oai-nr-ue/etc/nr-ue.conf + - rrc.config:/opt/oai-nr-ue/etc/rrc/ + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.150 + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +volumes: + rrc.config: + +networks: + public_net: + driver: bridge + name: rfsim5g-oai-public-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-public" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml index c04e634ca2..5d8de35ac8 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_sidelink/docker-compose.yaml @@ -1,6 +1,6 @@ services: oai-nr-ue-1: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue-1 cap_drop: - ALL @@ -25,7 +25,7 @@ services: retries: 5 oai-nr-ue-2: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue-2 cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml index 89f6562697..60484914a6 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_tdd_dora/docker-compose.yaml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-gnb cap_drop: - ALL @@ -25,7 +25,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index ed1701ef86..c4a4e2ebea 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -91,14 +91,15 @@ services: retries: 5 oai-vnf: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-vnf cap_drop: - ALL environment: USE_ADDITIONAL_OPTIONS: --nfapi VNF --log_config.global_log_options level,nocolor,time + --telnetsrv --telnetsrv.listenaddr 192.168.71.140 --telnetsrv.shrmod ci NFAPI_TRACE_LEVEL: info - ASAN_OPTIONS: detect_leaks=0 + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-ext-dn networks: @@ -115,14 +116,14 @@ services: retries: 5 oai-pnf: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: rfsim5g-oai-pnf cap_drop: - ALL environment: USE_ADDITIONAL_OPTIONS: --nfapi PNF --rfsim --log_config.global_log_options level,nocolor,time NFAPI_TRACE_LEVEL: info - ASAN_OPTIONS: detect_leaks=0 + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-vnf networks: @@ -139,7 +140,7 @@ services: retries: 5 oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} container_name: rfsim5g-oai-nr-ue cap_drop: - ALL @@ -147,7 +148,10 @@ services: - NET_ADMIN # for interface bringup - NET_RAW # for ping environment: - USE_ADDITIONAL_OPTIONS: --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152680000 --CO -400000000 --ssb 48 --rfsimulator.serveraddr 192.168.71.141 --extra-pdu-id 2 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152680000 --CO -400000000 --ssb 48 + --rfsimulator.serveraddr 192.168.71.141 --extra-pdu-id 2 --log_config.global_log_options level,nocolor,time + --telnetsrv --telnetsrv.shrmod ciUE --telnetsrv.listenaddr 192.168.71.150 --telnetsrv.listenport 8091 + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-pnf networks: diff --git a/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml index c1c3db1607..937f7d5d65 100644 --- a/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_f1_b210_ho/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-cu: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: oai-cu cap_drop: - ALL @@ -26,7 +26,7 @@ services: retries: 5 oai-du0: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: oai-du0 cap_drop: - ALL @@ -58,7 +58,7 @@ services: retries: 5 oai-du1: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: oai-du1 cap_drop: - ALL diff --git a/ci-scripts/yaml_files/5g_sa_n2_ho_b210/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n2_ho_b210/docker-compose.yml new file mode 100644 index 0000000000..e02afae7cc --- /dev/null +++ b/ci-scripts/yaml_files/5g_sa_n2_ho_b210/docker-compose.yml @@ -0,0 +1,61 @@ +services: + oai-gnb-pci0: + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: oai-gnb-pci0 + cap_drop: + - ALL + cap_add: + - SYS_NICE + - IPC_LOCK + ulimits: + core: -1 # for core dumps + environment: + USE_B2XX: 'yes' + USE_ADDITIONAL_OPTIONS: --RUs.[0].sdr_addrs serial=30AD30F + --telnetsrv --telnetsrv.shrmod ci + --log_config.global_log_options level,nocolor,utc_time,line_num,function + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 + devices: + - /dev/bus/usb/:/dev/bus/usb/ + volumes: + - ../../conf_files/neighbour-config-ho.conf:/opt/oai-gnb/etc/neighbour-config-ho.conf + - ../../conf_files/gnb.sa.band77.51prb.usrpb200.n2-ho.conf:/opt/oai-gnb/etc/gnb.conf + network_mode: "host" + healthcheck: + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-gnb-pci1: + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: oai-gnb-pci1 + cap_drop: + - ALL + cap_add: + - SYS_NICE + - IPC_LOCK + ulimits: + core: -1 # for core dumps + environment: + USE_B2XX: 'yes' + USE_ADDITIONAL_OPTIONS: --RUs.[0].sdr_addrs serial=31F8010 + --gNBs.[0].nr_cellid 11111111 + --gNBs.[0].gNB_ID 0xe01 + --gNBs.[0].servingCellConfigCommon.[0].physCellId 1 + --gNBs.[0].servingCellConfigCommon.[0].ssb_PositionsInBurst_Bitmap 2 + --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NG_AMF 172.21.19.99 + --gNBs.[0].NETWORK_INTERFACES.GNB_IPV4_ADDRESS_FOR_NGU 172.21.19.99 + --telnetsrv --telnetsrv.shrmod ci + --log_config.global_log_options level,nocolor,utc_time,line_num,function + devices: + - /dev/bus/usb/:/dev/bus/usb/ + volumes: + - ../../conf_files/neighbour-config-ho.conf:/opt/oai-gnb/etc/neighbour-config-ho.conf + - ../../conf_files/gnb.sa.band77.51prb.usrpb200.n2-ho.conf:/opt/oai-gnb/etc/gnb.conf + network_mode: "host" + healthcheck: + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 diff --git a/ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz/docker-compose.yml index 11ecb20f08..879f86ce90 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} network_mode: "host" container_name: oai-gnb cap_drop: diff --git a/ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz/docker-compose.yml index 332fb23503..b5eb5dd441 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} network_mode: "host" container_name: oai-gnb cap_drop: diff --git a/ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz/docker-compose.yml index d3d2ddf582..487672ae1f 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-vnf: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} network_mode: "host" container_name: oai-vnf cap_drop: @@ -20,7 +20,7 @@ services: timeout: 5s retries: 5 oai-pnf: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} network_mode: "host" container_name: oai-pnf cap_drop: diff --git a/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml index 562b72561a..e1cd519d22 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} network_mode: "host" container_name: oai-gnb cap_drop: diff --git a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml index aac787a916..5db92f6ee2 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-nr-ue: - image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} network_mode: host container_name: oai-nr-ue cap_drop: @@ -17,7 +17,7 @@ services: #entrypoint: /bin/bash -c "sleep infinity" environment: TZ: Europe/Paris - USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.10.2 -r 106 --numerology 1 --band 78 -C 3425010000 --ssb 509 --ue-fo-compensation --ue-rxgain 65 --tune-offset 20000000 -A 90 --log_config.global_log_options level,nocolor,time --uicc0.imsi 001020000000111 --uicc0.nssai_sd 16777215 + USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.10.2 -r 106 --numerology 1 --band 78 -C 3425010000 --ssb 509 --ue-fo-compensation --ue-rxgain 65 --tune-offset 20000000 -A 90 --log_config.global_log_options level,nocolor,time --uicc0.imsi 001020000000111 volumes: - ../../conf_files/ue.sa.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: diff --git a/ci-scripts/yaml_files/fr1_enb_mono_fdd_tim/docker-compose.yml b/ci-scripts/yaml_files/fr1_enb_mono_fdd_tim/docker-compose.yml index 4c40d738a4..7963f823b1 100644 --- a/ci-scripts/yaml_files/fr1_enb_mono_fdd_tim/docker-compose.yml +++ b/ci-scripts/yaml_files/fr1_enb_mono_fdd_tim/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: prod-enb-mono-fdd environment: diff --git a/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_if4.5/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_if4.5/docker-compose.yml index d15a9df172..290edf23b1 100644 --- a/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_if4.5/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_if4.5/docker-compose.yml @@ -1,6 +1,6 @@ services: rru_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-rru-fdd-05Mhz-tm1 network_mode: "host" @@ -17,7 +17,7 @@ services: timeout: 5s retries: 5 rcc_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-rcc-fdd-05Mhz-tm1 network_mode: "host" diff --git a/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1/docker-compose.yml index 2a6e7bb51a..d3f6897534 100644 --- a/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-fdd-05Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1_no_rrc_activity/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1_no_rrc_activity/docker-compose.yml index 7cdc585d34..6bf2f4606f 100644 --- a/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1_no_rrc_activity/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_fdd_05Mhz_tm1_no_rrc_activity/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-fdd-05Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma/docker-compose.yml index c6d64cc028..a213d1900b 100644 --- a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma/docker-compose.yml @@ -1,6 +1,6 @@ services: lte_ue0: - image: ${REGISTRY:-oaisoftwarealliance}/oai-lte-ue:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-lte-ue:${TAG:-develop} privileged: true container_name: lte-b200-ue-fdd-10Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1/docker-compose.yml index 14d1045de8..3cbf927f8e 100644 --- a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-fdd-10Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_cdrx/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_cdrx/docker-compose.yml index d1fcd91850..38c14472b6 100644 --- a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_cdrx/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_cdrx/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-fdd-10Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma/docker-compose.yml index 6b1b583863..c1c9c4b531 100644 --- a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-fdd-10Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_fdd_20Mhz_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_20Mhz_tm1/docker-compose.yml index a36afb957e..e027c521d7 100644 --- a/ci-scripts/yaml_files/lte_b200_fdd_20Mhz_tm1/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_fdd_20Mhz_tm1/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-fdd-20Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_if4.5/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_if4.5/docker-compose.yml index 0311390ab7..56c730083a 100644 --- a/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_if4.5/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_if4.5/docker-compose.yml @@ -1,6 +1,6 @@ services: rru_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-rru-tdd-05Mhz-tm1 network_mode: "host" @@ -17,7 +17,7 @@ services: timeout: 5s retries: 5 rcc_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-rcc-tdd-05Mhz-tm1 network_mode: "host" diff --git a/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm1/docker-compose.yml index 68f48d7087..9ce6bf3609 100644 --- a/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm1/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm1/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-tdd-05Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm2/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm2/docker-compose.yml index b11b268129..d462baac14 100644 --- a/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm2/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_tdd_05Mhz_tm2/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-tdd-05Mhz-tm2 environment: diff --git a/ci-scripts/yaml_files/lte_b200_tdd_10Mhz_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_tdd_10Mhz_tm1/docker-compose.yml index 7934784cdc..025c5ad26b 100644 --- a/ci-scripts/yaml_files/lte_b200_tdd_10Mhz_tm1/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_tdd_10Mhz_tm1/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-tdd-10Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1/docker-compose.yml index 0bca3bc43a..748525aa82 100644 --- a/ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-tdd-20Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1_default_scheduler/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1_default_scheduler/docker-compose.yml index 953cce7ffc..dfdd4ed877 100644 --- a/ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1_default_scheduler/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_b200_tdd_20Mhz_tm1_default_scheduler/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: lte-b200-enb-tdd-20Mhz-tm1 environment: diff --git a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml index 5ac5b93d14..0aefaf5ef0 100644 --- a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-enb: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: oai-enb environment: diff --git a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml index 929c9633c7..db6215a148 100644 --- a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml +++ b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-enb: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: oai-enb environment: diff --git a/ci-scripts/yaml_files/nsa_b200_enb/docker-compose.yml b/ci-scripts/yaml_files/nsa_b200_enb/docker-compose.yml index 76790c44f9..6dfe229265 100644 --- a/ci-scripts/yaml_files/nsa_b200_enb/docker-compose.yml +++ b/ci-scripts/yaml_files/nsa_b200_enb/docker-compose.yml @@ -1,6 +1,6 @@ services: enb_mono_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/oai-enb:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-enb:${TAG:-develop} privileged: true container_name: nsa-b200-enb ulimits: diff --git a/ci-scripts/yaml_files/nsa_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/nsa_b200_gnb/docker-compose.yml index bb6576054e..f104735fa0 100644 --- a/ci-scripts/yaml_files/nsa_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/nsa_b200_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: gnb_mono_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: nsa-b200-gnb cap_drop: - ALL diff --git a/ci-scripts/yaml_files/sa_aw2s_2x2_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_aw2s_2x2_gnb/docker-compose.yml index a1baef974a..fadeea96ef 100644 --- a/ci-scripts/yaml_files/sa_aw2s_2x2_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_aw2s_2x2_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-aw2s:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-aw2s:${TAG:-develop} network_mode: "host" container_name: oai-gnb-aw2s cap_drop: diff --git a/ci-scripts/yaml_files/sa_aw2s_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_aw2s_gnb/docker-compose.yml index 9530b3cd5c..54bf6cec00 100644 --- a/ci-scripts/yaml_files/sa_aw2s_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_aw2s_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-aw2s:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-aw2s:${TAG:-develop} network_mode: "host" container_name: oai-gnb-aw2s cap_drop: diff --git a/ci-scripts/yaml_files/sa_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_b200_gnb/docker-compose.yml index 7fe7db5317..d57ec4b5bd 100644 --- a/ci-scripts/yaml_files/sa_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_b200_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: gnb_mono_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: sa-b200-gnb cap_drop: - ALL diff --git a/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml index c20a43c0e1..bbcd04238c 100644 --- a/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: gnb_cucp: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: sa-cucp-gnb cap_drop: - ALL @@ -25,7 +25,7 @@ services: retries: 5 gnb_cuup: - image: ${REGISTRY:-oaisoftwarealliance}/${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${NRCUUP_IMG:-oai-nr-cuup}:${TAG:-develop} container_name: sa-cuup-gnb cap_drop: - ALL @@ -51,7 +51,7 @@ services: retries: 5 gnb_du_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: sa-du-b200-gnb cap_drop: - ALL diff --git a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml index 2c1ab75e92..740b0eff1a 100644 --- a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: gnb_cu: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: sa-cu-gnb cap_drop: - ALL @@ -25,7 +25,7 @@ services: retries: 5 gnb_du_fdd: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: sa-du-b200-gnb cap_drop: - ALL diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml index b70229ac94..8c38739994 100644 --- a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-fhi72:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop} cap_add: - SYS_ADMIN - IPC_LOCK diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml index f08859a516..3e29c33ff9 100644 --- a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-fhi72:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop} cap_add: - IPC_LOCK - SYS_NICE diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml index ff06893fa0..2e6c044fcb 100644 --- a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: oai-gnb: - image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-fhi72:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop} cap_add: - IPC_LOCK - SYS_NICE diff --git a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml index c9f3d90131..f04beeb6c2 100644 --- a/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml +++ b/ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml @@ -34,7 +34,7 @@ services: retries: 5 oai-gnb-aerial: cpuset: "13-14" - image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-aerial:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb-aerial}:${TAG:-develop} depends_on: nv-cubb: condition: service_healthy diff --git a/ci-scripts/yaml_files/sa_gnb_aerial_ul/docker-compose.yaml b/ci-scripts/yaml_files/sa_gnb_aerial_ul/docker-compose.yaml index 077c58c67c..c0b3e6f81d 100644 --- a/ci-scripts/yaml_files/sa_gnb_aerial_ul/docker-compose.yaml +++ b/ci-scripts/yaml_files/sa_gnb_aerial_ul/docker-compose.yaml @@ -34,7 +34,7 @@ services: retries: 5 oai-gnb-aerial: cpuset: "13-16" - image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-aerial:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb-aerial}:${TAG:-develop} depends_on: nv-cubb: condition: service_healthy diff --git a/ci-scripts/yaml_files/sa_sc_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_sc_b200_gnb/docker-compose.yml index f0b86f4c33..51571332bd 100644 --- a/ci-scripts/yaml_files/sa_sc_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_sc_b200_gnb/docker-compose.yml @@ -1,6 +1,6 @@ services: gnb_mono_tdd: - image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop} + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} container_name: sa-b200-gnb cap_drop: - ALL diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 658b0b858a..6f61196e7e 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -92,7 +92,7 @@ Options: USRP, BLADERF, LMSSDR, IRIS, SIMU, AW2SORI, AERIAL, None (Default) Adds this RF board support (in external packages installation and in compilation) -t | --transport - Selects the transport protocol type, options: None, Ethernet, benetel4g, benetel5g, oran_fhlib_5g, oran_fhlib_5g_mplane, WLS + Selects the transport protocol type, options: None, Ethernet, oran_fhlib_5g, oran_fhlib_5g_mplane, WLS -P | --phy_simulators Makes the unitary tests Layer 1 simulators -V | --vcd @@ -278,10 +278,6 @@ function main() { TARGET_LIST="$TARGET_LIST oai_eth_transpro" CMAKE_CMD="$CMAKE_CMD -DOAI_${2^^}=ON" # ^^ makes uppercase ;; - "benetel4g" | "benetel5g" | "oran_fhlib_4g") - TARGET_LIST="$TARGET_LIST $2" - CMAKE_CMD="$CMAKE_CMD -DOAI_${2^^}=ON" # ^^ makes uppercase - ;; "oran_fhlib_5g") TARGET_LIST="$TARGET_LIST $2" CMAKE_CMD="$CMAKE_CMD -DOAI_FHI72=ON" diff --git a/cmake_targets/tools/install_wls_lib.patch b/cmake_targets/tools/install_wls_lib.patch index 5050b79a4e..c551f842b5 100644 --- a/cmake_targets/tools/install_wls_lib.patch +++ b/cmake_targets/tools/install_wls_lib.patch @@ -1,5 +1,5 @@ diff --git a/wls_lib/Makefile b/wls_lib/Makefile -index 2f8e4b2..e657488 100644 +index 2f8e4b2..7b99a26 100644 --- a/wls_lib/Makefile +++ b/wls_lib/Makefile @@ -1,20 +1,6 @@ @@ -23,7 +23,7 @@ index 2f8e4b2..e657488 100644 +################################################################ +# +################################################################ - + MYCUSTOMTAB=' ' MYCUSTOMSPACE='============================================================================================' @@ -24,11 +10,17 @@ MYCUSTOMSPACE1='------------------------------------------------------------' @@ -48,9 +48,12 @@ index 2f8e4b2..e657488 100644 else ifeq ($(WIRELESS_SDK_TOOLCHAIN),icx) CC := icx CPP := icx -@@ -44,9 +36,9 @@ ifeq ($(WIRELESS_SDK_TARGET_ISA),sse) +@@ -42,11 +34,11 @@ endif + ifeq ($(WIRELESS_SDK_TARGET_ISA),sse) + TARGET_PROCESSOR := -xSSE4.2 else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx2) - TARGET_PROCESSOR := -xCORE-AVX2 +- TARGET_PROCESSOR := -xCORE-AVX2 ++ TARGET_PROCESSOR := -march=core-avx2 else ifeq ($(WIRELESS_SDK_TARGET_ISA),avx512) - TARGET_PROCESSOR := -xCORE-AVX512 + TARGET_PROCESSOR := -march=skylake-avx512 @@ -63,7 +66,7 @@ index 2f8e4b2..e657488 100644 @@ -66,15 +58,38 @@ PROJECT_DIR := ./ BUILDDIR := make PROJECT_BINARY := $(PROJECT_NAME).so - + +PKGCONF ?= pkg-config +LIBDPDK_VERSION=20.11.3 + @@ -79,7 +82,7 @@ index 2f8e4b2..e657488 100644 +$(error "Please define RTE_SDK environment variable OR install DPDK version $(LIBDPDK_VERSION)") +endif endif - + -RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk) +# At least one of the options is defined + @@ -88,10 +91,10 @@ index 2f8e4b2..e657488 100644 +else ifeq ($(DPDK_INSTALLED),1) + RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig $(PKGCONF) --cflags-only-I libdpdk) +endif - + CC_SRC = wls_lib_dpdk.c \ syslib.c - + +CC_HDR = syslib.h \ + ttypes.h \ + wls.h \ @@ -104,74 +107,74 @@ index 2f8e4b2..e657488 100644 @@ -84,18 +99,19 @@ CC_FLAGS += -std=gnu11 -Wall -Wno-deprecated-declarations \ -Wimplicit-function-declaration \ -g -O3 -mcmodel=large $(TARGET_PROCESSOR) - + -INC := -I$(RTE_INC) +INC := -I$(RTE_INC) -I../intel_fapi/ DEF := - + AS_FLAGS := AR_FLAGS := rc - + PROJECT_OBJ_DIR := $(BUILDDIR)/obj +PROJECT_DEP_DIR := $(PROJECT_OBJ_DIR)/$(PROJECT_NAME).dep.d - + CC_OBJS := $(patsubst %.c,%.o,$(CC_SRC)) AS_OBJS := $(patsubst %.s,%.o,$(AS_SRC)) OBJS := $(CC_OBJS) $(AS_OBJS) $(LIBS) -DIRLIST := $(addprefix $(PROJECT_OBJ_DIR)/,$(sort $(dir $(OBJS)))) +DIRLIST := $(addprefix $(PROJECT_OBJ_DIR)/,$(sort $(dir $(OBJS)))) $(PROJECT_DEP_DIR) - + CC_OBJTARGETS := $(addprefix $(PROJECT_OBJ_DIR)/,$(CC_OBJS)) - + @@ -104,9 +120,7 @@ CC_FLAGS_FULL := $(CC_FLAGS) $(INC) $(DEF) - + AS_FLAGS := $(AS_FLAGS) $(INC) - + -PROJECT_DEP_FILE := $(PROJECT_OBJ_DIR)/$(PROJECT_NAME).dep - -ifeq ($(wildcard $(PROJECT_DEP_FILE)),$(PROJECT_DEP_FILE)) +ifeq ($(wildcard $(PROJECT_DEP_DIR)),$(PROJECT_DEP_DIR)) GENERATE_DEPS := else - + @@ -119,11 +133,11 @@ all : welcome_line $(PROJECT_BINARY) - + .PHONY : clear_dep clear_dep: - @$(RM) $(PROJECT_DEP_FILE) - @echo [DEP] $(subst $(PROJECT_OBJ_DIR)/,,$(PROJECT_DEP_FILE)) + @echo [DEP] rm $(PROJECT_DEP_DIR)/$(@F).dep + @$(RM) $(PROJECT_DEP_DIR)/$(@F).dep - + -$(CC_DEPS) : - @$(CC) -MM $(subst __up__,../,$(subst __dep__,,$@)) -MT $(PROJECT_OBJ_DIR)/$(patsubst %.c,%.o,$(subst __up__,../,$(subst __dep__,,$@))) $(CC_FLAGS_FULL) >> $(PROJECT_DEP_FILE) +$(CC_DEPS) : $(PROJECT_DEP_DIR) + @$(CC) $(CC_FLAGS_FULL) -MM $(subst __up__,../,$(subst __dep__,,$@)) -MT $(PROJECT_OBJ_DIR)/$(patsubst %.c,%.o,$(subst __up__,../,$(subst __dep__,,$@))) >> $(PROJECT_DEP_DIR)/$(@F).dep - + .PHONY : generate_deps generate_deps : clear_dep $(CC_DEPS) @@ -136,17 +150,17 @@ echo_start_build : $(DIRLIST) : -@$(MD) $@ - + -$(CC_OBJTARGETS) : +$(CC_OBJTARGETS) : $(GENERATE_DEPS) @echo [CC] $(subst $(PROJECT_OBJ_DIR)/,,$@) @$(CC) -c $(CC_FLAGS_FULL) -o"$@" $(patsubst %.o,%.c,$(subst $(PROJECT_OBJ_DIR)/,,$@)) - + -$(AS_OBJTARGETS) : +$(AS_OBJTARGETS) : $(CC_OBJTARGETS) $(CPP_OBJTARGETS) @echo [AS] $(subst $(PROJECT_OBJ_DIR)/,,$@) @$(AS) $(AS_FLAGS) -o"$@" $(patsubst %.o,%.s,$(subst $(PROJECT_OBJ_DIR)/,,$@)) - + -ifeq ($(wildcard $(PROJECT_DEP_FILE)),$(PROJECT_DEP_FILE)) +ifeq ($(wildcard $(PROJECT_DEP_DIR)),$(PROJECT_DEP_DIR)) - + -include $(PROJECT_DEP_FILE) +include $(PROJECT_DEP_DIR)/* - + endif - + @@ -156,7 +170,7 @@ clean: @$(RM) $(CC_OBJTARGETS) $(AS_OBJTARGETS) ifneq ($(wildcard $(PROJECT_DIR)/$(PROJECT_MAKE)),) @@ -179,17 +182,17 @@ index 2f8e4b2..e657488 100644 - @$(RM) $(PROJECT_BINARY) $(PROJECT_BINARY_LIB) $(PROJECT_DEP_FILE) + @$(RM) -rf $(PROJECT_BINARY) $(PROJECT_BINARY_LIB) $(PROJECT_DEP_DIR) endif - + xclean: clean @@ -172,7 +186,24 @@ welcome_line : debug : all release : all - + -$(PROJECT_BINARY) : $(DIRLIST) echo_start_build $(GENERATE_DEPS) $(PRE_BUILD) $(CC_OBJTARGETS) $(AS_OBJTARGETS) +$(PROJECT_BINARY) : $(DIRLIST) echo_start_build $(GENERATE_DEPS) $(CC_OBJTARGETS) $(AS_OBJTARGETS) @echo [AR] $(subst $(BUILDDIR)/,,$@) @$(CC) $(CC_OBJTARGETS) $(AS_OBJTARGETS) -shared -fPIC -o $@ - + +############################################################## +# Install configuration +############################################################## diff --git a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch index bec423b95e..3f953b36d9 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch @@ -1,5 +1,5 @@ diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h -index ac5f471..5efcce3 100644 +index ac5f471..b0f7ed1 100644 --- a/fhi_lib/app/src/common.h +++ b/fhi_lib/app/src/common.h @@ -28,7 +28,7 @@ @@ -7,7 +7,7 @@ index ac5f471..5efcce3 100644 #include -#define VERSIONX "oran_f_release_v1.0" -+#define VERSIONX "oran_f_release_v1.4" ++#define VERSIONX "oran_f_release_v1.5" #define APP_O_DU 0 #define APP_O_RU 1 @@ -919,7 +919,7 @@ index 4acade1..c939edc 100644 for(i = 0; i < xran_ports_num; i++){ g_xran_dev_ctx[i] = pCtx; diff --git a/fhi_lib/lib/src/xran_main.c b/fhi_lib/lib/src/xran_main.c -index 7c472d7..216c7f5 100644 +index 7c472d7..9da3621 100644 --- a/fhi_lib/lib/src/xran_main.c +++ b/fhi_lib/lib/src/xran_main.c @@ -35,7 +35,11 @@ @@ -969,7 +969,29 @@ index 7c472d7..216c7f5 100644 print_dbg("PRACH eAxC_offset %d\n", pPrachCPConfig->eAxC_offset); /* Save some configs for app */ -@@ -1570,6 +1593,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru +@@ -1169,6 +1192,10 @@ xran_prepare_cp_ul_slot(uint16_t xran_port_id, uint32_t nSlotIdx, uint32_t nCcS + uint8_t seqid = xran_get_cp_seqid(pHandle, XRAN_DIR_UL, cc_id, port_id); + + beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, port_id, slot_id); ++ pBufList = &(p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[buf_id][cc_id][ant_id].sBufferList); ++ struct xran_prb_map *prbMap = pBufList->pBuffers->pData; ++ struct xran_prb_elm *pPrbElm = &prbMap->prbMap[0]; //mjoang ++ beam_id = pPrbElm->nBeamIndex; + ret = generate_cpmsg_prach(pHandle, ¶ms, sect_geninfo, mbuf, p_xran_dev_ctx, + frame_id, subframe_id, slot_id, tti, + beam_id, cc_id, port_id, occasionid, seqid); +@@ -1338,6 +1365,10 @@ tx_cp_ul_cb(struct rte_timer *tim, void *arg) + uint8_t seqid = xran_get_cp_seqid(pHandle, XRAN_DIR_UL, cc_id, port_id); + + beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, port_id, slot_id); ++ pBufList = &(p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[buf_id][cc_id][ant_id].sBufferList); ++ struct xran_prb_map *prbMap = pBufList->pBuffers->pData; ++ struct xran_prb_elm *pPrbElm = &prbMap->prbMap[0]; //mjoang ++ beam_id = pPrbElm->nBeamIndex; + ret = generate_cpmsg_prach(pHandle, ¶ms, sect_geninfo, mbuf, p_xran_dev_ctx, + frame_id, subframe_id, slot_id, tti, + beam_id, cc_id, port_id, occasionid, seqid); +@@ -1570,6 +1601,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru { case ECPRI_IQ_DATA: pkt_data[num_data++] = pkt; @@ -977,7 +999,7 @@ index 7c472d7..216c7f5 100644 break; // For RU emulation case ECPRI_RT_CONTROL_DATA: -@@ -1587,7 +1611,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru +@@ -1587,7 +1619,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru break; default: if (p_dev_ctx->fh_init.io_cfg.id == O_DU) { @@ -986,7 +1008,7 @@ index 7c472d7..216c7f5 100644 } break; } -@@ -1876,7 +1900,7 @@ xran_sector_get_instances (uint32_t xran_port, void * pDevHandle, uint16_t nNumI +@@ -1876,7 +1908,7 @@ xran_sector_get_instances (uint32_t xran_port, void * pDevHandle, uint16_t nNumI for (i = 0; i < nNumInstances; i++) { /* Allocate Memory for CC handles */ @@ -995,7 +1017,7 @@ index 7c472d7..216c7f5 100644 if(pCcHandle == NULL) return XRAN_STATUS_RESOURCE; -@@ -2347,8 +2371,7 @@ ring_processing_func_per_port(void* args) +@@ -2347,8 +2379,7 @@ ring_processing_func_per_port(void* args) for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i = i+1) { if (ctx->vf2xran_port[i] == port_id) { for(qi = 0; qi < ctx->rxq_per_port[port_id]; qi++){ @@ -1005,7 +1027,7 @@ index 7c472d7..216c7f5 100644 } } } -@@ -2414,9 +2437,6 @@ xran_spawn_workers(void) +@@ -2414,9 +2445,6 @@ xran_spawn_workers(void) nWorkerCore = nWorkerCore << 1; } @@ -1015,7 +1037,7 @@ index 7c472d7..216c7f5 100644 printf("O-XU %d\n", eth_ctx->io_cfg.id); printf("HW %d\n", icx_cpu); printf("Num cores %d\n", total_num_cores); -@@ -2453,7 +2473,7 @@ xran_spawn_workers(void) +@@ -2453,7 +2481,7 @@ xran_spawn_workers(void) eth_ctx->time_wrk_cfg.arg = NULL; eth_ctx->time_wrk_cfg.state = 1; @@ -1024,7 +1046,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2475,7 +2495,7 @@ xran_spawn_workers(void) +@@ -2475,7 +2503,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1033,7 +1055,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2502,7 +2522,7 @@ xran_spawn_workers(void) +@@ -2502,7 +2530,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1042,7 +1064,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2536,7 +2556,7 @@ xran_spawn_workers(void) +@@ -2536,7 +2564,7 @@ xran_spawn_workers(void) else p_dev->tx_sym_gen_func = xran_process_tx_sym_cp_on_opt; @@ -1051,7 +1073,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2559,7 +2579,7 @@ xran_spawn_workers(void) +@@ -2559,7 +2587,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1060,7 +1082,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2586,7 +2606,7 @@ xran_spawn_workers(void) +@@ -2586,7 +2614,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1069,7 +1091,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2613,7 +2633,7 @@ xran_spawn_workers(void) +@@ -2613,7 +2641,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1078,7 +1100,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2628,7 +2648,7 @@ xran_spawn_workers(void) +@@ -2628,7 +2656,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1087,7 +1109,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2643,7 +2663,7 @@ xran_spawn_workers(void) +@@ -2643,7 +2671,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1096,7 +1118,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2682,7 +2702,7 @@ xran_spawn_workers(void) +@@ -2682,7 +2710,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1105,7 +1127,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2697,7 +2717,7 @@ xran_spawn_workers(void) +@@ -2697,7 +2725,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1114,7 +1136,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2712,7 +2732,7 @@ xran_spawn_workers(void) +@@ -2712,7 +2740,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1123,7 +1145,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2727,7 +2747,7 @@ xran_spawn_workers(void) +@@ -2727,7 +2755,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 UP GEN **/ @@ -1132,7 +1154,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2766,7 +2786,7 @@ xran_spawn_workers(void) +@@ -2766,7 +2794,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1141,7 +1163,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2781,7 +2801,7 @@ xran_spawn_workers(void) +@@ -2781,7 +2809,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 Eth Tx **/ @@ -1150,7 +1172,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); -@@ -2797,7 +2817,7 @@ xran_spawn_workers(void) +@@ -2797,7 +2825,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 - CP GEN **/ @@ -1159,7 +1181,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2812,7 +2832,7 @@ xran_spawn_workers(void) +@@ -2812,7 +2840,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 UP GEN **/ @@ -1168,7 +1190,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2827,7 +2847,7 @@ xran_spawn_workers(void) +@@ -2827,7 +2855,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 4 UP GEN **/ @@ -1177,7 +1199,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2861,7 +2881,7 @@ xran_spawn_workers(void) +@@ -2861,7 +2889,7 @@ xran_spawn_workers(void) /* workers */ /** 0 Eth RX */ @@ -1186,7 +1208,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2876,7 +2896,7 @@ xran_spawn_workers(void) +@@ -2876,7 +2904,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 FH RX and BBDEV */ @@ -1195,7 +1217,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2891,7 +2911,7 @@ xran_spawn_workers(void) +@@ -2891,7 +2919,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 FH RX and BBDEV */ @@ -1204,7 +1226,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2906,7 +2926,7 @@ xran_spawn_workers(void) +@@ -2906,7 +2934,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 FH RX and BBDEV */ @@ -1213,7 +1235,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2921,7 +2941,7 @@ xran_spawn_workers(void) +@@ -2921,7 +2949,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** FH TX and BBDEV */ @@ -1222,7 +1244,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2969,7 +2989,7 @@ xran_spawn_workers(void) +@@ -2969,7 +2997,7 @@ xran_spawn_workers(void) /* p_dev->tx_sym_gen_func = xran_process_tx_sym_cp_on_opt; */ @@ -1231,7 +1253,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3004,7 +3024,7 @@ xran_spawn_workers(void) +@@ -3004,7 +3032,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1240,7 +1262,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3031,7 +3051,7 @@ xran_spawn_workers(void) +@@ -3031,7 +3059,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1249,7 +1271,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3062,7 +3082,7 @@ xran_spawn_workers(void) +@@ -3062,7 +3090,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1258,7 +1280,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3089,7 +3109,7 @@ xran_spawn_workers(void) +@@ -3089,7 +3117,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1267,7 +1289,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3115,7 +3135,7 @@ xran_spawn_workers(void) +@@ -3115,7 +3143,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1276,7 +1298,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3130,7 +3150,7 @@ xran_spawn_workers(void) +@@ -3130,7 +3158,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1285,7 +1307,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3145,7 +3165,7 @@ xran_spawn_workers(void) +@@ -3145,7 +3173,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1294,7 +1316,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3184,7 +3204,7 @@ xran_spawn_workers(void) +@@ -3184,7 +3212,7 @@ xran_spawn_workers(void) /* workers */ /** 0 FH RX and BBDEV */ @@ -1303,7 +1325,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3199,7 +3219,7 @@ xran_spawn_workers(void) +@@ -3199,7 +3227,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1312,7 +1334,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3214,7 +3234,7 @@ xran_spawn_workers(void) +@@ -3214,7 +3242,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1321,7 +1343,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3229,7 +3249,7 @@ xran_spawn_workers(void) +@@ -3229,7 +3257,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 UP GEN **/ @@ -1330,7 +1352,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3266,7 +3286,7 @@ xran_spawn_workers(void) +@@ -3266,7 +3294,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1339,7 +1361,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3281,7 +3301,7 @@ xran_spawn_workers(void) +@@ -3281,7 +3309,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1348,7 +1370,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3296,7 +3316,7 @@ xran_spawn_workers(void) +@@ -3296,7 +3324,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1357,7 +1379,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3311,7 +3331,7 @@ xran_spawn_workers(void) +@@ -3311,7 +3339,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 UP GEN **/ @@ -1366,7 +1388,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3326,7 +3346,7 @@ xran_spawn_workers(void) +@@ -3326,7 +3354,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 4 UP GEN **/ @@ -1375,7 +1397,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3348,7 +3368,7 @@ xran_spawn_workers(void) +@@ -3348,7 +3376,7 @@ xran_spawn_workers(void) /* workers */ /** 0 Eth RX */ @@ -1384,7 +1406,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3363,7 +3383,7 @@ xran_spawn_workers(void) +@@ -3363,7 +3391,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 FH RX and BBDEV */ @@ -1393,7 +1415,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3378,7 +3398,7 @@ xran_spawn_workers(void) +@@ -3378,7 +3406,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 FH RX and BBDEV */ @@ -1402,7 +1424,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3393,7 +3413,7 @@ xran_spawn_workers(void) +@@ -3393,7 +3421,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 FH RX and BBDEV */ @@ -1411,7 +1433,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3408,7 +3428,7 @@ xran_spawn_workers(void) +@@ -3408,7 +3436,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** FH TX and BBDEV */ @@ -1420,7 +1442,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3435,7 +3455,7 @@ xran_spawn_workers(void) +@@ -3435,7 +3463,7 @@ xran_spawn_workers(void) /* workers */ /** 0 Eth RX */ @@ -1429,7 +1451,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3450,7 +3470,7 @@ xran_spawn_workers(void) +@@ -3450,7 +3478,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 FH RX and BBDEV */ @@ -1438,7 +1460,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3465,7 +3485,7 @@ xran_spawn_workers(void) +@@ -3465,7 +3493,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 FH RX and BBDEV */ @@ -1447,7 +1469,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3480,7 +3500,7 @@ xran_spawn_workers(void) +@@ -3480,7 +3508,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 FH RX and BBDEV */ @@ -1456,7 +1478,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3495,7 +3515,7 @@ xran_spawn_workers(void) +@@ -3495,7 +3523,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 4 FH RX and BBDEV */ @@ -1465,7 +1487,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3510,7 +3530,7 @@ xran_spawn_workers(void) +@@ -3510,7 +3538,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** FH TX and BBDEV */ @@ -1474,7 +1496,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3537,7 +3557,7 @@ xran_spawn_workers(void) +@@ -3537,7 +3565,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1483,7 +1505,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3562,7 +3582,7 @@ xran_spawn_workers(void) +@@ -3562,7 +3590,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1492,7 +1514,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3577,7 +3597,7 @@ xran_spawn_workers(void) +@@ -3577,7 +3605,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1501,7 +1523,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3602,7 +3622,7 @@ xran_spawn_workers(void) +@@ -3602,7 +3630,7 @@ xran_spawn_workers(void) } /** 3 UP GEN **/ @@ -1510,7 +1532,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3627,7 +3647,7 @@ xran_spawn_workers(void) +@@ -3627,7 +3655,7 @@ xran_spawn_workers(void) } /** 4 UP GEN **/ @@ -1519,7 +1541,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3642,7 +3662,7 @@ xran_spawn_workers(void) +@@ -3642,7 +3670,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 5 UP GEN **/ @@ -1528,7 +1550,7 @@ index 7c472d7..216c7f5 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -4034,6 +4054,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, +@@ -4034,6 +4062,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, return tti; } diff --git a/common/5g_platform_types.h b/common/5g_platform_types.h index 4ed7f33e47..7cae0afde7 100644 --- a/common/5g_platform_types.h +++ b/common/5g_platform_types.h @@ -37,9 +37,7 @@ typedef struct nssai_s { // Globally Unique AMF Identifier typedef struct nr_guami_s { - uint16_t mcc; - uint16_t mnc; - uint8_t mnc_len; + plmn_id_t plmn; uint8_t amf_region_id; uint16_t amf_set_id; uint8_t amf_pointer; diff --git a/common/config/config_load_configmodule.c b/common/config/config_load_configmodule.c index cfe05042ce..f5dfe6137f 100644 --- a/common/config/config_load_configmodule.c +++ b/common/config/config_load_configmodule.c @@ -240,6 +240,7 @@ configmodule_interface_t *load_configmodule(int argc, for (int i=0; i= 0 && computed_compidx log_component[computed_compidx].name = strdup(name); - g_log->log_component[computed_compidx].stream = stdout; - g_log->log_component[computed_compidx].filelog = 0; + log_component_t *c = &g_log->log_component[computed_compidx]; + c->name = strdup(name); + int n = snprintf(c->headerName, sizeof(c->headerName), "[%s", c->name); + if (n >= sizeof(c->headerName) - 1) // snprintf() truncated + n = sizeof(c->headerName) - 2; + c->headerName[n] = ']'; + c->headerName[n + 1] = 0; + c->stream = stdout; + c->filelog = 0; g_log->log_rarely_used[computed_compidx].filelog_name = calloc(1, strlen(name) + 16); /* /tmp/.%s */ sprintf(g_log->log_rarely_used[computed_compidx].filelog_name, "/tmp/%s.", name); strncat(g_log->log_rarely_used[computed_compidx].filelog_name, fext, 3); @@ -503,12 +515,15 @@ int logInit (void) for (int i = 0; i < MAX_LOG_PREDEF_COMPONENTS; i++) register_log_component(comp_name[i], comp_extension[i], i); - for (int i=0 ; log_level_names[i].name != NULL ; i++) - g_log->level2string[i] = toupper(log_level_names[i].name[0]); // uppercased first letter of level name - g_log->filelog_name = "/tmp/openair.log"; log_getconfig(g_log); + for (int i = 0; log_level_names[i].name != NULL; i++) + if (g_log->flag & FLAG_LEVEL) + snprintf(g_log->level2string[i], sizeof g_log->level2string[i], " %c ", toupper(log_level_names[i].name[0])); + else + snprintf(g_log->level2string[i], sizeof g_log->level2string[i], " "); + // set all unused component items to 0, they are for non predefined components for (int i=MAX_LOG_PREDEF_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) { memset(&(g_log->log_component[i]),0,sizeof(log_component_t)); @@ -569,8 +584,7 @@ static inline int log_header(log_component_t *c, struct tm utc_time; if (gmtime_r(&t.tv_sec, &utc_time) == NULL) abort(); - snprintf(timeString, sizeof(timeString), "%04d-%02d-%02d %02d:%02d:%02d.%06lu UTC ", - utc_time.tm_year + 1900, utc_time.tm_mon + 1, utc_time.tm_mday, + snprintf(timeString, sizeof(timeString), "[%02d:%02d:%02d.%06lu] ", utc_time.tm_hour, utc_time.tm_min, utc_time.tm_sec, t.tv_nsec / 1000); } else { snprintf(timeString, sizeof(timeString), "%lu.%06lu ", @@ -587,15 +601,18 @@ static inline int log_header(log_component_t *c, } else { threadIdString[0] = 0; } - return snprintf(log_buffer, buffsize, "%s%s%s[%s] %c %s%s", - flag & FLAG_NOCOLOR ? "" : log_level_highlight_start[level], - timeString, - threadIdString, - c->name, - flag & FLAG_LEVEL ? g_log->level2string[level] : ' ', - l, - threadname - ); + + return snprintf(log_buffer, + buffsize, + "%s%s%s%-8s%s%-*s%s", + flag & FLAG_NOCOLOR ? "" : log_level_highlight_start[level], + timeString, + threadIdString, + c->headerName, + g_log->level2string[level], // will print space if no level selected + l[0] == 0 ? 0 : 32, + l, + threadname); } void logRecord_mt(const char *file, diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h index 1f7474253c..312f2c9510 100644 --- a/common/utils/LOG/log.h +++ b/common/utils/LOG/log.h @@ -168,8 +168,9 @@ static const char *const flag_name[] = {FOREACH_FLAG(FLAG_TEXT) ""}; COMP_DEF(GNB_APP, log) \ COMP_DEF(NR_RRC, log) \ COMP_DEF(NR_MAC, log) \ - COMP_DEF(NR_MAC_DCI, log) \ - COMP_DEF(NR_PHY_DCI, log) \ + COMP_DEF(NR_MAC_DCI, log) \ + COMP_DEF(NR_PHY_DCI, log) \ + COMP_DEF(NR_PHY_RACH, log) \ COMP_DEF(NR_PHY, log) \ COMP_DEF(LOADER, log) \ COMP_DEF(ASN1, log) \ @@ -205,6 +206,7 @@ typedef struct { typedef struct { const char *name; + char headerName[19]; int level; int filelog; FILE *stream; @@ -216,7 +218,7 @@ typedef struct { typedef struct { log_component_t log_component[MAX_LOG_COMPONENTS]; log_component_back_t log_rarely_used[MAX_LOG_COMPONENTS]; - char level2string[NUM_LOG_LEVEL]; + char level2string[NUM_LOG_LEVEL][4]; int flag; char *filelog_name; debug_flags_t debug_mask; @@ -316,8 +318,14 @@ void close_log_mem(void); #define MATLAB_CSHORT_BRACKET1 13 #define MATLAB_CSHORT_BRACKET2 14 #define MATLAB_CSHORT_BRACKET3 15 - -int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format, int multiVec); + +int32_t write_file_matlab(const char *fname, + const char *vname, + const void *data, + int length, + int dec, + unsigned int format, + int multiVec); #define write_output(a, b, c, d, e, f) write_file_matlab(a, b, c, d, e, f, 0) /*----------------macro definitions for reading log configuration from the config module */ diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 2f17b62ea5..cd81deda2b 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -519,6 +519,27 @@ ID = LEGACY_NR_PHY_TRACE GROUP = ALL:LEGACY_NR_PHY:LEGACY_GROUP_TRACE:LEGACY FORMAT = string,log +ID = LEGACY_NR_PHY_RACH_INFO + DESC = NR_PHY_RACH legacy logs - info level + GROUP = ALL:LEGACY_NR_PHY_RACH:LEGACY_GROUP_INFO:LEGACY + FORMAT = string,log +ID = LEGACY_NR_PHY_RACH_ERROR + DESC = NR_PHY_RACH legacy logs - error level + GROUP = ALL:LEGACY_NR_PHY_RACH:LEGACY_GROUP_ERROR:LEGACY + FORMAT = string,log +ID = LEGACY_NR_PHY_RACH_WARNING + DESC = NR_PHY_RACH legacy logs - warning level + GROUP = ALL:LEGACY_NR_PHY_RACH:LEGACY_GROUP_WARNING:LEGACY + FORMAT = string,log +ID = LEGACY_NR_PHY_RACH_DEBUG + DESC = NR_PHY_RACH legacy logs - debug level + GROUP = ALL:LEGACY_NR_PHY_RACH:LEGACY_GROUP_DEBUG:LEGACY + FORMAT = string,log +ID = LEGACY_NR_PHY_RACH_TRACE + DESC = NR_PHY_RACH legacy logs - trace level + GROUP = ALL:LEGACY_NR_PHY_RACH:LEGACY_GROUP_TRACE:LEGACY + FORMAT = string,log + ID = LEGACY_S1AP_INFO DESC = S1AP legacy logs - info level GROUP = ALL:LEGACY_S1AP:LEGACY_GROUP_INFO:LEGACY diff --git a/common/utils/T/tracer/ue.c b/common/utils/T/tracer/ue.c index f4ea38f980..6d7d9ce4c5 100644 --- a/common/utils/T/tracer/ue.c +++ b/common/utils/T/tracer/ue.c @@ -196,7 +196,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, view *v; logger *l; - main_window = new_toplevel_window(g, 1200, 900, "eNB tracer"); + main_window = new_toplevel_window(g, 1200, 900, "UE tracer"); top_container = new_container(g, VERTICAL); widget_add_child(g, main_window, top_container, -1); @@ -207,7 +207,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, /* logo */ widget_add_child(g, line, logo, -1); - input_signal_plot = new_xy_plot(g, 256, 55, "input signal", 20); + input_signal_plot = new_xy_plot(g, 512, 110, "input signal", 20); widget_add_child(g, line, input_signal_plot, -1); xy_plot_set_range(g, input_signal_plot, 0, 7680*10, 20, 70); input_signal_log = new_framelog(h, database, @@ -221,7 +221,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, logger_add_view(input_signal_log, input_signal_view); /* UE x PDSCH IQ data */ - w = new_xy_plot(g, 55, 55, "", 50); + w = new_xy_plot(g, 110, 110, "", 50); e->pdsch_iq_ue_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, -500, 500, -500, 500); @@ -232,7 +232,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, e->pdsch_iq_ue_logger = l; /* UE x estimated DL channel */ - w = new_xy_plot(g, 280, 55, "", 50); + w = new_xy_plot(g, 560, 110, "", 50); e->dl_estimate_ue_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 512*10, -10, 80); @@ -245,7 +245,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, e->dl_estimate_ue_logger = l; /* PHY Meas */ - w = new_xy_plot(g, 128, 55, "", 50); + w = new_xy_plot(g, 256, 110, "", 50); e->phy_meas_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 1024*10, -130, 35); @@ -271,7 +271,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, /* UE x DL mcs */ line = new_container(g, HORIZONTAL); widget_add_child(g, top_container, line, -1); - w = new_xy_plot(g, 128, 55, "", 20); + w = new_xy_plot(g, 192, 110, "", 20); xy_plot_set_range(g, w, 0, 1024*10, -2, 30); e->dl_mcs_xy_plot = w; widget_add_child(g, line, w, -1); @@ -282,7 +282,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, e->dl_mcs_logger = l; /* UE x UL mcs */ - w = new_xy_plot(g, 128, 55, "", 20); + w = new_xy_plot(g, 192, 110, "", 20); xy_plot_set_range(g, w, 0, 1024*10, -2, 30); e->ul_mcs_xy_plot = w; widget_add_child(g, line, w, -1); @@ -295,7 +295,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, /* UE x PUSCH TX Power */ // line = new_container(g, HORIZONTAL); // widget_add_child(g, top_container, line, -1); - w = new_xy_plot(g, 128, 55, "", 20); + w = new_xy_plot(g, 192, 110, "", 20); e->pusch_power_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 1024*10, -30, 50); @@ -313,7 +313,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, /* UE x PUCCH TX Power */ // line = new_container(g, HORIZONTAL); // widget_add_child(g, top_container, line, -1); - w = new_xy_plot(g, 128, 55, "", 20); + w = new_xy_plot(g, 192, 110, "", 20); e->pucch_power_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 1024*10, -30, 50); @@ -329,7 +329,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, e->pucch_ampl_logger = l; /* UE x PDSCH energy */ - w = new_xy_plot(g, 128, 55, "", 50); + w = new_xy_plot(g, 192, 110, "", 50); e->pdsch_energy_ue_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 1024*10, -10, 80); @@ -355,7 +355,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, e->pdsch_energy_logger = l; /* UE x PDCCH energy */ - w = new_xy_plot(g, 128, 55, "", 50); + w = new_xy_plot(g, 192, 110, "", 50); e->pdcch_energy_ue_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 1024*10, -10, 80); @@ -381,7 +381,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, e->pdcch_energy_logger = l; /* UE x PDCCH IQ data */ - w = new_xy_plot(g, 55, 55, "", 50); + w = new_xy_plot(g, 110, 110, "", 50); e->pdcch_iq_ue_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, -100, 100, -100, 100); @@ -544,16 +544,16 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, /* phy/mac/rlc/pdcp/rrc textlog */ line = new_container(g, HORIZONTAL); widget_add_child(g, top_container, line, -1); - container_set_child_growable(g, top_container, line, 1); + container_set_child_growable(g, top_container, line, 0); /* phy */ col = new_container(g, VERTICAL); widget_add_child(g, line, col, -1); container_set_child_growable(g, line, col, 1); widget_add_child(g, col, new_label(g, "PHY"), -1); - text = new_textlist(g, 100, 10, new_color(g, "#afa")); + text = new_textlist(g, 100, 5, new_color(g, "#afa")); widget_add_child(g, col, text, -1); - container_set_child_growable(g, col, text, 1); + container_set_child_growable(g, col, text, 0); textview = new_view_textlist(10000, 10, g, text); e->phyview = textview; @@ -562,24 +562,24 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, col, -1); container_set_child_growable(g, line, col, 1); widget_add_child(g, col, new_label(g, "MAC"), -1); - text = new_textlist(g, 100, 10, new_color(g, "#adf")); + text = new_textlist(g, 100, 5, new_color(g, "#adf")); widget_add_child(g, col, text, -1); - container_set_child_growable(g, col, text, 1); + container_set_child_growable(g, col, text, 0); textview = new_view_textlist(10000, 10, g, text); e->macview = textview; line = new_container(g, HORIZONTAL); widget_add_child(g, top_container, line, -1); - container_set_child_growable(g, top_container, line, 1); + container_set_child_growable(g, top_container, line, 0); /* rlc */ col = new_container(g, VERTICAL); widget_add_child(g, line, col, -1); container_set_child_growable(g, line, col, 1); widget_add_child(g, col, new_label(g, "RLC"), -1); - text = new_textlist(g, 100, 10, new_color(g, "#aff")); + text = new_textlist(g, 100, 5, new_color(g, "#aff")); widget_add_child(g, col, text, -1); - container_set_child_growable(g, col, text, 1); + container_set_child_growable(g, col, text, 0); textview = new_view_textlist(10000, 10, g, text); e->rlcview = textview; @@ -588,24 +588,24 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database, widget_add_child(g, line, col, -1); container_set_child_growable(g, line, col, 1); widget_add_child(g, col, new_label(g, "PDCP"), -1); - text = new_textlist(g, 100, 10, new_color(g, "#ed9")); + text = new_textlist(g, 100, 5, new_color(g, "#ed9")); widget_add_child(g, col, text, -1); - container_set_child_growable(g, col, text, 1); + container_set_child_growable(g, col, text, 0); textview = new_view_textlist(10000, 10, g, text); e->pdcpview = textview; line = new_container(g, HORIZONTAL); widget_add_child(g, top_container, line, -1); - container_set_child_growable(g, top_container, line, 1); + container_set_child_growable(g, top_container, line, 0); /* rrc */ col = new_container(g, VERTICAL); widget_add_child(g, line, col, -1); container_set_child_growable(g, line, col, 1); widget_add_child(g, col, new_label(g, "RRC"), -1); - text = new_textlist(g, 100, 10, new_color(g, "#fdb")); + text = new_textlist(g, 100, 5, new_color(g, "#fdb")); widget_add_child(g, col, text, -1); - container_set_child_growable(g, col, text, 1); + container_set_child_growable(g, col, text, 0); textview = new_view_textlist(10000, 10, g, text); e->rrcview = textview; diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 8e6a16c97d..a842f66443 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -459,12 +459,50 @@ bool compare_relative_ul_channel_bw(int nr_band, int scs, int channel_bandwidth, return rel_bw > limit; } -uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) +static bool check_delta_duplex(int index, uint64_t dlfreq_khz, uint64_t ulfreq_khz, int64_t dlbw, int64_t ulbw) +{ + int uldl_min_offset = nr_bandtable[index].dl_min - nr_bandtable[index].ul_min; + int txrx_offset = dlfreq_khz - ulfreq_khz; + LOG_I(NR_PHY, "dlfreq:%ld ulfreq:%ld deltaduplex:%d khz, uldl_min_offset:%d khz\n", + dlfreq_khz, ulfreq_khz, txrx_offset, uldl_min_offset); + if (txrx_offset == uldl_min_offset) + return true; + + int band = nr_bandtable[index].band; + + // Refer to section 5.4.4 in spec 38.101-5 + if (band == 256 && txrx_offset >= 165000 && txrx_offset <= 215000) + return true; + if (band == 255 && txrx_offset >= -130500 && txrx_offset <= -72500) + return true; + if (band == 254 && txrx_offset >= 862000 && txrx_offset <= 885000) + return true; + + // Refer to section 5.4.4 in spec 38.101-1 for these bands 24, 91-94, 109 + if (band == 24 && (txrx_offset == -101500 || txrx_offset == -120500)) + return true; + //Delta duplex is also a range for these bands n91-n94, n109. + if ((band >= 91 && band <= 94) || band == 109) { + dlbw = ((dlbw / 1000) + 1) * 1000; + ulbw = ((ulbw / 1000) + 1) * 1000; + int lower_limit = nr_bandtable[index].dl_min - nr_bandtable[index].ul_max + ((dlbw + ulbw) >> 1); + int upper_limit = nr_bandtable[index].dl_max - nr_bandtable[index].ul_min - ((dlbw + ulbw) >> 1); + LOG_I(NR_PHY, "Band %d dlbw:%ld Khz, ulbw: %ld Khz RXTX lower limit:%d khz, upper limit:%d khz\n", + band, dlbw, ulbw, lower_limit, upper_limit); + + if (txrx_offset >= lower_limit && txrx_offset <= upper_limit) + return true; + } + + return false; +} + +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex, int64_t dlbw, int64_t ulbw) { const int64_t dl_freq_khz = downlink_frequency / 1000; const int32_t delta_duplex_khz = delta_duplex / 1000; + const int64_t ul_freq_khz = dl_freq_khz + delta_duplex_khz; - uint64_t center_freq_diff_khz = UINT64_MAX; // 2^64 uint16_t current_band = 0; for (int ind = 0; ind < sizeofArray(nr_bandtable); ind++) { @@ -472,17 +510,13 @@ uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max) continue; - int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min; - - if (current_offset_khz != delta_duplex_khz) + if (ul_freq_khz < nr_bandtable[ind].ul_min || ul_freq_khz > nr_bandtable[ind].ul_max) continue; - int64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2; + if (!check_delta_duplex(ind, dl_freq_khz, ul_freq_khz, dlbw, ulbw)) + continue; - if (labs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ - current_band = nr_bandtable[ind].band; - center_freq_diff_khz = labs(dl_freq_khz - center_frequency_khz); - } + current_band = nr_bandtable[ind].band; } printf("DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n", @@ -541,8 +575,8 @@ int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, return f; } -void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) { - +void get_coreset_rballoc(const uint8_t *FreqDomainResource, int *n_rb, int *rb_offset) +{ uint8_t count=0, start=0, start_set=0; uint64_t bitmap = (((uint64_t)FreqDomainResource[0])<<37)| @@ -565,7 +599,7 @@ void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) { } // According to 38.211 7.3.2.2 -int get_coreset_num_cces(uint8_t *FreqDomainResource, int duration) +int get_coreset_num_cces(const uint8_t *FreqDomainResource, int duration) { int num_rbs; int rb_offset; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index e0d68a45ad..52eb305824 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -280,12 +280,12 @@ uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, ui int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs); int get_SLIV(uint8_t S, uint8_t L); -void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset); -int get_coreset_num_cces(uint8_t *FreqDomainResource, int duration); +void get_coreset_rballoc(const uint8_t *FreqDomainResource, int *n_rb, int *rb_offset); +int get_coreset_num_cces(const uint8_t *FreqDomainResource, int duration); int get_nr_table_idx(int nr_bandP, uint8_t scs_index); int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index); frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index); -uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex); +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex, int64_t dlbw, int64_t ulbw); int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize); diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt index a249596d97..40380c0418 100644 --- a/common/utils/telnetsrv/CMakeLists.txt +++ b/common/utils/telnetsrv/CMakeLists.txt @@ -62,7 +62,7 @@ add_dependencies(telnetsrv telnetsrv_ci) message(STATUS "Add CI specific telnet functions for nrUE in telnetsrv_ciUE.so") add_library(telnetsrv_ciUE MODULE telnetsrv_ciUE.c) -target_link_libraries(telnetsrv_ciUE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) +target_link_libraries(telnetsrv_ciUE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL NR_L2_UE nr_nas) add_dependencies(telnetsrv telnetsrv_ciUE) message(STATUS "Add bearer specific telnet functions in libtelnetsrv_bearer.so") diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index 291f1f37a2..8b00d529c5 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -39,6 +39,7 @@ #include "openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/RRC/NR/rrc_gNB_mobility.h" +#include "openair3/NGAP/ngap_gNB_ue_context.h" #define TELNETSERVERCODE #include "telnetsrv.h" @@ -284,6 +285,86 @@ static int get_current_bwp(char *buf, int debug, telnet_printfunc_t prnt) return 0; } +/** @brief Trigger NGAP PDU Session Release for one or more PDU sessions associated with a UE ID/ + * Syntax: trigger_pdu_session_release [ue_id=gNB_ue_ngap_id(int,opt)],pdusession_id(int)[,pdusession_id(int)...] + * - If the gNB_ue_ngap_id is omitted, it is fetched from the only UE present in the RRC layer + * - At least one valid PDU session ID must be provided + * @param[in] buf Comma-separated input string: [ue_id=gNB_ue_ngap_id(int,opt)],PDU1[,PDU2,...] + * @param[in] debug Not used. + * @param[in] prnt Callback for telnet output printing. + * @return 0 on success; negative value on error. */ +static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfunc_t prnt) +{ + if (buf == NULL) { + ERROR_MSG_RET("Missing input. Usage: trigger_pdu_session_release [ue_id=gNB_ue_ngap_id(int,opt)],pdusession_id(int)[,pdusession_id(int)...]\n"); + } + + char *tokens[NGAP_MAX_PDU_SESSION + 1]; + int count = 0; + + for (char *tok = strtok(buf, ","); tok != NULL && count < (int)sizeofArray(tokens); tok = strtok(NULL, ",")) { + tokens[count++] = tok; + } + + if (count < 1) { + ERROR_MSG_RET("Invalid input. Usage: trigger_pdu_session_release [ue_id=gNB_ue_ngap_id(int,opt)],pdusession_id(int)[,pdusession_id(int)...]\n"); + } + + int gNB_ue_ngap_id = -1; + int pdu_start_index = 0; + + if (strncmp(tokens[0], "ue_id=", 6) == 0) { + gNB_ue_ngap_id = atoi(tokens[0] + 6); + pdu_start_index = 1; + } else { + // No UE ID: infer it + if (!RC.nrrrc) + ERROR_MSG_RET("No RRC present\n"); + rrc_gNB_ue_context_t *ue = get_single_rrc_ue(); + if (!ue) + ERROR_MSG_RET("No single UE in RRC present\n"); + gNB_ue_ngap_id = ue->ue_context.rrc_ue_id; + } + + if (pdu_start_index >= count) { + ERROR_MSG_RET("No pdusession_id(int) provided\n"); + } + + ngap_gNB_ue_context_t *ngap = ngap_get_ue_context(gNB_ue_ngap_id); + if (!ngap) { + ERROR_MSG_RET("No NGAP UE context for gNB_ue_ngap_id %d\n", gNB_ue_ngap_id); + } + + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_RELEASE_COMMAND); + ngap_pdusession_release_command_t *msg = &NGAP_PDUSESSION_RELEASE_COMMAND(message_p); + memset(msg, 0, sizeof(*msg)); + + msg->amf_ue_ngap_id = ngap->amf_ue_ngap_id; + msg->gNB_ue_ngap_id = ngap->gNB_ue_ngap_id; + + int nb_sessions = 0; + for (int i = pdu_start_index; i < count; ++i) { + int sid = atoi(tokens[i]); + if (sid < 1 || sid > 255) { + ERROR_MSG_RET("Invalid pdusession_id(int): %s (must be between 1 and 255)\n", tokens[i]); + } + msg->pdusession_release_params[nb_sessions++].pdusession_id = sid; + } + + msg->nb_pdusessions_torelease = nb_sessions; + + if (prnt) { + prnt("Triggering NGAP PDU Session Release for gNB_ue_ngap_id=%d: releasing pdusession_id=%d", gNB_ue_ngap_id); + for (int i = 0; i < nb_sessions; ++i) { + prnt(" %d,", msg->pdusession_release_params[i].pdusession_id); + } + prnt("\n"); + } + + itti_send_msg_to_task(TASK_RRC_GNB, 0, message_p); + return 0; +} + static telnetshell_cmddef_t cicmds[] = { {"get_single_rnti", "", get_single_rnti}, {"force_reestab", "[rnti(hex,opt)]", trigger_reestab}, @@ -294,6 +375,7 @@ static telnetshell_cmddef_t cicmds[] = { {"fetch_du_by_ue_id", "[rrc_ue_id(int,opt)]", fetch_du_by_ue_id}, {"get_current_bwp", "[rnti(hex,opt)]", get_current_bwp}, {"trigger_n2_ho", "[neighbour_pci(uint32_t),ueId(uint32_t)]", rrc_gNB_trigger_n2_ho}, + {"pdu_session_release", "[gNB_ue_ngap_id(int,opt)]", trigger_ngap_pdu_session_release}, {"", "", NULL}, }; diff --git a/common/utils/telnetsrv/telnetsrv_ciUE.c b/common/utils/telnetsrv/telnetsrv_ciUE.c index 90e044ed86..6f86f1678f 100644 --- a/common/utils/telnetsrv/telnetsrv_ciUE.c +++ b/common/utils/telnetsrv/telnetsrv_ciUE.c @@ -37,6 +37,9 @@ #include "openair2/LAYER2/NR_MAC_UE/mac_defs.h" #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" #include "openair2/RRC/NR_UE/rrc_proto.h" +#include "openair1/PHY/phy_extern_nr_ue.h" +#include "openair1/PHY/defs_nr_common.h" +#include "openair3/NAS/NR_UE/nr_nas_msg.h" #define TELNETSERVERCODE #include "telnetsrv.h" @@ -50,6 +53,14 @@ const char* NR_UE_L2_STATE_STR[] = { #undef UE_STATE }; +static int get_default_ue_id(void) +{ + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(0); + if (!rrc) + return -1; + return rrc->ue_id; +} + /** * Get the synchronization state of a UE. * @@ -110,6 +121,60 @@ static int force_deregistration(char *buf, int debug, telnet_printfunc_t prnt) return 0; } +extern float get_prs_max_dl_toa(prs_meas_t *prs_meas); +static int get_dl_toa(char *buf, int debug, telnet_printfunc_t prnt) +{ + // TODO multiple antennas, resources, gNBs? + int gNB_id = 0; + int rsc_id = 0; + int ant = 0; + + PHY_VARS_NR_UE *UE = PHY_vars_UE_g[0][0]; + if (!UE || !UE->prs_vars[gNB_id]) + ERROR_MSG_RET("no UE/prs_vars found!\n"); + NR_PRS_RESOURCE_t *prs_res = &UE->prs_vars[gNB_id]->prs_resource[rsc_id]; + if (!prs_res->prs_meas || !prs_res->prs_meas[ant]) + ERROR_MSG_RET("prs_meas not initialized!\n"); + + float max = get_prs_max_dl_toa(prs_res->prs_meas[ant]); + prnt("UE max PRS DL ToA %.3f\n", max); + return 0; +} + +static int add_pdu_session(char *buf, int debug, telnet_printfunc_t prnt) +{ + int ue_id = -1; + int pdusession_id = -1; + + if (!buf) { + ERROR_MSG_RET("Missing argument: expected PDUSessionID[,UE_ID]\n"); + } + + // Try parsing values in the form: "PDUSessionID[,UE_ID]" + int n = sscanf(buf, "%d,%d", &pdusession_id, &ue_id); + if (n == 1) { + // Only PDUSessionID provided: use default UE ID + ue_id = get_default_ue_id(); + if (ue_id < 0) + ERROR_MSG_RET("No default UE context found\n"); + } else if (n != 2) { + ERROR_MSG_RET("Invalid format: expected PDUSessionID[,UE_ID]\n"); + } + + if (pdusession_id < 0 || pdusession_id > 255) + ERROR_MSG_RET("PDUSessionID must be in range [0,255]\n"); + if (ue_id < 0) + ERROR_MSG_RET("UE_ID must be >= 0\n"); + + nr_ue_nas_t *nas = get_ue_nas_info(ue_id); + if (!nas) + ERROR_MSG_RET("No NAS context found for UE_ID %d\n", ue_id); + + request_pdusession(nas, pdusession_id); + prnt("Triggered PDU session request for UE %d with ID %d\n", ue_id, pdusession_id); + return 0; +} + /* Telnet shell command definitions */ static telnetshell_cmddef_t cicmds[] = { {"sync_state", "[UE_ID(int,opt)]", get_sync_state}, @@ -117,6 +182,8 @@ static telnetshell_cmddef_t cicmds[] = { {"force_RRC_IDLE", "", force_RRC_IDLE}, {"force_crnti_ra", "", force_crnti_ra}, {"deregistration", "", force_deregistration}, + {"get_max_dl_toa", "[ant]", get_dl_toa}, + {"add_pdu_session", "[PDUSessionID(int)],[UE_ID(int,opt)]", add_pdu_session}, {"", "", NULL}, }; diff --git a/common/utils/telnetsrv/telnetsrv_o1.c b/common/utils/telnetsrv/telnetsrv_o1.c index ac368885f6..9ff56e3521 100644 --- a/common/utils/telnetsrv/telnetsrv_o1.c +++ b/common/utils/telnetsrv/telnetsrv_o1.c @@ -105,10 +105,10 @@ static int get_stats(char *buf, int debug, telnet_printfunc_t prnt) int bw_index = get_supported_band_index(scs, fr, nrb); int bw_mhz = get_supported_bw_mhz(fr, bw_index); - const mac_stats_t *stat = &mac->mac_stats; - static mac_stats_t last = {0}; - int diff_used = stat->used_prb_aggregate - last.used_prb_aggregate; - int diff_total = stat->total_prb_aggregate - last.total_prb_aggregate; + const dlul_mac_stats_t *stat = &mac->mac_stats; + static dlul_mac_stats_t last = {0}; + int diff_used = stat->dl.used_prb_aggregate - last.dl.used_prb_aggregate; + int diff_total = stat->dl.total_prb_aggregate - last.dl.total_prb_aggregate; int load = diff_total > 0 ? 100 * diff_used / diff_total : 0; last = *stat; diff --git a/doc/Doxyfile b/doc/Doxyfile index 5f96bc2e4a..85cb5776c0 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1916,8 +1916,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/E1AP/e1ap_api.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/E1AP/e1ap_setup.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/E1AP/e1ap_asnc.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/nr_sched_response.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/nr_sched_response.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/NR_IF_Module.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/NR_IF_Module.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/SDAP/nr_sdap/nr_sdap.h \ @@ -2012,7 +2010,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_sss.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_uci_tools_common.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_prach.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_scrambling.c \ @@ -2294,10 +2291,8 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/phy_frame_config_nr.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/phy_frame_config_nr.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/nr_prach_procedures.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/fapi_nr_l1.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/phy_procedures_nr_gNB.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/sched_nr.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/fapi_nr_l1.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/nr_ru_procedures.c \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/if_defs.h \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/ethernet_lib.h \ diff --git a/doc/E1AP/e1ap_procedures.md b/doc/E1AP/e1ap_procedures.md index c46c710333..8857eee26b 100644 --- a/doc/E1AP/e1ap_procedures.md +++ b/doc/E1AP/e1ap_procedures.md @@ -72,3 +72,36 @@ sequenceDiagram u->>c: BEARER CONTEXT MODIFICATION RESPONSE Note over c: e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE ``` + +## PDU Session Release + +```mermaid +sequenceDiagram + participant AMF + participant CUCP + participant CUUP + participant DU + participant UE + + AMF->>CUCP: NG PDU SESSION RESOURCE RELEASE COMMAND + Note over CUCP: ngap_gNB_handle_pdusession_release_command + CUCP->>CUCP: rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND + Note over CUCP: set status PDU_SESSION_STATUS_TORELEASE + CUCP->>CUUP: E1 Bearer Context Modification Request + Note over CUUP: release_gtpu_tunnel (GTP tunnel, PDCP, SDAP) + CUUP->>CUCP: E1 Bearer Context Modification Response + Note over CUCP: rrc_gNB_send_f1_drb_release_request + CUCP->>DU: F1 UE Context Modification Request + Note over DU: handle_ue_context_drbs_release (release in MAC/RLC) + DU->>CUCP: F1 UE Context Modification Response + Note over CUCP: rrc_CU_process_ue_context_modification_response + Note over CUCP: replace existing CellGroupConfig + Note over CUCP: rrc_gNB_generate_dedicatedRRCReconfiguration + CUCP->>UE: RRCReconfiguration (DRB release list, NAS PDU) + UE->>CUCP: RRCReconfigurationComplete + Note over CUCP: handle_rrcReconfigurationComplete + Note over CUCP: rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE + CUCP->>AMF: NG PDU SESSION RESOURCE RELEASE RESPONSE + Note over CUCP: rm_drbs_by_pdusession (from stored RRC list) + Note over CUCP: rm_pduSession (from stored RRC list) +``` diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 43b8367e3b..c703899c16 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -29,9 +29,9 @@ The following features are valid for the gNB and the 5G-NR UE. * Static FDD * Normal CP * Subcarrier spacings: 15 and 30kHz (FR1), 120kHz (FR2) -* Bandwidths: 10, 20, 40, 60, 80, 100MHz +* Bandwidths: 5-100MHz (FR1), 100 and 200MHz (FR2) * Intermediate downlink and uplink frequencies to interface with IF equipment -* Procedures for 2-layer DL and UL MIMO +* Procedures for 4-layer DL and 2-layer UL SU-MIMO * Slot format: 14 OFDM symbols in UL or DL * Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 supported) * Highly efficient 3GPP compliant polar encoder and decoder @@ -47,7 +47,7 @@ These modes of operation are supported: * "noS1" mode (DL and UL, gNB, nrUE): - Connection setup stops after RA; RRC configuration is exchanged through files - - Creates TUN interface to PDCP to inject and receive user-place traffic + - Creates TUN interface to SDAP to inject and receive user-place traffic - No connection to the core network * Standalone (SA) mode (gNB, nrUE): - UE can register with the 5G Core Network through the gNB, establish a PDU @@ -73,7 +73,7 @@ These modes of operation are supported: - Single and multiple DMRS symbols - PTRS support - Support for up to 4 TX antennas - - Support for up to 2 layers + - Support for up to 4 layers - Support for 256 QAM * NR-CSIRS Generation of sequence at PHY * NR-PUSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). @@ -104,7 +104,9 @@ These modes of operation are supported: ## gNB MAC - MAC -> PHY configuration using NR FAPI P5 interface -- MAC <-> PHY data interface using FAPI P7 interface for BCH PDU, DCI PDU, PDSCH PDU +- MAC <-> PHY data interface using FAPI P7 interface for DL_TTI.request, + UL_TTI.request, UL_DCI.request, TX_data.request, RX_Data.indication, + CRC.indication, UCI.indication, SRS.indication - Generation of and scheduler procedures for MIB/SIB1 - Scheduler procedures for RA - 4-Step RA @@ -123,13 +125,14 @@ These modes of operation are supported: - MAC downlink scheduler - phy-test scheduler (fixed allocation and usable also without UE) - regular scheduler with dynamic proportionally-fair allocation - - MCS adaptation from HARQ BLER + - MCS adaptation from HARQ BLER or SSB-SINR report - MAC header generation (including timing advance) -- ACK / NACK handling and HARQ procedures for downlink +- ACK/NACK handling and HARQ procedures for downlink - MAC uplink scheduler - phy-test scheduler (fixed allocation) - regular scheduler with dynamic proportionally-fair allocation - HARQ procedures for uplink + - MCS adaption from HARQ BLER or PUSCH SINR - Scheduler procedures for SRS reception - Periodic SRS reception - Channel rank computation up to 2x2 scenario @@ -144,7 +147,15 @@ These modes of operation are supported: neighbors include cells operating on different frequencies - DUs must be synchronized with each other for the measurements to be properly performed - Initial support for RedCap -- Scheduling of SIBs (2, 19) + - RedCap SIB1 v17 IEs supported + - Coexistence of RedCap and Normal UEs + - Handling of RedCap capability for small PDCP/RLC SN size +- Scheduling of other SIBs (2, 19) +- NTN + - Support downlinkHARQ-FeedbackDisabled-r17 + - Support for 32 PDSCH and PUSCH HARQ processes per UE + - Consider ntn-Config-r17.cellSpecificKoffset-r17 in scheduling + - Function-based interface for ntn-Config-r17 updates (used by NTN-LEO RFsimulator) ## gNB RLC @@ -180,7 +191,7 @@ These modes of operation are supported: - NR RRC (38.331) Rel 17 messages using new [asn1c](https://github.com/mouse07410/asn1c) - LTE RRC (36.331) also updated to Rel 15 - Generation of system information (SIB2) -- RRC can configure PDCP, RLC, MAC +- RRC can configure PDCP and SDAP (through E1), and RLC and MAC (through F1) - Interface with GTP-U (tunnel creation/handling for S1-U (NSA), N3 (SA), F1 interfaces) - Integration of RRC messages and procedures supporting UE 5G SA connection - RRCSetupRequest/RRCSetup/RRCSetupComplete @@ -190,8 +201,17 @@ These modes of operation are supported: - Support for MasterCellGroup configuration (from DU) - Interface with NGAP for the interactions with the AMF - Interface with F1AP for CU/DU split deployment option - - Periodic RRC measurements of serving cell (no A/B events) -- Initial support for RedCap + - Interface with E1AP for CU-CP/CU-CP split deployment option + - Periodic RRC measurements of serving/neighbour cells and A2/A3 event + handling +- RRC Mobility Management Procedures: + - Inter-DU Handover (F1-based handover within same CU) + - Inter-gNB Handover (N2-based handover between different gNBs) + - Handover Preparation Information generation and processing + - Handover Command generation and processing + - PDCP Status transfer procedures + - Support for handover decision triggers (A3 events, manual triggers) +- Initial support for RedCap (see MAC) ## gNB X2AP @@ -209,6 +229,16 @@ These modes of operation are supported: - NGAP UE context release request/complete - NGAP UE radio capability info indication - NGAP PDU session resource setup request/response + - NGAP Mobility Management Procedures: + * NGAP Handover Required + * NGAP Handover Request + * NGAP Handover Request Acknowledge + * NGAP Handover Command + * NGAP Handover Notify + * NGAP Handover Cancel + * NGAP Handover Cancel Acknowledge + * NGAP Uplink RAN Status Transfer + * NGAP Downlink RAN Status Transfer - Interface with RRC ## gNB F1AP @@ -226,7 +256,10 @@ These modes of operation are supported: * F1 UE Context modification required * F1 UE Context release req/cmd/complete - F1 gNB CU configuration update + - F1 gNB DU configuration update - F1 Reset (handled at DU only, full reset only) + - F1 Mobility Management Procedures: + * F1 Intra-CU Handover (Inter-DU mobility) - Interface with RRC - Interface with GTP-u (tunnel creation/handling for F1-U interface) - One CU(-CP) can handle multiple DUs @@ -245,7 +278,8 @@ These modes of operation are supported: - Bearer Context Modification (gNB-CU-CP initiated) - E1 Bearer Context Modification Request - E1 Bearer Context Modification Response -- Interface with RRC and PDCP + - E1 Reset +- Interface with RRC and PDCP/SDAP - One CU-CP can handle multiple CU-UPs ## gNB GTP-U @@ -268,7 +302,8 @@ These modes of operation are supported: - non-blind synchronization (information required: carrier frequency, bandwidth, numerology) - option to search SSB inside the bandwidth available * Time tracking based on PBCH DMRS -* Frequency offset estimation based on PSS and SSS +* Initial Frequency offset estimation based on PSS and SSS +* Continuous Frequency offset estimation and compensation based on PBCH DMRS * 15kHz and 30kHz SCS for FR1 and 120 kHz SCS for FR2 * Reception of NR-PSS/NR-SSS * NR-PBCH supports multiple SSBs and flexible periodicity @@ -299,6 +334,7 @@ These modes of operation are supported: - Support for 256 QAM - Support for up to 2 TX antenna - Support for up to 2 layers + - Support for UCI on PUSCH * NR-PUCCH - Format 0 (2 bits for ACK/NACK and SR) - Format 2 (mainly for CSI feedback) @@ -314,6 +350,10 @@ These modes of operation are supported: - Support for multiple gNB reception with gNBs synced via GPSDO * NR-PRACH - Formats 0,1,2,3, A1-A3, B1-B3 +* NTN + - TA adjustemt based on ntn-Config-r17 information + - Autonomous TA adjustemt between SIB19 receptions based on DL time tracking + - UL Doppler pre-compensation based on continuous DL FO estimation * Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported) * Highly efficient 3GPP compliant polar encoder and decoder * Encoder and decoder for short block @@ -331,6 +371,8 @@ These modes of operation are supported: * Minimum system information (MSI) - MIB processing - Scheduling of system information block 1 (SIB1) reception +* Other system information + - Scheduling of other system information blocks reception * Random access procedure (needs improvement, there is still not a clear separation between MAC and PHY) - Mapping SSBs to multiple ROs - Scheduling of PRACH @@ -367,6 +409,10 @@ These modes of operation are supported: - Periodic and aperiodic SRS transmission * Bandwidth part (BWP) operation - Operation in configured dedicated BWP through RRCSetup or RRCReconfiguration +* NTN + - Support downlinkHARQ-FeedbackDisabled-r17 + - Support for 32 PDSCH and PUSCH HARQ processes + - Consider ntn-Config-r17.cellSpecificKoffset-r17 in scheduling ## UE RLC @@ -399,25 +445,41 @@ These modes of operation are supported: * Integration of RRC messages and procedures supporting UE 5G SA connection according to 38.331 Rel.16 - RRCSetupRequest/RRCSetup/RRCSetupComplete + - RRCReject + - RRCRelease/ RRC going to IDLE - RRC Uplink/Downlink Information transfer carrying NAS messages transparently - RRC Reconfiguration/Reconfiguration complete + - RRCSetup fallback (after reestablishment) - RRCReestablishmentRequest/RRC Reestablishment/Reestablishment complete - Support for master cell group configuration - Reception of UECapabilityEnquiry, encoding and transmission of UECapability +* NTN according to 38.331 Rel.17 + - Reception of ntn-Config-r17 from SIB19 or reconfigurationWithSync + - Handling of ntn-UlSyncValidityDuration-r17 in SIB19 * Interface with PDCP: configuration, DCCH and CCCH message handling * Interface with RLC and MAC for configuration -## UE NAS +## UE 5G NAS -* Transfer of NAS messages between the AMF and the UE supporting the UE registration with the core network and the PDU session establishment according to 24.501 Rel.16 +* Transfer of NAS messages between the AMF and the UE supporting the UE registration with the core network and the PDU session establishment according to 24.501 Rel.16 +* 5GMM (5G Mobility Management) messages: + - Service Request/Accept/Reject (enc/dec library only) - Identity Request/Response - Authentication Request/Response - Security Mode Command/Complete - Registration Request/Accept/Complete + - Deregistration Request (UE originating) + - Uplink NAS Transport +* 5GSM (5G Session Management) messages: - PDU Session Establishment Request/Accept - - NAS configuration and basic interfacing with RRC - +* Security Features: + - NAS message integrity protection and ciphering + - Security context establishment and management +* Integration: + - NAS configuration and interfacing with RRC + - Integration with SDAP for user plane data transfer +For detailed implementation status, encoding/decoding support, and unit test coverage, see [5G NAS Implementation Documentation](5Gnas.md). # OpenAirInterface 4G LTE eNB Feature Set # diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index f4583b7a23..a3b174f50c 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -236,6 +236,9 @@ In the `MACRLCs` section of the gNB/DU configuration file: case RSSI reaches the threshold and prevents ADC railing. Unit depends on RSSI reporting config. * `pucch_RSSI_Threshold`: Same as above but for PUCCH +* `stats_max_ue` (default 8): maximum number of UEs to show in periodical + stats; beyond this number, periodical statistics will be disabled (it can + still be seen in `nrMAC_stats.log`. Use `0` to disable periodical stats. In the `gNBs` section of the gNB/DU configuration file: some of the parameters affect RRC configuration (CellGroupConfig) of a UE, and are therefore listed @@ -257,7 +260,7 @@ configuration](../RRC/rrc-usage.md) as well for SIB configuration. * `do_CSIRS` (default 0): flag whether to use channel-state information reference signal (CSI-RS) * `do_SRS` (default 0): flag whether to use sounding reference signal (SRS) -* `do_SINR` (default 0): flag whether to enable CSI reporting of SSB-SINR (introduced in rel16) +* `CSI_report_type` (default `ssb_rsrp`): parameter to enable different CSI reporting (options: `ssb_rsrp`, `ssb_sinr` and `cri_rsrp`) Default setting of CSI reporting quantity is SSB-RSRP. * `min_rxtxtime` (default 2): minimum feedback time for UE to respond to transmissions (k1 and k2 in 3GPP spec) @@ -281,14 +284,17 @@ configuration](../RRC/rrc-usage.md) as well for SIB configuration. - `du_sibs` (default `[]`): list of SIBs to transmit in the cell. Currently, SIB19 (for NTN) is supported. -| DL MIMO |`do_CSIRS`|`do_SINR`| CSI report Quantity | -| ---------------------------- | -------- | ------- | --------------------------------------------------| -| OFF (pdsch_AntennaPorts = 1) | 0 | 0 | SSB-RSRP | -| OFF (pdsch_AntennaPorts = 1) | 0 | 1 | SSB-SINR | -| OFF (pdsch_AntennaPorts = 1) | 1 | 0 | CSI-Reference signal RSRP | -| OFF (pdsch_AntennaPorts = 1) | 1 | 1 | CSI-Reference signal SINR (not supported yet) | -| ON (pdsch_AntennaPorts > 1) | 1 | 0 | cri-RI-PMI-CQI | +| DL MIMO |`do_CSIRS`|`CSI_report_type`| CSI report Quantity | +| ------------------------------ | -------- | --------------- | --------------------------------------------------| +| any | any | `ssb_rsrp` | SSB-RSRP | +| any | 0 | `cri_rsrp` | SSB-RSRP (no CSI-RS configured) | +| any | 1 | `cri_rsrp` | CRI-RSRP | +| any | any | `ssb_sinr` | SSB-SINR | +| ON (`pdsch_AntennaPorts` > 1) | 1 | any | cri-RI-PMI-CQI | + +Note that activating `cri-RI-PMI-CQI` will result in that report to be produced +in addition to either `SSB-SINR`, `SSB-RSRP` or `CRI-RSRP`. DL-MIMO is configured using following parameters: `pdsch_AntennaPorts_XP` , `pdsch_AntennaPorts_N1` , `pdsch_AntennaPorts_N2`, `maxMIMO_layers` (see also [`RUNMODEM.md`](../RUNMODEM.md)) diff --git a/doc/NR_NFAPI_archi.md b/doc/NR_NFAPI_archi.md index 8065ddb4fc..8e6647f73c 100644 --- a/doc/NR_NFAPI_archi.md +++ b/doc/NR_NFAPI_archi.md @@ -161,9 +161,9 @@ unpack function is called. ## P7 DL Transmission by VNF DL messages are scheduled at the VNF, through gNB_dlsch_ulsch_scheduler(). gNB_dlsch_ulsch_scheduler() is called when -handling a SLOT.indication message in trigger_scheduler(). +handling a SLOT.indication message in phy_nr_slot_indication(). -The function trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind) calls the functions oai_nfapi_[DL P7 msg]_ +The function phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *slot_ind) calls the functions oai_nfapi_[DL P7 msg]_ req(), calling in turn call the send_p7_msg function pointer, which contain the logic to pack the message into a buffer and send it to the PNF. Finally, NR_UL_indication is called to process the other P7 messages received from the PNF that were put in theire @@ -215,7 +215,7 @@ bool nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_re graph TD softmodem_start[nr-softmodem init] --> P5_configuration[configure_nr_nfapi_vnf] --> transport_init[Transport mechanism init] --> send_first_msg[Send first P5 message to PNF] transport_init[Transport mechanism init] --> P5_recv_loop[P5 receive loop] -- P5 Message processing --> P5_recv_loop[P5 receive loop] - P5_recv_loop[P5 receive loop] -- Start.response callback called --> P7_config[P7 Configuration] --> P7_loop[P7 Loop] --> P7_msg_recv[P7 message received] --> call_vnf_handle_p7[Call vnf_nr_handle_p7_msg] --> hdr_unpack[Unpack header] --> call_specific_p7_handler[Call specific P7 message handler] --> slot_ind[Is a SLOT.indication?] -- Yes --> trig_scheduler[Call trigger_scheduler] --> gNB_ulsch_dlsch_sched[Call gNB_dlsch_ulsch_scheduler] --> send_p7_dl[Process and send P7 messages to PNF] --> call_ul_ind[Call NR_UL_indication] --> proc_p7[Process P7 messages in queue] --> P7_loop[P7 Loop] + P5_recv_loop[P5 receive loop] -- Start.response callback called --> P7_config[P7 Configuration] --> P7_loop[P7 Loop] --> P7_msg_recv[P7 message received] --> call_vnf_handle_p7[Call vnf_nr_handle_p7_msg] --> hdr_unpack[Unpack header] --> call_specific_p7_handler[Call specific P7 message handler] --> slot_ind[Is a SLOT.indication?] -- Yes --> trig_scheduler[Call phy_nr_slot_indication] --> gNB_ulsch_dlsch_sched[Call gNB_dlsch_ulsch_scheduler] --> send_p7_dl[Process and send P7 messages to PNF] --> call_ul_ind[Call NR_UL_indication] --> proc_p7[Process P7 messages in queue] --> P7_loop[P7 Loop] slot_ind[Is a SLOT.indication?] -- No --> put_queue[Put message in queue] --> P7_loop[P7 Loop]; diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index 1d7169f29f..5f95921a64 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -1243,8 +1243,8 @@ In OAI gNB, we support: ``` The reference specifications: -* `O-RAN.WG4.MP.0-v05.00` -* `O-RAN.WG4.MP-YANGs-v04.00` +* `O-RAN.WG4.MP.0-R004-v16.01` +* `O-RAN.WG4.MP-YANGs-R004-v16.01` ## M-plane prerequisites Before proceeding, please make sure you have a support for 7.2 interface, as described in [Prerequisites](#prerequisites). @@ -1366,7 +1366,7 @@ sudo ldconfig If you would like to install these libraries in the custom path, please replace `/usr/local` default path to e.g. `/opt/mplane-v2`. ## Benetel O-RU -Note: Only v1.2.2 RAN550 and RAN650 have been successfully tested. +Note: RAN550/650 v1.2.2 and v1.4.1 have been successfully tested. ### One time steps Connect to the RU as user `root`, enable the mplane service, and reboot: @@ -1400,6 +1400,8 @@ The reference DU configuration file for two Benetel RAN650: [gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf) In order to run gNB/DU with M-plane, we need to modify Tx gain `att_tx` in RU section, as well as the `fhi_72` section in the configuration file. + +**Important note: Benetel v1.4.1 requires only one VF if the same VLAN tag is used for both C-/U-planes. Otherwise, C-plane will not be properly configured. Benetel v1.2.2 will receive the C-plane packets no matter the DU MAC address value.** Example for one RU: ```bash fhi_72 = { @@ -1573,14 +1575,14 @@ sequenceDiagram
-4x4 MIMO and 100MHz BW with Benetel 550 RU example run +4x4 MIMO and 100MHz BW with Benetel 550 RU v1.2.2 example run ``` [HW] [MPLANE] RPC request to RU "192.168.80.9" = with username "oranbenetel" and port ID "830". [HW] [MPLANE] Successfuly connected to RU "192.168.80.9" with username "oranbenetel" and port ID "830". [HW] [MPLANE] RPC request to RU "192.168.80.9" = operational datastore. [HW] [MPLANE] Successfully retrieved operational datastore from RU "192.168.80.9". -[HW] [MPLANE] RU is already PTP synchronized. +[HW] [MPLANE] RU is in "LOCKED" sync state. [HW] [MPLANE] RPC request to RU "192.168.80.9" = with stream "NETCONF" and filter "(null)". [HW] [MPLANE] RPC reply = OK. [HW] [MPLANE] Successfully subscribed to all notifications from RU "192.168.80.9". @@ -2223,6 +2225,861 @@ sequenceDiagram ```
+
+4x4 MIMO and 100MHz BW with Benetel 550 RU v1.4.1 example run + +``` +[HW] [MPLANE] RPC request to RU "192.168.81.4" = with username "oranbenetel" and port ID "830". +[HW] [MPLANE] Successfuly connected to RU "192.168.81.4" with username "oranbenetel" and port ID "830". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = operational datastore. +[HW] [MPLANE] Successfully retrieved operational datastore from RU "192.168.81.4". +[HW] [MPLANE] RU is already PTP synchronized. +[HW] [MPLANE] RPC request to RU "192.168.81.4" = with stream "NETCONF" and filter "(null)". +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully subscribed to all notifications from RU "192.168.81.4". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = " +65535 +65535 +". +[HW] [MPLANE] Successfully updated supervision timer to (65535+65535)[s] for RU "192.168.81.4". +[HW] [MPLANE] Watchdog timer answer: + 2025-08-29T06:49:32+02:00 + +[HW] [MPLANE] Interface MTU 1500 unreliable/not correctly reported by Benetel O-RU, hardcoding to 9600. +[HW] [MPLANE] IQ bitwidth 16 unreliable/not correctly reported by Benetel O-RU, hardcoding to 9. +[HW] [MPLANE] Storing the following information to forward to xran: + RU MAC address 70:b3:d5:e1:5b:81 + MTU 9600 + IQ bitwidth 9 + PRACH offset 4 + DU port bitmask 61440 + Band sector bitmask 3840 + CC ID bitmask 240 + RU port ID bitmask 15 + DU port ID 0 + Band sector ID 0 + CC ID 0 + RU port ID 0 + max Tx gain 24.0 +[HW] [MPLANE] Successfully retrieved all the U-plane info - interface name, TX/RX carrier names, and TX/RX endpoint names. +[HW] [MPLANE] Successfully retreived all performance measurement names. +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-yang-metadata". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "yang". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-inet-types". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-yang-types". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-yang-schema-mount". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-yang-structure-ext". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-datastores". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "sysrepo". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-netconf-acm". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-factory-default". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "sysrepo-factory-default". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-yang-library". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "sysrepo-monitoring". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "sysrepo-plugind". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-netconf". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-netconf-with-defaults". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-netconf-notifications". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-origin". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-netconf-monitoring". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "ietf-netconf-nmda". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = for module "nc-notifications". +[HW] [MPLANE] [LIBYANG] ERROR: Data model "notifications" not found in local searchdirs. (path: (null)). +[HW] [MPLANE] [LIBYANG] ERROR: Loading "notifications" module failed. (path: (null)). +[HW] [MPLANE] [LIBYANG] ERROR: Parsing module "nc-notifications" failed. (path: (null)). +[HW] [MPLANE] Unable to load module "nc-notifications" from RU "192.168.81.4". +[HW] [MPLANE] Unable to load all yang modules from operational datastore for RU "192.168.81.4". Using yang models present in "models" subfolder. +[HW] [MPLANE] Successfully loaded all yang modules for RU "192.168.81.4". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = : + + + INTERFACE_0 + ianaift:l2vlan + true + 70:b3:d5:e1:5b:81 + eth0 + 3 + + + + 10 + 10 + 10 + + RX_ON_TIME + false + RU + COUNT + + + RX_EARLY + false + RU + COUNT + + + RX_LATE + false + RU + COUNT + + + RX_TOTAL + false + RU + COUNT + + + RX_ON_TIME_C + false + RU + COUNT + + + RX_EARLY_C + false + RU + COUNT + + + RX_LATE_C + false + RU + COUNT + + + TX_TOTAL + false + RU + COUNT + + + + ETH-INTERFACE + + PLANE_0 + + INTERFACE_0 + + 70:b3:d5:e1:5b:81 + 3 + 00:11:22:33:44:66 + + + + + + + PdschLink0 + PLANE_0 + TxArray0 + LowLevelTxEndpoint0 + + + PdschLink1 + PLANE_0 + TxArray1 + LowLevelTxEndpoint1 + + + PdschLink2 + PLANE_0 + TxArray2 + LowLevelTxEndpoint2 + + + PdschLink3 + PLANE_0 + TxArray3 + LowLevelTxEndpoint3 + + + PuschLink0 + PLANE_0 + RxArray0 + LowLevelRxEndpoint0 + + + PrachLink0 + PLANE_0 + RxArray0 + LowLevelRxPrachEndpoint0 + + + PuschLink1 + PLANE_0 + RxArray1 + LowLevelRxEndpoint1 + + + PrachLink1 + PLANE_0 + RxArray1 + LowLevelRxPrachEndpoint1 + + + PuschLink2 + PLANE_0 + RxArray2 + LowLevelRxEndpoint2 + + + PrachLink2 + PLANE_0 + RxArray2 + LowLevelRxPrachEndpoint2 + + + PuschLink3 + PLANE_0 + RxArray3 + LowLevelRxEndpoint3 + + + PrachLink3 + PLANE_0 + RxArray3 + LowLevelRxPrachEndpoint3 + + + LowLevelTxEndpoint0 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + 61440 + 3840 + 240 + 15 + 0 + + + + LowLevelTxEndpoint1 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + 61440 + 3840 + 240 + 15 + 1 + + + + LowLevelTxEndpoint2 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + 61440 + 3840 + 240 + 15 + 2 + + + + LowLevelTxEndpoint3 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + 61440 + 3840 + 240 + 15 + 3 + + + + LowLevelRxEndpoint0 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + KHZ_30 + 0 + + + 61440 + 3840 + 240 + 15 + 0 + + true + + + LowLevelRxPrachEndpoint0 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + KHZ_30 + 0 + + + 61440 + 3840 + 240 + 15 + 4 + + true + + + LowLevelRxEndpoint1 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + KHZ_30 + 0 + + + 61440 + 3840 + 240 + 15 + 1 + + true + + + LowLevelRxPrachEndpoint1 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + KHZ_30 + 0 + + + 61440 + 3840 + 240 + 15 + 5 + + true + + + LowLevelRxEndpoint2 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + KHZ_30 + 0 + + + 61440 + 3840 + 240 + 15 + 2 + + true + + + LowLevelRxPrachEndpoint2 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + KHZ_30 + 0 + + + 61440 + 3840 + 240 + 15 + 6 + + true + + + LowLevelRxEndpoint3 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + KHZ_30 + 0 + + + 61440 + 3840 + 240 + 15 + 3 + + true + + + LowLevelRxPrachEndpoint3 + + 9 + STATIC + + 193 + NORMAL + 352 + 288 + 0 + + KHZ_30 + 0 + + + 61440 + 3840 + 240 + 15 + 7 + + true + + + TxArray0 + 623334 + 3350010000 + 100000000 + ACTIVE + 24.0 + 0 + 0 + + + TxArray1 + 623334 + 3350010000 + 100000000 + ACTIVE + 24.0 + 0 + 0 + + + TxArray2 + 623334 + 3350010000 + 100000000 + ACTIVE + 24.0 + 0 + 0 + + + TxArray3 + 623334 + 3350010000 + 100000000 + ACTIVE + 24.0 + 0 + 0 + + + RxArray0 + 623334 + 3350010000 + 100000000 + ACTIVE + 0 + 0 + 0.0 + 0 + + + RxArray1 + 623334 + 3350010000 + 100000000 + ACTIVE + 0 + 0 + 0.0 + 0 + + + RxArray2 + 623334 + 3350010000 + 100000000 + ACTIVE + 0 + 0 + 0.0 + 0 + + + RxArray3 + 623334 + 3350010000 + 100000000 + ACTIVE + 0 + 0 + 0.0 + 0 + + + +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully edited the candidate datastore for RU "192.168.81.4". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = candidate datastore. +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully validated candidate datastore for RU "192.168.81.4". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = candidate datastore. +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully commited configuration into running datastore for RU "192.168.81.4". +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.335228846+00:00) +{ + "o-ran-uplane-conf:rx-array-carriers-state-change": { + "rx-array-carriers": [ + { + "name": "RxArray0", + "state": "BUSY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.368360865+00:00) +{ + "o-ran-uplane-conf:rx-array-carriers-state-change": { + "rx-array-carriers": [ + { + "name": "RxArray1", + "state": "BUSY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.414703766+00:00) +{ + "o-ran-uplane-conf:rx-array-carriers-state-change": { + "rx-array-carriers": [ + { + "name": "RxArray2", + "state": "BUSY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.452921618+00:00) +{ + "o-ran-uplane-conf:rx-array-carriers-state-change": { + "rx-array-carriers": [ + { + "name": "RxArray3", + "state": "BUSY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.471419021+00:00) +{ + "ietf-netconf-notifications:netconf-config-change": { + "changed-by": { + "username": "root", + "session-id": 0 + }, + "datastore": "running", + "edit": [ + { + "target": "/ietf-interfaces:interfaces/interface[name='INTERFACE_0']", + "operation": "create" + }, + { + "target": "/ietf-interfaces:interfaces/interface[name='INTERFACE_0']/name", + "operation": "create" + }, +... +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.678251110+00:00) +{ + "o-ran-uplane-conf:tx-array-carriers-state-change": { + "tx-array-carriers": [ + { + "name": "TxArray0", + "state": "BUSY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.715498360+00:00) +{ + "o-ran-uplane-conf:tx-array-carriers-state-change": { + "tx-array-carriers": [ + { + "name": "TxArray1", + "state": "BUSY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.830268973+00:00) +{ + "o-ran-uplane-conf:tx-array-carriers-state-change": { + "tx-array-carriers": [ + { + "name": "TxArray2", + "state": "BUSY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:19.853387657+00:00) +{ + "o-ran-uplane-conf:tx-array-carriers-state-change": { + "tx-array-carriers": [ + { + "name": "TxArray3", + "state": "BUSY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.515262267+00:00) +{ + "o-ran-uplane-conf:rx-array-carriers-state-change": { + "rx-array-carriers": [ + { + "name": "RxArray0", + "state": "READY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.535692962+00:00) +{ + "o-ran-uplane-conf:rx-array-carriers-state-change": { + "rx-array-carriers": [ + { + "name": "RxArray1", + "state": "READY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.557423764+00:00) +{ + "o-ran-uplane-conf:rx-array-carriers-state-change": { + "rx-array-carriers": [ + { + "name": "RxArray2", + "state": "READY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.579066867+00:00) +{ + "o-ran-uplane-conf:rx-array-carriers-state-change": { + "rx-array-carriers": [ + { + "name": "RxArray3", + "state": "READY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.604192995+00:00) +{ + "o-ran-uplane-conf:tx-array-carriers-state-change": { + "tx-array-carriers": [ + { + "name": "TxArray0", + "state": "READY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.629830498+00:00) +{ + "o-ran-uplane-conf:tx-array-carriers-state-change": { + "tx-array-carriers": [ + { + "name": "TxArray1", + "state": "READY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.651062685+00:00) +{ + "o-ran-uplane-conf:tx-array-carriers-state-change": { + "tx-array-carriers": [ + { + "name": "TxArray2", + "state": "READY" + } + ] + } +} + +[HW] [MPLANE] Received notification from RU "192.168.81.4" at (2025-08-28T10:37:24.672865767+00:00) +{ + "o-ran-uplane-conf:tx-array-carriers-state-change": { + "tx-array-carriers": [ + { + "name": "TxArray3", + "state": "READY" + } + ] + } +} + +[HW] [MPLANE] RU "192.168.81.4" is now ready. +[HW] [MPLANE] RPC request to RU "192.168.81.4" = : + + 10 + 10 + 10 + + RX_ON_TIME + true + RU + COUNT + + + RX_EARLY + true + RU + COUNT + + + RX_LATE + true + RU + COUNT + + + RX_TOTAL + true + RU + COUNT + + + RX_ON_TIME_C + true + RU + COUNT + + + RX_EARLY_C + true + RU + COUNT + + + RX_LATE_C + true + RU + COUNT + + + TX_TOTAL + true + RU + COUNT + + + +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully edited the candidate datastore for RU "192.168.81.4". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = candidate datastore. +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully validated candidate datastore for RU "192.168.81.4". +[HW] [MPLANE] RPC request to RU "192.168.81.4" = candidate datastore. +[HW] [MPLANE] RPC reply = OK. +[HW] [MPLANE] Successfully commited configuration into running datastore for RU "192.168.81.4". +[HW] [MPLANE] Sucessfully activated PM after start-up procedure for RU "192.168.81.4". +``` +
Note: If you wish to run the fronthaul without M-plane, no need for recompilation, as the library `oran_fhlib_5g` already exists. The only mandatory step is to link `oran_fhlib_5g` to `oai_transpro` library. diff --git a/doc/SW-archi-graph.md b/doc/SW-archi-graph.md index a3397ed297..467ce5cd04 100644 --- a/doc/SW-archi-graph.md +++ b/doc/SW-archi-graph.md @@ -1,74 +1,97 @@ +This document is a high-level overview over the L1 threading mechanism. + ```mermaid flowchart TB - A[ru_thread] --> RFin>block rx_rf] --> feprx - feprx --> half-slot --> end_feprx - feprx --> second-thread -- block_end_feprx --> end_feprx>feprx] - end_feprx --> rx_nr_prach_ru -rx_nr_prach_ru -- block_queue_singleton --> resp_L1>resp L1] -resp_L1 -- async launch --> rx_func -resp_L1 -- immediate return --> RFin - -subgraph rxfunc -rx_func_implem[rx_func] - subgraph rxfuncbeg - handle_nr_slot_ind - --> rnti_to_remove-mgmt - --> L1_nr_prach_procedures - --> apply_nr_rotation_RX - end - subgraph phy_procedures_gNB_uespec_RX - fill_ul_rb_mask - --> pucch(decode each gNB->pucch) - -->nr_fill_ul_indication - --> nr_ulsch_procedures - --> nr_ulsch_decoding - --> segInParallel[[all segments decode in parallel]] - --> barrier_end_of_ulsch_decoding - end - subgraph NR_UL_indication - handle_nr_rach - --> handle_nr_uci - --> handle_nr_ulsch - subgraph gNB_dlsch_ulsch_scheduler - run_pdcp - --> schedule_xxxx - end - handle_nr_ulsch --> gNB_dlsch_ulsch_scheduler - subgraph NR_Schedule_response - L1_tx_free3>L1_tx_free] - --> handle_nr_nfapi_xxx_pdu - --> sendTxFilled((L1_tx_filled)) - --> nr_fill_ul_xxx - --> nr_fill_prach - end - gNB_dlsch_ulsch_scheduler --> NR_Schedule_response - end - rx_func_implem --> rxfuncbeg - rxfuncbeg --> phy_procedures_gNB_uespec_RX -phy_procedures_gNB_uespec_RX --> NR_UL_indication --- block_queue_block_PNF_monolithic --> L1_tx_free2>L1 tx filled] --- async launch --> tx_func -L1_tx_free2 -- send_msg --> rsp((resp_L1)) -end -rx_func --> rxfunc - - -subgraph tx_func - direction LR - subgraph phy_procedures_gNB_TX - dcitop[nr_generate dci top] - --> nr_generate_csi_rs - --> apply_nr_rotation_TX - -- send_msg --> end_tx_func((L1_tx_out)) - end - subgraph tx_reorder_thread - L1_tx_out>L1_tx_out] - --> reorder{re order} --> reorder - reorder --> ru_tx_func - reorder --> L1_tx_free((L1_tx_free)) - ru_tx_func --> feptx_prec - --> feptx_ofdm - end -end - + ru_thread --> RFin[block rx_rf] --> UL{is UL slot?} + UL -- yes --> wait_free_rx_tti --> fep_rx --> rx_nr_prach_ru --> msg:L1_tx_out + UL -- no --> msg:L1_tx_out + msg:L1_tx_out -- asnyc launch --> L1_tx_thread + msg:L1_tx_out --> RFin ``` + +The main thread is `ru_thread()`. It blocks on reception of radio samples +(either time domain or frequency domain). In the case of an UL slot, it waits +that no more than N UL jobs are scheduled (via `wait_free_rx_tti()`, which +waits on queue `L1_rx_out`, cf. the RX L1 processing further below). Then: + +- if the radio is time domain-based, it performs RX front-end processing (RX + FEP -> `fep_rx()`, i.e. DFT) to reach a frequency domain representation of + the RX signal, as well as does DFT for PRACH. +- if the radio is frequency domain-based, nothing is done. + +Afterwards, it triggers TX processing by pushing a message into the FIFO queue +`L1_tx_out`, which asynchronously starts a TX job in `L1_tx_thread()` (see +below). After that, it blocks again on reception on the radio. + + +```mermaid +flowchart TB + L1_tx_thread --> TX_in[block L1_tx_out] --> NR_slot_indication + + subgraph tx_func + + NR_slot_indication --> msg:resp_L1 --> phy_procedures_gNB_tx --> ru_tx_func + NR_slot_indication["run the scheduler: + - monolithic: run_scheduler_monolithic() + - nFAPI: send indication via pnf_send_slot_ind()"] + msg:resp_L1 -- async launch --> L1_RX_thread + end + ru_tx_func --> TX_in +``` + +The `L1_tx_thread()` processes individual TX jobs sequentially, by waiting for +new messages on queue `L1_tx_out`, signalling individual TX jobs. For each +message, it calls `tx_func()` which does in order: + +- run the scheduler through `NR_slot_indication`, which corresponds to a + "Slot.indication" in FAPI parlance. This runs the scheduler, and schedules a + given slot (either downlink, uplink, or both). +- trigger RX processing by pushing a message into the FIFO queue `resp_L1`, + asynchronously starting an RX job in `L1_rx_thread()` (see below). +- process the current L1 TX job through `phy_procedures_gNB_tx()` +- write to the radio board via `ru_tx_func()`. + +After these steps, `tx_func()` return to `L1_tx_thread()`, which will wait for +the next TX job. + +```mermaid +flowchart TB + L1_rx_thread --> RX_in[block resp_L1] --> L1_nr_prach_proc + + subgraph rx_func + + L1_nr_prach_proc --> phase_comp{apply phase comp.?} + phase_comp -- yes --> apply_nr_rotation --> phy_procedures_gNB_uespec_RX + phase_comp -- no --> phy_procedures_gNB_uespec_RX + phy_procedures_gNB_uespec_RX --> NR_ul_indication --> msg:L1_rx_out + NR_ul_indication["run the scheduler: NR_UL_indication()"] + msg:L1_rx_out -- async signal free --> ru_thread + end + msg:L1_rx_out --> RX_in +``` + +The `L1_rx_thread()` processes individual RX jobs sequentially. It waits for a +new RX job through the queue `resp_L1`, and then calls `rx_func()`, which does +in order: + +- run PRACH processing via `L1_nr_prach_proc()` +- optionally apply rotation to the RX signal if phase compensation is to be + applied +- run the current L1 RX job through (`phy_procedures_gNB_uespec_RX()`), which + notably includes PUCCH, PUSCH, SRS processing +- call the scheduler through `NR_ul_indication()`, which corresponds to FAPI + uplink messages (e.g., `RX_data.indication`, `CRC.indication`, + `UCI.indication` etc.) +- signal completion via FIFO queue `L1_rx_out()`, which tells `ru_thread()` + that RX processing finished. + +The signalling of scheduler data is done through a variable `UL_INFO`, which is +filled by `L1_nr_prach_proc()` (for PRACH) and `phy_procedures_gNB_uespec_RX()` +(for PUCCH, PUSCH, SRS). + +After these steps, `rx_func()` returns to `L1_rx_thread()`, which will wait the +next RX job. + +Note that while individual TX (RX) jobs are run sequentially through +`L1_tx_thread()` (`L1_rx_thread()`), both TX and RX processing run in +parallel. diff --git a/doc/SW_archi.md b/doc/SW_archi.md index 9c3736ac2a..78004a5a74 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -177,7 +177,7 @@ it would be better to call **NR_UL_indication()** now instead of before (on prev * nr_common_signal_procedures() generate common signals {: .func4} -* nr_generate_dci_top() +* nr_generate_dci() generate DCI: the scheduling informtion for each UE in both DL and UL {: .func4} * nr_generate_pdsch() @@ -325,7 +325,7 @@ The PDCP implementation is secured by a general mutex, akin to the design of the Initialization of the PDCP layer follows a structure similar to that of the RLC layer. The function `nr_pdcp_layer_init()` initializes PDCP, while a second initialization function, `pdcp_module_init()`, must also be invoked. -To manage UE connections, `nr_pdcp_add_srbs()` is employed for adding UE SRBs in PDCP, while `nr_pdcp_remove_UE()` is used for their removal. Similarly, `nr_pdcp_add_drbs()` adds UE DRBs in PDCP, with `nr_pdcp_remove_UE()` handling their removal. +To manage UE connections, `nr_pdcp_add_srbs()` is employed for adding UE SRBs in PDCP, while `nr_pdcp_remove_UE()` is used for their removal. Similarly, `nr_pdcp_add_drb()` adds UE DRB in PDCP, with `nr_pdcp_remove_UE()` handling their removal. ## PDCP Tx flow diff --git a/doc/nfapi.md b/doc/nfapi.md index 214aa2799f..b901b15269 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -194,14 +194,19 @@ Clone the Radisys repository (We're currently using the `oai_integration` branch git clone https://gerrit.o-ran-sc.org/r/o-du/l2 -b oai-integration -Build the O-DU +Build the O-DU (More details can be found in O-RAN's documentation page [here](https://docs.o-ran-sc.org/projects/o-ran-sc-o-du-l2/en/latest/user-guide.html#i-execution-on-locally-compiling-o-du-high-source-code)) cd ~/l2/build/odu make clean_all;make odu PHY=INTEL_L1 MACHINE=BIT64 MODE=TDD;make cu_stub NODE=TEST_STUB MACHINE=BIT64 MODE=TDD;make ric_stub NODE=TEST_STUB MACHINE=BIT64 MODE=TDD +The O-DU requires some virtual interfaces to be setup in order to enable communication between the O-DU, CU_stub and RIC_stub Setup local interfaces for the cu_stub, ric_stub and o_du +The IP addresses shown match the ones specified in OSC ODU configuration file, found in /build/config/tdd_odu_config.xml +The parameters referenced are , and - sudo ifconfig enp7s0:ODU "192.168.130.81" && sudo ifconfig enp7s0:CU_STUB "192.168.130.82" && sudo ifconfig enp7s0:RIC_STUB "192.168.130.80" + sudo ifconfig :ODU "192.168.130.81" + sudo ifconfig :CU_STUB "192.168.130.82" + sudo ifconfig :RIC_STUB "192.168.130.80" Run cu_stu and ric_stub in separate terminals @@ -242,10 +247,10 @@ To see the (any) periodical output at the PNF, define `NFAPI_TRACE_LEVEL=info`. This output shows: ``` -41056.739654 [I] 3556767424: pnf_p7_slot_ind: [P7:1] msgs ontime 489 thr DL 0.06 UL 0.01 msg late 0 (vtime) +41056.739654 [I] 3556767424: nr_pnf_p7_get_msgs: [P7:1] msgs ontime 489 thr DL 0.06 UL 0.01 msg late 0 (vtime) ``` -The first numbers are timestamps. `pnf_p7_slot_ind` is the name of the +The first numbers are timestamps. `nr_pnf_p7_get_msgs` is the name of the functions that prints the output. `[P7:1]` refers to the fact that these are information on P7, of PHY ID 1. Finally, `msgs ontime 489` means that in the last window (since the last print), 489 messages arrived at the PNF in total. diff --git a/doc/rach_processing_in_gNB.md b/doc/rach_processing_in_gNB.md new file mode 100644 index 0000000000..5c15cf0812 --- /dev/null +++ b/doc/rach_processing_in_gNB.md @@ -0,0 +1,24 @@ +The gNB RACH processing + +1. Collect I/Q samples +The gNB/ru main loop, in ru_thread() +If there is rach occasions in this slot +this main loop calls rx_nr_prach_ru() that stores the I/Q samples in the prach_item_t context + +2.process the samples +L1_rx_thread() has received slot indication by msg on queue resp_L1, it calls rx_func() => L1_nr_prach_procedures() +L1_nr_prach_procedures() fills nfapi_nr_rach_indication_t structure from result of rx_nr_prach() that process the content of rxsigF[prachOccasion][aa] +rx_func() sends the decoded rach to upper processing by call to NR_UL_indication() that calls handle_nr_rach() => nr_initiate_ra_proc() + +nr_initiate_ra_proc() creates a UE context if it needs, then sets UE.ra.ra_state to what it should do + +3. send the RACH DL +tx_func() that is launched by L1_tx_thread() as it gets L1_tx_out msg (from main loop in 1.) +tx_func()=>run_scheduler_monolithic()=>gNB_dlsch_ulsch_scheduler()=>nr_scheduler_RA() +nr_scheduler_RA() process all existing UE contexts, to see it it has to schedule a RACH DL + +4. global synchronisation +resp_L1 msg for (2.) is created in tx_func() that is launched by L1_tx_thread() (see3.) when it receives slot indication as it gets L1_tx_out msg +this msg is sent by the main loop (see 1.) +tx_func()=>run_scheduler_monolithic()=>nr_schedule_response ()=>nr_schedule_ul_tti_req ()=> nr_schedule_rx_prach() +writes in the triggering structure to (1.) that it will have to run rx_nr_prach_ru() in a given future slot diff --git a/docker/Dockerfile.nakaolab.test b/docker/Dockerfile.nakaolab.test new file mode 100644 index 0000000000..1ac5af2768 --- /dev/null +++ b/docker/Dockerfile.nakaolab.test @@ -0,0 +1,56 @@ +FROM ran-base-temp:latest AS ran-build +ARG BUILD_OPTION + +RUN rm -Rf /oai-ran +WORKDIR /oai-ran +COPY . . + +# build all targets so final targets can be created afterwards +RUN /bin/sh oaienv && \ + cd cmake_targets && \ + mkdir -p log && \ + ./build_oai -c --ninja \ + --gNB --RU --nrUE -w SIMU\ + --build-lib "telnetsrv enbscope uescope nrscope" \ + -w USRP -t Ethernet \ + --build-e2 --cmake-opt -DKPM_VERSION=KPM_V2_03 --cmake-opt -DE2AP_VERSION=E2AP_V2 \ + --noavx512 \ + --build-tool-opt -k10 \ + --cmake-opt -DCMAKE_C_FLAGS="-Werror" --cmake-opt -DCMAKE_CXX_FLAGS="-Werror" $BUILD_OPTION && \ + echo "---- ldd on executables ----" && \ + ldd ran_build/build/*softmodem* ran_build/build/nr-cuup ran_build/build/oairu && \ + echo "---- ldd on shared libraries ----" && \ + ldd ran_build/build/*.so + +RUN set -eux; \ + apt-get update; \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + ca-certificates curl wget iproute2 iputils-ping dnsutils jq \ + iperf iperf3 ffmpeg gdb\ + nghttp2-client || true; \ + if ! command -v h2load >/dev/null 2>&1; then \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends nghttp2 || true; \ + fi; \ + # Try to install sipp from apt; if unavailable, build from source + if apt-cache show sipp >/dev/null 2>&1; then \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends sipp; \ + else \ + echo "sipp not in apt, building from source..."; \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential cmake git libncurses5-dev libpcap-dev libssl-dev libpcre3-dev; \ + git clone --depth=1 https://github.com/SIPp/sipp.git /tmp/sipp; \ + cd /tmp/sipp; cmake -DENABLE_SSL=1 -DENABLE_PCAP=1 -DCMAKE_BUILD_TYPE=Release .; \ + make -j"$(nproc)"; make install; strip /usr/local/bin/sipp || true; \ + rm -rf /tmp/sipp; \ + fi; \ + rm -rf /var/lib/apt/lists/* + +# Traffic runner +COPY tools/scripts/traffic_runner.sh /usr/local/bin/traffic_runner +RUN chmod +x /usr/local/bin/traffic_runner + +COPY flexric/etc/flexric /usr/local/etc/flexric/ +COPY flexric/lib/flexric /usr/local/lib/flexric/ +RUN echo "/usr/local/lib/flexric" > /etc/ld.so.conf.d/flexric.conf && ldconfig + +ENTRYPOINT ["/bin/bash"] \ No newline at end of file diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 77fdb21eb4..6ff535fb5b 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -151,7 +151,6 @@ double cpuf; bool sdap_data_req(protocol_ctxt_t *ctxt_p, const ue_id_t ue_id, const srb_flag_t srb_flag, - const rb_id_t rb_id, const mui_t mui, const confirm_t confirm, const sdu_size_t sdu_buffer_size, @@ -195,13 +194,7 @@ void handle_nr_srs_measurements(const module_id_t module_id, void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); /* TODO these declarations are to be removed */ -void nr_schedule_dl_tti_req(void) {}; -void nr_schedule_ul_dci_req() {}; -void nr_schedule_tx_req() {}; -void nr_schedule_ul_tti_req() {}; void nr_slot_select() {}; -void NR_UL_indication(NR_UL_IND_t *UL_INFO) {}; -void gNB_dlsch_ulsch_scheduler() {}; /*------------------------------------------------------------------------*/ diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index b212ceb3f1..f36bdde2b5 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -156,10 +156,6 @@ extern char uecap_xer[1024]; char uecap_xer_in=0; /* TODO these declarations are to be removed */ -void nr_schedule_dl_tti_req(void) {}; -void nr_schedule_ul_dci_req() {}; -void nr_schedule_tx_req() {}; -void nr_schedule_ul_tti_req() {}; void nr_slot_select() {}; /* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 403f78ddb3..df2f633d95 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -51,8 +51,9 @@ static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args) printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip ); - fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL); - memcpy(args.libs_dir, oai_args.sm_dir, 128); + fr_args_t args = {0}; + memcpy(args.ip, oai_args.ip, FR_IP_ADDRESS_LEN); + memcpy(args.libs_dir, oai_args.sm_dir, FR_CONF_FILE_LEN); sleep(1); @@ -150,7 +151,8 @@ int main(int argc, char **argv) time_manager_start(tick_functions, tick_functions_count, TIME_SOURCE_REALTIME); // strdup to put the sring in the core file for post mortem identification - LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION)); + char *v = strdup(OAI_PACKAGE_VERSION); + LOG_I(HW, "Version: %s\n", v); set_softmodem_sighandler(); itti_init(TASK_MAX, tasks_info); int rc; @@ -189,6 +191,8 @@ int main(int argc, char **argv) time_manager_finish(); + free(v); + logClean(); printf("Bye.\n"); return 0; diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 505adf825c..94fc22cf46 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -55,7 +55,6 @@ #include "PHY/defs_gNB.h" #include "PHY/defs_nr_common.h" #include "PHY/impl_defs_nr.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "SCHED_NR/phy_frame_config_nr.h" #include "SCHED_NR/sched_nr.h" #include "assertions.h" @@ -65,7 +64,6 @@ #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi_nr_interface_scf.h" #include "notified_fifo.h" -#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #include "thread-pool.h" #include "time_meas.h" #include "utils.h" @@ -82,8 +80,6 @@ static void tx_func(processingData_L1tx_t *info) int slot_rx = info->slot_rx; LOG_D(NR_PHY, "%d.%d running tx_func\n", frame_tx, slot_tx); PHY_VARS_gNB *gNB = info->gNB; - module_id_t module_id = gNB->Mod_id; - uint8_t CC_id = gNB->CC_id; NR_IF_Module_t *ifi = gNB->if_inst; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; @@ -94,15 +90,22 @@ static void tx_func(processingData_L1tx_t *info) reset_active_ulsch(gNB, frame_rx); } + clear_slot_beamid(gNB, slot_tx); + + nfapi_nr_slot_indication_scf_t ind = {.sfn = frame_tx, .slot = slot_tx}; start_meas(&gNB->slot_indication_stats); - ifi->NR_slot_indication(module_id, CC_id, frame_tx, slot_tx); + // this variable is very big (multiple MB), so we put it into static storage + // to not overflow the stack while still having it in local (function) scope + // also, tx_func() is only executed by one thread, serially + static NR_Sched_Rsp_t sched_response; + ifi->NR_slot_indication(&ind, &sched_response); stop_meas(&gNB->slot_indication_stats); - gNB->msgDataTx->timestamp_tx = info->timestamp_tx; - info = gNB->msgDataTx; + info->gNB = gNB; // At this point, MAC scheduler just ran, including scheduling // PRACH/PUCCH/PUSCH, so trigger RX chain processing + nr_save_ul_tti_req(gNB, &sched_response.UL_tti_req); LOG_D(NR_PHY, "Trigger RX for %d.%d\n", frame_rx, slot_rx); notifiedFIFO_elt_t *res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->resp_L1, NULL); processingData_L1_t *syncMsg = NotifiedFifoData(res); @@ -114,9 +117,18 @@ static void tx_func(processingData_L1tx_t *info) pushNotifiedFIFO(&gNB->resp_L1, res); int tx_slot_type = nr_slot_select(cfg, frame_tx, slot_tx); - if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx || IS_SOFTMODEM_RFSIM) { + // TODO check for analog_beam_list is a workaround while no beam API for beam + // selection is implemented + if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx || IS_SOFTMODEM_RFSIM + || cfg->analog_beamforming_ve.analog_beam_list) { start_meas(&info->gNB->phy_proc_tx); - phy_procedures_gNB_TX(info, frame_tx, slot_tx, 1); + phy_procedures_gNB_TX(info->gNB, + &sched_response.DL_req, + &sched_response.TX_req, + &sched_response.UL_dci_req, + frame_tx, + slot_tx, + 1); PHY_VARS_gNB *gNB = info->gNB; processingData_RU_t syncMsgRU; @@ -128,14 +140,6 @@ static void tx_func(processingData_L1tx_t *info) ru_tx_func((void *)&syncMsgRU); stop_meas(&info->gNB->phy_proc_tx); } - - if (NFAPI_MODE == NFAPI_MONOLITHIC) { - /* this thread is done with the sched_info, decrease the reference counter. - * This only applies for monolithic; in the PNF, the memory is allocated in - * a ring buffer that should never be overwritten (one frame duration). */ - LOG_D(NR_PHY, "Calling deref_sched_response for id %d (tx_func) in %d.%d\n", info->sched_response_id, frame_tx, slot_tx); - deref_sched_response(info->sched_response_id); - } } void *L1_rx_thread(void *arg) @@ -147,7 +151,9 @@ void *L1_rx_thread(void *arg) if (res == NULL) break; processingData_L1_t *info = (processingData_L1_t *)NotifiedFifoData(res); + start_meas(&gNB->l1_rx_proc); rx_func(info); + stop_meas(&gNB->l1_rx_proc); delNotifiedFIFO_elt(res); } return NULL; @@ -161,7 +167,9 @@ void *L1_tx_thread(void *arg) { if (res == NULL) // stopping condition, happens only when queue is freed break; processingData_L1tx_t *info = (processingData_L1tx_t *)NotifiedFifoData(res); + start_meas(&gNB->l1_tx_proc); tx_func(info); + stop_meas(&gNB->l1_tx_proc); delNotifiedFIFO_elt(res); } return NULL; @@ -190,17 +198,17 @@ static void rx_func(processingData_L1_t *info) //WA: comment rotation in tx/rx if (gNB->phase_comp) { //apply the rx signal rotation here - int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; + int soffset = (slot_rx % RU_RX_SLOT_DEPTH) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; for (int bb = 0; bb < gNB->common_vars.num_beams_period; bb++) { for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { - apply_nr_rotation_RX(&gNB->frame_parms, - gNB->common_vars.rxdataF[bb][aa], - gNB->frame_parms.symbol_rotation[1], - slot_rx, - gNB->frame_parms.N_RB_UL, - soffset, - 0, - gNB->frame_parms.Ncp == EXTENDED ? 12 : 14); + const uint max_symb = (gNB->frame_parms.Ncp == EXTENDED) ? 12 : 14; + for (int sym = 0; sym < max_symb; sym++) + apply_nr_rotation_symbol_RX(&gNB->frame_parms, + gNB->common_vars.rxdataF[bb][aa] + soffset + sym * gNB->frame_parms.ofdm_symbol_size, + gNB->frame_parms.symbol_rotation[1], + gNB->frame_parms.N_RB_UL, + slot_rx, + sym); } } } @@ -226,6 +234,8 @@ static void rx_func(processingData_L1_t *info) static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size_t outputlen) { const char *begin = output; const char *end = output + outputlen; + output += print_meas_log(&gNB->l1_tx_proc, "L1 Tx job", NULL, NULL, output, end - output); + output += print_meas_log(&gNB->l1_rx_proc, "L1 Rx job", NULL, NULL, output, end - output); output += print_meas_log(&gNB->phy_proc_tx, "L1 Tx processing", NULL, NULL, output, end - output); output += print_meas_log(&gNB->dlsch_encoding_stats, "DLSCH encoding", NULL, NULL, output, end - output); output += print_meas_log(&gNB->dlsch_scrambling_stats, "DLSCH scrambling", NULL, NULL, output, end-output); @@ -239,7 +249,6 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size output += print_meas_log(&gNB->ul_indication_stats, "UL Indication", NULL, NULL, output, end - output); output += print_meas_log(&gNB->slot_indication_stats, "Slot Indication", NULL, NULL, output, end - output); output += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL, output, end - output); - output += print_meas_log(&gNB->schedule_response_stats, "Schedule Response", NULL, NULL, output, end - output); output += print_meas_log(&gNB->rx_prach, "PRACH RX", NULL, NULL, output, end - output); if (ru->feprx) output += print_meas_log(&ru->ofdm_demod_stats, "feprx", NULL, NULL, output, end - output); @@ -290,6 +299,8 @@ void *nrL1_stats_thread(void *param) { return NULL; } + reset_meas(&gNB->l1_tx_proc); + reset_meas(&gNB->l1_rx_proc); reset_meas(&gNB->phy_proc_tx); reset_meas(&gNB->dlsch_encoding_stats); reset_meas(&gNB->phy_proc_rx); @@ -299,20 +310,22 @@ void *nrL1_stats_thread(void *param) { reset_meas(&gNB->ul_indication_stats); reset_meas(&gNB->slot_indication_stats); reset_meas(&gNB->rx_pusch_stats); - reset_meas(&gNB->schedule_response_stats); reset_meas(&gNB->dlsch_scrambling_stats); reset_meas(&gNB->dlsch_modulation_stats); reset_meas(&gNB->dlsch_resource_mapping_stats); reset_meas(&gNB->dlsch_precoding_stats); while (!oai_exit) { sleep(1); + if (ftruncate(fileno(fd), 0) != 0 || fseek(fd, 0, SEEK_SET) != 0) { + LOG_E(NR_MAC, "error while writing nrL1_stats.log: %d, %s\n", errno, strerror(errno)); + break; + } dump_nr_I0_stats(fd,gNB); dump_pdsch_stats(fd,gNB); dump_pusch_stats(fd,gNB); dump_L1_meas_stats(gNB, ru, output, L1STATSSTRLEN); fprintf(fd,"%s\n",output); fflush(fd); - fseek(fd,0,SEEK_SET); } fclose(fd); return(NULL); @@ -344,14 +357,6 @@ void init_gNB_Tpool(int inst) // create the TX thread responsible for TX processing start event (L1_tx_out msg queue), then launch tx_func() threadCreate(&gNB->L1_tx_thread, L1_tx_thread, (void *)gNB, "L1_tx_thread", gNB->L1_tx_thread_core, OAI_PRIORITY_RT_MAX); - notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, NULL); - processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx); - memset(msgDataTx, 0, sizeof(processingData_L1tx_t)); - init_DLSCH_struct(gNB, msgDataTx); - memset(msgDataTx->ssb, 0, 64 * sizeof(NR_gNB_SSB_t)); - // this will be removed when the msgDataTx is not necessary anymore - gNB->msgDataTx = msgDataTx; - if (!IS_SOFTMODEM_NOSTATS) threadCreate(&proc->L1_stats_thread, nrL1_stats_thread, (void *)gNB, "L1_stats", -1, OAI_PRIORITY_RT_LOW); } @@ -384,10 +389,8 @@ void init_eNB_afterRU(void) int aa = 0; for (int ru_id = 0; ru_id < gNB->num_RU; ru_id++) { AssertFatal(gNB->RU_list[ru_id]->common.rxdataF != NULL, "RU %d : common.rxdataF is NULL\n", gNB->RU_list[ru_id]->idx); - AssertFatal(gNB->RU_list[ru_id]->prach_rxsigF != NULL, "RU %d : prach_rxsigF is NULL\n", gNB->RU_list[ru_id]->idx); for (int i = 0; i < gNB->RU_list[ru_id]->nb_rx; aa++, i++) { - LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n", gNB->RU_list[ru_id]->idx, i, aa); - gNB->prach_vars.rxsigF[aa] = gNB->RU_list[ru_id]->prach_rxsigF[0][i]; + LOG_I(PHY, "Attaching RU %d antenna %d to gNB antenna %d\n", gNB->RU_list[ru_id]->idx, i, aa); for (int b = 0; b < gNB->RU_list[ru_id]->num_beams_period; b++) { int idx = i + b * gNB->RU_list[ru_id]->nb_rx; gNB->common_vars.rxdataF[b][aa] = (c16_t *)gNB->RU_list[ru_id]->common.rxdataF[idx]; @@ -430,7 +433,6 @@ void init_gNB() AssertFatal((gNB->if_inst = NR_IF_Module_init(inst)) != NULL, "Cannot register interface"); LOG_I(NR_PHY, "Registered with MAC interface module (%p)\n", gNB->if_inst); - gNB->if_inst->NR_Schedule_response = nr_schedule_response; gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; gNB->prach_energy_counter = 0; diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 20deff5725..ea43ecdff1 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1034,7 +1034,7 @@ void *ru_thread(void *param) RU_t *ru = (RU_t *)param; RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - PHY_VARS_gNB *gNB = RC.gNB[0]; + PHY_VARS_gNB *gNB = RC.gNB[0]; // this RU main loop handes only one RU int ret; int slot = fp->slots_per_frame-1; int frame = 1023; @@ -1047,7 +1047,7 @@ void *ru_thread(void *param) // set default return value sprintf(threadname,"ru_thread %u",ru->idx); LOG_I(PHY,"Starting RU %d (%s,%s) on cpu %d\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing],sched_getcpu()); - ru->config = RC.gNB[0]->gNB_config; + ru->config = gNB->gNB_config; nr_init_frame_parms(&ru->config, fp); nr_dump_frame_parms(fp); @@ -1179,12 +1179,17 @@ void *ru_thread(void *param) proc->timestamp_tx += fp->get_samples_per_slot(i % fp->slots_per_frame, fp); proc->tti_tx = (proc->tti_rx + ru->sl_ahead) % fp->slots_per_frame; proc->frame_tx = proc->tti_rx > proc->tti_tx ? (proc->frame_rx + 1) & 1023 : proc->frame_rx; - LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", - frame,slot, - proc->frame_rx,proc->tti_rx, - proc->frame_tx,proc->tti_tx, - RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); + LOG_D(PHY, + "AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", + frame, + slot, + proc->frame_rx, + proc->tti_rx, + proc->frame_tx, + proc->tti_tx, + gNB->proc.frame_rx, + gNB->proc.slot_rx, + gNB->proc.frame_tx); if (ru->idx != 0) proc->frame_tx = (proc->frame_tx + proc->frame_offset) & 1023; @@ -1199,7 +1204,7 @@ void *ru_thread(void *param) LOG_D(NR_PHY, "Setting %d.%d (%d) to busy\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH); //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); - gNBscopeCopy(RC.gNB[0], + gNBscopeCopy(gNB, gNBRxdataF, ru->common.rxdataF[0], sizeof(c16_t), @@ -1208,34 +1213,11 @@ void *ru_thread(void *param) proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP); // Do PRACH RU processing - int prach_id = find_nr_prach_ru(ru, proc->frame_rx, proc->tti_rx, SEARCH_EXIST); - if (prach_id >= 0) { + prach_item_t *p = find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, SEARCH_EXIST); + if (p) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); - - T(T_GNB_PHY_PRACH_INPUT_SIGNAL, - T_INT(proc->frame_rx), - T_INT(proc->tti_rx), - T_INT(0), - T_BUFFER(&ru->common.rxdata[0][fp->get_samples_slot_timestamp(proc->tti_rx - 1, fp, 0) /*-ru->N_TA_offset*/], - (fp->get_samples_per_slot(proc->tti_rx - 1, fp) + fp->get_samples_per_slot(proc->tti_rx, fp)) * 4)); - RU_PRACH_list_t *p = ru->prach_list + prach_id; - int N_dur = get_nr_prach_duration(p->fmt); - - for (int prach_oc = 0; prach_oc < p->num_prach_ocas; prach_oc++) { - int prachStartSymbol = p->prachStartSymbol + prach_oc * N_dur; - int beam_id = ru->prach_list[prach_id].beam ? ru->prach_list[prach_id].beam[prach_oc] : 0; - //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. - rx_nr_prach_ru(ru, - p->fmt, // could also use format - p->numRA, - beam_id, - prachStartSymbol, - p->slot, - prach_oc, - proc->frame_rx, - proc->tti_rx); - } - free_nr_ru_prach_entry(ru,prach_id); + // need to extract RACH data for lqter processing by rx_nr_prach() + rx_nr_prach_ru(p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0); } // end if (prach_id >= 0) } // end if (ru->feprx) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 0bd583662b..3e22659400 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -423,8 +423,6 @@ int start_L1L2(module_id_t gnb_id) /* block threads */ oai_exit = 0; sync_var = -1; - extern void init_sched_response(void); - init_sched_response(); /* update config */ gNB_MAC_INST *mac = RC.nrmac[0]; @@ -473,8 +471,9 @@ static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args) printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip ); - fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL); - memcpy(args.libs_dir, oai_args.sm_dir, 128); + fr_args_t args = {0}; + memcpy(args.ip, oai_args.ip, FR_IP_ADDRESS_LEN); + memcpy(args.libs_dir, oai_args.sm_dir, FR_CONF_FILE_LEN); sleep(1); const gNB_RRC_INST* rrc = RC.nrrrc[0]; @@ -721,6 +720,8 @@ int main( int argc, char **argv ) { itti_wait_tasks_end(NULL); printf("Returned from ITTI signal handler\n"); + nfapi_stop_l1(); + if (RC.nb_nr_L1_inst > 0 || RC.nb_RU > 0) stop_L1(0); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index f789484465..5721b45f8d 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -564,7 +564,8 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE->if_inst->dl_indication(&dl_indication); } - sampleShift = pbch_pdcch_processing(UE, proc, phy_data); + sampleShift = pbch_processing(UE, proc, phy_data); + pdcch_processing(UE, proc, phy_data); if (phy_data->dlsch[0].active && (phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_ || phy_data->dlsch[0].rnti_type == TYPE_RA_RNTI_)) { // indicate to tx thread to wait for DLSCH decoding @@ -1090,7 +1091,7 @@ void *UE_thread(void *arg) stream_status = STREAM_STATUS_SYNCED; tx_wait_for_dlsch[slot] = 0; } - + LOG_W(NR_PHY, "UE main thread is ending\n"); return NULL; } diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index fbac6402f5..ca6c48dbef 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -139,10 +139,7 @@ int create_tasks_nrue(uint32_t ue_nb) { void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { int CC_id; - - if (s != NULL) { - printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); - } + LOG_W(NR_PHY, "called by: %s:%d %s() Exiting OAI softmodem: %s\n", file, line, function, s ? s : "no msg"); oai_exit = 1; @@ -496,9 +493,8 @@ int main(int argc, char **argv) printf("Entering ITTI signals handler\n"); printf("TYPE TO TERMINATE\n"); itti_wait_tasks_end(trigger_deregistration); - printf("Returned from ITTI signal handler\n"); - oai_exit=1; - printf("oai_exit=%d\n",oai_exit); + LOG_W(NR_PHY, "Returned from ITTI signal handler\n"); + oai_exit = 1; if (ouput_vcd) vcd_signal_dumper_close(); diff --git a/flexric/etc/flexric/flexric.conf b/flexric/etc/flexric/flexric.conf index a9417505d4..fda5bb4a7c 100644 --- a/flexric/etc/flexric/flexric.conf +++ b/flexric/etc/flexric/flexric.conf @@ -1,5 +1,6 @@ [NEAR-RIC] NEAR_RIC_IP = 192.168.71.21 +NEAR_RIC_PORT = 36422 [XAPP] DB_DIR = /tmp/ diff --git a/flexric/lib/flexric/libgtp_sm.so b/flexric/lib/flexric/libgtp_sm.so index ff4632b12e..1cbd2f13b6 100644 Binary files a/flexric/lib/flexric/libgtp_sm.so and b/flexric/lib/flexric/libgtp_sm.so differ diff --git a/flexric/lib/flexric/libkpm_sm.so b/flexric/lib/flexric/libkpm_sm.so index 6f8ceac498..562a9f801d 100644 Binary files a/flexric/lib/flexric/libkpm_sm.so and b/flexric/lib/flexric/libkpm_sm.so differ diff --git a/flexric/lib/flexric/libmac_sm.so b/flexric/lib/flexric/libmac_sm.so index 46bec2341f..d0b7ceaa4a 100644 Binary files a/flexric/lib/flexric/libmac_sm.so and b/flexric/lib/flexric/libmac_sm.so differ diff --git a/flexric/lib/flexric/libpdcp_sm.so b/flexric/lib/flexric/libpdcp_sm.so index 05933ae57f..3ccb770472 100644 Binary files a/flexric/lib/flexric/libpdcp_sm.so and b/flexric/lib/flexric/libpdcp_sm.so differ diff --git a/flexric/lib/flexric/librc_sm.so b/flexric/lib/flexric/librc_sm.so index d0294518c7..048667a7b2 100644 Binary files a/flexric/lib/flexric/librc_sm.so and b/flexric/lib/flexric/librc_sm.so differ diff --git a/flexric/lib/flexric/librlc_sm.so b/flexric/lib/flexric/librlc_sm.so index 4ee064445b..11665b3517 100644 Binary files a/flexric/lib/flexric/librlc_sm.so and b/flexric/lib/flexric/librlc_sm.so differ diff --git a/flexric/lib/flexric/libslice_sm.so b/flexric/lib/flexric/libslice_sm.so index 3b5412d405..42ad6b4702 100644 Binary files a/flexric/lib/flexric/libslice_sm.so and b/flexric/lib/flexric/libslice_sm.so differ diff --git a/flexric/lib/flexric/libtc_sm.so b/flexric/lib/flexric/libtc_sm.so index e3bf930933..ec1395a863 100644 Binary files a/flexric/lib/flexric/libtc_sm.so and b/flexric/lib/flexric/libtc_sm.so differ diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index b1bfae5415..05c08d391d 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -63,12 +63,20 @@ char cpu_buf_recv[RECV_BUF_LEN]; uint16_t sfn = 0, slot = 0; nv_ipc_t *ipc; -nfapi_vnf_config_t *vnf_config = 0; - -void set_config(nfapi_vnf_config_t *conf) +void nvIPC_Stop() { - vnf_config = conf; + LOG_I(NR_MAC, "Received STOP.indication\n"); + ((vnf_t *)get_config())->terminate = true; } + +void nvIPC_send_stop_request() +{ + nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST, .header.phy_id = 0}; + LOG_I(NR_MAC, "Sending NFAPI STOP.request\n"); + nfapi_nr_vnf_stop_req(get_config(), get_config()->pnf_list->p5_idx, &req); +} + + static uint16_t old_sfn = 0; static uint16_t old_slot = 0; //////////////////////////////////////////////////////////////////////// @@ -84,6 +92,7 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) uint8_t *end = msg->msg_buf + msg->msg_len; // unpack FAPI messages and handle them + nfapi_vnf_config_t * vnf_config = get_config(); if (vnf_config != 0) { // first, unpack the header fapi_phy_api_msg fapi_msg; @@ -479,7 +488,6 @@ static int aerial_recv_msg(nv_ipc_t *ipc, nv_ipc_msg_t *recv_msg) return 0; } -bool recv_task_running = false; void *epoll_recv_task(void *arg) { struct epoll_event ev, events[MAX_EVENTS]; @@ -497,11 +505,12 @@ void *epoll_recv_task(void *arg) if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) { LOG_E(NFAPI_VNF, "%s epoll_ctl failed\n", __func__); } - - while (1) { - if (!recv_task_running) { - recv_task_running = true; - } + // From here on out the thread is ready to receive data, simulate the reception + // of a PARAM.response to get the VNF to send a CONFIG.request + nfapi_nr_param_response_scf_t resp_msg = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE}; + nfapi_vnf_config_t * vnf_config = get_config(); + vnf_config->nr_param_resp(vnf_config, 1, &resp_msg); + while (((vnf_t *)vnf_config)->terminate == false) { LOG_D(NFAPI_VNF, "%s: epoll_wait fd_rx=%d ...\n", __func__, ipc_rx_event_fd); int nfds; @@ -524,6 +533,7 @@ void *epoll_recv_task(void *arg) } } close(epoll_fd); + ipc->ipc_destroy(ipc); return NULL; } @@ -568,21 +578,18 @@ int nvIPC_Init(nvipc_params_t nvipc_params_s) LOG_I(NFAPI_VNF, "%s: create IPC interface successful\n", __func__); sleep(1); create_recv_thread(nvipc_params_s.nvipc_poll_core); - while(!recv_task_running){usleep(100000);} - nfapi_nr_param_response_scf_t resp_msg; - vnf_config->nr_param_resp(vnf_config, 1, &resp_msg); return 0; } int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) { - nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; // int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); - int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &ul_tti_req->header); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_tti_req->header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); @@ -598,11 +605,11 @@ int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) { - nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; // int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); - int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &ul_dci_req->header); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_dci_req->header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { @@ -613,12 +620,12 @@ int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) { - nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; // LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_data_req->SFN), // tx_data_req->Number_of_PDUs); int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); - int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &tx_data_req->header); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &tx_data_req->header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { @@ -630,10 +637,10 @@ int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { - nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); dl_config_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &dl_config_req->header); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &dl_config_req->header); dl_config_req->dl_tti_request_body.nPDUs = 0; dl_config_req->dl_tti_request_body.nGroup = 0; @@ -644,9 +651,9 @@ int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) } int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot){ - nfapi_vnf_p7_config_t *p7_config = (((vnf_info *)vnf_config->user_data)->p7_vnfs[0].config); + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); nfapi_nr_slot_indication_scf_t nr_slot_resp = {.header.message_id = 0x8F, .sfn = frame, .slot = slot}; - int retval = p7_config->send_p7_msg((vnf_p7_t *)p7_config, &nr_slot_resp.header); + int retval = p7_config->send_p7_msg(get_p7_vnf(), &nr_slot_resp.header); if (retval != 0) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index 482d8103f0..8740c1ecd3 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -56,11 +56,13 @@ bool aerial_send_P7_msg_with_data(void *packedBuf, void *dataBuf, uint32_t dataLength, nfapi_nr_p7_message_header_t *header); -void set_config(nfapi_vnf_config_t *conf); + int nvIPC_Init(nvipc_params_t nvipc_params_s); int oai_fapi_send_end_request(int cell_id, uint32_t frame, uint32_t slot); int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req); int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); +void nvIPC_Stop(); +void nvIPC_send_stop_request(); #endif // OPENAIRINTERFACE_FAPI_NVIPC_H diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 3de11d8003..7a6e4f7657 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -55,7 +55,6 @@ #include "PHY/INIT/phy_init.h" #include "PHY/INIT/nr_phy_init.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" -#include "openair1/SCHED_NR/fapi_nr_l1.h" #include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h" #include "openair1/PHY/defs_gNB.h" #include @@ -1108,17 +1107,6 @@ void pnf_nr_phy_deallocate_p7_vendor_ext(void *header) free(header); } -extern void nr_schedule_ul_dci_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_t *UL_dci_req); -int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_dci_request_t *req) -{ - DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL); - PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst? - - nr_schedule_ul_dci_req(gNB, req); - - return 0; -} - int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) { if (req->hi_dci0_request_body.number_of_dci == 0 && req->hi_dci0_request_body.number_of_hi == 0) @@ -1149,21 +1137,6 @@ int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfa } -// from dl_tti_req_fn fptr -extern void nr_schedule_dl_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_request_t *DL_req); -int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_dl_tti_request_t *DL_req) -{ - DevAssert(proc == NULL); - DevAssert(sync_var == 0); - DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL); - PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst? - - nr_schedule_dl_tti_req(gNB, DL_req); - - return 0; -} - - int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { if (RC.eNB == 0) { @@ -1256,18 +1229,6 @@ int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, n } -extern void nr_schedule_tx_req(PHY_VARS_gNB *gNB, nfapi_nr_tx_data_request_t *TX_req); -int pnf_phy_tx_data_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_tx_data_request_t *req) -{ - DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL); - PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst? - - nr_schedule_tx_req(gNB, req); - - return 0; -} - - int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { uint16_t sfn = NFAPI_SFNSF2SFN(req->sfn_sf); uint16_t sf = NFAPI_SFNSF2SF(req->sfn_sf); @@ -1293,16 +1254,6 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { return 0; } -extern void nr_schedule_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req); -int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_tti_request_t *req) -{ - DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL); - PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst? - - nr_schedule_ul_tti_req(gNB, req); - return 0; -} - int pnf_phy_ul_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", __FUNCTION__, @@ -1711,10 +1662,10 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf } // NR - p7_config->dl_tti_req_fn = &pnf_phy_dl_tti_req; - p7_config->ul_tti_req_fn = &pnf_phy_ul_tti_req; - p7_config->ul_dci_req_fn = &pnf_phy_ul_dci_req; - p7_config->tx_data_req_fn = &pnf_phy_tx_data_req; + p7_config->dl_tti_req_fn = NULL; + p7_config->ul_tti_req_fn = NULL; + p7_config->ul_dci_req_fn = NULL; + p7_config->tx_data_req_fn = NULL; // LTE p7_config->dl_config_req = &pnf_phy_dl_config_req; @@ -1825,17 +1776,39 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf nfapi_nr_send_pnf_start_resp(config, p7_config->phy_id); printf("[PNF] Sending first P7 slot indication\n"); #endif -#if 1 - nfapi_pnf_p7_slot_ind(p7_config, p7_config->phy_id, 0, 0); - printf("[PNF] Sent first P7 slot ind\n"); -#else - nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // SFN_SF set to zero - correct??? - printf("[PNF] Sent first P7 subframe ind\n"); -#endif return 0; } +void stop_nr_nfapi_pnf() +{ +#ifdef ENABLE_WLS + wls_fapi_nr_pnf_stop(); +#endif +#ifdef ENABLE_SOCKET + socket_nfapi_nr_pnf_stop(); +#endif +} +static bool has_sent_stop_ind = false; +int nr_stop_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_stop_request_scf_t *req) +{ + if (has_sent_stop_ind) { + // STOP.indication already sent, nothing to do + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "Send STOP.indication\n"); + nfapi_nr_stop_indication_scf_t resp = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION, + .header.phy_id = req->header.phy_id}; + nfapi_nr_stop_indication(config, &resp); + has_sent_stop_ind = true; +#ifdef ENABLE_WLS + wls_pnf_close(pnf_p5_init_and_receive_pthread); +#endif + // raise the SIGTERM to simulate CTRL+C + raise(SIGTERM); + return 0; +} + int measurement_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_measurement_request_t *req) { nfapi_measurement_response_t resp; memset(&resp, 0, sizeof(resp)); @@ -2191,6 +2164,7 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add config->nr_param_req = &nr_param_request; config->nr_config_req = &nr_config_request; config->nr_start_req = &nr_start_request; + config->nr_stop_req = &nr_stop_request; config->rssi_req = &rssi_request; config->broadcast_detect_req = &broadcast_detect_request; config->system_information_schedule_req = &system_information_schedule_request; @@ -2321,7 +2295,7 @@ static void maybe_slow_down_pnf(int mu) last_execution = current_execution; } -void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, NR_Sched_Rsp_t *sched_resp) { nfapi_pnf_p7_config_t *config = p7_config_g; pnf_p7_t *_this = (pnf_p7_t *)(config); @@ -2352,7 +2326,14 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) oai_nfapi_nr_slot_indication(&ind); // copy data from appropriate p7 slot buffers into channel structures for PHY processing - nfapi_pnf_p7_slot_ind(config, config->phy_id, sfn, slot); + nfapi_pnf_p7_get_msgs(config, + config->phy_id, + sfn, + slot, + &sched_resp->DL_req, + &sched_resp->UL_tti_req, + &sched_resp->UL_dci_req, + &sched_resp->TX_req); return; } diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 0ba0676f10..f632eaabcd 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -28,7 +28,8 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); void oai_subframe_ind(uint16_t sfn, uint16_t sf); -void handle_nr_slot_ind(uint16_t sfn, uint16_t slot); +struct NR_Sched_Rsp; +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, struct NR_Sched_Rsp *resp); void sfnslot_add_slot(int mu, uint16_t *sfn, uint16_t *slot, int offset); int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); @@ -37,5 +38,5 @@ int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); - +void stop_nr_nfapi_pnf(); #endif /* NFAPI_PNF_H_ */ diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 5ea99de7ea..777da7c319 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -70,10 +70,25 @@ #endif #define TEST - +static nfapi_vnf_config_t *config; extern RAN_CONTEXT_t RC; extern UL_RCC_IND_t UL_RCC_INFO; +nfapi_vnf_config_t * get_config() +{ + return config; +} +vnf_p7_t *get_p7_vnf() +{ + vnf_info *vnf = config->user_data; + return (vnf_p7_t *)vnf->p7_vnfs->config; +} + +nfapi_vnf_p7_config_t *get_p7_vnf_config() +{ + return &get_p7_vnf()->_public; +} + int vnf_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *codec) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "vnf_pack_vendor_extension_tlv\n"); nfapi_tl_t *tlv = (nfapi_tl_t *)ve; @@ -124,7 +139,6 @@ int vnf_nr_unpack_vendor_extension_tlv(nfapi_tl_t *tl, { return -1; } -void install_nr_schedule_handlers(NR_IF_Module_t *if_inst); void install_schedule_handlers(IF_Module_t *if_inst); extern int sf_ahead; @@ -326,71 +340,6 @@ int pnf_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_config_ return 0; } -int wake_gNB_rxtx(PHY_VARS_gNB *gNB, uint16_t sfn, uint16_t slot) { - struct timespec curr_t; - clock_gettime(CLOCK_MONOTONIC,&curr_t); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "\n wake_gNB_rxtx before assignment sfn:%d slot:%d TIME %d.%d",sfn,slot,curr_t.tv_sec,curr_t.tv_nsec); - gNB_L1_proc_t *proc=&gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc= (slot&1)? &proc->L1_proc : &proc->L1_proc_tx; - - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(eNB:%p, sfn:%d, sf:%d)\n", __FUNCTION__, eNB, sfn, sf); - //int i; - struct timespec wait; - clock_gettime(CLOCK_REALTIME, &wait); - wait.tv_sec = 0; - wait.tv_nsec +=5000L; - //wait.tv_nsec = 0; - // wake up TX for subframe n+sf_ahead - // lock the TX mutex and make sure the thread is ready - AssertFatal(gNB->if_inst->sl_ahead==6,"gNB->if_inst->sl_ahead %d : This is hard-coded to 6 in nfapi P7!!!\n",gNB->if_inst->sl_ahead); - if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt ); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } - - { - static uint16_t old_slot = 0; - static uint16_t old_sfn = 0; - proc->slot_rx = old_slot; - proc->frame_rx = old_sfn; - // Try to be 1 frame back - old_slot = slot; - old_sfn = sfn; - //NFAPI_TRACE(NFAPI_TRACE_INFO, "\n wake_gNB_rxtx after assignment sfn:%d slot:%d",proc->frame_rx,proc->slot_rx); - if (old_slot == 0 && old_sfn % 100 == 0) LOG_W( PHY,"[gNB] sfn/slot:%d%d old_sfn/slot:%d%d proc[rx:%d%d]\n", sfn, slot, old_sfn, old_slot, proc->frame_rx, proc->slot_rx); - } - - ++L1_proc->instance_cnt; - //LOG_D( PHY,"[VNF-subframe_ind] sfn/sf:%d:%d proc[frame_rx:%d subframe_rx:%d] L1_proc->instance_cnt_rxtx:%d \n", sfn, sf, proc->frame_rx, proc->subframe_rx, L1_proc->instance_cnt_rxtx); - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired - // transmitted timestamp of the next TX slot (first). - // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, - // we want to generate subframe (n+N), so TS_tx = TX_rx+N*samples_per_tti, - // and proc->subframe_tx = proc->subframe_rx+sf_ahead - L1_proc->timestamp_tx = proc->timestamp_rx + (gNB->if_inst->sl_ahead *fp->samples_per_subframe); - L1_proc->frame_rx = proc->frame_rx; - L1_proc->slot_rx = proc->slot_rx; - L1_proc->frame_tx = (L1_proc->slot_rx > (19-gNB->if_inst->sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; - L1_proc->slot_tx = (L1_proc->slot_rx + gNB->if_inst->sl_ahead)%20; - - //LOG_D(PHY, "sfn/sf:%d%d proc[rx:%d%d] rx:%d%d] About to wake rxtx thread\n\n", sfn, slot, proc->frame_rx, proc->slot_rx, L1_proc->frame_rx, L1_proc->slot_rx); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "\nEntering wake_gNB_rxtx sfn %d slot %d\n",L1_proc->frame_rx,L1_proc->slot_rx); - // the thread can now be woken up - if (pthread_cond_signal(&L1_proc->cond) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_clond_signal" ); - return(-1); - } - - //LOG_D(PHY,"%s() About to attempt pthread_mutex_unlock\n", __FUNCTION__); - pthread_mutex_unlock( &L1_proc->mutex ); - //LOG_D(PHY,"%s() UNLOCKED pthread_mutex_unlock\n", __FUNCTION__); - return(0); -} - int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) { L1_proc_t *proc=&eNB->proc; L1_rxtx_proc_t *L1_proc= (sf&1)? &proc->L1_proc : &proc->L1_proc_tx; @@ -498,28 +447,6 @@ int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { } -int phy_slot_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn, uint16_t slot) { - static uint8_t first_time = 1; - - if (first_time) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] slot indication %d.%d\n", sfn, slot); - first_time = 0; - } - - if (RC.gNB && RC.gNB[0]->configured) { - // uint16_t sfn = NFAPI_SFNSF2SFN(sfn_sf); - // uint16_t sf = NFAPI_SFNSF2SF(sfn_sf); - LOG_D(PHY,"[VNF] slot indication sfn:%d slot:%d\n", sfn, slot); - wake_gNB_rxtx(RC.gNB[0], sfn, slot); // DONE: find NR equivalent - } else { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() RC.gNB:%p\n", __FUNCTION__, RC.gNB); - - if (RC.gNB) NFAPI_TRACE(NFAPI_TRACE_INFO, "RC.gNB[0]->configured:%d\n", RC.gNB[0]->configured); - } - - return 0; -} - int phy_subframe_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn_sf) { static uint8_t first_time = 1; @@ -971,65 +898,63 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ //NR phy indication -NR_Sched_Rsp_t g_sched_resp; -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slot, NR_Sched_Rsp_t* sched_info); int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t* tx_data_req); int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t* ul_dci_req); -int trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind) -{ - // Call into the scheduler (this is hardcoded and should be init properly!) - // memset(sched_resp, 0, sizeof(*sched_resp)); - gNB_dlsch_ulsch_scheduler(0, slot_ind->sfn, slot_ind->slot, &g_sched_resp); - -#ifdef ENABLE_AERIAL - bool send_slt_resp = false; - if (g_sched_resp.DL_req.dl_tti_request_body.nPDUs> 0) { - oai_fapi_dl_tti_req(&g_sched_resp.DL_req); - send_slt_resp = true; - } - if (g_sched_resp.UL_tti_req.n_pdus > 0) { - oai_fapi_ul_tti_req(&g_sched_resp.UL_tti_req); - send_slt_resp = true; - } - if (g_sched_resp.TX_req.Number_of_PDUs > 0) { - oai_fapi_tx_data_req(&g_sched_resp.TX_req); - send_slt_resp = true; - } - if (g_sched_resp.UL_dci_req.numPdus > 0) { - oai_fapi_ul_dci_req(&g_sched_resp.UL_dci_req); - send_slt_resp = true; - } - if (send_slt_resp) { - oai_fapi_send_end_request(0,slot_ind->sfn, slot_ind->slot); - } -#else - if (g_sched_resp.DL_req.dl_tti_request_body.nPDUs > 0) - oai_nfapi_dl_tti_req(&g_sched_resp.DL_req); - - if (g_sched_resp.UL_tti_req.n_pdus > 0) - oai_nfapi_ul_tti_req(&g_sched_resp.UL_tti_req); - - if (g_sched_resp.TX_req.Number_of_PDUs > 0) - oai_nfapi_tx_data_req(&g_sched_resp.TX_req); - - if (g_sched_resp.UL_dci_req.numPdus > 0) - oai_nfapi_ul_dci_req(&g_sched_resp.UL_dci_req); -#endif - - NR_UL_IND_t ind = {.frame = slot_ind->sfn, .slot = slot_ind->slot, }; - NR_UL_indication(&ind); - - return 1; -} - int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { LOG_D(MAC, "VNF SFN/Slot %d.%d \n", ind->sfn, ind->slot); - trigger_scheduler(ind); + // this variable is very big (multiple MB), so we put it into static storage + // to not overflow the stack while still having it in local (function) scope + // also, phy_nr_slot_indication() is only executed by one thread, serially + static NR_Sched_Rsp_t sched_response; + NR_IF_Module_t *ifi = RC.nrmac[0]->if_inst; + ifi->NR_slot_indication(ind, &sched_response); + +#ifdef ENABLE_AERIAL + bool send_slt_resp = false; + if (sched_response.DL_req.dl_tti_request_body.nPDUs> 0) { + oai_fapi_dl_tti_req(&sched_response.DL_req); + send_slt_resp = true; + } + if (sched_response.UL_tti_req.n_pdus > 0) { + oai_fapi_ul_tti_req(&sched_response.UL_tti_req); + send_slt_resp = true; + } + if (sched_response.TX_req.Number_of_PDUs > 0) { + oai_fapi_tx_data_req(&sched_response.TX_req); + send_slt_resp = true; + } + if (sched_response.UL_dci_req.numPdus > 0) { + oai_fapi_ul_dci_req(&sched_response.UL_dci_req); + send_slt_resp = true; + } + if (send_slt_resp) { + oai_fapi_send_end_request(0, ind->sfn, ind->slot); + } +#else + if (sched_response.DL_req.dl_tti_request_body.nPDUs > 0) + oai_nfapi_dl_tti_req(&sched_response.DL_req); + + if (sched_response.UL_tti_req.n_pdus > 0) + oai_nfapi_ul_tti_req(&sched_response.UL_tti_req); + + if (sched_response.TX_req.Number_of_PDUs > 0) + oai_nfapi_tx_data_req(&sched_response.TX_req); + + if (sched_response.UL_dci_req.numPdus > 0) + oai_nfapi_ul_dci_req(&sched_response.UL_dci_req); +#endif + + /* the below works because the function behind the callback collects + * messages from queue into which messages have been copied. + * TODO we should have different callbacks for received messages and call + * into the scheduler separately for each message instead of one big one. */ + NR_UL_IND_t ul_ind = {.frame = ind->sfn, .slot = ind->slot, }; + ifi->NR_UL_indication(&ul_ind); return 1; } @@ -1305,7 +1230,7 @@ void *configure_nr_p7_vnf(void *ptr) p7_vnf->config->port = p7_vnf->local_port; #ifndef ENABLE_AERIAL p7_vnf->config->sync_indication = &phy_sync_indication; - p7_vnf->config->slot_indication = &phy_slot_indication; + p7_vnf->config->slot_indication = NULL; p7_vnf->config->harq_indication = &phy_harq_indication; #endif p7_vnf->config->nr_crc_indication = &phy_nr_crc_indication; @@ -1341,7 +1266,6 @@ void *configure_nr_p7_vnf(void *ptr) p7_vnf->config->hdr_unpack_func = &fapi_nr_p7_message_header_unpack; p7_vnf->config->pack_func = &fapi_nr_p7_message_pack; p7_vnf->config->send_p7_msg = &wls_vnf_nr_send_p7_message; - wls_vnf_set_p7_config(p7_vnf->config); #endif #ifdef ENABLE_SOCKET @@ -1367,7 +1291,7 @@ void *vnf_p7_thread_start(void *ptr) { p7_vnf->config->port = p7_vnf->local_port; p7_vnf->config->sync_indication = &phy_sync_indication; p7_vnf->config->subframe_indication = &phy_subframe_indication; - p7_vnf->config->slot_indication = &phy_slot_indication; + p7_vnf->config->slot_indication = NULL; p7_vnf->config->harq_indication = &phy_harq_indication; p7_vnf->config->crc_indication = &phy_crc_indication; @@ -1735,32 +1659,86 @@ void vnf_start_thread(void *ptr) { nfapi_vnf_start((nfapi_vnf_config_t *)ptr); } -static vnf_info vnf; +static bool has_stop_ind = false; +static bool waiting_stop_ind = false; +int nr_stop_ind_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_stop_indication_scf_t *resp) +{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_STOP_IND idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + has_stop_ind = true; +#ifdef ENABLE_AERIAL + nvIPC_Stop(); +#endif +#ifdef ENABLE_SOCKET + nfapi_vnf_p7_stop(get_p7_vnf_config()); +#endif +#ifdef ENABLE_WLS + wls_vnf_stop(); +#endif + if (!waiting_stop_ind) { + // hasn't been initialized yet, means the PNF stopped before the VNF did + // raise a SIGINT to stop the VNF + raise(SIGINT); + } + return 0; +} + +void stop_nr_nfapi_vnf() +{ + if (has_stop_ind) { + // If it got here with the STOP.indication flag already set, it means it was triggered by the PNF, + // no need to send a STOP.request + return; + } +#ifdef ENABLE_WLS + wls_vnf_send_stop_request(); +#endif +#ifdef ENABLE_AERIAL + nvIPC_send_stop_request(); +#endif +#ifdef ENABLE_SOCKET + socket_nfapi_send_stop_request((vnf_t *)config); +#endif + waiting_stop_ind = true; + uint64_t counter = 0; + vnf_p7_t *p7_vnf = get_p7_vnf(); + while (p7_vnf->terminate == 0 && counter < 50) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Not terminated yet, counter %ld\n", counter); + usleep(1000); + counter++; + } + if (p7_vnf->terminate == 0) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "STOP.indication timed out, exiting\n"); + nfapi_nr_stop_indication_scf_t msg = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION, .header.phy_id = 0}; + config->nr_stop_ind(config, 0, &msg); + } else { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Terminated, exiting\n"); + } +} void configure_nr_nfapi_vnf(eth_params_t params) { #ifndef ENABLE_AERIAL nfapi_setmode(NFAPI_MODE_VNF); #endif - memset(&vnf, 0, sizeof(vnf)); - memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); - vnf.p7_vnfs[0].timing_window = 30; - vnf.p7_vnfs[0].periodic_timing_enabled = 0; - vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; - vnf.p7_vnfs[0].periodic_timing_period = 1; - vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); + vnf_info *vnf = calloc(1, sizeof(vnf_info)); + memset(vnf->p7_vnfs, 0, sizeof(vnf->p7_vnfs)); + vnf->p7_vnfs[0].timing_window = 30; + vnf->p7_vnfs[0].periodic_timing_enabled = 0; + vnf->p7_vnfs[0].aperiodic_timing_enabled = 0; + vnf->p7_vnfs[0].periodic_timing_period = 1; + vnf->p7_vnfs[0].config = nfapi_vnf_p7_config_create(); #ifndef ENABLE_AERIAL NFAPI_TRACE(NFAPI_TRACE_INFO, - "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", + "[VNF] %s() vnf->p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, - vnf.p7_vnfs[0].config, + vnf->p7_vnfs[0].config, params.my_addr, params.my_portc); - strcpy(vnf.p7_vnfs[0].local_addr, params.my_addr); - vnf.p7_vnfs[0].local_port = params.my_portd; + strcpy(vnf->p7_vnfs[0].local_addr, params.my_addr); + vnf->p7_vnfs[0].local_port = params.my_portd; #endif - vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); - nfapi_vnf_config_t *config = nfapi_vnf_config_create(); + vnf->p7_vnfs[0].mac = malloc(sizeof(mac_t)); + config = nfapi_vnf_config_create(); config->malloc = malloc; config->free = free; config->vnf_p5_port = params.my_portc; @@ -1778,9 +1756,10 @@ void configure_nr_nfapi_vnf(eth_params_t params) config->nr_param_resp = &nr_param_resp_cb; config->nr_config_resp = &nr_config_resp_cb; config->nr_start_resp = &nr_start_resp_cb; + config->nr_stop_ind = &nr_stop_ind_cb; config->nr_error_ind = &nr_error_ind_cb; config->vendor_ext = &vendor_nr_ext_cb; - config->user_data = &vnf; + config->user_data = vnf; // To allow custom vendor extentions to be added to nfapi config->codec_config.unpack_vendor_extension_tlv = &vnf_nr_unpack_vendor_extension_tlv; config->codec_config.pack_vendor_extension_tlv = &vnf_nr_pack_vendor_extension_tlv; @@ -1817,7 +1796,6 @@ void configure_nr_nfapi_vnf(eth_params_t params) config->hdr_unpack_func = &fapi_nr_message_header_unpack; config->pack_func = &fapi_nr_p5_message_pack; config->send_p5_msg = &aerial_nr_send_p5_message; - set_config(config); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); nfapi_vnf_pnf_info_t *pnf = (nfapi_vnf_pnf_info_t *)malloc(sizeof(nfapi_vnf_pnf_info_t)); NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); @@ -1826,7 +1804,6 @@ void configure_nr_nfapi_vnf(eth_params_t params) pnf->connected = 1; // Add needed parameters - vnf_info *vnf = (vnf_info *)(config->user_data); pnf_info *pnf_info = vnf->pnfs; for (int i = 0; i < 1; ++i) { @@ -1863,18 +1840,23 @@ void configure_nr_nfapi_vnf(eth_params_t params) void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { nfapi_setmode(NFAPI_MODE_VNF); - memset(&vnf, 0, sizeof(vnf)); - memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); - vnf.p7_vnfs[0].timing_window = 32; - vnf.p7_vnfs[0].periodic_timing_enabled = 1; - vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; - vnf.p7_vnfs[0].periodic_timing_period = 10; - vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port); - strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr); - vnf.p7_vnfs[0].local_port = vnf_p7_port; - vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); - nfapi_vnf_config_t *config = nfapi_vnf_config_create(); + vnf_info *vnf = calloc(1, sizeof(vnf_info)); + memset(vnf->p7_vnfs, 0, sizeof(vnf->p7_vnfs)); + vnf->p7_vnfs[0].timing_window = 32; + vnf->p7_vnfs[0].periodic_timing_enabled = 1; + vnf->p7_vnfs[0].aperiodic_timing_enabled = 0; + vnf->p7_vnfs[0].periodic_timing_period = 10; + vnf->p7_vnfs[0].config = nfapi_vnf_p7_config_create(); + NFAPI_TRACE(NFAPI_TRACE_INFO, + "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", + __FUNCTION__, + vnf->p7_vnfs[0].config, + vnf_addr, + vnf_p5_port); + strcpy(vnf->p7_vnfs[0].local_addr, vnf_addr); + vnf->p7_vnfs[0].local_port = vnf_p7_port; + vnf->p7_vnfs[0].mac = malloc(sizeof(mac_t)); + config = nfapi_vnf_config_create(); config->malloc = malloc; config->free = free; config->vnf_p5_port = vnf_p5_port; @@ -1893,7 +1875,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int config->config_resp = &config_resp_cb; config->start_resp = &start_resp_cb; config->vendor_ext = &vendor_ext_cb; - config->user_data = &vnf; + config->user_data = vnf; // To allow custom vendor extentions to be added to nfapi config->codec_config.unpack_vendor_extension_tlv = &vnf_unpack_vendor_extension_tlv; config->codec_config.pack_vendor_extension_tlv = &vnf_pack_vendor_extension_tlv; @@ -1910,7 +1892,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); dl_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! dl_config_req->header.message_id = NFAPI_DL_CONFIG_REQUEST; LOG_D(PHY, "[VNF] %s() DL_CONFIG_REQ sfn_sf:%d_%d number_of_pdus:%d\n", __FUNCTION__, @@ -1946,7 +1928,7 @@ int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { LOG_D(NR_PHY, "Entering oai_nfapi_nr_dl_config_req sfn:%d,slot:%d\n", dl_config_req->SFN, dl_config_req->Slot); - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; dl_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! @@ -1965,7 +1947,7 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) { LOG_D(NR_PHY, "Entering oai_nfapi_nr_tx_data_req sfn:%d,slot:%d\n", tx_data_req->SFN, tx_data_req->Slot); - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); tx_data_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; //LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus); @@ -1982,7 +1964,7 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); tx_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! tx_req->header.message_id = NFAPI_TX_REQUEST; //LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus); @@ -1998,7 +1980,7 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); ul_dci_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; //LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi); @@ -2014,7 +1996,7 @@ int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) { } int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); hi_dci0_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST; //LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi); @@ -2050,7 +2032,7 @@ static void remove_ul_config_req_pdu(int index, nfapi_ul_config_request_t *ul_co } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); ul_tti_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; @@ -2070,7 +2052,7 @@ int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) { } int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); ul_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! ul_config_req->header.message_id = NFAPI_UL_CONFIG_REQUEST; //LOG_D(PHY, "[VNF] %s() header message_id:%02x\n", __FUNCTION__, ul_config_req->header.message_id); @@ -2130,7 +2112,7 @@ int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { int oai_nfapi_ue_release_req(nfapi_ue_release_request_t *release_req){ if(release_req->ue_release_request_body.number_of_TLVs <= 0) return 0; - nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); release_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!! release_req->header.message_id = NFAPI_UE_RELEASE_REQUEST; diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index 104cff44f4..d71f9a2926 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -148,5 +148,8 @@ typedef struct { void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); void configure_nr_nfapi_vnf(eth_params_t params); - +void stop_nr_nfapi_vnf(); +nfapi_vnf_config_t *get_config(); +vnf_p7_t *get_p7_vnf(); +nfapi_vnf_p7_config_t *get_p7_vnf_config(); #endif /* NFAPI_VNF_H_ */ diff --git a/nfapi/oai_integration/socket/include/socket_pnf.h b/nfapi/oai_integration/socket/include/socket_pnf.h index ccb3eaea3a..cf5258eabb 100644 --- a/nfapi/oai_integration/socket/include/socket_pnf.h +++ b/nfapi/oai_integration/socket/include/socket_pnf.h @@ -36,4 +36,5 @@ bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, ui bool pnf_nr_send_p7_message(pnf_p7_t* pnf_p7, nfapi_nr_p7_message_header_t* header, uint32_t msg_len); void *pnf_start_p5_thread(void *ptr); void *pnf_nr_p7_thread_start(void *ptr); +void socket_nfapi_nr_pnf_stop(); #endif // SOCKET_PNF_H diff --git a/nfapi/oai_integration/socket/include/socket_vnf.h b/nfapi/oai_integration/socket/include/socket_vnf.h index c11e009153..65c36d034f 100644 --- a/nfapi/oai_integration/socket/include/socket_vnf.h +++ b/nfapi/oai_integration/socket/include/socket_vnf.h @@ -31,4 +31,5 @@ bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_head bool vnf_nr_send_p7_msg(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t* header); void vnf_start_p5_thread(void* ptr); void* vnf_nr_start_p7_thread(void* ptr); +void socket_nfapi_send_stop_request(vnf_t *vnf); #endif // SOCKET_VNF_H diff --git a/nfapi/oai_integration/socket/socket_pnf.c b/nfapi/oai_integration/socket/socket_pnf.c index fe4999c998..6a96247b74 100644 --- a/nfapi/oai_integration/socket/socket_pnf.c +++ b/nfapi/oai_integration/socket/socket_pnf.c @@ -20,6 +20,15 @@ */ #include "socket_pnf.h" #include "nfapi.h" +static nfapi_pnf_config_t *config; +void socket_nfapi_nr_pnf_stop() +{ + AssertFatal(config->nr_stop_req, "STOP.request Handler should be set!"); + nfapi_nr_stop_request_scf_t req = {0}; + req.header.phy_id = 0; + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST; + config->nr_stop_req(config, 0, &req); +} bool pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) { @@ -148,7 +157,7 @@ bool pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *head void *pnf_start_p5_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__); - nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr; + config = (nfapi_pnf_config_t *)ptr; struct sched_param sp; sp.sched_priority = 20; pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp); diff --git a/nfapi/oai_integration/socket/socket_vnf.c b/nfapi/oai_integration/socket/socket_vnf.c index 6440109ed6..75d4a37026 100644 --- a/nfapi/oai_integration/socket/socket_vnf.c +++ b/nfapi/oai_integration/socket/socket_vnf.c @@ -20,9 +20,26 @@ */ #include "socket_vnf.h" +#include "common/utils/LOG/log.h" #include "nfapi.h" +#include "nfapi_vnf.h" +#include #include "nfapi/oai_integration/vendor_ext.h" //TODO: Remove this include when removing the Aerial transport stuff + +void socket_stop_nfapi_p5_p7() +{ + get_p7_vnf()->terminate = 1; + get_config()->pnf_disconnect_indication = NULL; +} + +void socket_nfapi_send_stop_request(vnf_t *vnf) +{ + nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST, .header.phy_id = 0}; + nfapi_nr_vnf_stop_req(&vnf->_public, 0, &req); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Sent NFAPI STOP.request\n"); +} + static bool send_p5_msg(vnf_t *vnf, nfapi_vnf_pnf_info_t *pnf, const void *msg, int len, uint8_t stream) { int result = socket_send_p5_msg(vnf->sctp, pnf->p5_sock, &pnf->p5_pnf_sockaddr, msg, len, stream); @@ -279,7 +296,6 @@ static int nfapi_nr_vnf_p5_start(nfapi_vnf_config_t *config) // Verify that config is not null if (config == 0) return -1; - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); int p5ListenSock, p5Sock; @@ -293,7 +309,7 @@ static int nfapi_nr_vnf_p5_start(nfapi_vnf_config_t *config) struct sctp_initmsg initMsg = {0}; int noDelay; - vnf_t *vnf = (vnf_t *)(config); + vnf_t *vnf = (vnf_t *)(get_config()); NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port); @@ -747,8 +763,8 @@ static int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t *config) return -1; NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); - - vnf_p7_t *vnf_p7 = (vnf_p7_t *)config; + vnf_p7_t *vnf_p7 = get_p7_vnf(); + vnf_p7 = (vnf_p7_t *)config; // Create p7 receive udp port // todo : this needs updating for Ipv6 diff --git a/nfapi/oai_integration/wls_integration/include/wls_common.h b/nfapi/oai_integration/wls_integration/include/wls_common.h index 1b6a8e4cdf..e823e93380 100644 --- a/nfapi/oai_integration/wls_integration/include/wls_common.h +++ b/nfapi/oai_integration/wls_integration/include/wls_common.h @@ -25,7 +25,6 @@ #include #include #include -#include "wls_lib.h" #include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h" #include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h" diff --git a/nfapi/oai_integration/wls_integration/include/wls_pnf.h b/nfapi/oai_integration/wls_integration/include/wls_pnf.h index c678345967..ca89761b27 100644 --- a/nfapi/oai_integration/wls_integration/include/wls_pnf.h +++ b/nfapi/oai_integration/wls_integration/include/wls_pnf.h @@ -30,4 +30,6 @@ bool wls_pnf_nr_send_p7_message(pnf_p7_t* pnf_p7,nfapi_nr_p7_message_header_t *m void *wls_fapi_pnf_nr_start_thread(void *ptr); int wls_fapi_nr_pnf_start(); void wls_pnf_set_p7_config(void *p7_config); +void wls_fapi_nr_pnf_stop(); +void wls_pnf_close(pthread_t p5_thread); #endif // OPENAIRINTERFACE_WLS_PNF_H diff --git a/nfapi/oai_integration/wls_integration/include/wls_vnf.h b/nfapi/oai_integration/wls_integration/include/wls_vnf.h index 645b24d056..9206a03d62 100644 --- a/nfapi/oai_integration/wls_integration/include/wls_vnf.h +++ b/nfapi/oai_integration/wls_integration/include/wls_vnf.h @@ -27,7 +27,8 @@ void *wls_fapi_vnf_nr_start_thread(void *ptr); int wls_fapi_nr_vnf_start(); -void wls_vnf_set_p7_config(void *p7_config); bool wls_vnf_nr_send_p5_message(vnf_t *vnf,uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len); bool wls_vnf_nr_send_p7_message(vnf_p7_t* vnf_p7,nfapi_nr_p7_message_header_t* msg); +void wls_vnf_send_stop_request(); +void wls_vnf_stop(); #endif //OPENAIRINTERFACE_WLS_VNF_H diff --git a/nfapi/oai_integration/wls_integration/wls_common.c b/nfapi/oai_integration/wls_integration/wls_common.c index fe4112eba8..6b471e0e96 100644 --- a/nfapi/oai_integration/wls_integration/wls_common.c +++ b/nfapi/oai_integration/wls_integration/wls_common.c @@ -20,7 +20,7 @@ */ #include "wls_common.h" - +#include "wls_lib.h" void fill_fapi_list_elem(p_fapi_api_queue_elem_t currElem, p_fapi_api_queue_elem_t nextElem, const uint8_t msgType, const uint8_t numMsgInBlock, const uint32_t alignOffset) { currElem->msg_type = msgType; @@ -90,9 +90,19 @@ uint8_t wls_send_fapi_msg(PWLS_MAC_CTX pWls, const uint16_t message_id, const in { int num_avail_blocks = WLS_NumBlocks(pWls->hWls); NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + int counter = 0; while (num_avail_blocks < 2) { num_avail_blocks = WLS_NumBlocks(pWls->hWls); NFAPI_TRACE(NFAPI_TRACE_DEBUG,"num_avail_blocks is %d\n", num_avail_blocks); + if (message_id == NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION) { + // In the case of the STOP.indication, it can happen that this is called after the VNF stopped + // For example, if it crashed for some reason, in that case, implement a timeout and return + usleep(10 * 1000); + counter++; + if (counter == 10) { + return true; + } + } } /* get PA blocks for header and msg */ uint64_t pa_hdr = dequeueBlock(pWls); diff --git a/nfapi/oai_integration/wls_integration/wls_pnf.c b/nfapi/oai_integration/wls_integration/wls_pnf.c index bed517ad01..e6fd609346 100644 --- a/nfapi/oai_integration/wls_integration/wls_pnf.c +++ b/nfapi/oai_integration/wls_integration/wls_pnf.c @@ -29,9 +29,10 @@ #include #include +#include "wls_lib.h" #include "pnf.h" #include "nr_nfapi_p7.h" -#include "nr_fapi_p5.h" +#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p7_utils.h" // A copy of the PNF P7 config is needed for the message processing thread, in other transport mechanisms where P7 is handled in a // different thread, the config is passed to it upon the thread creation @@ -65,6 +66,28 @@ void *wls_fapi_pnf_nr_start_thread(void *ptr) return (void *)0; } +void wls_pnf_close(pthread_t p5_thread) +{ + _this->terminate = 1; + WLS_WakeUp(wls_mac_get_ctx()->hWls); + pthread_join(p5_thread, NULL); + if (WLS_Close(wls_mac_get_ctx()->hWls) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] WLS_CLose call failed...\n"); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] WLS_CLose called successfully...\n"); + } + rte_eal_cleanup(); +} + +void wls_fapi_nr_pnf_stop() +{ + AssertFatal(cfg->nr_stop_req, "STOP.request Handler should be set!"); + nfapi_nr_stop_request_scf_t req = {0}; + req.header.phy_id = 0; + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST; + cfg->nr_stop_req(cfg, 0, &req); +} + int wls_fapi_nr_pnf_start() { int64_t ret; @@ -194,6 +217,9 @@ bool wls_pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t * NFAPI_TRACE(NFAPI_TRACE_DEBUG, "num_avail_blocks is %d\n", num_avail_blocks); while (num_avail_blocks < 2) { num_avail_blocks = WLS_NumBlocks(pWls->hWls); + if (_this->terminate) { + return false; + } NFAPI_TRACE(NFAPI_TRACE_DEBUG, "num_avail_blocks is %d\n", num_avail_blocks); } /* get PA blocks for header and msg */ @@ -254,7 +280,7 @@ void phy_mac_recv() bool to_return = false; while (_this->terminate == 0) { int numMsgToGet = WLS_Wait(pWls->hWls); - if (numMsgToGet == 0) { + if (numMsgToGet == 0 || _this->terminate) { continue; } uint64_t PAs[numMsgToGet]; @@ -279,6 +305,11 @@ void phy_mac_recv() } } } + // A STOP.indication might have been processed, which set's terminate to 1 + // don't return pages in that case + if (_this->terminate) { + break; + } if (to_return) { // We only return the pages to be enqueued in case we're using the OAI VNF, // The Radisys O-DU handles enqueueing the blocks differently, and also doesn't handle receiving a single block diff --git a/nfapi/oai_integration/wls_integration/wls_vnf.c b/nfapi/oai_integration/wls_integration/wls_vnf.c index ccc68b4905..c72e17a2b6 100644 --- a/nfapi/oai_integration/wls_integration/wls_vnf.c +++ b/nfapi/oai_integration/wls_integration/wls_vnf.c @@ -21,26 +21,23 @@ #include "wls_vnf.h" #include "vnf_p7.h" - +#include "common/utils/LOG/log.h" +#include "wls_lib.h" #include #include #include #include -#include #include +#include "common/utils/LOG/log.h" +#include +#include #include +#include +#include "nfapi_vnf.h" -static nfapi_vnf_config_t *config; static WLS_MAC_CTX wls_mac_iface; vnf_t *_vnf = NULL; -// A copy of the VNF P7 config is needed for the message processing thread, in other transport mechanisms where P7 is handled in a -// different thread, the config is passed to it upon the thread creation -nfapi_vnf_p7_config_t *wls_vnf_p7_config = NULL; -void wls_vnf_set_p7_config(void *p7_config) -{ - wls_vnf_p7_config = (nfapi_vnf_p7_config_t *)p7_config; -} static PWLS_MAC_CTX wls_mac_get_ctx(void) { @@ -99,17 +96,54 @@ static bool wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pMemArr return true; } -void mac_dpdk_init() +bool primary_process_running(int argc, char *argv[]) { - char *my_argv[] = {"OAI_VNF", "-c3", "--proc-type=auto", "--file-prefix", WLS_DEV_NAME, "--iova-mode=pa"}; - printf("\nCalling rte_eal_init: "); - for (unsigned long i = 0; i < RTE_DIM(my_argv); i++) { - printf("%s ", my_argv[i]); - } - printf("\n"); + // If the PNF was stopped normally, this is enough, as the mp_socket file does not exist + if (access("/var/run/dpdk/" WLS_DEV_NAME "/mp_socket", W_OK | R_OK) != 0) + return false; - if (rte_eal_init(RTE_DIM(my_argv), my_argv) < 0) - rte_panic("\nCannot init EAL\n"); + // If we run rte_eal_init before the primary process is running, it will result in a 'Connection Refused' error in the logs, but + // the call itself will succeed ( retval not -1 ) + // + // We can use rte_eal_primary_proc_alive to determine if the primary process is running, the issue is that since the init had a + // refused connection, if we try to open WLS after rte_eal_primary_proc_alive reports that the primary is running, it will fail, + // since rte_eal_init failed to connect to the primary process, and we can't call rte_eal_init in the same process more than once, + // or it will result in an EALREADY error + // + // Given this, a new process is created that calls rte_eal_init and checks whether the primary process is running, exiting + // right after and reporting to our VNF the primary status + // + // When the VNF receives the status from the forked process that the + // primary process is running, it then calls rte_eal_init, which at this point we know will be successful, and continue to open + // the WLS instance + pid_t pid = fork(); + if (pid == 0) { + // We set the log level to emergency , effectively disabling logs in the child process + // This prevents too many logs being printed out to the terminal while we wait for the primary process to be available + rte_log_set_global_level(RTE_LOG_EMERG); + AssertFatal(rte_eal_init(argc, argv) != -1, "rte_eal_init() failed\n"); + int status = rte_eal_primary_proc_alive(NULL) == 0; + rte_eal_cleanup(); + _exit(status); + } + int status; + waitpid(pid, &status, 0); + return WIFEXITED(status) && WEXITSTATUS(status) == 0; +} + +bool mac_dpdk_init() +{ + char *my_argv[] = {"OAI_VNF", "-c3", "--proc-type=secondary", "--file-prefix", WLS_DEV_NAME, "--iova-mode=pa"}; + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "\nCalling rte_eal_init: "); + for (int i = 0; i < RTE_DIM(my_argv); i++) { + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "%s ", my_argv[i]); + } + NFAPI_TRACE(NFAPI_TRACE_DEBUG, "\n"); + while (!primary_process_running(RTE_DIM(my_argv), my_argv)) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "DPDK primary process not available yet, retrying in 1 second...\n"); + sleep(1); + } + return rte_eal_init(RTE_DIM(my_argv), my_argv) >= 0; } static uint32_t wls_mac_alloc_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void **ppBlock) @@ -258,7 +292,7 @@ for(int i = 0 ; i< pWls->nTotalBlocks; i++){ void* pMsg = wls_mac_alloc_buffer(pWls, 0, i); /* Enqueue all blocks */ nBlocks += WLS_EnqueueBlock(pWls->hWls, WLS_VA2PA(pWls->hWls, pMsg)); -} +} NFAPI_TRACE(NFAPI_TRACE_INFO, "\nAllocated %d Blocks \n", nBlocks); return true; } @@ -274,6 +308,33 @@ static int vnf_wls_init() return 1; } +void wls_vnf_stop() +{ + vnf_p7_t *p7_vnf = get_p7_vnf(); + _vnf->terminate = 1; + p7_vnf->terminate = 1; + rte_eal_cleanup(); +} + +void wls_vnf_send_stop_request() +{ + PWLS_MAC_CTX pWls = wls_mac_get_ctx(); + nfapi_nr_stop_request_scf_t req = {.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST, .header.phy_id = 0}; + vnf_p7_t *p7_vnf = get_p7_vnf(); + nfapi_vnf_config_t * config = get_config(); + if (p7_vnf == NULL || pWls->hWls == NULL) { + nfapi_nr_stop_indication_scf_t msg; + msg.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION; + msg.header.phy_id = 0; + config->nr_stop_ind(config, 0, &msg); + return; + } + + if (pWls->hWls != NULL) { + nfapi_nr_vnf_stop_req(config, 0, &req); + } +} + void *wls_fapi_vnf_nr_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] IN WLS PNF NFAPI start thread %s\n", __FUNCTION__); @@ -294,11 +355,11 @@ static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id) case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: - vnf_nr_handle_p4_p5_message(msg_buf, msg_size, 0, config); + vnf_nr_handle_p4_p5_message(msg_buf, msg_size, 0, get_config()); break; case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST ... NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: { - vnf_nr_handle_p7_message(msg_buf, msg_size + NFAPI_NR_P7_HEADER_LENGTH, (vnf_p7_t *)wls_vnf_p7_config); + vnf_nr_handle_p7_message(msg_buf, msg_size + NFAPI_NR_P7_HEADER_LENGTH, get_p7_vnf()); break; } default: @@ -308,6 +369,7 @@ static void procPhyMessages(uint32_t msg_size, void *msg_buf, uint16_t msg_id) int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg) { + nfapi_vnf_config_t * config = get_config(); config = cfg; if (config == 0) { @@ -333,7 +395,7 @@ int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg) PWLS_MAC_CTX pWls = wls_mac_get_ctx(); while (_vnf->terminate == 0) { int numMsgToGet = WLS_Wait(pWls->hWls); - if (numMsgToGet == 0) { + if (numMsgToGet == 0 || _vnf->terminate) { continue; } @@ -351,6 +413,9 @@ int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg) procPhyMessages(len, (void *)(msg + 1), msg->msg_type); } } + if (_vnf->terminate) { + break; + } for (int i = 0; i < pa_idx; i++) { if (WLS_EnqueueBlock(pWls->hWls, PAs[i]) == -1) { NFAPI_TRACE(NFAPI_TRACE_DEBUG, "Error in WLS_EnqueueBlock for block %lu\n", PAs[i]); @@ -403,7 +468,7 @@ bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t * AssertFatal(fapiMsgElem, "WLS_PA2VA failed for fapiMsgElem\n"); //memcpy((uint8_t *)(fapiMsgElem + 1), message, packed_len + NFAPI_HEADER_LENGTH); const uint8_t wls_header[] = {1, 0}; // num_messages , opaque_handle - + fill_fapi_list_elem(headerElem, fapiMsgElem, FAPI_VENDOR_MSG_HEADER_IND, 1, 2); memcpy((uint8_t *)(headerElem + 1), wls_header, 2); int packed_len = ((nfapi_vnf_p7_config_t *)vnf_p7)->pack_func(msg, (fapiMsgElem + 1), NFAPI_MAX_PACKED_MESSAGE_SIZE, NULL); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index dc52f1de2a..faebaffc6f 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -73,6 +73,7 @@ typedef struct { /// frequency_domain_resource; uint8_t frequency_domain_resource[6]; uint8_t StartSymbolIndex; + uint16_t StartSymbolBitmap; uint8_t duration; uint8_t CceRegMappingType; // interleaved or noninterleaved uint8_t RegBundleSize; // valid if CCE to REG mapping type is interleaved type diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 754ef60e55..12cf081fdc 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -1481,7 +1481,10 @@ typedef enum { NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE, NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE, } nfapi_nr_ul_config_pdu_type_e; - +static const char* const txt_nfapi_nr_ul_config_pdu_type[] = {"NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE", + "NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE", + "NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE", + "NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE"}; typedef struct { uint16_t pdu_type;//0: PRACH PDU, 1: PUSCH PDU, 2: PUCCH PDU, 3: SRS PDU diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index 4516302e48..7d7388bad5 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -1254,6 +1254,10 @@ uint8_t pack_nr_p5_message_body(nfapi_nr_p4_p5_message_header_t *header, result = pack_stop_request(header, ppWritePackedMsg, end, config); break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: + result = pack_nr_stop_indication(header, ppWritePackedMsg, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: result = pack_stop_response(header, ppWritePackedMsg, end, config); break; @@ -2447,6 +2451,10 @@ bool nfapi_nr_p5_message_unpack(void *pMessageBuf, result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: + result = unpack_nr_stop_indication(&pReadPackedMessage, end, pMessageHeader, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); break; diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 5805e07445..3040d9de09 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -145,8 +145,14 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len); int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len); - -int pnf_p7_slot_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); +int nr_pnf_p7_get_msgs(pnf_p7_t* pnf_p7, + uint16_t phy_id, + uint16_t sfn, + uint16_t slot, + nfapi_nr_dl_tti_request_t* ret_dl_tti, + nfapi_nr_ul_tti_request_t* ret_ul_tti, + nfapi_nr_ul_dci_request_t* ret_ul_dci, + nfapi_nr_tx_data_request_t* ret_tx_data); int pnf_p7_subframe_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn_sf); int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind); int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind); diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 957e032f69..306216a1d5 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -497,6 +497,14 @@ int nfapi_nr_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_start_response_ */ int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp); +/*! Send the STOP.indication + * \param config A pointer to a pnf configuration + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_nr_stop_indication(nfapi_pnf_config_t* config, nfapi_nr_stop_indication_scf_t* resp); + /*! Send the MEASUREMENT.response * \param config A pointer to a pnf configuraiton * \param resp A pointer to the message structure @@ -856,7 +864,7 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config); */ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config); -/*! NR Slot indication +/*! NR get stuff * message copied from nfapi_pnf_p7_subframe_ind * \param config A pointer to a PNF P7 config * \param phy_id The phy_id for the phy instance @@ -868,8 +876,14 @@ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config); * * If messages are not in the subframe buffer, they dummy subframe messages will be sent */ -int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); - +int nfapi_pnf_p7_get_msgs(nfapi_pnf_p7_config_t* config, + uint16_t phy_id, + uint16_t sfn, + uint16_t slot, + nfapi_nr_dl_tti_request_t* ret_dl_tti, + nfapi_nr_ul_tti_request_t* ret_ul_tti, + nfapi_nr_ul_dci_request_t* ret_ul_dci, + nfapi_nr_tx_data_request_t* ret_tx_data); /*! Subframe indication * \param config A pointer to a PNF P7 config diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c index d80ab168fa..76db8ac2d5 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c @@ -387,6 +387,18 @@ int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp) return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_stop_response_t)); } +int nfapi_nr_stop_indication(nfapi_pnf_config_t* config, nfapi_nr_stop_indication_scf_t* resp) +{ + if (config == NULL || resp == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + AssertFatal(config->send_p5_msg, "Function pointer must be configured|"); + return config->send_p5_msg(_this, &(resp->header), sizeof(nfapi_nr_stop_indication_scf_t)); +} + int nfapi_pnf_measurement_resp(nfapi_pnf_config_t* config, nfapi_measurement_response_t* resp) { if (config == NULL || resp == NULL) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index e2b6d253d2..8b684261a7 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -672,145 +672,136 @@ void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) } } +int nr_pnf_p7_get_msgs(pnf_p7_t* pnf_p7, + uint16_t phy_id, + uint16_t sfn, + uint16_t slot, + nfapi_nr_dl_tti_request_t* ret_dl_tti, + nfapi_nr_ul_tti_request_t* ret_ul_tti, + nfapi_nr_ul_dci_request_t* ret_ul_dci, + nfapi_nr_tx_data_request_t* ret_tx_data) +{ + if (pthread_mutex_lock(&(pnf_p7->mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return -1; + } -int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t slot) -{ - //This function is aligned with rx sfn/slot + // save the curren time, sfn and slot + // TODO useful? + pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); - // We could either send an event to the p7 thread have have it run the - // subframe or we could handle it here and lock access to the subframe - // buffers. If we do it on the p7 thread then we run the risk of blocking - // on the udp send. - - // todo : consider a more efficent lock mechasium - //uint16_t NUM_SLOTS = 20;//10* 2^mu - - if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); - return -1; - } + // We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs + // slot_ahead from rx thread. + pnf_p7->sfn = sfn; + pnf_p7->slot = slot; - // save the curren time, sfn and slot - pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); + uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(pnf_p7->mu, sfn, slot); + uint8_t buffer_index_tx = tx_slot_dec % NFAPI_SLOTNUM(pnf_p7->mu); - //We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread. + // If the subframe_buffer has been configured + if (pnf_p7->_public.slot_buffer_size != 0) // for now value is same as sf_buffer_size + { + // apply the shift to the incoming sfn_sf + if (pnf_p7->slot_shift != 0) // see in vnf_build_send_dl_node_sync + { + uint16_t shifted_slot = slot + pnf_p7->slot_shift; - pnf_p7->sfn = sfn; - pnf_p7->slot = slot; + // adjust for wrap-around + if (shifted_slot < 0) + shifted_slot += NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu); + else if (shifted_slot > NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu)) + shifted_slot -= NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu); - uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(pnf_p7->mu, sfn,slot); - uint8_t buffer_index_tx = tx_slot_dec % NFAPI_SLOTNUM(pnf_p7->mu); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Applying shift %d to sfn/slot (%d -> %d)\n", pnf_p7->sfn_slot_shift, + //NFAPI_SFNSF2DEC(sfn_slot), shifted_sfn_slot); + slot = shifted_slot; - // If the subframe_buffer has been configured - if(pnf_p7->_public.slot_buffer_size!= 0) // for now value is same as sf_buffer_size - { + // + // why does the shift not apply to pnf_p7->sfn_sf??? + // - // apply the shift to the incoming sfn_sf - if(pnf_p7->slot_shift != 0) // see in vnf_build_send_dl_node_sync - { - uint16_t shifted_slot = slot + pnf_p7->slot_shift; + pnf_p7->slot_shift = 0; + } - // adjust for wrap-around - if(shifted_slot < 0) - shifted_slot += NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu); - else if(shifted_slot > NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu)) - shifted_slot -= NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu); - - // NFAPI_TRACE(NFAPI_TRACE_INFO, "Applying shift %d to sfn/slot (%d -> %d)\n", pnf_p7->sfn_slot_shift, NFAPI_SFNSF2DEC(sfn_slot), shifted_sfn_slot); - slot = shifted_slot; - - // - // why does the shift not apply to pnf_p7->sfn_sf??? - // - - pnf_p7->slot_shift = 0; - } - - nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]); + nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]); + ret_dl_tti->SFN = sfn; + ret_dl_tti->Slot = slot; + ret_dl_tti->dl_tti_request_body.nPDUs = 0; nfapi_nr_dl_tti_request_t* dl_tti_req = &tx_slot_buffer->dl_tti_req; - nfapi_nr_tx_data_request_t* tx_data_req = &tx_slot_buffer->tx_data_req; - if (dl_tti_req->dl_tti_request_body.nPDUs > 0 && dl_tti_req->SFN == sfn && dl_tti_req->Slot == slot) { - DevAssert(pnf_p7->_public.dl_tti_req_fn != NULL); - DevAssert(pnf_p7->_public.tx_data_req_fn != NULL); - if (tx_data_req->Number_of_PDUs > 0 && tx_data_req->SFN == sfn && tx_data_req->Slot == slot) { - (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), dl_tti_req); - (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_data_req); - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%4d.%2d no corresponding tx_data.request for dl_tti.request, dropping\n", sfn, slot); - } + if (dl_tti_req->SFN == sfn && dl_tti_req->Slot == slot) { + copy_dl_tti_request(dl_tti_req, ret_dl_tti); tx_slot_buffer->dl_tti_req.SFN = -1; tx_slot_buffer->dl_tti_req.Slot = -1; - tx_slot_buffer->tx_data_req.SFN = -1; - tx_slot_buffer->tx_data_req.Slot = -1; } - if (tx_data_req->Number_of_PDUs > 0 && tx_data_req->SFN == sfn && tx_data_req->Slot == slot) { - // there is a tx_data.request in this slot, but no corresponding - // dl_tti.request (when they need to come pairwise) - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%4d.%2d no corresponding dl_tti.request for tx_data.request, dropping\n", sfn, slot); + + ret_tx_data->SFN = sfn; + ret_tx_data->Slot = slot; + ret_tx_data->Number_of_PDUs = 0; + nfapi_nr_tx_data_request_t* txd = &tx_slot_buffer->tx_data_req; + if (txd->SFN == sfn && txd->Slot == slot) { + copy_tx_data_request(txd, ret_tx_data); tx_slot_buffer->tx_data_req.SFN = -1; tx_slot_buffer->tx_data_req.Slot = -1; } - if(tx_slot_buffer->ul_tti_req.n_pdus > 0 && tx_slot_buffer->ul_tti_req.SFN == sfn && tx_slot_buffer->ul_tti_req.Slot == slot) - { - DevAssert(pnf_p7->_public.ul_tti_req_fn != NULL); - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), &tx_slot_buffer->ul_tti_req); + ret_ul_tti->SFN = sfn; + ret_ul_tti->Slot = slot; + ret_ul_tti->n_pdus = 0; + if (tx_slot_buffer->ul_tti_req.SFN == sfn && tx_slot_buffer->ul_tti_req.Slot == slot) { + copy_ul_tti_request(&tx_slot_buffer->ul_tti_req, ret_ul_tti); tx_slot_buffer->ul_tti_req.SFN = -1; tx_slot_buffer->ul_tti_req.Slot = -1; - } + } - if(tx_slot_buffer->ul_dci_req.numPdus > 0 && tx_slot_buffer->ul_dci_req.SFN == sfn && tx_slot_buffer->ul_dci_req.Slot == slot) - { - DevAssert(pnf_p7->_public.ul_dci_req_fn != NULL); - (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), &tx_slot_buffer->ul_dci_req); + ret_ul_dci->SFN = sfn; + ret_ul_dci->Slot = slot; + ret_ul_dci->numPdus = 0; + if (tx_slot_buffer->ul_dci_req.SFN == sfn && tx_slot_buffer->ul_dci_req.Slot == slot) { + copy_ul_dci_request(&tx_slot_buffer->ul_dci_req, ret_ul_dci); tx_slot_buffer->ul_dci_req.SFN = -1; tx_slot_buffer->ul_dci_req.Slot = -1; - } + } - //send the periodic timing info if configured - if(pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period) - { - pnf_nr_pack_and_send_timing_info(pnf_p7); + // send the periodic timing info if configured + if (pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period) { + pnf_nr_pack_and_send_timing_info(pnf_p7); - pnf_p7->timing_info_period_counter = 0; - } - else if(pnf_p7->_public.timing_info_mode_aperiodic && pnf_p7->timing_info_aperiodic_send) - { - pnf_nr_pack_and_send_timing_info(pnf_p7); + pnf_p7->timing_info_period_counter = 0; + } else if (pnf_p7->_public.timing_info_mode_aperiodic && pnf_p7->timing_info_aperiodic_send) { + pnf_nr_pack_and_send_timing_info(pnf_p7); - pnf_p7->timing_info_aperiodic_send = 0; - } - else - { - pnf_p7->timing_info_ms_counter++; - } - - } + pnf_p7->timing_info_aperiodic_send = 0; + } else { + pnf_p7->timing_info_ms_counter++; + } + } if (sfn % 128 == 0 && slot == 0) { pnf_p7_nr_stats_t* s = &pnf_p7->nr_stats; int ontime = s->dl_tti.ontime + s->ul_tti.ontime + s->ul_dci.ontime + s->tx_data.ontime; int late = s->dl_tti.late + s->ul_tti.late + s->ul_dci.late + s->tx_data.late; - float dl_thr = (float) s->dl.bytes * 8 / 1000 / 1000 / 1.28f; // every 128 frames = 1.28 s - float ul_thr = (float) s->ul.bytes * 8 / 1000 / 1000 / 1.28f; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[P7:%d] msgs ontime %d thr DL %.2f UL %.2f msg late %d (vtime)\n", pnf_p7->_public.phy_id, ontime, dl_thr, ul_thr, late); + float dl_thr = (float)s->dl.bytes * 8 / 1000 / 1000 / 1.28f; // every 128 frames = 1.28 s + float ul_thr = (float)s->ul.bytes * 8 / 1000 / 1000 / 1.28f; + NFAPI_TRACE(NFAPI_TRACE_INFO, + "[P7:%d] msgs ontime %d thr DL %.2f UL %.2f msg late %d (vtime)\n", + pnf_p7->_public.phy_id, + ontime, + dl_thr, + ul_thr, + late); memset(s, 0, sizeof(*s)); } - if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return -1; - } + if (pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } - return 0; + return 0; } - - int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) { // We could either send an event to the p7 thread have have it run the diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index b021e67fc9..af02ef7a4e 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -89,15 +89,22 @@ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config) return 0; } -int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot) +int nfapi_pnf_p7_get_msgs(nfapi_pnf_p7_config_t* config, + uint16_t phy_id, + uint16_t sfn, + uint16_t slot, + nfapi_nr_dl_tti_request_t* ret_dl_tti, + nfapi_nr_ul_tti_request_t* ret_ul_tti, + nfapi_nr_ul_dci_request_t* ret_ul_dci, + nfapi_nr_tx_data_request_t* ret_tx_data) { - // Verify that config is not null - if(config == 0) - return -1; - - pnf_p7_t* _this = (pnf_p7_t*)(config); + // Verify that config is not null + if (config == 0) + return -1; - return pnf_p7_slot_ind(_this, phy_id, sfn, slot); + pnf_p7_t* _this = (pnf_p7_t*)(config); + + return nr_pnf_p7_get_msgs(_this, phy_id, sfn, slot, ret_dl_tti, ret_ul_tti, ret_ul_dci, ret_tx_data); } int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf) diff --git a/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c index bd6bedbea5..3460d4d9d7 100644 --- a/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c +++ b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c @@ -1210,12 +1210,6 @@ void send_dl_subframe_msgs_interleaved(int p7Sock, int phy_id, struct sockaddr_i //free(req.tx_request_body.tx_pdu_list); } -void send_slot_indication(phy_info_t* phy_info) -{ - // DONE: add sfn and slot as members in the phy_info - nfapi_pnf_p7_slot_ind(phy_info->config, phy_info->phy_id, phy_info->sfn, phy_info->slot); -} - void send_subframe_indication(phy_info_t* phy_info) { nfapi_pnf_p7_subframe_ind(phy_info->config, phy_info->phy_id, phy_info->sfn_sf); diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index db303b8b4a..3f326e841c 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -210,6 +210,24 @@ typedef struct nfapi_vnf_config int (*pnf_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* resp); int (*pnf_nr_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_start_response_t* resp); + /*! A callback for the STOP.indication + * \param config A pointer to the vnf configuration + * \param p5_idx The p5 index used to indicate a particular pnf p5 connection + * \param ind A data structure for the decoded STOP.indication This will + * have been allocated on the stack. + * \return not currently used. + * + * The STOP.indication contains the result of the STOP.request + * + * + * ind may contain pointers to dynamically allocated sub structures + * such as the vendor_extention. The dynamically allocated structure will + * be deallocated on return. If the client wishes to 'keep' the structures + * then the substructure pointers should be set to 0 and then the client should + * use the codec_config.deallocate function to release it at a future point + */ + int (*nr_stop_ind)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_stop_indication_scf_t* ind); + /*! A callback for the PNF_STOP.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection @@ -640,6 +658,7 @@ int nfapi_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_star * \return 0 means success, -1 failure */ int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req); +int nfapi_nr_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_stop_request_scf_t* req); /*! Send the MEASUREMENT.request * \param config A pointer to a vnf config diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index b61d5f26ae..84d4026188 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -665,6 +665,30 @@ void vnf_nr_handle_error_indication(void *pRecvMsg, int recvMsgLen, nfapi_vnf_co } } +void vnf_nr_handle_stop_indication(void* pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } else { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received STOP.indication\n"); + + nfapi_nr_stop_indication_scf_t msg; + + // unpack the message + if (config->unpack_func(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config)) { + if (config->nr_stop_ind) { + (config->nr_stop_ind)(config, p5_idx, &msg); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dynamic part of the message + if (msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} void vnf_handle_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { @@ -1172,6 +1196,10 @@ void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfa vnf_handle_stop_response(pRecvMsg, recvMsgLen, config, p5_idx); break; + case NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION: + vnf_nr_handle_stop_indication(pRecvMsg, recvMsgLen, config, p5_idx); + break; + default: { if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 111d88e8dc..d421976cf1 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -665,6 +665,18 @@ int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_reques return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_stop_request_t)); } + +int nfapi_nr_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_stop_request_scf_t* req) +{ + if (config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + AssertFatal(config->send_p5_msg, "Function pointer must be configured\n"); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Sending NFAPI STOP.request\n"); + return config->send_p5_msg(_this, p5_idx, &req->header, sizeof(nfapi_nr_stop_request_scf_t)); +} + int nfapi_vnf_measurement_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_measurement_request_t* req) { if(config == 0 || req == 0) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c index 3fece46ac8..374ecb4b19 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c @@ -36,7 +36,6 @@ #include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "SCHED_NR/sched_nr.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "defs.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/utils/LOG/log.h" diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c index b23db3781d..1d9aa53d25 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c @@ -38,7 +38,6 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/defs_gNB.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "SCHED_NR/sched_nr.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 60bc63dac4..58ad0f2449 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -39,11 +39,13 @@ #include #include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/NR_REFSIG/nr_refsig.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" #include #include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h" +static void init_DLSCH_struct(PHY_VARS_gNB *gNB); +static void destroy_DLSCH_struct(const PHY_VARS_gNB *gNB); + int l1_north_init_gNB() { AssertFatal(RC.nb_nr_L1_inst > 0, "Failed to init PHY callbacks: nb_nr_L1_inst = %d\n", RC.nb_nr_L1_inst); @@ -58,7 +60,6 @@ int l1_north_init_gNB() LOG_D(NR_PHY, "RC.gNB[%d]: installing callbacks\n", i); RC.gNB[i]->if_inst->NR_PHY_config_req = nr_phy_config_request; - RC.gNB[i]->if_inst->NR_Schedule_response = nr_schedule_response; } return 0; @@ -104,9 +105,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) // shortcuts NR_DL_FRAME_PARMS *const fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - NR_gNB_COMMON *const common_vars = &gNB->common_vars; - NR_gNB_PRACH *const prach_vars = &gNB->prach_vars; - + NR_gNB_COMMON *const common_vars = &gNB->common_vars; common_vars->analog_bf = cfg->analog_beamforming_ve.analog_bf_vendor_ext.value; LOG_I(PHY, "L1 configured with%s analog beamforming\n", common_vars->analog_bf ? "" : "out"); if (common_vars->analog_bf) { @@ -157,6 +156,8 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) /// Transport init necessary for NR synchro init_nr_transport(gNB); + init_DLSCH_struct(gNB); + gNB->nr_srs_info = (nr_srs_info_t **)malloc16_clear(gNB->max_nb_srs * sizeof(nr_srs_info_t*)); for (int id = 0; id < gNB->max_nb_srs; id++) { gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); @@ -175,8 +176,10 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) if (cfg->analog_beamforming_ve.analog_bf_vendor_ext.value) { common_vars->beam_id = (int **)malloc16(common_vars->num_beams_period * sizeof(int*)); - for (int i = 0; i < common_vars->num_beams_period; i++) - common_vars->beam_id[i] = (int*)malloc16_clear(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int)); + for (int i = 0; i < common_vars->num_beams_period; i++) { + common_vars->beam_id[i] = (int*)malloc16(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int)); + memset(common_vars->beam_id[i], -1, fp->symbols_per_slot * fp->slots_per_frame * sizeof(int)); + } } common_vars->txdataF = (c16_t ***)malloc16(common_vars->num_beams_period * sizeof(c16_t**)); for (int i = 0; i < common_vars->num_beams_period; i++) { @@ -188,10 +191,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) common_vars->debugBuff_sample_offset = 0; // PRACH - prach_vars->rxsigF = (int16_t **)malloc16_clear(Prx*sizeof(int16_t*)); - prach_vars->prach_ifft = (int32_t *)malloc16_clear(1024*2*sizeof(int32_t)); - - init_prach_list(gNB); + init_prach_list(&gNB->prach_list); int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value; int n_buf = Prx*max_ul_mimo_layers; @@ -244,6 +244,8 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) reset_nr_transport(gNB); + destroy_DLSCH_struct(gNB); + NR_gNB_COMMON * common_vars = &gNB->common_vars; for (int j = 0; j < common_vars->num_beams_period; j++) { if (common_vars->beam_id) @@ -264,10 +266,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(common_vars->debugBuff); - NR_gNB_PRACH* prach_vars = &gNB->prach_vars; - free_and_zero(prach_vars->rxsigF); - free_and_zero(prach_vars->prach_ifft); - for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; for (int i = 0; i < n_buf; i++) { @@ -288,13 +286,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) } -//Adding nr_schedule_handler -void install_nr_schedule_handlers(NR_IF_Module_t *if_inst) -{ - if_inst->NR_PHY_config_req = nr_phy_config_request; - if_inst->NR_Schedule_response = nr_schedule_response; -} - void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, int N_RB_DL, int N_RB_UL, @@ -373,7 +364,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ; int32_t dlul_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; - fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset); + fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset, dl_bw_khz, ul_bw_khz); LOG_I(PHY, "DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, dlul_offset); @@ -408,37 +399,27 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) init_timeshift_rotation(fp); } -void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) +static void init_DLSCH_struct(PHY_VARS_gNB *gNB) { NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value; - msg->num_pdsch_slot = 0; - - msg->dlsch = malloc16(gNB->max_nb_pdsch * sizeof(NR_gNB_DLSCH_t *)); - int num_cw = NR_MAX_NB_LAYERS > 4? 2:1; + gNB->dlsch = calloc(gNB->max_nb_pdsch, sizeof(*gNB->dlsch)); for (int i = 0; i < gNB->max_nb_pdsch; i++) { LOG_D(PHY, "Allocating Transport Channel Buffers for DLSCH %d/%d\n", i, gNB->max_nb_pdsch); - msg->dlsch[i] = (NR_gNB_DLSCH_t *)malloc16(num_cw * sizeof(NR_gNB_DLSCH_t)); - for (int j = 0; j < num_cw; j++) { - msg->dlsch[i][j] = new_gNB_dlsch(fp, grid_size); - } + gNB->dlsch[i] = new_gNB_dlsch(fp, grid_size); } } -void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) +static void destroy_DLSCH_struct(const PHY_VARS_gNB *gNB) { const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; const nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; const uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value; - int num_cw = NR_MAX_NB_LAYERS > 4? 2:1; for (int i = 0; i < gNB->max_nb_pdsch; i++) { - for (int j = 0; j < num_cw; j++) { - free_gNB_dlsch(&msg->dlsch[i][j], grid_size, fp); - } - free(msg->dlsch[i]); + free_gNB_dlsch(&gNB->dlsch[i], grid_size, fp); } - free(msg->dlsch); + free(gNB->dlsch); } void init_nr_transport(PHY_VARS_gNB *gNB) diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index a0766c348f..71418bb1e3 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -27,8 +27,6 @@ #include #include "openair1/PHY/defs_RU.h" -void init_prach_ru_list(RU_t *ru); - void nr_phy_init_RU(RU_t *ru) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; @@ -53,8 +51,10 @@ void nr_phy_init_RU(RU_t *ru) int nb_rx_streams = ru->nb_rx * ru->num_beams_period; LOG_I(NR_PHY, "nb_tx_streams %d, nb_rx_streams %d, num_Beams_period %d\n", nb_tx_streams, nb_rx_streams, ru->num_beams_period); ru->common.beam_id = malloc16_clear(ru->num_beams_period * sizeof(int*)); - for(int i = 0; i < ru->num_beams_period; i++) - ru->common.beam_id[i] = malloc16_clear(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int)); + for(int i = 0; i < ru->num_beams_period; i++) { + ru->common.beam_id[i] = malloc16(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int)); + memset(ru->common.beam_id[i], -1, fp->symbols_per_slot * fp->slots_per_frame * sizeof(int)); + } if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so allocate memory for time-domain signals // Time-domain signals @@ -112,25 +112,10 @@ void nr_phy_init_RU(RU_t *ru) LOG_D(PHY, "rxdataF[%d] %p for RU %d\n", i, ru->common.rxdataF[i], ru->idx); } - /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */ - // AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]), - // "nb_antennas_rx too large"); - for (int j = 0; j < NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX; j++) { - ru->prach_rxsigF[j] = (int16_t**)malloc(nb_rx_streams * sizeof(int16_t*)); - - for (int i = 0; i < nb_rx_streams; i++) { - // largest size for PRACH FFT is 4x98304 (16*24576) - ru->prach_rxsigF[j][i] = (int16_t*)malloc16_clear(4 * 98304 * 2 * sizeof(int16_t)); - LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n", i, ru->prach_rxsigF[j][i]); - } - } - AssertFatal(ru->num_gNB <= NUMBER_OF_gNB_MAX, "gNB instances %d > %d\n", ru->num_gNB,NUMBER_OF_gNB_MAX); LOG_D(PHY, "[INIT] %s() ru->num_gNB:%d \n", __FUNCTION__, ru->num_gNB); } // !=IF5 - - init_prach_ru_list(ru); } void nr_phy_free_RU(RU_t *ru) @@ -172,11 +157,6 @@ void nr_phy_free_RU(RU_t *ru) free_and_zero(ru->common.rxdataF[i]); free_and_zero(ru->common.rxdataF); - for (int j = 0; j < NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX; j++) { - for (int i = 0; i < nb_rx_streams; i++) - free_and_zero(ru->prach_rxsigF[j][i]); - free_and_zero(ru->prach_rxsigF[j]); - } for(int i = 0; i < ru->num_beams_period; ++i) free_and_zero(ru->common.beam_id[i]); free_and_zero(ru->common.beam_id); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index e617b08172..7ab8a8863d 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -157,6 +157,9 @@ void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue) for (int j=0; jnb_antennas_rx; j++) { prs_vars[idx]->prs_resource[k].prs_meas[j] = malloc16_clear(sizeof(prs_meas_t)); AssertFatal((prs_vars[idx]->prs_resource[k].prs_meas[j]!=NULL), "%s: PRS measurements malloc failed for gNB_id %d, rx_ant %d\n", __FUNCTION__, idx, j); + prs_meas_t *m = prs_vars[idx]->prs_resource[k].prs_meas[j]; + m->next_dl_toa = m->dl_toa; + pthread_mutex_init(&m->dl_toa_mtx, NULL); } } } diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 2ace21eab5..cc31dc173a 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -379,15 +379,13 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->N_RB_SL = config->carrier_config.sl_grid_size[fp->numerology_index]; fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index); - int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index); + int64_t uplink_frequency_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; uplink_frequency_offset *= 1000; - LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset); + LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %ld Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset); AssertFatal(fp->frame_type==config->cell_config.frame_duplex_type, "Invalid duplex type (frame_type %d,cell_config.frame_duplex_type %d) in config request file for band %d\n", fp->frame_type,config->cell_config.frame_duplex_type,fp->nr_band); - AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset), "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + uplink_frequency_offset); - LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",fp->numerology_index, fp->N_RB_DL, Ncp); @@ -508,7 +506,7 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, fp->ofdm_offset_divisor = ofdm_offset_divisor; fp->threequarter_fs = threequarter_fs; - fp->nr_band = get_band(config->sl_carrier_config.sl_frequency, 0); + fp->nr_band = get_band(config->sl_carrier_config.sl_frequency, 0, 0, 0); fp->att_rx = 0; fp->att_tx = 0; @@ -522,8 +520,6 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, fp->Ncp = config->sl_bwp_config.sl_cyclic_prefix; fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index); - int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index); - uplink_frequency_offset *= 1000; uint64_t bw_khz = (12 * config->sl_carrier_config.sl_grid_size) * (15 << config->sl_bwp_config.sl_scs); // REfer to section 3GPP spec 38.101 5.4E.2.1 @@ -539,20 +535,14 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, LOG_D(PHY, "CarrierFreq %lu Hz\n", fp->sl_CarrierFreq); LOG_I(PHY, - "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz SL frequency %lu Hz: band %d, uldl offset %d Hz\n", + "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz SL frequency %lu Hz: band %d\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->sl_CarrierFreq, - fp->nr_band, - uplink_frequency_offset); + fp->nr_band); AssertFatal(fp->frame_type == TDD, "Sidelink bands only support TDD"); - AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset), - "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", - fp->nr_band, - fp->ul_CarrierFreq, - fp->dl_CarrierFreq + uplink_frequency_offset); LOG_I(PHY, "Initializing frame parms for mu %d, N_RB %d, Ncp %d\n", fp->numerology_index, fp->N_RB_DL, fp->Ncp); diff --git a/openair1/PHY/INIT/nr_phy_init.h b/openair1/PHY/INIT/nr_phy_init.h index 1b1a0fa1b0..f556498f0f 100644 --- a/openair1/PHY/INIT/nr_phy_init.h +++ b/openair1/PHY/INIT/nr_phy_init.h @@ -46,9 +46,6 @@ int l1_north_init_gNB(void); void init_nr_transport(PHY_VARS_gNB *gNB); void reset_nr_transport(PHY_VARS_gNB *gNB); -void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg); -void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg); - void RCconfig_nrUE_prs(void *cfg); void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue); void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb); diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 64886a2809..996a66b343 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -117,14 +117,12 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp); void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp); -void apply_nr_rotation_RX(const NR_DL_FRAME_PARMS *frame_parms, - c16_t *rxdataF, - const c16_t *rot, - int slot, - int nb_rb, - int soffset, - int first_symbol, - int nsymb); +void apply_nr_rotation_symbol_RX(const NR_DL_FRAME_PARMS *frame_parms, + c16_t *rxdataF, + const c16_t *rot, + int nb_rb, + int slot, + int symbol); /*! \brief Perform NR precoding. TS 38.211 V15.4.0 subclause 6.3.1.5 @param[in] datatx_F_precoding, Pointer to n_layers*re data array diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index cad3f92c33..50e19d8563 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -28,6 +28,36 @@ #include "PHY/nr_phy_common/inc/nr_phy_common.h" #include +/* rxdataF should be 16 bytes aligned */ +void nr_symbol_fep(const NR_DL_FRAME_PARMS *frame_parms, + const int slot, + const unsigned char symbol, + const int link_type, + c16_t *rxdata[frame_parms->nb_antennas_rx], + c16_t *rxdataF[frame_parms->nb_antennas_rx], + time_stats_t* dft_stats) +{ + AssertFatal(symbol < frame_parms->symbols_per_slot, + "slot_fep: symbol must be between 0 and %d\n", + frame_parms->symbols_per_slot - 1); + AssertFatal(slot < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame - 1); + + dft_size_idx_t dftsize = get_dft(frame_parms->ofdm_symbol_size); + for (unsigned char aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + if (dft_stats) start_meas(dft_stats); + dft(dftsize, (int16_t *)rxdata[aa], (int16_t *)rxdataF[aa], 1); + if (dft_stats) stop_meas(dft_stats); + + const bool is_sl = (link_type == link_type_sl); + apply_nr_rotation_symbol_RX(frame_parms, + rxdataF[aa], + frame_parms->symbol_rotation[link_type], + is_sl ? frame_parms->N_RB_SL : frame_parms->N_RB_DL, + slot, + symbol); + } +} + int nr_slot_fep(PHY_VARS_NR_UE *ue, const NR_DL_FRAME_PARMS *frame_parms, unsigned int slot, @@ -37,35 +67,23 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, uint32_t sample_offset, c16_t **rxdata) { - AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1); + AssertFatal(symbol < frame_parms->symbols_per_slot, + "slot_fep: symbol must be between 0 and %d\n", + frame_parms->symbols_per_slot - 1); AssertFatal(slot < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame - 1); - bool is_sl = (linktype == link_type_sl) ? true : false; + bool is_sl = (linktype == link_type_sl); bool is_synchronized = (ue) ? ue->is_synchronized : false; - unsigned int nb_prefix_samples; - unsigned int nb_prefix_samples0; + unsigned int nb_prefix_samples = frame_parms->nb_prefix_samples; + unsigned int nb_prefix_samples0 = (is_synchronized || is_sl) ? frame_parms->nb_prefix_samples0 : nb_prefix_samples; + // For Sidelink 16 frames worth of samples is processed to find SSB, for 5G-NR 2. - unsigned int total_samples = (is_sl) ? 16 * frame_parms->samples_per_frame : 2 * frame_parms->samples_per_frame; - - int N_RB = (is_sl) ? frame_parms->N_RB_SL : frame_parms->N_RB_DL; - - if (is_synchronized || is_sl) { - nb_prefix_samples = frame_parms->nb_prefix_samples; - nb_prefix_samples0 = frame_parms->nb_prefix_samples0; - } else { - nb_prefix_samples = frame_parms->nb_prefix_samples; - nb_prefix_samples0 = frame_parms->nb_prefix_samples; - AssertFatal(slot == 0, "Slot should be 0\n"); - } - - dft_size_idx_t dftsize = get_dft(frame_parms->ofdm_symbol_size); - // This is for misalignment issues - c16_t tmp_dft_in[frame_parms->ofdm_symbol_size] __attribute__ ((aligned (32))); + const unsigned int total_samples = (is_sl) ? 16 * frame_parms->samples_per_frame : 2 * frame_parms->samples_per_frame; unsigned int rx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); - unsigned int abs_symbol = slot * frame_parms->symbols_per_slot + symbol; + const unsigned int abs_symbol = slot * frame_parms->symbols_per_slot + symbol; for (int idx_symb = slot * frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) - rx_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rx_offset += (idx_symb % (0x7 << frame_parms->numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; rx_offset += frame_parms->ofdm_symbol_size * symbol; rx_offset += sample_offset; @@ -73,48 +91,47 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, // use OFDM symbol from within 1/8th of the CP to avoid ISI rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor); - rx_offset %= total_samples; - - for (unsigned char aa=0; aanb_antennas_rx; aa++) { - c16_t *rxdata_ptr = &rxdata[aa][rx_offset]; + LOG_D(PHY, + "slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u energy %d\n", + slot, + symbol, + nb_prefix_samples, + nb_prefix_samples0, + rx_offset, + dB_fixed(signal_energy((int32_t *)&rxdata[0][rx_offset], frame_parms->ofdm_symbol_size))); + c16_t tmp_dft_in[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); + c16_t *rxdata_symb_ptr[frame_parms->nb_antennas_rx]; + c16_t *rxdataF_symb_ptr[frame_parms->nb_antennas_rx]; + for (unsigned char aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + rxdataF_symb_ptr[aa] = &rxdataF[aa][frame_parms->ofdm_symbol_size * symbol]; // This happens only during initial sync if (rx_offset + frame_parms->ofdm_symbol_size > total_samples) { - // rxdata is 2 frames len // we have to wrap on the end - - memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], (total_samples - rx_offset) * sizeof(int32_t)); - memcpy((void *)&tmp_dft_in[total_samples - rx_offset], - (void *)&rxdata[aa][0], + memcpy(&tmp_dft_in[aa][0], &rxdata[aa][rx_offset], (total_samples - rx_offset) * sizeof(int32_t)); + memcpy(&tmp_dft_in[aa][total_samples - rx_offset], + &rxdata[aa][0], (frame_parms->ofdm_symbol_size - (total_samples - rx_offset)) * sizeof(int32_t)); - rxdata_ptr = tmp_dft_in; - - } else if ((rx_offset & 7) != 0) { // if input to dft is not 256-bit aligned - memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], frame_parms->ofdm_symbol_size * sizeof(int32_t)); - rxdata_ptr = tmp_dft_in; + rxdata_symb_ptr[aa] = tmp_dft_in[aa]; + } else { + rxdata_symb_ptr[aa] = &rxdata[aa][rx_offset]; } if (ue && ue->cont_fo_comp) { start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS); - nr_fo_compensation(ue->freq_offset, frame_parms->samples_per_subframe, rx_offset, rxdata_ptr, tmp_dft_in, frame_parms->ofdm_symbol_size); - rxdata_ptr = tmp_dft_in; + nr_fo_compensation(ue->freq_offset, + frame_parms->samples_per_subframe, + rx_offset, + rxdata_symb_ptr[aa], + tmp_dft_in[aa], + frame_parms->ofdm_symbol_size); stop_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS); + rxdata_symb_ptr[aa] = tmp_dft_in[aa]; } - - if (ue) - start_meas_nr_ue_phy(ue, RX_DFT_STATS); - - dft(dftsize, - (int16_t *)rxdata_ptr, - (int16_t *)&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], - 1); - - if (ue) - stop_meas_nr_ue_phy(ue, RX_DFT_STATS); - - apply_nr_rotation_RX(frame_parms, rxdataF[aa], frame_parms->symbol_rotation[linktype], slot, N_RB, 0, symbol, 1); } - + time_stats_t* dft_stats = NULL; + if (ue) dft_stats = &ue->phy_cpu_stats.cpu_time_stats[RX_DFT_STATS]; + nr_symbol_fep(frame_parms, slot, symbol, linktype, rxdata_symb_ptr, rxdataF_symb_ptr, dft_stats); return 0; } @@ -177,54 +194,46 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, return 0; } -void apply_nr_rotation_RX(const NR_DL_FRAME_PARMS *frame_parms, - c16_t *rxdataF, - const c16_t *rot, - int slot, - int nb_rb, - int soffset, - int first_symbol, - int nsymb) +void apply_nr_rotation_symbol_RX(const NR_DL_FRAME_PARMS *frame_parms, + c16_t *rxdataF, + const c16_t *rot, + int nb_rb, + int slot, + int symbol) { - AssertFatal(first_symbol + nsymb <= NR_NUMBER_OF_SYMBOLS_PER_SLOT, - "First symbol %d and number of symbol %d not compatible with number of symbols in a slot %d\n", - first_symbol, nsymb, NR_NUMBER_OF_SYMBOLS_PER_SLOT); - int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot; + const int symb_offset = (slot % frame_parms->slots_per_subframe) * frame_parms->symbols_per_slot; - for (int symbol = first_symbol; symbol < first_symbol + nsymb; symbol++) { - - c16_t rot2 = rot[symbol + symb_offset]; - rot2.i = -rot2.i; - LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i); - const c16_t *shift_rot = frame_parms->timeshift_symbol_rotation; - c16_t *this_symbol = &rxdataF[soffset + (frame_parms->ofdm_symbol_size * symbol)]; + c16_t rot2 = rot[symbol + symb_offset]; + rot2.i = -rot2.i; + LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n", slot, symb_offset, rot2.r, rot2.i); + const c16_t *shift_rot = frame_parms->timeshift_symbol_rotation; + c16_t *this_symbol = rxdataF; - if (nb_rb & 1) { - rotate_cpx_vector(this_symbol, &rot2, this_symbol, - (nb_rb + 1) * 6, 15); - rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, - &rot2, - this_symbol + frame_parms->first_carrier_offset - 6, - (nb_rb + 1) * 6, 15); - mult_cpx_vector(this_symbol, shift_rot, this_symbol, (nb_rb + 1) * 6, 15); - mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, - shift_rot + frame_parms->first_carrier_offset - 6, + if (nb_rb & 1) { + rotate_cpx_vector(this_symbol, &rot2, this_symbol, (nb_rb + 1) * 6, 15); + rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, + &rot2, this_symbol + frame_parms->first_carrier_offset - 6, (nb_rb + 1) * 6, 15); - } else { - rotate_cpx_vector(this_symbol, &rot2, this_symbol, - nb_rb * 6, 15); - rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset, - &rot2, - this_symbol + frame_parms->first_carrier_offset, - nb_rb * 6, 15); - mult_cpx_vector(this_symbol, shift_rot, this_symbol, nb_rb * 6, 15); - mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset, - shift_rot + frame_parms->first_carrier_offset, + mult_cpx_vector(this_symbol, shift_rot, this_symbol, (nb_rb + 1) * 6, 15); + mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset - 6, + shift_rot + frame_parms->first_carrier_offset - 6, + this_symbol + frame_parms->first_carrier_offset - 6, + (nb_rb + 1) * 6, + 15); + } else { + rotate_cpx_vector(this_symbol, &rot2, this_symbol, nb_rb * 6, 15); + rotate_cpx_vector(this_symbol + frame_parms->first_carrier_offset, + &rot2, this_symbol + frame_parms->first_carrier_offset, nb_rb * 6, 15); - } + mult_cpx_vector(this_symbol, shift_rot, this_symbol, nb_rb * 6, 15); + mult_cpx_vector(this_symbol + frame_parms->first_carrier_offset, + shift_rot + frame_parms->first_carrier_offset, + this_symbol + frame_parms->first_carrier_offset, + nb_rb * 6, + 15); } } diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 2e6e4a54a6..a1fde35b00 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -136,7 +136,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy // TODO modify the measurements to take into account concurrent beams for (int s = first_symb; s < first_symb + num_symb; s++) { - int offset0 = ((slot&3)*frame_parms->symbols_per_slot + s) * frame_parms->ofdm_symbol_size; + int offset0 = ((slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot + s) * frame_parms->ofdm_symbol_size; for (int rb = 0; rb < frame_parms->N_RB_UL; rb++) { if ((rb_mask_ul[s][rb >> 5] & (1U << (rb & 31))) == 0 && // check that rb was not used in this subframe !(I0_SKIP_DC && rb == frame_parms->N_RB_UL >> 1)) { // skip middle PRB because of artificial noise possibly created by FFT @@ -188,74 +188,3 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy } } } - -// Scope: This function computes the UL SNR from the UL channel estimates -// -// Todo: -// - averaging IIR filter for RX power and noise -void nr_gnb_measurements(PHY_VARS_gNB *gNB, - NR_gNB_ULSCH_t *ulsch, - NR_gNB_PUSCH *pusch_vars, - unsigned char symbol, - uint8_t nrOfLayers) -{ - uint32_t rx_power_tot = 0; - unsigned short rx_power_avg_dB; - unsigned short rx_power_tot_dB; - RU_t *ru = gNB->RU_list[0]; - double rx_gain, rx_gain_offset; - if (ru && ru->rfdevice.openair0_cfg) { - rx_gain = ru->rfdevice.openair0_cfg->rx_gain[0]; - rx_gain_offset = ru->rfdevice.openair0_cfg->rx_gain_offset[0]; - } else if (ru && ru->ifdevice.openair0_cfg) { - rx_gain = ru->ifdevice.openair0_cfg->rx_gain[0]; - rx_gain_offset = ru->ifdevice.openair0_cfg->rx_gain_offset[0]; - } else { - LOG_W(NR_PHY, "no device for rx gain, take arbitrary gain = 1)\n"); - rx_gain = 1; - rx_gain_offset = 0; - } - PHY_MEASUREMENTS_gNB *meas = &gNB->measurements; - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - int ch_offset = fp->ofdm_symbol_size * symbol; - int N_RB_UL = ulsch->harq_process->ulsch_pdu.rb_size; - ulsch_measurements_gNB *ulsch_measurements = &ulsch->ulsch_measurements; - - int rx_power[fp->nb_antennas_rx]; - int rx_spatial_power[nrOfLayers][fp->nb_antennas_rx]; - for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++){ - rx_power[aarx] = 0; - - for (int aatx = 0; aatx < nrOfLayers; aatx++){ - rx_spatial_power[aatx][aarx] = - (signal_energy_nodc((c16_t*)&pusch_vars->ul_ch_estimates[aatx * fp->nb_antennas_rx + aarx][ch_offset], - N_RB_UL * NR_NB_SC_PER_RB)); - - if (rx_spatial_power[aatx][aarx] < 0) { - rx_spatial_power[aatx][aarx] = 0; - } - - rx_power[aarx] += rx_spatial_power[aatx][aarx]; - } - LOG_D(PHY, "[RNTI %04x] RX power in antenna %d = %d\n", ulsch->rnti, aarx, rx_power[aarx]); - - rx_power_tot += rx_power[aarx]; - } - - rx_power_tot_dB = (unsigned short)dB_fixed(rx_power_tot); - rx_power_avg_dB = rx_power_tot_dB; - - ulsch_measurements->wideband_cqi_tot = dB_fixed2(rx_power_tot, meas->n0_power_tot); - ulsch_measurements->rx_rssi_dBm = - rx_power_avg_dB + 30 - SQ15_SQUARED_NORM_FACTOR_DB - (rx_gain - rx_gain_offset) - dB_fixed(fp->ofdm_symbol_size); - - LOG_D(PHY, - "[RNTI %04x] RSSI %d dBm/RE, RSSI (digital) %d dB (N_RB_UL %d), WBand CQI tot %d dB, N0 Power tot %d, RX Power tot %d\n", - ulsch->rnti, - ulsch_measurements->rx_rssi_dBm, - rx_power_avg_dB, - N_RB_UL, - ulsch_measurements->wideband_cqi_tot, - meas->n0_power_tot, - rx_power_tot); -} diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 93d7feebe0..d73a315354 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -111,7 +111,7 @@ static void nr_pusch_antenna_processing(void *arg) c16_t **ul_ch_estimates = (c16_t **)pusch_vars->ul_ch_estimates; NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms; const int symbolSize = frame_parms->ofdm_symbol_size; - const int slot_offset = (Ns & 3) * frame_parms->symbols_per_slot * symbolSize; + const int slot_offset = (Ns % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * symbolSize; const int delta = get_delta(p, pusch_pdu->dmrs_config_type); const int symbol_offset = symbolSize * symbol; const int k0 = bwp_start_subcarrier; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 04377db1b8..7e0a2a97bd 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -59,12 +59,6 @@ void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][9]); -void nr_gnb_measurements(PHY_VARS_gNB *gNB, - NR_gNB_ULSCH_t *ulsch, - NR_gNB_PUSCH *pusch_vars, - unsigned char symbol, - uint8_t nrOfLayers); - int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, const c16_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]); diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 7fd703ea30..3624d754e9 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -150,24 +150,11 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, return(0); } -int nr_pdcch_dmrs_rx(const PHY_VARS_NR_UE *ue, - unsigned int Ns, - const unsigned int *nr_gold_pdcch, - c16_t *output, - unsigned short p, - unsigned short nb_rb_coreset) +void nr_pdcch_dmrs_ref(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_coreset) { - if (p==2000) { - for (int i=0; i<((nb_rb_coreset*6)>>1); i++) { - output[i] = get_modulated(nr_gold_pdcch, i, true); -#ifdef DEBUG_PDCCH - if (i<8) - printf("i %d idx %d pdcch mod_dmrs %d %d\n", i, idx, output[i].r, output[i].i); -#endif - } + for (int i = 0; i < ((nb_rb_coreset * 6) >> 1); i++) { + output[i] = get_modulated(nr_gold_pdcch, i, true); } - - return(0); } void nr_pbch_dmrs_rx(int symbol, const unsigned int *nr_gold_pbch, c16_t *output, bool sidelink) diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index 1d2d4b87ae..fb7dce4489 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -35,12 +35,7 @@ void nr_pbch_dmrs_rx(int dmrss, const unsigned int *nr_gold_pbch, c16_t *output, /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS. @param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables */ -int nr_pdcch_dmrs_rx(const PHY_VARS_NR_UE *ue, - unsigned int Ns, - const unsigned int *nr_gold_pdcch, - c16_t *output, - unsigned short p, - unsigned short nb_rb_corset); +void nr_pdcch_dmrs_ref(const unsigned int *nr_gold_pdcch, c16_t *output, unsigned short nb_rb_corset); int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned int Ns, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 0548c8fc10..2df2df8eb0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -51,11 +51,11 @@ static void nr_pdcch_scrambling(uint32_t *in, uint32_t size, uint32_t Nid, uint3 out[i] = in[i] ^ seq[i]; } -static void nr_generate_dci(PHY_VARS_gNB *gNB, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, - int txdataF_offset, - NR_DL_FRAME_PARMS *frame_parms, - int slot) +void nr_generate_dci(PHY_VARS_gNB *gNB, + const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + int txdataF_offset, + NR_DL_FRAME_PARMS *frame_parms, + int slot) { // fill reg list per symbol int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE]; @@ -237,16 +237,3 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, *(unsigned long long *)dci_pdu->Payload); } // for (int d=0;dnumDlDci;d++) } - -void nr_generate_dci_top(processingData_L1tx_t *msgTx, int slot, int txdataF_offset) -{ - PHY_VARS_gNB *gNB = msgTx->gNB; - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - start_meas(&gNB->dci_generation_stats); - for (int i = 0; i < msgTx->num_ul_pdcch; i++) - nr_generate_dci(msgTx->gNB, &msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, frame_parms, slot); - for (int i = 0; i < msgTx->num_dl_pdcch; i++) - nr_generate_dci(msgTx->gNB, &msgTx->pdcch_pdu[i].pdcch_pdu_rel15, txdataF_offset, frame_parms, slot); - stop_meas(&gNB->dci_generation_stats); -} - diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.h b/openair1/PHY/NR_TRANSPORT/nr_dci.h index e735069975..57651f03a2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.h @@ -26,7 +26,11 @@ #include "PHY/NR_REFSIG/nr_refsig.h" #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h" -void nr_generate_dci_top(processingData_L1tx_t *msgTx, int slot, int txdataF_offset); +void nr_generate_dci(PHY_VARS_gNB *gNB, + const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + int txdataF_offset, + NR_DL_FRAME_PARMS *frame_parms, + int slot); int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type); @@ -42,6 +46,6 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB, int slot, nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu); -void nr_fill_reg_list(int cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15); +void nr_fill_reg_list(int cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15); #endif //__PHY_NR_TRANSPORT_DCI__H diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index 538b54ac0b..c2d2ab7a24 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -42,7 +42,7 @@ int compfunc(const void *a, const void *b) return (*(int *)a - *(int *)b); } -void nr_fill_reg_list(int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15) +void nr_fill_reg_list(int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15) { int bsize = pdcch_pdu_rel15->RegBundleSize; int R = pdcch_pdu_rel15->InterleaverSize; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 535c68f419..8df7b4814c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -51,7 +51,7 @@ static void nr_pdsch_codeword_scrambling(uint8_t *in, uint32_t size, uint8_t q, nr_codeword_scrambling(in, size, q, Nid, n_RNTI, out); } -static int do_ptrs_symbol(nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, +static int do_ptrs_symbol(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, int start_sc, int symbol_sz, c16_t *txF, @@ -339,7 +339,7 @@ static inline void neg_dmrs(c16_t *in, c16_t *out, int sz) static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, int slot, - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, int layer, c16_t *output, c16_t *txl_start, @@ -457,7 +457,7 @@ static inline void do_txdataF(c16_t **txdataF, int symbol_sz, c16_t txdataF_precoding[][symbol_sz], PHY_VARS_gNB *gNB, - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, int ant, int start_sc, int txdataF_offset_per_symbol) @@ -465,7 +465,7 @@ static inline void do_txdataF(c16_t **txdataF, NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; int rb = 0; uint16_t subCarrier = start_sc; - nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; + const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; while (rb < rel15->rbSize) { // get pmi info const int pmi = (pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0; @@ -555,8 +555,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC time_stats_t *dlsch_scrambling_stats = &gNB->dlsch_scrambling_stats; time_stats_t *dlsch_modulation_stats = &gNB->dlsch_modulation_stats; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; const int layerSz = frame_parms->N_RB_DL * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB; const int symbol_sz=frame_parms->ofdm_symbol_size; const int dmrs_Type = rel15->dmrsConfigType; @@ -580,7 +579,6 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC /* PTRS */ uint16_t dlPtrsSymPos = 0; int n_ptrs = 0; - uint32_t ptrsSymbPerSlot = 0; if (rel15->pduBitmap & 0x1) { set_ptrs_symb_idx(&dlPtrsSymPos, rel15->NrOfSymbols, @@ -588,15 +586,13 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC 1 << rel15->PTRSTimeDensity, rel15->dlDmrsSymbPos); n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity; - ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, rel15->StartSymbolIndex, rel15->NrOfSymbols); } - harq->unav_res = ptrsSymbPerSlot * n_ptrs; #ifdef DEBUG_DLSCH printf("PDSCH encoding:\nPayload:\n"); - for (int i = 0; i < (harq->B >> 3); i += 16) { + for (int i = 0; i < (dlsch->B >> 3); i += 16) { for (int j = 0; j < 16; j++) - printf("0x%02x\t", harq->pdu[i + j]); + printf("0x%02x\t", dlsch->pdu[i + j]); printf("\n"); } printf("\nEncoded payload:\n"); @@ -609,7 +605,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC #endif if (IS_SOFTMODEM_DLSIM) - memcpy(harq->f, input_ptr, (encoded_length + 7) >> 3); + memcpy(dlsch->f, input_ptr, (encoded_length + 7) >> 3); c16_t mod_symbs[rel15->NrOfCodewords][encoded_length] __attribute__((aligned(64))); for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) { @@ -680,7 +676,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC // pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1 // The Precoding matrix: // The Codebook Type I - nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; + const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; // beam number in multi-beam scenario (concurrent beams) int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols); int beam_nb = beam_index_allocation(gNB->enable_analog_das, @@ -777,9 +773,8 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC return ((size_output_tb + 511) >> 9) << 6; } -void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) +void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_array, int frame, int slot) { - PHY_VARS_gNB *gNB = msgTx->gNB; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; time_stats_t *dlsch_encoding_stats = &gNB->dlsch_encoding_stats; time_stats_t *tinput = &gNB->tinput; @@ -792,10 +787,9 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) size_t size_output = 0; - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + for (int i = 0; i < n_dlsch; i++) { + NR_gNB_DLSCH_t *dlsch = &dlsch_array[i]; + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; LOG_D(PHY, "pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n", @@ -819,10 +813,10 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity; ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, rel15->StartSymbolIndex, rel15->NrOfSymbols); } - harq->unav_res = ptrsSymbPerSlot * n_ptrs; + dlsch->unav_res = ptrsSymbPerSlot * n_ptrs; /// CRC, coding, interleaving and rate matching - AssertFatal(harq->pdu != NULL, "%4d.%2d no HARQ PDU for PDSCH generation\n", msgTx->frame, msgTx->slot); + AssertFatal(dlsch->pdu != NULL, "%4d.%2d no PDU for PDSCH generation\n", frame, slot); /* output and its parts for each dlsch should be aligned on 64 bytes (or 8 * 64 bits) * => size_output is a sum of parts sizes rounded up to a multiple of 8 * 64 @@ -836,7 +830,8 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) start_meas(dlsch_encoding_stats); if (nr_dlsch_encoding(gNB, - msgTx, + n_dlsch, + dlsch_array, frame, slot, frame_parms, @@ -854,8 +849,8 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) stop_meas(dlsch_encoding_stats); unsigned char *output_ptr = output; - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - output_ptr += do_one_dlsch(output_ptr, gNB, msgTx->dlsch[dlsch_id], slot); + for (int i = 0; i < n_dlsch; i++) { + output_ptr += do_one_dlsch(output_ptr, gNB, &dlsch_array[i], slot); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index 15f48825f5..0a82b2c47f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -35,15 +35,11 @@ #include "PHY/defs_gNB.h" -void nr_fill_dlsch_dl_tti_req(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu); -void nr_fill_dlsch_tx_req(processingData_L1tx_t *msgTx, int idx, uint8_t *sdu); - -void nr_generate_pdsch(processingData_L1tx_t *msgTx, - int frame, - int slot); +void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_array, int frame, int slot); int nr_dlsch_encoding(PHY_VARS_gNB *gNB, - processingData_L1tx_t *msgTx, + int n_dlsch, + NR_gNB_DLSCH_t *dlsch_array, int frame, uint8_t slot, NR_DL_FRAME_PARMS *frame_parms, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 56a849a4af..f74685ed71 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -52,20 +52,19 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM a_segments = a_segments / 273 + 1; } - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - if (harq->b) { - free16(harq->b, a_segments * 1056); - harq->b = NULL; + if (dlsch->b) { + free16(dlsch->b, a_segments * 1056); + dlsch->b = NULL; } - if (harq->f) { - free16(harq->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); - harq->f = NULL; + if (dlsch->f) { + free16(dlsch->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + dlsch->f = NULL; } for (int r = 0; r < a_segments; r++) { - free(harq->c[r]); - harq->c[r] = NULL; + free(dlsch->c[r]); + dlsch->c[r] = NULL; } - free(harq->c); + free(dlsch->c); } NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) @@ -80,34 +79,33 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) LOG_D(PHY, "Allocating %d segments (MAX %d, N_PRB %d)\n", a_segments, MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER, N_RB); uint32_t dlsch_bytes = a_segments * 1056; // allocated bytes per segment - NR_gNB_DLSCH_t dlsch; + NR_gNB_DLSCH_t dlsch = {0}; - NR_DL_gNB_HARQ_t *harq = &dlsch.harq_process; - bzero(harq, sizeof(NR_DL_gNB_HARQ_t)); - harq->b = malloc16(dlsch_bytes); - AssertFatal(harq->b, "cannot allocate memory for harq->b\n"); - bzero(harq->b, dlsch_bytes); + dlsch.b = malloc16(dlsch_bytes); + AssertFatal(dlsch.b, "cannot allocate memory for dlsch.b\n"); + bzero(dlsch.b, dlsch_bytes); - harq->c = (uint8_t **)malloc16(a_segments * sizeof(uint8_t *)); + dlsch.c = (uint8_t **)malloc16(a_segments * sizeof(uint8_t *)); for (int r = 0; r < a_segments; r++) { // account for filler in first segment and CRCs for multiple segment case // [hna] 8448 is the maximum CB size in NR // 68*348 = 68*(maximum size of Zc) // In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc) - harq->c[r] = malloc16(8448); - AssertFatal(harq->c[r], "cannot allocate harq->c[%d]\n", r); - bzero(harq->c[r], 8448); + dlsch.c[r] = malloc16(8448); + AssertFatal(dlsch.c[r], "cannot allocate dlsch.c[%d]\n", r); + bzero(dlsch.c[r], 8448); } - harq->f = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); - AssertFatal(harq->f, "cannot allocate harq->f\n"); - bzero(harq->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + dlsch.f = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + AssertFatal(dlsch.f, "cannot allocate dlsch->f\n"); + bzero(dlsch.f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); return (dlsch); } int nr_dlsch_encoding(PHY_VARS_gNB *gNB, - processingData_L1tx_t *msgTx, + int n_dlsch, + NR_gNB_DLSCH_t *dlsch_array, int frame, uint8_t slot, NR_DL_FRAME_PARMS *frame_parms, @@ -122,28 +120,18 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); - nrLDPC_TB_encoding_parameters_t TBs[msgTx->num_pdsch_slot]; + nrLDPC_TB_encoding_parameters_t TBs[n_dlsch]; memset(TBs, 0, sizeof(TBs)); - nrLDPC_slot_encoding_parameters_t slot_parameters = {.frame = frame, - .slot = slot, - .nb_TBs = msgTx->num_pdsch_slot, - .threadPool = &gNB->threadPool, - .tinput = tinput, - .tprep = tprep, - .tparity = tparity, - .toutput = toutput, - .TBs = TBs}; int num_segments = 0; - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; + for (int i = 0; i < n_dlsch; i++) { + NR_gNB_DLSCH_t *dlsch = &dlsch_array[i]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; unsigned int crc = 1; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; uint32_t A = rel15->TBSize[0] << 3; - unsigned char *a = harq->pdu; + unsigned char *a = dlsch->pdu; if (rel15->rnti != SI_RNTI) { ws_trace_t tmp = {.nr = true, .direction = DIRECTION_DOWNLINK, @@ -182,9 +170,8 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, // printf("CRC %x (A %d)\n",crc,A); // printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); B = A + 24; - // harq->b = a; AssertFatal((A / 8) + 4 <= max_bytes, "A %d is too big (A/8+4 = %d > %d)\n", A, (A / 8) + 4, max_bytes); - memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes? + memcpy(dlsch->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes? } else { // Add 16-bit crc (polynomial A) to payload crc = crc16(a, A) >> 16; @@ -193,21 +180,19 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, // printf("CRC %x (A %d)\n",crc,A); // printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); B = A + 16; - // harq->b = a; AssertFatal((A / 8) + 3 <= max_bytes, "A %d is too big (A/8+3 = %d > %d)\n", A, (A / 8) + 3, max_bytes); - memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc + memcpy(dlsch->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc } - nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i]; - // The harq_pid is not unique among the active HARQ processes in the instance so we use dlsch_id instead - TB_parameters->harq_unique_pid = dlsch_id; + // The harq_pid is not unique among the active HARQ processes in the instance so we use i instead + TB_parameters->harq_unique_pid = i; TB_parameters->BG = rel15->maintenance_parms_v3.ldpcBaseGraph; - TB_parameters->Z = harq->Z; TB_parameters->A = A; start_meas(dlsch_segmentation_stats); - TB_parameters->Kb = nr_segmentation(harq->b, - harq->c, + TB_parameters->Kb = nr_segmentation(dlsch->b, + dlsch->c, B, &TB_parameters->C, &TB_parameters->K, @@ -228,20 +213,19 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, size_t segments_offset = 0; size_t dlsch_offset = 0; - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + for (int i = 0; i < n_dlsch; i++) { + NR_gNB_DLSCH_t *dlsch = &dlsch_array[i]; + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; - nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i]; #ifdef DEBUG_DLSCH_CODING for (int r = 0; r < TB_parameters->C; r++) { - LOG_D(PHY, "Encoder: B %d F %d \n", harq->B, TB_parameters->F); + LOG_D(PHY, "Encoder: B %d F %d \n", dlsch->B, TB_parameters->F); LOG_D(PHY, "start ldpc encoder segment %d/%d\n", r, TB_parameters->C); - LOG_D(PHY, "input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2], harq->c[r][3], harq->c[r][4]); + LOG_D(PHY, "input %d %d %d %d %d \n", dlsch->c[r][0], dlsch->c[r][1], dlsch->c[r][2], dlsch->c[r][3], dlsch->c[r][4]); for (int cnt = 0; cnt < 22 * (TB_parameters->Z) / 8; cnt++) { - LOG_D(PHY, "%d ", harq->c[r][cnt]); + LOG_D(PHY, "%d ", dlsch->c[r][cnt]); } LOG_D(PHY, "\n"); } @@ -259,7 +243,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, rel15->NrOfSymbols, nb_re_dmrs, get_num_dmrs(rel15->dlDmrsSymbPos), - harq->unav_res, + dlsch->unav_res, rel15->qamModOrder[0], rel15->nrOfLayers); @@ -270,7 +254,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, for (int r = 0; r < TB_parameters->C; r++) { nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; - segment_parameters->c = harq->c[r]; + segment_parameters->c = dlsch->c[r]; segment_parameters->E = nr_get_E(TB_parameters->G, TB_parameters->C, TB_parameters->Qm, rel15->nrOfLayers, r); reset_meas(&segment_parameters->ts_interleave); @@ -287,10 +271,19 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, dlsch_offset += ceil_mod(dlsch_size, 8 * 64); } + nrLDPC_slot_encoding_parameters_t slot_parameters = {.frame = frame, + .slot = slot, + .nb_TBs = n_dlsch, + .threadPool = &gNB->threadPool, + .tinput = tinput, + .tprep = tprep, + .tparity = tparity, + .toutput = toutput, + .TBs = TBs}; gNB->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters); - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; + for (int i = 0; i < n_dlsch; i++) { + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i]; for (int r = 0; r < TB_parameters->C; r++) { nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; merge_meas(dlsch_interleaving_stats, &segment_parameters->ts_interleave); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c deleted file mode 100644 index 3f1d988c53..0000000000 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ /dev/null @@ -1,62 +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 PHY/NR_TRANSPORT/nr_dlsch_tools.c -* \brief Top-level routines for decoding DLSCH transport channel from 38-214, V15.2.0 2018-06 -* \author Guy De Souza -* \date 2018 -* \version 0.1 -* \company Eurecom -* \email: desouza@eurecom.fr -* \note - -* \warning -*/ - -#include "nr_dlsch.h" -#include "../../../nfapi/oai_integration/vendor_ext.h" - -void nr_fill_dlsch_dl_tti_req(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu) -{ - NR_gNB_DLSCH_t *dlsch = &msgTx->dlsch[msgTx->num_pdsch_slot][0]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - /// DLSCH struct - memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu)); - AssertFatal(msgTx->num_pdsch_slot == pdsch_pdu->pdsch_pdu_rel15.pduIndex, - "PDSCH PDU index %d does not match msgTx index %d\n", - pdsch_pdu->pdsch_pdu_rel15.pduIndex, - msgTx->num_pdsch_slot); - msgTx->num_pdsch_slot++; - harq->pdu = NULL; -} - -void nr_fill_dlsch_tx_req(processingData_L1tx_t *msgTx, int idx, uint8_t *sdu) -{ - AssertFatal(sdu != NULL, "sdu is null\n"); - - /* not sure if FAPI could transmit DL_TTI_req and TX_req in different orders. - * for the moment, assume they are in the same order (and check!) */ - NR_gNB_DLSCH_t *dlsch = &msgTx->dlsch[idx][0]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - nfapi_nr_dl_tti_pdsch_pdu *pdsch = &harq->pdsch_pdu; - AssertFatal(pdsch->pdsch_pdu_rel15.pduIndex == idx, "PDSCH PDU index %d does not match %d\n", pdsch->pdsch_pdu_rel15.pduIndex, idx); - harq->pdu = sdu; -} diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 76d9b1185f..823af815d3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -36,286 +36,230 @@ #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "openair1/PHY/NR_TRANSPORT/nr_prach.h" -void init_prach_list(PHY_VARS_gNB *gNB) +void init_prach_list(prach_list_t *l) { - AssertFatal(gNB != NULL, "gNB is null\n"); - for (int i = 0; i < NUMBER_OF_NR_PRACH_MAX; i++){ - gNB->prach_vars.list[i].frame = -1; - gNB->prach_vars.list[i].slot = -1; - gNB->prach_vars.list[i].num_slots = -1; - } + pthread_mutex_init(&l->prach_list_mutex, NULL); + for (prach_item_t *p = l->list; p < l->list + NUMBER_OF_NR_PRACH_MAX; p++) + *p = (prach_item_t){.frame = -1, .slot = -1}; } -void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id) +void free_nr_prach_entry(prach_list_t *l, prach_item_t *p) { - gNB->prach_vars.list[prach_id].frame = -1; - gNB->prach_vars.list[prach_id].slot = -1; - gNB->prach_vars.list[prach_id].num_slots = -1; - free_and_zero(gNB->prach_vars.list[prach_id].beam_nb); + pthread_mutex_lock(&l->prach_list_mutex); + if (p->frame == -1) + LOG_E(NR_PHY_RACH, "Freeing a not allocated prach entry\n"); + *p = (prach_item_t){.frame = -1, .slot = -1, .num_slots = -1}; + pthread_mutex_unlock(&l->prach_list_mutex); } -int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) { - - AssertFatal(gNB!=NULL,"gNB is null\n"); - for (uint16_t i=0; iprach_vars.list + i; - LOG_D(PHY, "searching for PRACH in %d.%d prach_index %d=> %d.%d\n", frame, slot, i, p->frame, p->slot); - if ((type == SEARCH_EXIST_OR_FREE) && (p->frame == -1) && (p->slot == -1)) { - return i; - } else if ((type == SEARCH_EXIST) && (p->frame == frame) && (p->slot + p->num_slots - 1 == slot)) { - return i; +prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, find_type_t type) +{ + pthread_mutex_lock(&l->prach_list_mutex); + prach_item_t *p = l->list; + prach_item_t *end = p + NUMBER_OF_NR_PRACH_MAX; + for (; p < end; p++) + if (p->frame == frame && (p->slot + p->num_slots - 1) == slot) + break; + if (p == end) { + if (type == SEARCH_EXIST) { + pthread_mutex_unlock(&l->prach_list_mutex); + return NULL; } + for (p = l->list; p < end; p++) + if (p->frame == -1 && p->slot == -1) + break; } - return -1; + if (p == end) { + pthread_mutex_unlock(&l->prach_list_mutex); + return NULL; + } + // mark it used, it will be filled later + p->frame = frame; + pthread_mutex_unlock(&l->prach_list_mutex); + return p; } -int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) +prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) { - int prach_id = find_nr_prach(gNB, SFN, Slot, SEARCH_EXIST_OR_FREE); - AssertFatal(((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX)), "illegal or no prach_id found!!! prach_id %d\n", prach_id); - gNB_PRACH_list_t *prach = &gNB->prach_vars.list[prach_id]; + prach_item_t *prach = find_nr_prach(&gNB->prach_list, SFN, Slot, SEARCH_EXIST_OR_FREE); + if (!prach) { + LOG_W(PHY, "no free space for a new detected rach, discarding\n"); + return NULL; + } + const int fmt = prach_pdu->prach_format; + NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + // we set only elements as the whole structure has been cleaned when we release it prach->frame = SFN; prach->slot = Slot; - const int format = prach_pdu->prach_format; - prach->num_slots = (format < 4) ? get_long_prach_dur(format, gNB->frame_parms.numerology_index) : 1; + prach->num_slots = fmt < 4 ? get_long_prach_dur(fmt, fp->numerology_index) : 1; if (gNB->common_vars.beam_id) { int n_symb = get_nr_prach_duration(prach_pdu->prach_format); - prach->beam_nb = calloc(prach_pdu->beamforming.dig_bf_interface, sizeof(*prach->beam_nb)); + AssertFatal(prach_pdu->beamforming.dig_bf_interface < NFAPI_MAX_NUM_BG_IF, + "impossible beams size %d\n", + prach_pdu->beamforming.dig_bf_interface); for (int i = 0; i < prach_pdu->beamforming.dig_bf_interface; i++) { int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[i].beam_idx; int start_symb = prach_pdu->prach_start_symbol + i * n_symb; int bitmap = SL_to_bitmap(start_symb, n_symb); - prach->beam_nb[i] = beam_index_allocation(gNB->enable_analog_das, - fapi_beam_idx, - &gNB->gNB_config.analog_beamforming_ve, - &gNB->common_vars, - Slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, - bitmap); + prach->beams[i] = beam_index_allocation(gNB->enable_analog_das, + fapi_beam_idx, + &gNB->gNB_config.analog_beamforming_ve, + &gNB->common_vars, + Slot, + NR_NUMBER_OF_SYMBOLS_PER_SLOT, + bitmap); } } - LOG_D(NR_PHY,"Copying prach pdu %d bytes to index %d\n", (int)sizeof(*prach_pdu), prach_id); - memcpy(&prach->pdu, prach_pdu, sizeof(*prach_pdu)); - return prach_id; + prach->pdu = *prach_pdu; + nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; + nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; + prach->rootSequenceIndex = occ->prach_root_sequence_index.value; + prach->numrootSequenceIndex = occ->num_root_sequences.value; + prach->msg1_frequencystart = occ->k1.value; + prach->mu = cfg->prach_sub_c_spacing.value; + prach->prach_sequence_length = cfg->prach_sequence_length.value; + prach->restricted_set = cfg->restricted_set_config.value; + prach->numerology_index = fp->numerology_index; + prach->nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value; + prach->Xu = gNB->X_u; + prach->rx_prach = &gNB->rx_prach; + return prach; } -void init_prach_ru_list(RU_t *ru) +static void rx_nr_prach_ru_internal(prach_item_t *p, + int beam_id, + int prachStartSymbol, + int prachOccasion, + int32_t **rxdata, + NR_DL_FRAME_PARMS *fp, + int N_TA_offset) { - AssertFatal(ru != NULL, "ru is null\n"); - for (int i = 0; i < NUMBER_OF_NR_RU_PRACH_MAX; i++) { - ru->prach_list[i].frame = -1; - ru->prach_list[i].slot = -1; - ru->prach_list[i].num_slots = -1; - } - pthread_mutex_init(&ru->prach_list_mutex, NULL); -} - -int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type) -{ - AssertFatal(ru != NULL, "ru is null\n"); - pthread_mutex_lock(&ru->prach_list_mutex); - for (int i = 0; i < NUMBER_OF_NR_RU_PRACH_MAX; i++) { - RU_PRACH_list_t *p = ru->prach_list + i; - LOG_D(PHY, "searching for PRACH in %d.%d : prach_index %d=> %d.%d\n", frame, slot, i, p->frame, p->slot); - if ((type == SEARCH_EXIST_OR_FREE) && (p->frame == -1) && (p->slot == -1)) { - pthread_mutex_unlock(&ru->prach_list_mutex); - return i; - } else if ((type == SEARCH_EXIST) && (p->frame == frame) && (p->slot + p->num_slots - 1 == slot)) { - pthread_mutex_unlock(&ru->prach_list_mutex); - return i; - } - } - pthread_mutex_unlock(&ru->prach_list_mutex); - return -1; -} - -void nr_fill_prach_ru(RU_t *ru, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu, int *beam_id) -{ - int prach_id = find_nr_prach_ru(ru, SFN, Slot, SEARCH_EXIST_OR_FREE); - AssertFatal((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX), - "illegal or no prach_id found!!! prach_id %d\n", - prach_id); - - pthread_mutex_lock(&ru->prach_list_mutex); - ru->prach_list[prach_id].frame = SFN; - ru->prach_list[prach_id].slot = Slot; - const int fmt = prach_pdu->prach_format; - ru->prach_list[prach_id].num_slots = (fmt < 4) ? get_long_prach_dur(fmt, ru->nr_frame_parms->numerology_index) : 1; - ru->prach_list[prach_id].fmt = fmt; - ru->prach_list[prach_id].numRA = prach_pdu->num_ra; - ru->prach_list[prach_id].beam = beam_id; - ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol; - ru->prach_list[prach_id].num_prach_ocas = prach_pdu->num_prach_ocas; - pthread_mutex_unlock(&ru->prach_list_mutex); -} - -void free_nr_ru_prach_entry(RU_t *ru, int prach_id) -{ - pthread_mutex_lock(&ru->prach_list_mutex); - ru->prach_list[prach_id].frame = -1; - ru->prach_list[prach_id].slot = -1; - pthread_mutex_unlock(&ru->prach_list_mutex); -} - -void rx_nr_prach_ru(RU_t *ru, - int prachFormat, - int numRA, - int beam, - int prachStartSymbol, - int prachStartSlot, - int prachOccasion, - int frame, - int slot) -{ - AssertFatal(ru != NULL,"ru is null\n"); - - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - int slot2 = slot; - int16_t *prach[ru->nb_rx]; - int prach_sequence_length = ru->config.prach_config.prach_sequence_length.value; - int msg1_frequencystart = ru->config.prach_config.num_prach_fd_occasions_list[numRA].k1.value; - const uint8_t prach_mu = ru->config.prach_config.prach_sub_c_spacing.value; - int sample_offset_slot; + const int sum = fp->ofdm_symbol_size + fp->nb_prefix_samples; + const int sum0 = fp->ofdm_symbol_size + fp->nb_prefix_samples0; if (prachStartSymbol == 0) { sample_offset_slot = 0; } else if (fp->slots_per_subframe == 1) { if (prachStartSymbol <= 7) - sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * (prachStartSymbol - 1) + (fp->ofdm_symbol_size + fp->nb_prefix_samples0); + sample_offset_slot = sum * (prachStartSymbol - 1) + sum0; else - sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * (prachStartSymbol - 2) + (fp->ofdm_symbol_size + fp->nb_prefix_samples0) * 2; + sample_offset_slot = sum * (prachStartSymbol - 2) + sum0 * 2; } else { - if (!(slot%(fp->slots_per_subframe/2))) - sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * (prachStartSymbol - 1) + (fp->ofdm_symbol_size + fp->nb_prefix_samples0); + if (!(p->slot % (fp->slots_per_subframe / 2))) + sample_offset_slot = sum * (prachStartSymbol - 1) + sum0; else - sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * prachStartSymbol; + sample_offset_slot = sum * prachStartSymbol; } LOG_D(PHY, "frame %d, slot %d: doing rx_nr_prach_ru for format %d, numRA %d, prachStartSymbol %d, prachOccasion %d\n", - frame, - slot, - prachFormat, - numRA, + p->frame, + p->slot, + p->pdu.prach_format, + p->pdu.num_ra, prachStartSymbol, prachOccasion); - - int16_t **rxsigF = ru->prach_rxsigF[prachOccasion]; - - AssertFatal(ru->if_south == LOCAL_RF || ru->if_south == REMOTE_IF5, - "we shouldn't call this if if_south != LOCAL_RF or REMOTE_IF5\n"); - - for (int aa = 0; aa < ru->nb_rx; aa++) { - if (prach_sequence_length == 0) - slot2 = prachStartSlot; - int idx = aa + beam * ru->nb_rx; - prach[aa] = (int16_t*)&ru->common.rxdata[idx][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - ru->N_TA_offset]; - } - int reps; int Ncp; int dftlen; - int mu = fp->numerology_index; + int mu = p->numerology_index; - if (prach_sequence_length == 0) { + if (p->prach_sequence_length == 0) { LOG_D(PHY, - "PRACH (ru %d) in %d.%d, format %d, msg1_frequencyStart %d\n", - ru->idx, - frame, - slot2, - prachFormat, - msg1_frequencystart); - switch (prachFormat) { - case 0: - reps = 1; - Ncp = 3168; - dftlen = 24576; - break; + "PRACH in %d.%d, format %d, msg1_frequencyStart %d\n", + p->frame, + p->slot, + p->pdu.prach_format, + p->msg1_frequencystart); + switch (p->pdu.prach_format) { + case 0: + reps = 1; + Ncp = 3168; + dftlen = 24576; + break; - case 1: - reps = 2; - Ncp = 21024; - dftlen = 24576; - break; + case 1: + reps = 2; + Ncp = 21024; + dftlen = 24576; + break; - case 2: - reps = 4; - Ncp = 4688; - dftlen = 24576; - break; + case 2: + reps = 4; + Ncp = 4688; + dftlen = 24576; + break; - case 3: - reps = 4; - Ncp = 3168; - dftlen = 6144; - break; + case 3: + reps = 4; + Ncp = 3168; + dftlen = 6144; + break; - default: - AssertFatal(1==0, "Illegal prach format %d for length 839\n", prachFormat); - break; + default: + AssertFatal(1 == 0, "Illegal prach format %d for length 839\n", p->pdu.prach_format); + break; } - } - else { + } else { LOG_D(PHY, - "PRACH (ru %d) in %d.%d, format %s, msg1_frequencyStart %d,startSymbol %d\n", - ru->idx, - frame, - slot, - prachfmt[prachFormat], - msg1_frequencystart, - prachStartSymbol); - switch (prachFormat) { - case 4: //A1 - reps = 2; - Ncp = 288 >> mu; - break; + "PRACH in %d.%d, format %s, msg1_frequencyStart %d,startSymbol %d\n", + p->frame, + p->slot, + prachfmt[p->pdu.prach_format], + p->msg1_frequencystart, + prachStartSymbol); + switch (p->pdu.prach_format) { + case 4: // A1 + reps = 2; + Ncp = 288 >> mu; + break; - case 5: //A2 - reps = 4; - Ncp = 576 >> mu; - break; + case 5: // A2 + reps = 4; + Ncp = 576 >> mu; + break; - case 6: //A3 - reps = 6; - Ncp = 864 >> mu; - break; + case 6: // A3 + reps = 6; + Ncp = 864 >> mu; + break; - case 7: //B1 - reps = 2; - Ncp = 216 >> mu; - break; + case 7: // B1 + reps = 2; + Ncp = 216 >> mu; + break; - /* - // B2 and B3 do not exist in FAPI - case 4: //B2 - reps = 4; - Ncp = 360 >> mu; - break; + /* + // B2 and B3 do not exist in FAPI + case 4: //B2 + reps = 4; + Ncp = 360 >> mu; + break; - case 5: //B3 - reps = 6; - Ncp = 504 >> mu; - break; - */ + case 5: //B3 + reps = 6; + Ncp = 504 >> mu; + break; + */ - case 8: //B4 - reps = 12; - Ncp = 936 >> mu; - break; + case 8: // B4 + reps = 12; + Ncp = 936 >> mu; + break; - case 9: //C0 - reps = 1; - Ncp = 1240 >> mu; - break; + case 9: // C0 + reps = 1; + Ncp = 1240 >> mu; + break; - case 10: //C2 - reps = 4; - Ncp = 2048 >> mu; - break; + case 10: // C2 + reps = 4; + Ncp = 2048 >> mu; + break; - default: - AssertFatal(1==0,"unknown prach format %x\n",prachFormat); - break; + default: + AssertFatal(1 == 0, "unknown prach format %x\n", p->pdu.prach_format); + break; } dftlen = 2048 >> mu; } @@ -323,12 +267,11 @@ void rx_nr_prach_ru(RU_t *ru, //actually what we should be checking here is how often the current prach crosses a 0.5ms boundary. //I am not quite sure for which paramter set this would be the case, //so I will ignore it for now and just check if the prach starts on a 0.5ms boundary - if(fp->numerology_index == 0) { + if (p->numerology_index == 0) { if (prachStartSymbol == 0 || prachStartSymbol == 7) Ncp += 16; - } - else { - if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) + } else { + if (p->slot % (fp->slots_per_subframe / 2) == 0 && prachStartSymbol == 0) Ncp += 16; } @@ -399,183 +342,156 @@ void rx_nr_prach_ru(RU_t *ru, // Do forward transform if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - LOG_D(PHY, "rx_prach: Doing PRACH FFT for nb_rx:%d Ncp:%d dftlen:%d\n", ru->nb_rx, Ncp, dftlen); + LOG_D(PHY, "rx_prach: Doing PRACH FFT for nb_rx:%d Ncp:%d dftlen:%d\n", p->nb_rx, Ncp, dftlen); } - const unsigned int K = get_prach_K(prach_sequence_length, prachFormat, fp->numerology_index, prach_mu); - const uint8_t kbar = get_PRACH_k_bar(prach_mu, fp->numerology_index); + const unsigned int K = get_prach_K(p->prach_sequence_length, p->pdu.prach_format, p->numerology_index, p->mu); + const uint8_t kbar = get_PRACH_k_bar(p->mu, p->numerology_index); - int n_ra_prb = msg1_frequencystart; + int n_ra_prb = p->msg1_frequencystart; int k = (12*n_ra_prb) - 6*fp->N_RB_UL; - int N_ZC = (prach_sequence_length==0)?839:139; + int N_ZC = (p->prach_sequence_length == 0) ? 839 : 139; if (k<0) k+=(fp->ofdm_symbol_size); k*=K; k+=kbar; - for (int aa=0; aanb_rx; aa++) { - AssertFatal(prach[aa]!=NULL,"prach[%d] is null\n",aa); + for (int aa = 0; aa < p->nb_rx; aa++) { + // Fixme: slot or slot makes no sense ??? + int slot2 = p->prach_sequence_length ? p->slot : p->slot; + int idx = aa + beam_id * p->nb_rx; + c16_t *prach = (c16_t *)&rxdata[idx][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - N_TA_offset]; // do DFT - int16_t *prach2 = prach[aa] + (2*Ncp); // times 2 for complex samples - for (int i = 0; i < reps; i++) - dft(dftsize, prach2 + 2*dftlen*i, rxsigF[aa] + 2*dftlen*i, 1); - - //LOG_M("ru_rxsigF_tmp.m","rxsFtmp", rxsigF[aa], dftlen*2*reps, 1, 1); - - //Coherent combining of PRACH repetitions (assumes channel does not change, to be revisted for "long" PRACH) - LOG_D(PHY,"Doing PRACH combining of %d reptitions N_ZC %d\n",reps,N_ZC); - int16_t rxsigF_tmp[N_ZC<<1]; - // if (k+N_ZC > dftlen) { // PRACH signal is split around DC - int16_t *rxsigF2=rxsigF[aa]; - int k2=k<<1; - - for (int j=0;j dftlen) { // PRACH signal is split around DC + int k2 = k; + for (int j = 0; j < N_ZC; j++, k2++) { + if (k2 == dftlen) + k2 = 0; + rxsigF_tmp[j] = c16add(rxsigF_tmp[j], tmp[k2]); + } } - memcpy((void*)rxsigF2,(void *)rxsigF_tmp,N_ZC<<2); + memcpy(p->rxsigF[prachOccasion][aa], rxsigF_tmp, sizeof(rxsigF_tmp)); } } -void rx_nr_prach(PHY_VARS_gNB *gNB, - nfapi_nr_prach_pdu_t *prach_pdu, - int prachOccasion, - int frame, - int slot, - uint16_t *max_preamble, - uint16_t *max_preamble_energy, - uint16_t *max_preamble_delay) +void rx_nr_prach_ru(prach_item_t *p, int32_t **rxdata, NR_DL_FRAME_PARMS *fp, int N_TA_offset) { - AssertFatal(gNB != NULL, "Can only be called from gNB\n"); - nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; - NR_DL_FRAME_PARMS *fp; + int N_dur = get_nr_prach_duration(p->pdu.prach_format); + LOG_D(NR_PHY_RACH, "%d.%d try to decode %d occasions \n", p->frame, p->slot, p->pdu.num_prach_ocas); + for (int prach_oc = 0; prach_oc < p->pdu.num_prach_ocas; prach_oc++) { + int prachStartSymbol = p->pdu.prach_start_symbol + prach_oc * N_dur; + int beam_id = p->beams[prach_oc]; + // comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is + // given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots + // where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. + rx_nr_prach_ru_internal(p, beam_id, prachStartSymbol, prach_oc, rxdata, fp, N_TA_offset); + } +} - uint16_t rootSequenceIndex; - int numrootSequenceIndex; - uint8_t restricted_set; - uint8_t n_ra_prb=0xFF; - int nb_rx; +rx_prach_out_t rx_nr_prach(const prach_item_t *in, int occasion) +{ + rx_prach_out_t out = {}; + uint16_t preamble_index0 = 0; + uint16_t numshift = 0; + int first_nonzero_root_idx = 0; + bool new_dft = false; + int log2_ifft_size = 10; - int16_t **rxsigF = gNB->prach_vars.rxsigF; + const int nb_rx = in->nb_rx; + const int NCS = in->pdu.num_cs; + const int prach_fmt = in->pdu.prach_format; + const int N_ZC = in->prach_sequence_length == 0 ? 839 : 139; - uint8_t preamble_index; - uint16_t NCS=99,NCS2; - uint16_t preamble_offset=0,preamble_offset_old; - int16_t preamble_shift=0; - uint32_t preamble_shift2; - uint16_t preamble_index0=0,n_shift_ra=0,n_shift_ra_bar; - uint16_t d_start=0; - uint16_t numshift=0; - const uint16_t *prach_root_sequence_map; - uint8_t not_found; - uint16_t u; - int16_t *Xu=0; - uint16_t first_nonzero_root_idx=0; - uint8_t new_dft=0; - int32_t lev; - int16_t levdB; - int log2_ifft_size=10; - int16_t prach_ifft_tmp[2048*2] __attribute__((aligned(32))); - int32_t *prach_ifft=(int32_t*)NULL; - - fp = &gNB->frame_parms; + LOG_D(NR_PHY_RACH, + "L1 PRACH RX: rooSequenceIndex %d, numRootSeqeuences %d, NCS %d, N_ZC %d, format %d \n", + in->rootSequenceIndex, + in->numrootSequenceIndex, + NCS, + N_ZC, + prach_fmt); - nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value; - rootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].prach_root_sequence_index.value; - numrootSequenceIndex = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].num_root_sequences.value; - NCS = prach_pdu->num_cs;//cfg->num_prach_fd_occasions_list[0].prach_zero_corr_conf.value; - int prach_sequence_length = cfg->prach_sequence_length.value; - int msg1_frequencystart = cfg->num_prach_fd_occasions_list[prach_pdu->num_ra].k1.value; - // int num_unused_root_sequences = cfg->num_prach_fd_occasions_list[0].num_unused_root_sequences.value; - // cfg->num_prach_fd_occasions_list[0].unused_root_sequences_list - - restricted_set = cfg->restricted_set_config.value; - - uint8_t prach_fmt = prach_pdu->prach_format; - uint16_t N_ZC = (prach_sequence_length==0)?839:139; - - LOG_D(PHY,"L1 PRACH RX: rooSequenceIndex %d, numRootSeqeuences %d, NCS %d, N_ZC %d, format %d \n",rootSequenceIndex,numrootSequenceIndex,NCS,N_ZC,prach_fmt); - - prach_ifft = gNB->prach_vars.prach_ifft; if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - if ((frame&1023) < 20) LOG_D(PHY,"PRACH (gNB) : running rx_prach for slot %d, msg1_frequencystart %d, rootSequenceIndex %d\n", slot, msg1_frequencystart, rootSequenceIndex); + if ((in->frame & 1023) < 20) + LOG_D(PHY, "PRACH (gNB) : running rx_prach for slot %d, rootSequenceIndex %d\n", in->slot, in->rootSequenceIndex); } - start_meas(&gNB->rx_prach); + start_meas(in->rx_prach); - prach_root_sequence_map = (cfg->prach_sequence_length.value==0) ? prach_root_sequence_map_0_3 : prach_root_sequence_map_abc; + const uint16_t *prach_root_sequence_map = + in->prach_sequence_length == 0 ? prach_root_sequence_map_0_3 : prach_root_sequence_map_abc; // PDP is oversampled, e.g. 1024 sample instead of 839 // Adapt the NCS (zero-correlation zones) with oversampling factor e.g. 1024/839 - NCS2 = (N_ZC==839) ? ((NCS<<10)/839) : ((NCS<<8)/139); + int NCS2 = N_ZC == 839 ? (NCS << 10) / 839 : (NCS << 8) / 139; - if (NCS2==0) NCS2 = N_ZC; + if (NCS2 == 0) + NCS2 = N_ZC; + int preamble_offset = 0, preamble_offset_old = 99; - preamble_offset_old = 99; - - - *max_preamble_energy = 0; - *max_preamble_delay = 0; - *max_preamble = 0; - int16_t prachF[2 * 1024]; - for (preamble_index=0 ; preamble_index<64 ; preamble_index++) { + int16_t preamble_shift = 0; + const int dft_sz = N_ZC == 839 ? 1024 : 256; + int32_t prach_ifft[dft_sz] __attribute__((aligned(32))); + for (int preamble_index = 0; preamble_index < 64; preamble_index++) { if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],(N_ZC==839) ? 840: 140)); - if (en>60) LOG_D(PHY,"frame %d, slot %d : Trying preamble %d \n",frame,slot,preamble_index); + int en = dB_fixed(signal_energy((int32_t *)in->rxsigF[occasion][0], N_ZC == 839 ? 840 : 140)); + if (en > 60) + LOG_D(PHY, "frame %d, slot %d : Trying preamble %d \n", in->frame, in->slot, preamble_index); } - if (restricted_set == 0) { + if (in->restricted_set == 0) { // This is the relative offset in the root sequence table (5.7.2-4 from 36.211) for the given preamble index preamble_offset = ((NCS==0)? preamble_index : (preamble_index/(N_ZC/NCS))); if (preamble_offset != preamble_offset_old) { preamble_offset_old = preamble_offset; - new_dft = 1; + new_dft = true; // This is the \nu corresponding to the preamble index preamble_shift = 0; - } - - else { - preamble_shift -= NCS; + } else { + preamble_shift -= NCS; if (preamble_shift < 0) - preamble_shift+=N_ZC; + preamble_shift += N_ZC; } } else { // This is the high-speed case - new_dft = 0; + new_dft = false; uint16_t nr_du[NR_PRACH_SEQ_LEN_L - 1]; nr_fill_du(N_ZC, prach_root_sequence_map, nr_du); // set preamble_offset to initial rootSequenceIndex and look if we need more root sequences for this // preamble index and find the corresponding cyclic shift // Check if all shifts for that root have been processed + int n_shift_ra = 0, n_shift_ra_bar, d_start = 0; if (preamble_index0 == numshift) { - not_found = 1; - new_dft = 1; + bool not_found = true; + new_dft = true; preamble_index0 -= numshift; - //(preamble_offset==0 && numshift==0) ? (preamble_offset) : (preamble_offset++); - - while (not_found == 1) { + while (not_found) { // current root depending on rootSequenceIndex - int index = (rootSequenceIndex + preamble_offset) % N_ZC; - - u = prach_root_sequence_map[index]; - + int index = (in->rootSequenceIndex + preamble_offset) % N_ZC; + int u = nr_du[prach_root_sequence_map[index]]; uint16_t n_group_ra = 0; - - if ((nr_du[u] < (N_ZC / 3)) && (nr_du[u] >= NCS) ) { - n_shift_ra = nr_du[u] / NCS; - d_start = (nr_du[u] << 1) + (n_shift_ra * NCS); + + if (u < (N_ZC / 3) && u >= NCS) { + n_shift_ra = u / NCS; + d_start = (u << 1) + (n_shift_ra * NCS); n_group_ra = N_ZC / d_start; - n_shift_ra_bar = max(0, (N_ZC-(nr_du[u] << 1) - (n_group_ra * d_start)) / N_ZC); - } else if ((nr_du[u] >= (N_ZC / 3)) && (nr_du[u] <= ((N_ZC - NCS) >> 1))) { - n_shift_ra = (N_ZC - (nr_du[u] << 1)) / NCS; - d_start = N_ZC - (nr_du[u] << 1) + (n_shift_ra * NCS); - n_group_ra = nr_du[u] / d_start; - n_shift_ra_bar = min(n_shift_ra, max(0, (nr_du[u]- (n_group_ra * d_start)) / NCS)); + n_shift_ra_bar = max(0, (N_ZC - (u << 1) - (n_group_ra * d_start)) / N_ZC); + } else if (u >= (N_ZC / 3) && u <= ((N_ZC - NCS) >> 1)) { + n_shift_ra = (N_ZC - (u << 1)) / NCS; + d_start = N_ZC - (u << 1) + (n_shift_ra * NCS); + n_group_ra = u / d_start; + n_shift_ra_bar = min(n_shift_ra, max(0, (u - (n_group_ra * d_start)) / NCS)); } else { n_shift_ra = 0; n_shift_ra_bar = 0; @@ -584,12 +500,13 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, // This is the number of cyclic shifts for the current root u numshift = (n_shift_ra * n_group_ra) + n_shift_ra_bar; // skip to next root and recompute parameters if numshift==0 - (numshift>0) ? (not_found = 0) : (preamble_offset++); + numshift > 0 ? not_found = false : preamble_offset++; } } if (n_shift_ra>0) - preamble_shift = -((d_start * (preamble_index0/n_shift_ra)) + ((preamble_index0%n_shift_ra)*NCS)); // minus because the channel is h(t -\tau + Cv) + preamble_shift = -(d_start * (preamble_index0 / n_shift_ra) + + (preamble_index0 % n_shift_ra) * NCS); // minus because the channel is h(t -\tau + Cv) else preamble_shift = 0; @@ -602,14 +519,14 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, first_nonzero_root_idx = preamble_offset; } - // Compute DFT of RX signal (conjugate input, results in conjugate output) for each new rootSequenceIndex + // Compute DFT of RX signal (conjugate in->rxsigF[occasion], results in conjugate output) for each new rootSequenceIndex if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840)); + int en = dB_fixed(signal_energy((int32_t *)in->rxsigF[occasion][0], 840)); if (en>60) LOG_D(PHY, "frame %d, slot %d : preamble index %d, NCS %d, N_ZC/NCS %d: offset %d, preamble shift %d , en %d)\n", - frame, - slot, + in->frame, + in->slot, preamble_index, NCS, N_ZC / NCS, @@ -618,44 +535,37 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, en); } - LOG_D(PHY,"PRACH RX preamble_index %d, preamble_offset %d\n",preamble_index,preamble_offset); + LOG_D(NR_PHY_RACH, + "PRACH RX preamble_index %d, preamble_offset %d, preamb shift %d new dft %d\n", + preamble_index, + preamble_offset, + preamble_shift, + new_dft); + if (new_dft) { + new_dft = false; - if (new_dft == 1) { - new_dft = 0; - - Xu = (int16_t*)gNB->X_u[preamble_offset-first_nonzero_root_idx]; - + c16_t *Xu = in->Xu[preamble_offset - first_nonzero_root_idx]; LOG_D(PHY,"PRACH RX new dft preamble_offset-first_nonzero_root_idx %d\n",preamble_offset-first_nonzero_root_idx); - memset(prach_ifft,0,((N_ZC==839) ? 2048 : 256)*sizeof(int32_t)); - memset(prachF, 0, sizeof(int16_t) * 2 * 1024); + memset(prach_ifft, 0, sizeof(prach_ifft)); if (LOG_DUMPFLAG(DEBUG_PRACH)) { - LOG_M("prach_rxF0.m","prach_rxF0",rxsigF[0],N_ZC,1,1); - LOG_M("prach_rxF1.m","prach_rxF1",rxsigF[1],6144,1,1); + LOG_M("prach_rxF0.m", "prach_rxF0", in->rxsigF[occasion][0], N_ZC, 1, 1); + LOG_M("prach_rxF1.m", "prach_rxF1", in->rxsigF[occasion][1], 6144, 1, 1); } - + c16_t prachF[dft_sz] __attribute__((aligned(32))); for (int aa = 0; aa < nb_rx; aa++) { - // Do componentwise product with Xu* on each antenna - - for (int offset = 0; offset < (N_ZC << 1); offset += 2) { - prachF[offset] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset] + (int32_t)Xu[offset+1]*rxsigF[aa][offset+1])>>15); - prachF[offset+1] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][offset+1] - (int32_t)Xu[offset+1]*rxsigF[aa][offset])>>15); + // Do componentwise product with Xu* on each antenna + for (int offset = 0; offset < N_ZC; offset++) { + prachF[offset] = c16MulConjShift(Xu[offset], in->rxsigF[occasion][aa][offset], 15); } - + memset(prachF + N_ZC, 0, sizeof(*prachF) * (dft_sz - N_ZC)); // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) - if (N_ZC == 839) { - idft(IDFT_1024, prachF, prach_ifft_tmp, 1); - // compute energy and accumulate over receive antennas - for (int i = 0; i < 1024; i++) - prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[i<<1] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)]; - } else { - idft(IDFT_256, prachF, prach_ifft_tmp, 1); - log2_ifft_size = 8; - // compute energy and accumulate over receive antennas and repetitions for BR - for (int i = 0; i < 256; i++) - prach_ifft[i] += (int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[(i<<1)] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)]; - } + c16_t prach_ifft_tmp[dft_sz] __attribute__((aligned(32))); + idft(get_idft(dft_sz), (int16_t *)prachF, (int16_t *)prach_ifft_tmp, 1); + // compute energy and accumulate over receive antennas + for (int i = 0; i < dft_sz; i++) + prach_ifft[i] += squaredMod(prach_ifft_tmp[i]); if (LOG_DUMPFLAG(DEBUG_PRACH)) { if (aa == 0) @@ -678,23 +588,22 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, } } // new dft - - // check energy in nth time shift, for - preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<*max_preamble_energy) { - LOG_D(PHY,"preamble_index %d, delay %d en %d dB > %d dB\n",preamble_index,i,levdB,*max_preamble_energy); - *max_preamble_energy = levdB; - *max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate - *max_preamble = preamble_index; + int lev = prach_ifft[preamble_shift2 + i]; + int levdB = dB_fixed_times10(lev); + if (levdB > out.max_preamble_energy || (levdB == out.max_preamble_energy && out.max_preamble_delay > i)) { + LOG_D(NR_PHY_RACH, "preamble_index %d, delay %d en %d dB > %d dB\n", preamble_index, i, levdB, out.max_preamble_energy); + out.max_preamble_energy = levdB; + out.max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate + out.max_preamble = preamble_index; } } - }// preamble_index - + } // preamble_index // The conversion from *max_preamble_delay from TA value is done here. // It is normalized to the 30.72 Ms/s, considering the numerology, N_RB and the sampling rate @@ -711,34 +620,15 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, // Format >3: 2048/2^mu samples @ 30.72 Ms/s, 2048/2^mu * 4 samples @ 122.88 Ms/s // By solving: // max_preamble_delay * ( (2048/2^mu*(fs/30.72M)) / 256 ) / fs = TA * 16 * 64 / 2^mu * Tc - uint16_t *TA = max_preamble_delay; - int mu = fp->numerology_index; - if (cfg->prach_sequence_length.value == 0) { + int mu = in->numerology_index; + if (in->prach_sequence_length == 0) { if (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2) - *TA = *TA * 3 * (1 << mu) / 2; + out.max_preamble_delay *= 3 * (1 << mu) / 2; else if (prach_fmt == 3) - *TA = *TA * 3 * (1 << mu) / 8; - } - else *TA = *TA/2; - - if (LOG_DUMPFLAG(DEBUG_PRACH)) { - //int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840)); - // if (en>60) { - int k = (12 * n_ra_prb) - 6 * fp->N_RB_UL; - if (k < 0) - k += fp->ofdm_symbol_size; - - k*=12; - k+=13; - k*=2; - - LOG_M("rxsigF.m","prach_rxF", &rxsigF[0][0], 12288, 1, 1); - LOG_M("prach_rxF_comp0.m","prach_rxF_comp0", prachF, 1024, 1, 1); - LOG_M("Xu.m","xu", Xu, N_ZC, 1, 1); - LOG_M("prach_ifft0.m","prach_t0", prach_ifft, 1024, 1, 1); - // } - } - stop_meas(&gNB->rx_prach); + out.max_preamble_delay *= 3 * (1 << mu) / 8; + } else + out.max_preamble_delay /= 2; + stop_meas(in->rx_prach); + return out; } - diff --git a/openair1/PHY/NR_TRANSPORT/nr_prs.c b/openair1/PHY/NR_TRANSPORT/nr_prs.c index 6f26b9a07f..799912713d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prs.c @@ -13,7 +13,7 @@ int nr_generate_prs(int slot, int16_t amp, prs_config_t *prs_cfg, nfapi_nr_config_request_scf_t *config, - NR_DL_FRAME_PARMS *frame_parms) + const NR_DL_FRAME_PARMS *frame_parms) { int k_prime = 0, k = 0, idx; diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index a7769dc84d..29fca5975e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -45,7 +45,7 @@ int nr_generate_prs(int slot, int16_t amp, prs_config_t *prs_cfg, nfapi_nr_config_request_scf_t *config, - NR_DL_FRAME_PARMS *frame_parms); + const NR_DL_FRAME_PARMS *frame_parms); /*! \fn int nr_generate_pss @@ -200,32 +200,18 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu); -int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); +prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); -void rx_nr_prach(PHY_VARS_gNB *gNB, - nfapi_nr_prach_pdu_t *prach_pdu, - int prachOccasion, - int frame, - int subframe, - uint16_t *max_preamble, - uint16_t *max_preamble_energy, - uint16_t *max_preamble_delay); +typedef struct rx_prach_out { + uint16_t max_preamble; + uint16_t max_preamble_energy; + uint16_t max_preamble_delay; +} rx_prach_out_t; +rx_prach_out_t rx_nr_prach(const prach_item_t *, int occasion); -void rx_nr_prach_ru(RU_t *ru, - int prach_fmt, - int numRA, - int beam, - int prachStartSymbol, - int prachStartSlot, - int prachOccasion, - int frame, - int subframe); - -void nr_fill_prach_ru(RU_t *ru,int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu, int *beam_nb); - -int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, find_type_t type); -int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type); +void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset); +prach_item_t *find_nr_prach(prach_list_t *, int frame, int slot, find_type_t type); void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, @@ -245,12 +231,9 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]); -void init_prach_list(PHY_VARS_gNB *gNB); -void init_prach_ru_list(RU_t *ru); -void free_nr_ru_prach_entry(RU_t *ru, int prach_id); int get_nr_prach_duration(uint8_t prach_format); -void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id); +void free_nr_prach_entry(prach_list_t *, prach_item_t *); void nr_decode_pucch1(c16_t **rxdataF, pucch_GroupHopping_t pucch_GroupHopping, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index 4621e184a6..06aef61935 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -59,8 +59,88 @@ static NR_gNB_ULSCH_t *find_nr_ulsch(PHY_VARS_gNB *gNB, uint16_t rnti, int pid) return ulsch; } +static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu_t *pusch_pdu) +{ + LOG_D(PHY, + "[gNB %d] %d.%d ULSCH PDU pdu_bit_map %u " + "rnti %u " + "handle %u " + "bwp_size %u " + "bwp_start %u " + "subcarrier_spacing %u " + "cyclic_prefix %u " + "target_code_rate %u " + "qam_mod_order %u " + "mcs_index %u " + "mcs_table %u " + "transform_precoding %u " + "data_scrambling_id %u " + "nrOfLayers %u " + "ul_dmrs_symb_pos %u " + "dmrs_config_type %u " + "ul_dmrs_scrambling_id %u " + "scid %u " + "num_dmrs_cdm_grps_no_data %u " + "dmrs_ports %u " + "resource_alloc %u " + "rb_start %u " + "rb_size %u " + "vrb_to_prb_mapping %u " + "frequency_hopping %u " + "tx_direct_current_location %u " + "uplink_frequency_shift_7p5khz %u " + "start_symbol_index %u " + "nr_of_symbols %u " + "tbslbrm %u " + "ldpcBaseGraph %u " + "pusch_data->rv_index %u " + "pusch_data->harq_process_id %u " + "pusch_data->new_data_indicator %u " + "pusch_data->num_cb %u\n", + instance, + frame, + slot, + pusch_pdu->pdu_bit_map, + pusch_pdu->rnti, + pusch_pdu->handle, + pusch_pdu->bwp_size, + pusch_pdu->bwp_start, + pusch_pdu->subcarrier_spacing, + pusch_pdu->cyclic_prefix, + pusch_pdu->target_code_rate, + pusch_pdu->qam_mod_order, + pusch_pdu->mcs_index, + pusch_pdu->mcs_table, + pusch_pdu->transform_precoding, + pusch_pdu->data_scrambling_id, + pusch_pdu->nrOfLayers, + pusch_pdu->ul_dmrs_symb_pos, + pusch_pdu->dmrs_config_type, + pusch_pdu->ul_dmrs_scrambling_id, + pusch_pdu->scid, + pusch_pdu->num_dmrs_cdm_grps_no_data, + pusch_pdu->dmrs_ports, + pusch_pdu->resource_alloc, + pusch_pdu->rb_start, + pusch_pdu->rb_size, + pusch_pdu->vrb_to_prb_mapping, + pusch_pdu->frequency_hopping, + pusch_pdu->tx_direct_current_location, + pusch_pdu->uplink_frequency_shift_7p5khz, + pusch_pdu->start_symbol_index, + pusch_pdu->nr_of_symbols, + pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes, + pusch_pdu->maintenance_parms_v3.ldpcBaseGraph, + pusch_pdu->pusch_data.rv_index, + pusch_pdu->pusch_data.harq_process_id, + pusch_pdu->pusch_data.new_data_indicator, + pusch_pdu->pusch_data.num_cb); +} + + void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu) { + dump_pusch_pdu(gNB->Mod_id, frame, slot, ulsch_pdu); int harq_pid = ulsch_pdu->pusch_data.harq_process_id; NR_gNB_ULSCH_t *ulsch = find_nr_ulsch(gNB, ulsch_pdu->rnti, harq_pid); if (ulsch == NULL) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 239b6f2f29..24d4950dfa 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -35,7 +35,6 @@ #include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "SCHED_NR/sched_nr.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "defs.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/utils/LOG/log.h" diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 28f3e2cc67..316a16c459 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1188,12 +1188,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, pusch_ch_est_dmrs_pos_slot_mem); nvar += nvar_tmp; } - // measure the SNR from the channel estimation - nr_gnb_measurements(gNB, - &gNB->ulsch[ulsch_id], - pusch_vars, - symbol, - rel15_ul->nrOfLayers); + allocCast2D(n0_subband_power, unsigned int, gNB->measurements.n0_subband_power, @@ -1212,7 +1207,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, int end_sc = (start_sc + rel15_ul->rb_size * NR_NB_SC_PER_RB - 1) % frame_parms->ofdm_symbol_size; for (int s = rel15_ul->start_symbol_index; s < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); s++) { - int offset0 = ((slot & 3) * frame_parms->symbols_per_slot + s) * frame_parms->ofdm_symbol_size; + int offset0 = ((slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot + s) * frame_parms->ofdm_symbol_size; int offset = offset0 + (frame_parms->first_carrier_offset + start_sc) % frame_parms->ofdm_symbol_size; c16_t *ul_ch = &gNB->common_vars.rxdataF[beam_nb][aarx][offset]; if (end_sc < start_sc) { diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index ddf16a0541..2a3987e755 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -161,7 +161,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, nfapi_nr_pucch_pdu_t *pucch_pdu) { NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - int soffset = (slot & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; + int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; AssertFatal(pucch_pdu->bit_len_harq > 0 || pucch_pdu->sr_flag > 0, "Either bit_len_harq (%d) or sr_flag (%d) must be > 0\n", diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 296606a426..46e2918749 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -47,12 +47,12 @@ #define NO_INTERP 1 /* Generic function to find the peak of channel estimation buffer */ -void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val) +void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val) { int32_t max_val = 0, max_idx = 0, abs_val = 0; for(int k = 0; k < buf_len; k++) { - abs_val = squaredMod(((c16_t*)buffer)[k]); + abs_val = squaredMod(buffer[k]); if(abs_val > max_val) { max_val = abs_val; @@ -71,6 +71,32 @@ void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t } } +void set_prs_dl_toa(prs_meas_t *prs_meas, float dl_toa) +{ + int rc = pthread_mutex_lock(&prs_meas->dl_toa_mtx); + AssertFatal(rc == 0, "pthread_mutex_lock() failed: errno %d, %s\n", errno, strerror(errno)); + *prs_meas->next_dl_toa++ = dl_toa; + if (prs_meas->next_dl_toa >= prs_meas->dl_toa + sizeofArray(prs_meas->dl_toa)) + prs_meas->next_dl_toa = prs_meas->dl_toa; + LOG_D(NR_PHY, "next_dl_toa %p\n", prs_meas->next_dl_toa); + rc = pthread_mutex_unlock(&prs_meas->dl_toa_mtx); + AssertFatal(rc == 0, "pthread_mutex_unlock() failed: errno %d, %s\n", errno, strerror(errno)); +} + +float get_prs_max_dl_toa(prs_meas_t *prs_meas) +{ + float max = 0.0f; + int rc = pthread_mutex_lock(&prs_meas->dl_toa_mtx); + AssertFatal(rc == 0, "pthread_mutex_lock() failed: errno %d, %s\n", errno, strerror(errno)); + for (int i = 0; i < sizeofArray(prs_meas->dl_toa); ++i) { + max = cmax(max, prs_meas->dl_toa[i]); + LOG_I(NR_PHY, "i %d dl_toa %.3f max %.3f\n", i, prs_meas->dl_toa[i], max); + } + rc = pthread_mutex_unlock(&prs_meas->dl_toa_mtx); + AssertFatal(rc == 0, "pthread_mutex_unlock() failed: errno %d, %s\n", errno, strerror(errno)); + return max; +} + int nr_prs_channel_estimation(uint8_t gNB_id, uint8_t rsc_id, uint8_t rep_num, @@ -83,8 +109,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, prs_config_t *prs_cfg = &ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_cfg; prs_meas_t **prs_meas = ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_meas; c16_t ch_tmp_buf[ ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); - int32_t chF_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); - int32_t chT_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); + c16_t chF_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); + c16_t chT_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32))); memset(ch_tmp_buf,0,sizeof(ch_tmp_buf)); memset(chF_interpol,0,sizeof(chF_interpol)); memset(chT_interpol,0,sizeof(chF_interpol)); @@ -315,10 +341,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, //Start pilot c16_t ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fl, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fl, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -331,10 +354,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k]; ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fml, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fml, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -352,10 +372,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, for(int pIdx = 2; pIdx < num_pilots-2; pIdx++) { c16_t ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fmm, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fmm, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -372,10 +389,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, //End pilot ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fmr, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fmr, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -388,10 +402,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k]; ch = c16MulConjShift(*pil, *rxF, 15); - multadd_real_vector_complex_scalar(fr, - ch, - ch_tmp, - 16); + multadd_real_vector_complex_scalar(fr, ch, ch_tmp, 16); // SNR & RSRP estimation rsrp += squaredMod(*rxF); @@ -435,9 +446,9 @@ int nr_prs_channel_estimation(uint8_t gNB_id, // Place PRS channel estimates in FFT shifted format if(first_half > 0) - memcpy((int16_t *)&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half * sizeof(int32_t)); + memcpy(&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half * sizeof(c16_t)); if(second_half > 0) - memcpy((int16_t *)&chF_interpol[rxAnt][0], &ch_tmp[first_half << 1], second_half * sizeof(int32_t)); + memcpy(&chF_interpol[rxAnt][0], &ch_tmp[first_half], second_half * sizeof(c16_t)); // Convert to time domain freq2time(NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size, @@ -463,9 +474,9 @@ int nr_prs_channel_estimation(uint8_t gNB_id, prs_meas[rxAnt]->slot = proc->nr_slot_rx; prs_meas[rxAnt]->rxAnt_idx = rxAnt; prs_meas[rxAnt]->dl_aoa = rsc_id; - prs_meas[rxAnt]->dl_toa = prs_toa / (float)NR_PRS_IDFT_OVERSAMP_FACTOR; - if ((frame_params->ofdm_symbol_size - prs_meas[rxAnt]->dl_toa) < frame_params->ofdm_symbol_size / 2) - prs_meas[rxAnt]->dl_toa -= (frame_params->ofdm_symbol_size); + float dl_toa = prs_toa / (float)NR_PRS_IDFT_OVERSAMP_FACTOR; + if ((frame_params->ofdm_symbol_size - dl_toa) < frame_params->ofdm_symbol_size / 2) + dl_toa -= (frame_params->ofdm_symbol_size); LOG_I(PHY, "[gNB %d][rsc %d][Rx %d][sfn %d][slot %d] DL PRS ToA ==> %.1f / %d samples, peak channel power %.1f dBm, SNR %+.1f dB, rsrp %+.1f dBm\n", gNB_id, @@ -473,12 +484,14 @@ int nr_prs_channel_estimation(uint8_t gNB_id, rxAnt, proc->frame_rx, proc->nr_slot_rx, - prs_meas[rxAnt]->dl_toa, + dl_toa, frame_params->ofdm_symbol_size, ch_pwr_dbm, prs_meas[rxAnt]->snr, prs_meas[rxAnt]->rsrp_dBm); + set_prs_dl_toa(prs_meas[rxAnt], dl_toa); + #ifdef DEBUG_PRS_CHEST sprintf(filename, "%s%i%s", "PRSpilot_", rxAnt, ".m"); LOG_M(filename, "prs_loc", mod_prs, num_pilots, 1, 1); @@ -496,7 +509,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, // T tracer dump T(T_UE_PHY_INPUT_SIGNAL, T_INT(gNB_id), T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx), - T_INT(rxAnt), T_BUFFER(&rxdataF[rxAnt][0], frame_params->samples_per_slot_wCP*sizeof(int32_t))); + T_INT(rxAnt), T_BUFFER(&rxdataF[rxAnt][0], frame_params->samples_per_slot_wCP*sizeof(c16_t))); T(T_UE_PHY_DL_CHANNEL_ESTIMATE_FREQ, T_INT(gNB_id), @@ -504,7 +517,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx), T_INT(rxAnt), - T_BUFFER(&chF_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(int32_t))); + T_BUFFER(&chF_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(c16_t))); T(T_UE_PHY_DL_CHANNEL_ESTIMATE, T_INT(gNB_id), @@ -512,7 +525,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx), T_INT(rxAnt), - T_BUFFER(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(int32_t))); + T_BUFFER(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(c16_t))); } return(0); @@ -797,30 +810,18 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp, return(0); } -void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - fapi_nr_coreset_t *coreset, +void nr_pdcch_channel_estimation(const PHY_VARS_NR_UE *ue, + int nb_rb_coreset, + int coreset_start_rb, + int dmrs_ref, uint16_t first_carrier_offset, uint16_t BWPStart, int32_t pdcch_est_size, c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) + c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size], + c16_t *pilot) { - int slot = proc->nr_slot_rx; - unsigned char aarx; - unsigned short k; - unsigned int pilot_cnt; - int ch_offset,symbol_offset; - - ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; - - symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol; - - int nb_rb_coreset=0; - int coreset_start_rb=0; - get_coreset_rballoc(coreset->frequency_domain_resource,&nb_rb_coreset,&coreset_start_rb); - if(nb_rb_coreset==0) return; + const int symb_sz = ue->frame_parms.ofdm_symbol_size; #ifdef DEBUG_PDCCH printf("pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d, coreset_nb_rb %d\n", @@ -829,39 +830,19 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short coreset_start_subcarrier = first_carrier_offset+(BWPStart + coreset_start_rb)*12; -#ifdef DEBUG_PDCCH - printf("PDCCH Channel Estimation : ch_offset %d, OFDM size %d, Ncp=%d, slot=%d, symbol %d\n", - ch_offset, - ue->frame_parms.ofdm_symbol_size, - ue->frame_parms.Ncp, - slot, - symbol); -#endif - #if CH_INTERP int16_t *fl = filt16a_l1; int16_t *fm = filt16a_m1; int16_t *fr = filt16a_r1; #endif - unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id; - int dmrs_ref = 0; - if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) - dmrs_ref = BWPStart; - // generate pilot - c16_t pilot[(nb_rb_coreset + dmrs_ref) * 3] __attribute__((aligned(16))); - // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS - const uint32_t *gold = nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, slot, symbol); - nr_pdcch_dmrs_rx(ue, slot, gold, pilot, 2000, (nb_rb_coreset + dmrs_ref)); - - for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { - - k = coreset_start_subcarrier; + for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) { + int k = coreset_start_subcarrier; c16_t *pil = &pilot[dmrs_ref * 3]; - c16_t *rxF = &rxdataF[aarx][symbol_offset + k + 1]; - c16_t *dl_ch = &pdcch_dl_ch_estimates[aarx][ch_offset]; + c16_t *rxF = &rxdataF[aarx][k + 1]; + c16_t *dl_ch = pdcch_dl_ch_estimates[aarx]; - memset(dl_ch, 0, sizeof(c16_t) * ue->frame_parms.ofdm_symbol_size); + memset(dl_ch, 0, sizeof(c16_t) * symb_sz); #ifdef DEBUG_PDCCH printf("pdcch ch est pilot addr %p RB_DL %d\n",&pilot[dmrs_ref*3], ue->frame_parms.N_RB_DL); @@ -877,36 +858,36 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, rxF += 4; k += 2; - if (k >= ue->frame_parms.ofdm_symbol_size) { - k -= ue->frame_parms.ofdm_symbol_size; - rxF = &rxdataF[aarx][(symbol_offset + k + 1)]; + if (k >= symb_sz) { + k -= symb_sz; + rxF = &rxdataF[aarx][k + 1]; } multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1)]; multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); dl_ch += 12; - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; - for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt += 3) { + for (int pilot_cnt = 3; pilot_cnt < (3 * nb_rb_coreset); pilot_cnt += 3) { multadd_real_vector_complex_scalar(fl, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16); dl_ch += 12; - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; } - #else //ELSE CH_INTERP +#else //ELSE CH_INTERP c32_t ch_sum = {0, 0}; - for (pilot_cnt = 0; pilot_cnt < 3*nb_rb_coreset; pilot_cnt++) { + for (int pilot_cnt = 0; pilot_cnt < 3 * nb_rb_coreset; pilot_cnt++) { #ifdef DEBUG_PDCCH printf("pilot[%u] = (%d, %d)\trxF[%d] = (%d, %d)\n", pilot_cnt, pil[0], pil[1], k+1, rxF[0], rxF[1]); @@ -914,8 +895,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t ch = c16mulShift(*pil++, *rxF, 15); ch_sum.r += ch.r; ch_sum.i += ch.i; - k = (k + 4) % ue->frame_parms.ofdm_symbol_size; - rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)]; + k = (k + 4) % symb_sz; + rxF = &rxdataF[aarx][k + 1]; if (pilot_cnt % 3 == 2) { ch.r = ch_sum.r / 3; @@ -929,11 +910,10 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, ch_sum = (c32_t){0}; } } - #endif //END CH_INTERP +#endif //END CH_INTERP //} - } } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 66339e25a2..7a47c67c52 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -39,20 +39,21 @@ int nr_prs_channel_estimation(uint8_t gNB_id, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); /* Generic function to find the peak of channel estimation buffer */ -void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val); +void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val); /*! \brief This function performs channel estimation including frequency and temporal interpolation */ -void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - fapi_nr_coreset_t *coreset, +void nr_pdcch_channel_estimation(const PHY_VARS_NR_UE *ue, + int nb_rb, + int rb_offset, + int dmrs_ref, uint16_t first_carrier_offset, uint16_t BWPStart, int32_t pdcch_est_size, c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); + c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size], + c16_t *pilot); c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp, const UE_nr_rxtx_proc_t *proc, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 36b8d8a673..4c8c57d9fd 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -125,8 +125,9 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { ue->measurements.rx_power_avg_dB[gNB_id] = dB_fixed( ue->measurements.rx_power_avg[gNB_id]); + ue->measurements.n0_power_avg_dB = dB_fixed(ue->measurements.n0_power_avg); ue->measurements.wideband_cqi_tot[gNB_id] = ue->measurements.rx_power_tot_dB[gNB_id] - ue->measurements.n0_power_tot_dB; - ue->measurements.wideband_cqi_avg[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] - dB_fixed(ue->measurements.n0_power_avg); + ue->measurements.wideband_cqi_avg[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] - ue->measurements.n0_power_avg_dB; ue->measurements.rx_rssi_dBm[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)ue->openair0_cfg[0].rx_gain[0] - (int)ue->openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); @@ -235,6 +236,7 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, .meas_type = NFAPI_NR_SS_MEAS, .Nid_cell = ue->frame_parms.Nid_cell, .rsrp_dBm = ue->measurements.ssb_rsrp_dBm[ssb_index], + .sinr_dB = ue->measurements.ssb_sinr_dB[ssb_index], .ssb_index = ssb_index, .is_neighboring_cell = false, }; diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index c28830e4d7..26cad50f12 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -905,6 +905,11 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, rxdataF); + if (csirs_config_pdu->measurement_bitmap == 0) { + LOG_D(NR_PHY, "No CSI-RS measurements configured\n"); + return; + } + uint32_t noise_power = 0; int16_t log2_re = 0; int16_t log2_maxh = 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 43b27e3932..f4ab076921 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -40,7 +40,8 @@ #include "PHY/sse_intrin.h" #include "common/utils/nr/nr_common.h" #include -#include "openair1/PHY/NR_REFSIG/nr_refsig_common.h" +#include "openair1/PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "assertions.h" #include "T.h" @@ -72,15 +73,16 @@ #define RE_PER_RB_OUT_DMRS 9 static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb, - c16_t llr[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], + c16_t *llr, c16_t *e_rx, uint8_t coreset_time_dur, - uint8_t reg_bundle_size_L, + uint8_t reg_bundle_size_L_in, uint8_t coreset_interleaver_size_R, uint8_t n_shift, uint8_t number_of_candidates, uint16_t *CCE, - uint8_t *L) + uint8_t *L, + int llr_stride_per_symbol) { /* * This function will do demapping and deinterleaving from llr containing demodulated symbols @@ -118,17 +120,11 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb, | REG 0 (bundle 0) bundle 0 bundle 0 */ - - uint32_t coreset_C = 0; - int coreset_interleaved = 0; const int N_regs = coreset_nbr_rb * coreset_time_dur; - - if (reg_bundle_size_L != 0) { // interleaving will be done only if reg_bundle_size_L != 0 - coreset_interleaved = 1; - coreset_C = (uint32_t)(N_regs / (coreset_interleaver_size_R * reg_bundle_size_L)); - } else { - reg_bundle_size_L = 6; - } + /* interleaving will be done only if reg_bundle_size_L != 0 */ + const int coreset_C = (reg_bundle_size_L_in != 0) ? (uint32_t)(N_regs / (coreset_interleaver_size_R * reg_bundle_size_L_in)) : 0; + const int coreset_interleaved = (reg_bundle_size_L_in != 0) ? 1 : 0; + const int reg_bundle_size_L = (reg_bundle_size_L_in != 0) ? reg_bundle_size_L_in : 6; int B_rb = reg_bundle_size_L / coreset_time_dur; // nb of RBs occupied by each REG bundle int num_bundles_per_cce = 6 / reg_bundle_size_L; @@ -173,7 +169,7 @@ static void nr_pdcch_demapping_deinterleaving(uint32_t coreset_nbr_rb, for (int cce_count = 0; cce_count < L[c_id]; cce_count++) { for (int k = 0; k < NR_NB_REG_PER_CCE / reg_bundle_size_L; k++) { // loop over REG bundles int f = f_bundle_j_list_ord[c_id][k + NR_NB_REG_PER_CCE * cce_count / reg_bundle_size_L]; - c16_t *in = llr[symbol_idx] + f * B_rb * RE_PER_RB_OUT_DMRS; + c16_t *in = llr + f * B_rb * RE_PER_RB_OUT_DMRS + symbol_idx * llr_stride_per_symbol; // loop over the RBs of the bundle memcpy(e_rx + RE_PER_RB_OUT_DMRS * rb_count, in, B_rb * RE_PER_RB_OUT_DMRS * sizeof(*e_rx)); rb_count += B_rb; @@ -200,16 +196,15 @@ static void nr_pdcch_llr(uint32_t sz, c16_t *rxF, c16_t *llr) // This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources) static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, - uint32_t coreset_nbr_rb, c16_t rxdataF[][rxdataF_sz], int32_t est_size, c16_t dl_ch_estimates[][est_size], int arraySz, c16_t rxdataF_ext[][arraySz], c16_t dl_ch_estimates_ext[][arraySz], - int symbol, NR_DL_FRAME_PARMS *frame_parms, uint8_t *coreset_freq_dom, + uint32_t coreset_nbr_rb, uint32_t n_BWP_start) { /* @@ -224,8 +219,8 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, */ for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - const c16_t *dl_ch0 = dl_ch_estimates[aarx] + frame_parms->ofdm_symbol_size * symbol; - c16_t *rxFbase = rxdataF[aarx] + frame_parms->ofdm_symbol_size * symbol; + c16_t *dl_ch0 = dl_ch_estimates[aarx]; + c16_t *rxFbase = rxdataF[aarx]; LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n", aarx); c16_t *dl_ch0_ext = dl_ch_estimates_ext[aarx]; @@ -249,51 +244,60 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, * the position 0+c_rb-N_RB_DL/2 in rxdataF and we have to point the pointer at (1+c_rb-N_RB_DL/2) in rxdataF */ - int c_rb = 0; - for (int rb = 0; rb < coreset_nbr_rb; rb++, c_rb++) { - int c_rb_by6 = c_rb / 6; + c16_t middle_prb_buffer[RE_PER_RB]; + for (int rb_group = 0; rb_group < coreset_nbr_rb / 6; rb_group++) { + if ((coreset_freq_dom[rb_group / 8] & (1 << (7 - (rb_group & 7)))) == 0) { + continue; + } + for (int rb = 0; rb < 6; rb++) { + int c_rb = rb_group * 6 + rb; + c16_t *rxF = NULL; + if ((frame_parms->N_RB_DL & 1) == 0) { + if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) + // if RB to be treated is lower than middle system bandwidth then rxdataF pointed + // at (offset + c_br + symbol * ofdm_symbol_size): even case + rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); + else + // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) + // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF + // we point at the 1st part of the rxdataF in symbol + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2); + } else { + if ((c_rb + n_BWP_start) <= frame_parms->N_RB_DL / 2) + // if RB to be treated is lower than middle system bandwidth then rxdataF pointed + // at (offset + c_br + symbol * ofdm_symbol_size): odd case + // Reassemble the middle PRB + if (c_rb + n_BWP_start == frame_parms->N_RB_DL / 2) { + memcpy(middle_prb_buffer, rxFbase + frame_parms->ofdm_symbol_size - RE_PER_RB / 2, sizeof(c16_t) * RE_PER_RB / 2); + memcpy(middle_prb_buffer + RE_PER_RB / 2, rxFbase, sizeof(c16_t) * RE_PER_RB / 2); + rxF = middle_prb_buffer; + } else { + rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); + } - // skip zeros in frequency domain bitmap - while ((coreset_freq_dom[c_rb_by6 / 8] & (1 << (7 - (c_rb_by6 & 7)))) == 0) { - c_rb += 6; - c_rb_by6 = c_rb / 6; + else + // number of RBs is odd and c_rb is higher than half system bandwidth + 1 + // if these conditions are true the pointer has to be situated at the 1st part of + // the rxdataF just after the first IQ symbols of the RB containing DC + // we point at the 1st part of the rxdataF in symbol + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2) - 6; + } + + const int valid_re[RE_PER_RB_OUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; + for (int i = 0; i < sizeofArray(valid_re); i++) { + *rxF_ext++ = rxF[valid_re[i]]; + *dl_ch0_ext++ = dl_ch0[valid_re[i]]; + } + dl_ch0 += RE_PER_RB; } - c16_t *rxF = NULL; - if ((frame_parms->N_RB_DL & 1) == 0) { - if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) - // if RB to be treated is lower than middle system bandwidth then rxdataF pointed - // at (offset + c_br + symbol * ofdm_symbol_size): even case - rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); - else - // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) - // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF - // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2); - } else { - if ((c_rb + n_BWP_start) <= frame_parms->N_RB_DL / 2) - // if RB to be treated is lower than middle system bandwidth then rxdataF pointed - // at (offset + c_br + symbol * ofdm_symbol_size): odd case - rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); - else - // number of RBs is odd and c_rb is higher than half system bandwidth + 1 - // if these conditions are true the pointer has to be situated at the 1st part of - // the rxdataF just after the first IQ symbols of the RB containing DC - // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2) - 6; - } - const int valid_re[RE_PER_RB_OUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; - for (int i = 0; i < sizeofArray(valid_re); i++) { - *rxF_ext++ = rxF[valid_re[i]]; - *dl_ch0_ext++ = dl_ch0[valid_re[i]]; - } - dl_ch0 += RE_PER_RB; } } } static void nr_pdcch_channel_compensation(int arraySz, - c16_t rxdataF_ext[][arraySz], - c16_t dl_ch_estimates_ext[][arraySz], + int sz2, + c16_t rxdataF_ext[][sz2], + c16_t dl_ch_estimates_ext[][sz2], c16_t rxdataF_comp[][arraySz], int antRx, uint8_t output_shift) @@ -304,106 +308,247 @@ static void nr_pdcch_channel_compensation(int arraySz, } } -static void nr_pdcch_detection_mrc(int sz, c16_t rxdataF_comp[][sz]) +static void nr_pdcch_detection_mrc(int nb_ant, int sz, c16_t rxdataF_comp[][sz]) { - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); c16_t *rx0 = rxdataF_comp[0]; - c16_t *rx1 = rxdataF_comp[1]; - // MRC on each re of rb // input always aligned and accepting tail padding to process all actual samples - for (int i = 0; i < sz; i += 4) { - *(simde__m128i *)(rx0 + i) = - simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), simde_mm_srai_epi16(*(simde__m128i *)(rx1 + i), 1)); + for (int a = 1; a < nb_ant; a++) { + c16_t *rx = rxdataF_comp[a]; + for (int i = 0; i < sz; i += 4) { + *(simde__m128i *)(rx0 + i) = simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), + simde_mm_srai_epi16(*(simde__m128i *)(rx + i), 1)); + } } } -void nr_rx_pdcch(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - int32_t pdcch_est_size, - c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - c16_t *pdcch_e_rx, - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) +/* Produce LLRs from received PDCCH signal */ +static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + int symbol, + int rel_symb_monOcc, + int ss_idx, + nr_phy_data_t *phy_data, + int llr_size_symbol, + c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size], + c16_t llr[llr_size_symbol]) { - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; + NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; + fapi_nr_coreset_t *coreset = &phy_pdcch_config->pdcch_config[ss_idx].coreset; + int32_t pdcch_est_size = ceil_mod(fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH, 16); + __attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size]; + int n_rb; + int rb_offset; + get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset); - int n_rb,rb_offset; - get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); - const int antRx = frame_parms->nb_antennas_rx; + unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id; + int dmrs_ref = 0; + if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) + dmrs_ref = phy_pdcch_config->pdcch_config[ss_idx].BWPStart; + // generate pilot + c16_t pilot[(n_rb + dmrs_ref) * 3] __attribute__((aligned(16))); + // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS + const uint32_t *gold = + nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, proc->nr_slot_rx, symbol); + nr_pdcch_dmrs_ref(gold, pilot, n_rb + dmrs_ref); + nr_pdcch_channel_estimation(ue, + n_rb, + rb_offset, + dmrs_ref, + fp->first_carrier_offset, + phy_pdcch_config->pdcch_config[ss_idx].BWPStart, + pdcch_est_size, + pdcch_dl_ch_estimates, + rxdataF, + pilot); - // Pointer to llrs - const int symb_size = n_rb * RE_PER_RB_OUT_DMRS; - c16_t llr[rel15->coreset.duration][symb_size]; + const int32_t rx_size = ceil_mod(fp->N_RB_DL * 12, 32); + __attribute__((aligned(32))) c16_t rxdataF_ext[fp->nb_antennas_rx][rx_size]; + __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[fp->nb_antennas_rx][rx_size]; - LOG_D(NR_PHY_DCI, - "pdcch coreset: freq %x, n_rb %d, rb_offset %d\n", - rel15->coreset.frequency_domain_resource[0], - n_rb, - rb_offset); - for (int s = 0; s < rel15->coreset.duration; s++) { - LOG_D(NR_PHY_DCI, "in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); - const int arraySz = ceil_mod(symb_size, 32); - __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][arraySz]; - __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][arraySz]; - nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP, - n_rb, - rxdataF, - pdcch_est_size, - pdcch_dl_ch_estimates, - arraySz, + nr_pdcch_extract_rbs_single(ue->frame_parms.ofdm_symbol_size, + rxdataF, + pdcch_est_size, + pdcch_dl_ch_estimates, + rx_size, + rxdataF_ext, + pdcch_dl_ch_estimates_ext, + fp, + coreset->frequency_domain_resource, + n_rb, + phy_pdcch_config->pdcch_config[ss_idx].BWPStart); + + LOG_D(NR_PHY_DCI, "in channel level function (dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); + int avg[fp->nb_antennas_rx]; + nr_channel_level(0, rx_size, pdcch_dl_ch_estimates_ext, fp->nb_antennas_rx, 1, avg, n_rb * RE_PER_RB_OUT_DMRS); + int avgs = avg[0]; + for (int i = 1; i < fp->nb_antennas_rx; i++) + avgs = cmax(avgs, avg[i]); + const int log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; + int rx_comp_sz = ceil_mod(llr_size_symbol, 4); + __attribute__((aligned(32))) c16_t rxdataF_comp[fp->nb_antennas_rx][rx_comp_sz]; + memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); + nr_pdcch_channel_compensation(rx_comp_sz, + rx_size, rxdataF_ext, pdcch_dl_ch_estimates_ext, - rel15->coreset.StartSymbolIndex + s, - frame_parms, - rel15->coreset.frequency_domain_resource, - rel15->BWPStart); + rxdataF_comp, + fp->nb_antennas_rx, + log2_maxh); // log2_maxh+I0_shift - LOG_D(NR_PHY_DCI, "in channel level function (dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); - // compute channel level based on ofdm symbol 0 - int avg[antRx]; - nr_channel_level(0, arraySz, pdcch_dl_ch_estimates_ext, antRx, 1, avg, n_rb); - int avgs = avg[0]; - for (int i = 1; i < antRx; i++) - avgs = cmax(avgs, avg[i]); - uint8_t log2_maxh = (log2_approx(avgs) / 2) + 5; //+antRx; - -#ifdef UE_DEBUG_TRACE - LOG_D(NR_PHY_DCI, "slot %d: pdcch log2_maxh = %d (%d,%d)\n", proc->nr_slot_rx, log2_maxh, avgP[0], avgs); -#endif -#if T_TRACER - T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(proc->frame_rx % 1024), T_INT(proc->nr_slot_rx), T_INT(avgs)); -#endif - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh); - LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); - // compute LLRs for ofdm symbol 0 only - __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][arraySz]; - nr_pdcch_channel_compensation(arraySz, - rxdataF_ext, - pdcch_dl_ch_estimates_ext, - rxdataF_comp, - antRx, - log2_maxh); // log2_maxh+I0_shift - - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, symb_size, 0); - - if (antRx > 1) - nr_pdcch_detection_mrc(arraySz, rxdataF_comp); - - nr_pdcch_llr(symb_size, rxdataF_comp[0], llr[s]); + if (fp->nb_antennas_rx > 1) { + nr_pdcch_detection_mrc(fp->nb_antennas_rx, rx_comp_sz, rxdataF_comp); } - UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, rel15->coreset.duration * symb_size, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp[0], sizeof(c16_t), 1, llr_size_symbol, 0); + nr_pdcch_llr(llr_size_symbol, rxdataF_comp[0], llr); +} - nr_pdcch_demapping_deinterleaving(n_rb, - llr, - pdcch_e_rx, - rel15->coreset.duration, - rel15->coreset.RegBundleSize, - rel15->coreset.InterleaverSize, - rel15->coreset.ShiftIndex, - rel15->number_of_candidates, - rel15->CCE, - rel15->L); +bool is_start_symbol_in_ss(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, const int symbol) +{ + return ((ss->coreset.StartSymbolBitmap >> (NR_SYMBOLS_PER_SLOT - 1 - symbol)) & 1); +} + +int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, uint8_t start_symb[NR_SYMBOLS_PER_SLOT]) +{ + int sum = 0; + for (int s = 0; s < NR_SYMBOLS_PER_SLOT; s++) { + if (is_start_symbol_in_ss(ss, s)) { + if (start_symb != NULL) + start_symb[sum] = s; + sum++; + } + } + + return sum; +} + +int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config) +{ + int monOcc = 0; + for (int ss = 0; ss < phy_pdcch_config->nb_search_space; ss++) { + monOcc = max(monOcc, get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss], NULL)); + } + return monOcc; +} + +static void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + c16_t *pdcch_e_rx, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, + fapi_nr_dci_indication_t *dci_ind); + +void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int *first_symb, int *last_symb) +{ + *first_symb = NR_SYMBOLS_PER_SLOT; // max first pdcch symbol + *last_symb = 0; // min last pdcch symbol + for (int ss = 0; ss < phy_pdcch_config->nb_search_space; ss++) { + for (int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { + if (is_start_symbol_in_ss(&phy_pdcch_config->pdcch_config[ss], symb)) { + const int duration = phy_pdcch_config->pdcch_config[ss].coreset.duration; + *first_symb = min(*first_symb, symb); + *last_symb = max(*last_symb, symb + duration - 1); + } + } + } +} + +/* Generates PDCCH LLRs from received symbol for each Search-Space */ +void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + int symbol, + nr_phy_data_t *phy_data, + int llr_size_symbol, + int num_monitoring_occ, + int max_symb, + c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size], + c16_t pdcch_llr[phy_data->phy_pdcch_config.nb_search_space][num_monitoring_occ][max_symb * llr_size_symbol]) +{ + const NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; + + // Loop over search spaces + for (int ss_idx = 0; ss_idx < phy_pdcch_config->nb_search_space; ss_idx++) { + uint8_t start_symb[NR_SYMBOLS_PER_SLOT] = {0}; + const int num_monOcc = get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss_idx], start_symb); + // Loop over monitoring occations within the slot in this ss + for (int occ = 0; occ < num_monOcc; occ++) { + const int first_symb = start_symb[occ]; + const int last_symb = first_symb + phy_pdcch_config->pdcch_config[ss_idx].coreset.duration; + // Decode PDCCH and generate LLR for each ss in this OFDM symbol + if ((symbol >= first_symb) && (symbol < last_symb)) { + const int rel_symb_monOcc = symbol - first_symb; + nr_rx_pdcch_symbol(ue, + proc, + symbol, + rel_symb_monOcc, + ss_idx, + phy_data, + llr_size_symbol, + rxdataF, + &pdcch_llr[ss_idx][occ][rel_symb_monOcc * llr_size_symbol]); + } + } + } +} + +/* Decode DCI from LLRs for each Search-Space and send to MAC */ +void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc, + int llr_size, + int max_monOcc, + PHY_VARS_NR_UE *ue, + nr_phy_data_t *phy_data, + c16_t llr[phy_data->phy_pdcch_config.nb_search_space][max_monOcc][llr_size]) +{ + NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; + + nr_downlink_indication_t dl_indication; + fapi_nr_dci_indication_t dci_ind = {.SFN = proc->frame_rx, .slot = proc->nr_slot_rx}; + + for (int ss_idx = 0; ss_idx < phy_pdcch_config->nb_search_space; ss_idx++) { + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[ss_idx]; + uint8_t unused_start_symb[NR_SYMBOLS_PER_SLOT] = {0}; + const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, unused_start_symb); + const int llr_stride = llr_size / rel15->coreset.duration; + + int n_rb; + int rb_offset; + get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset); + + for (int m = 0; m < num_monitoring_occ; m++) { + /// PDCCH/DCI e-sequence (input to rate matching). + c16_t pdcch_e_rx[NR_MAX_PDCCH_SIZE]; + + nr_pdcch_demapping_deinterleaving(n_rb, + llr[ss_idx][m], + pdcch_e_rx, + rel15->coreset.duration, + rel15->coreset.RegBundleSize, + rel15->coreset.InterleaverSize, + rel15->coreset.ShiftIndex, + rel15->number_of_candidates, + rel15->CCE, + rel15->L, + llr_stride); + + nr_dci_decoding_procedure(ue, proc, pdcch_e_rx, rel15, &dci_ind); + } + } + + for (int i = 0; i < dci_ind.number_of_dcis; i++) { + LOG_D(PHY, + "Frame.slot: %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n", + proc->frame_rx, + proc->nr_slot_rx, + i + 1, + dci_ind.number_of_dcis, + dci_ind.dci_list[i].rnti, + dci_ind.dci_list[i].dci_format); + } + + /* Send to MAC */ + nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data); + ue->if_inst->dl_indication(&dl_indication); + phy_pdcch_config->nb_search_space = 0; } static void nr_pdcch_unscrambling(c16_t *e_rx, @@ -425,14 +570,13 @@ static void nr_pdcch_unscrambling(c16_t *e_rx, } } -void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - c16_t *pdcch_e_rx, - fapi_nr_dci_indication_t *dci_ind, - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) +static void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + c16_t *pdcch_e_rx, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, + fapi_nr_dci_indication_t *dci_ind) { int e_rx_cand_idx = 0; - *dci_ind = (fapi_nr_dci_indication_t){.SFN = proc->frame_rx, .slot = proc->nr_slot_rx}; // if DCI for SIB we don't break after finding 1st DCI with that RNTI // there might be SIB1 and otherSIB in the same slot with the same length bool is_SI = rel15->rnti == SI_RNTI; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 5e677b542b..ab73bedb4f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -540,6 +540,16 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, } *log2_maxh = (log2_approx(avgs) / 2) + 1; LOG_D(PHY, "[DLSCH] AbsSubframe %d.%d log2_maxh = %d (%d)\n", frame % 1024, nr_slot_rx, *log2_maxh, avgs); +#if T_TRACER + T(T_UE_PHY_PDSCH_ENERGY, + T_INT(gNB_id), + T_INT(frame % 1024), + T_INT(nr_slot_rx), + T_INT(avg[0]), // layer 0, antenna 0 + T_INT(n_rx > 1 ? avg[1] : 0), // layer 0, antenna 1 + T_INT(nl > 1 ? avg[n_rx] : 0), // layer 1, antenna 0 + T_INT(nl > 1 && n_rx > 1 ? avg[n_rx + 1] : 0)); // layer 1, antenna 1 +#endif } stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_LEVEL_STATS); if (meas_enabled) { @@ -552,9 +562,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, first_symbol_flag, ue->phy_cpu_stats.cpu_time_stats[DLSCH_CHANNEL_LEVEL_STATS].p_time / (cpuf * 1000.0)); } -#if T_TRACER - T(T_UE_PHY_PDSCH_ENERGY, T_INT(gNB_id), T_INT(0), T_INT(frame % 1024), T_INT(nr_slot_rx)); -#endif //---------------------------------------------------------- //--------------------- channel compensation --------------- @@ -746,13 +753,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, #if T_TRACER T(T_UE_PHY_PDSCH_IQ, T_INT(gNB_id), - T_INT(ue->Mod_id), T_INT(frame % 1024), T_INT(nr_slot_rx), T_INT(nb_rb_pdsch), T_INT(fp->N_RB_UL), T_INT(fp->symbols_per_slot), - T_BUFFER(&rxdataF_comp[gNB_id][0], 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ fp->N_RB_UL * 12 * 2)); + T_BUFFER(&rxdataF_comp[gNB_id][0], 2 * fp->N_RB_UL * 12 * fp->symbols_per_slot * 2)); #endif if (ue->phy_sim_pdsch_rxdataF_comp) 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 41747a9ef1..ed348986e8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -69,6 +69,12 @@ typedef struct pdsch_scope_req_s { void nr_ue_dlsch_init(NR_UE_DLSCH_t *dlsch_list, int num_dlsch, uint8_t max_ldpc_iterations); void nr_conjch0_mult_ch1(c16_t *ch0, c16_t *ch1, c16_t *ch0conj_ch1, unsigned short nb_rb, unsigned char output_shift0); +void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int *first_symb, int *last_symb); + +int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, uint8_t start_symb[NR_SYMBOLS_PER_SLOT]); + +int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config); + /** \brief This is the alternative top-level entry point for DLSCH decoding in UE. It handles all the HARQ processes in only one call. The routine first computes the segmentation information and then call LDPC decoder on the @@ -180,14 +186,6 @@ void nr_dlsch_unscrambling(int16_t* llr, uint32_t Nid, uint32_t n_RNTI); -void nr_rx_pdcch(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - int32_t pdcch_est_size, - c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - c16_t *pdcch_e_rx, - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); - /*! \brief Performs detection of SSS to find cell ID and other framing parameters (FDD/TDD, normal/extended prefix) @param phy_vars_ue Pointer to UE variables @param tot_metric Pointer to variable containing maximum metric under framing hypothesis (to be compared to other hypotheses @@ -279,12 +277,6 @@ void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue, openair0_config_t *openair0_cfg, int freq_offset); -void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - c16_t *pdcch_e_rx, - fapi_nr_dci_indication_t *dci_ind, - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15); - /** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel estimation. It performs - RB extraction (signal and channel estimates) diff --git a/openair1/PHY/TOOLS/imscope/imgui.ini b/openair1/PHY/TOOLS/imscope/imgui.ini index 3fc08b6f7c..f3269ebfc6 100644 --- a/openair1/PHY/TOOLS/imscope/imgui.ini +++ b/openair1/PHY/TOOLS/imscope/imgui.ini @@ -1,13 +1,47 @@ +[Window][WindowOverViewport_11111111] +Pos=0,19 +Size=1920,927 +Collapsed=0 + [Window][Debug##Default] Pos=60,60 Size=400,400 Collapsed=0 +[Window][Status bar] +Pos=0,914 +Size=1920,32 +Collapsed=0 +DockId=0x00000004,0 + +[Window][Global scope settings] +Pos=697,153 +Size=545,478 +Collapsed=0 + +[Window][PUSCH SLOT IQ] +Pos=0,257 +Size=789,655 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][PUSCH LLRs] +Pos=791,257 +Size=1129,655 +Collapsed=0 +DockId=0x0000000C,0 + +[Window][Time domain samples] +Pos=997,201 +Size=923,711 +Collapsed=0 +DockId=0x0000000E,0 + [Window][NR KPI] Pos=0,19 Size=1133,667 Collapsed=0 -DockId=0x00000005,0 +DockId=0x00000007,0 [Window][Dear ImGui Demo] Pos=531,19 @@ -21,79 +55,223 @@ Size=529,667 Collapsed=0 DockId=0x00000002,0 -[Window][WindowOverViewport_11111111] -Pos=0,19 -Size=1280,701 -Collapsed=0 - -[Window][Status bar] -Pos=0,688 -Size=1280,32 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Global scope settings] -Pos=1038,19 -Size=242,667 -Collapsed=0 -DockId=0x00000006,0 - [Window][UE KPI] -Pos=532,19 -Size=528,667 +Pos=0,19 +Size=1920,180 Collapsed=0 -DockId=0x00000008,0 +DockId=0x00000007,0 [Window][UE PDSCH IQ] -Pos=0,19 -Size=530,667 +Pos=997,201 +Size=923,711 Collapsed=0 -DockId=0x00000005,1 - -[Window][Time domain samples] -Pos=0,19 -Size=1036,667 -Collapsed=0 -DockId=0x00000005,0 +DockId=0x0000000E,3 [Window][Time domain samples - before sync] -Pos=0,19 -Size=530,667 +Pos=0,201 +Size=995,711 Collapsed=0 -DockId=0x00000005,2 +DockId=0x0000000D,0 [Window][Broadcast channel] -Pos=0,19 -Size=530,667 +Pos=997,201 +Size=923,711 Collapsed=0 -DockId=0x00000005,3 +DockId=0x0000000E,1 [Window][RX IQ] Pos=532,19 Size=528,667 Collapsed=0 -DockId=0x00000008,0 +DockId=0x00000001,0 -[Window][PUSCH SLOT IQ] -Pos=0,19 -Size=1036,667 +[Window][UE PDSCH Chan est] +Pos=997,201 +Size=923,711 Collapsed=0 -DockId=0x00000005,1 +DockId=0x0000000E,2 -[Window][PUSCH LLRs] -Pos=0,19 -Size=1036,667 +[Window][UE PDSCH IQ before compensation] +Pos=0,201 +Size=995,711 Collapsed=0 -DockId=0x00000005,2 +DockId=0x0000000D,1 + +[Window][gNB Scope] +Pos=-4,30 +Size=1728,834 +Collapsed=0 + +[Window][UE Scope] +Pos=-1,23 +Size=1922,902 +Collapsed=0 + +[Window][Dear ImGui Demo/##Basket_379447C1] +IsChild=1 +Size=1202,260 + +[Window][Dear ImGui Demo/ResizableChild_D5443E47] +IsChild=1 +Size=1153,32 + +[Window][Dear ImGui Demo/Red_1D4E05CE] +IsChild=1 +Size=200,100 + +[Window][Delete?] +Pos=804,420 +Size=311,105 +Collapsed=0 + +[Window][Stacked 1] +Pos=755,387 +Size=409,172 +Collapsed=0 + +[Window][Example: Simple layout] +Pos=354,164 +Size=981,698 +Collapsed=0 + +[Window][Example: Simple layout/left pane_AED60EF8] +IsChild=1 +Size=150,644 + +[Window][Example: Log] +Pos=60,60 +Size=500,400 +Collapsed=0 + +[Window][Example: Auto-resizing window] +Pos=179,108 +Size=654,437 +Collapsed=0 + +[Window][gNB Scope/##pusch_time_domain_5637DE0C] +IsChild=1 +Size=1728,302 + +[Window][gNB Scope/##pusch_iq_903C5250] +IsChild=1 +Size=408,500 + +[Window][gNB Scope/##pusch_llr_FE553CCC] +IsChild=1 +Size=1443,502 + +[Window][Dear ImGui Demo/##Tree_C1CE970E] +IsChild=1 +Size=1132,260 + +[Window][Dear ImGui Demo/##Basket_97A64F14] +IsChild=1 +Size=1132,260 + +[Window][Dear ImGui Demo/##Basket_745C408A] +IsChild=1 +Size=1132,260 + +[Window][UE Scope/##ue_kpi_A22981AC] +IsChild=1 +Size=1839,183 + +[Window][UE Scope/##ue_iq_plots_F23AA7B4] +IsChild=1 +Size=814,517 + +[Window][UE Scope/##ue_plots0_D75041C0] +IsChild=1 +Size=1067,610 + +[Window][UE Scope/##ue_plots1_A0577156] +IsChild=1 +Size=733,604 + +[Window][UE PDCCH IQ] +Pos=997,201 +Size=923,711 +Collapsed=0 +DockId=0x0000000E,4 + +[Window][UE PDCCH LLR] +Pos=0,201 +Size=995,711 +Collapsed=0 +DockId=0x0000000D,2 + +[Table][0xC9935533,3] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 +Column 2 Weight=1.0000 + +[Table][0xE0773582,3] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 +Column 2 Weight=1.0000 + +[Table][0x45A0E60D,7] +RefScale=13 +Column 0 Width=49 +Column 1 Width=112 +Column 2 Width=112 +Column 3 Width=112 +Column 4 Width=112 +Column 5 Width=112 +Column 6 Width=112 + +[Table][0xDA36A7E0,6] +RefScale=13 +Column 0 Width=28 Sort=0v +Column 1 Width=42 +Column 2 Width=73 +Column 3 Width=68 +Column 4 Weight=1.0000 +Column 5 Width=-1 + +[Table][0x0919F5A2,14] +RefScale=13 +Column 0 Width=56 +Column 1 Width=19 +Column 2 Width=19 +Column 3 Width=19 +Column 4 Width=19 +Column 5 Width=19 +Column 6 Width=19 +Column 7 Width=19 +Column 8 Width=19 +Column 9 Width=19 +Column 10 Width=19 +Column 11 Width=19 +Column 12 Width=19 +Column 13 Width=19 + +[Table][0x8DFA6E86,2] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 + +[Table][0xFABAAEF7,2] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 + +[Table][0xC179E37C,3] +RefScale=13 +Column 0 Width=108 Sort=0v +Column 1 Width=63 +Column 2 Width=-1 [Docking][Data] -DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Size=1280,701 Split=Y Selected=0x71C89FCB - DockNode ID=0x00000003 Parent=0x7C6B3D9B SizeRef=1280,667 Split=X - DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1319,720 Split=X Selected=0x6627CA6C - DockNode ID=0x00000007 Parent=0x00000001 SizeRef=530,667 Split=X Selected=0x93FDECFF - DockNode ID=0x00000005 Parent=0x00000007 SizeRef=1036,334 CentralNode=1 Selected=0x93FDECFF - DockNode ID=0x00000006 Parent=0x00000007 SizeRef=242,334 Selected=0xFAA8D9D5 - DockNode ID=0x00000008 Parent=0x00000001 SizeRef=528,667 Selected=0x6627CA6C - DockNode ID=0x00000002 Parent=0x00000003 SizeRef=529,720 Selected=0xB903C8C9 - DockNode ID=0x00000004 Parent=0x7C6B3D9B SizeRef=1280,32 HiddenTabBar=1 Selected=0xD9B9B9C7 +DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Size=1920,927 Split=Y Selected=0x71C89FCB + DockNode ID=0x00000003 Parent=0x7C6B3D9B SizeRef=1280,667 Split=X + DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1319,720 Split=Y Selected=0x6627CA6C + DockNode ID=0x00000009 Parent=0x00000001 SizeRef=1920,236 Split=Y Selected=0x6627CA6C + DockNode ID=0x00000007 Parent=0x00000009 SizeRef=1920,180 CentralNode=1 Selected=0x6627CA6C + DockNode ID=0x00000008 Parent=0x00000009 SizeRef=1920,711 Split=X Selected=0x3A5D5B36 + DockNode ID=0x0000000D Parent=0x00000008 SizeRef=995,711 Selected=0xF0B5A18D + DockNode ID=0x0000000E Parent=0x00000008 SizeRef=923,711 Selected=0x752F58D8 + DockNode ID=0x0000000A Parent=0x00000001 SizeRef=1920,655 Split=X Selected=0x93FDECFF + DockNode ID=0x0000000B Parent=0x0000000A SizeRef=789,444 Selected=0x93FDECFF + DockNode ID=0x0000000C Parent=0x0000000A SizeRef=1129,444 Selected=0x43E927D5 + DockNode ID=0x00000002 Parent=0x00000003 SizeRef=529,720 Selected=0xB903C8C9 + DockNode ID=0x00000004 Parent=0x7C6B3D9B SizeRef=1280,32 HiddenTabBar=1 Selected=0xD9B9B9C7 diff --git a/openair1/PHY/TOOLS/imscope/imscope.cpp b/openair1/PHY/TOOLS/imscope/imscope.cpp index cce7a595f7..a80b5cfd98 100644 --- a/openair1/PHY/TOOLS/imscope/imscope.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope.cpp @@ -100,6 +100,7 @@ class LLRPlot { ImScopeDataWrapper &scope_data = scope_array[type]; if (ImPlot::BeginPlot(label)) { + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); if (!frozen || next) { if (scope_data.is_data_ready) { iq_procedure_timer.Add(scope_data.data.time_taken_in_ns); @@ -205,6 +206,7 @@ class IQHist { if (plot_type == 0) { float x = ImGui::CalcItemWidth(); if (ImPlot::BeginPlot(label.c_str(), {x, x})) { + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); ImPlot::PlotHistogram2D(label.c_str(), iq_data->real.data(), iq_data->imag.data(), @@ -217,6 +219,7 @@ class IQHist { } else if (plot_type == 2) { float x = ImGui::CalcItemWidth(); if (ImPlot::BeginPlot(label.c_str(), {x, x})) { + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); int points_drawn = 0; while (points_drawn < iq_data->len) { // Limit the amount of data plotted with PlotScatter call (issue with vertices/draw call) @@ -232,6 +235,7 @@ class IQHist { } } else if (plot_type == 1) { if (ImPlot::BeginPlot(label.c_str())) { + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); ImPlot::PlotLine(label.c_str(), iq_data->power.data(), iq_data->len); ImPlot::EndPlot(); } @@ -364,6 +368,7 @@ class IQSlotHeatmap { static std::vector symbol_boundaries = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; if (ImPlot::BeginPlot(label.c_str(), {(float)ImGui::GetWindowWidth() * 0.9f, 0})) { auto num_sc = num_rb * NR_NB_SC_PER_RB; + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); ImPlot::SetupAxes("symbols", "subcarriers"); ImPlot::SetupAxisLimits(ImAxis_X1, num_symbols, 0); ImPlot::SetupAxisLimits(ImAxis_Y1, num_sc, 0); @@ -429,6 +434,7 @@ void ShowUeScope(void *data_void_ptr, float t) rbs_buffer.AddPoint(t, getKPIUE()->nofRBs); bler.AddPoint(t, (float)getKPIUE()->nb_nack / (float)getKPIUE()->nb_total); mcs.AddPoint(t, (float)getKPIUE()->dl_mcs); + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); ImPlot::SetupAxes("time", "noOfRbs"); ImPlot::SetupAxisLimits(ImAxis_X1, t - history, t, ImGuiCond_Always); ImPlot::SetupAxisLimits(ImAxis_Y1, 0, NR_MAX_RB); @@ -444,6 +450,23 @@ void ShowUeScope(void *data_void_ptr, float t) } ImGui::End(); + if (ImGui::Begin("UE PDCCH IQ")) { + static auto iq_data = new IQData(); + static auto pdcch_iq_hist = new IQHist("PDCCH IQ"); + bool new_data = false; + if (pdcch_iq_hist->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[pdcchRxdataF_comp], t, pdcch_iq_hist->GetEpsilon(), iq_procedure_timer); + } + pdcch_iq_hist->Draw(iq_data, t, new_data); + } + ImGui::End(); + + if (ImGui::Begin("UE PDCCH LLR")) { + static auto llr_plot = new LLRPlot(); + llr_plot->Draw(t, pdcchLlr, "PDCCH LLR"); + } + ImGui::End(); + if (ImGui::Begin("UE PDSCH IQ")) { static auto iq_data = new IQData(); static auto pdsch_iq_hist = new IQHist("PDSCH IQ"); @@ -710,6 +733,7 @@ void *imscope_thread(void *data_void_ptr) static float t = 0; static bool show_imgui_demo_window = false; static bool show_implot_demo_window = false; + static bool show_scope_settings_window = false; ImGui::DockSpaceOverViewport(); if (ImGui::BeginMainMenuBar()) { if (ImGui::BeginMenu("File")) { @@ -729,6 +753,12 @@ void *imscope_thread(void *data_void_ptr) } ImGui::EndMenu(); } + if (ImGui::BeginMenu("Settings")) { + if (ImGui::MenuItem("Global scope settings")) { + show_scope_settings_window = !show_scope_settings_window; + } + ImGui::EndMenu(); + } ImGui::EndMainMenuBar(); } @@ -739,16 +769,6 @@ void *imscope_thread(void *data_void_ptr) } ImGui::End(); - ImGui::Begin("Global scope settings"); - ImGui::ShowStyleSelector("ImGui Style"); - ImPlot::ShowStyleSelector("ImPlot Style"); - ImPlot::ShowColormapSelector("ImPlot Colormap"); - ImGui::SliderInt("FPS target", &target_fps, 12, 60); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Reduces scope flickering in unfrozen mode. Can reduce impact on perfromance of the modem"); - } - ImGui::End(); - t += ImGui::GetIO().DeltaTime; iq_procedure_timer.UpdateAverage(t); @@ -765,7 +785,19 @@ void *imscope_thread(void *data_void_ptr) ImPlot::ShowDemoWindow(); if (show_imgui_demo_window) ImGui::ShowDemoWindow(); - + // Settings + if (show_scope_settings_window) { + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); + ImGui::Begin("Global scope settings", &show_scope_settings_window); + ImGui::ShowStyleSelector("ImGui Style"); + ImPlot::ShowStyleSelector("ImPlot Style"); + ImPlot::ShowColormapSelector("ImPlot Colormap"); + ImGui::SliderInt("FPS target", &target_fps, 12, 60); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Reduces scope flickering in unfrozen mode. Can reduce impact on perfromance of the modem"); + } + ImGui::End(); + } // Rendering ImGui::Render(); glViewport(0, 0, display_w, display_h); diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index e72465c4a9..0e21f37fde 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -190,19 +190,6 @@ typedef struct { task_ans_t *ans; } feptx_cmd_t; -typedef struct { - int frame; - int slot; - int fmt; - int numRA; - int prachStartSymbol; - int num_prach_ocas; - int num_slots; - int *beam; -} RU_PRACH_list_t; - -#define NUMBER_OF_NR_RU_PRACH_MAX 8 -#define NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX 12 #define RU_RX_SLOT_DEPTH 4 typedef struct RU_proc_t_s { /// Pointer to associated RU descriptor @@ -604,11 +591,7 @@ typedef struct RU_t_s { int32_t *bw_list[NUMBER_OF_eNB_MAX+1]; /// beamforming weight vectors int32_t **beam_weights[NUMBER_OF_eNB_MAX+1][15]; - /// prach commands - RU_PRACH_list_t prach_list[NUMBER_OF_NR_RU_PRACH_MAX]; - /// mutex for prach_list access - pthread_mutex_t prach_list_mutex; - /// received frequency-domain signal for PRACH (IF4p5 RRU) + /// received frequency-domain signal for PRACH (IF4p5 RRU) int16_t **prach_rxsigF[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX]; /// received frequency-domain signal for PRACH BR (IF4p5 RRU) int16_t **prach_rxsigF_br[4]; diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h index b6619efc6e..dbb07a9bbb 100644 --- a/openair1/PHY/defs_common.h +++ b/openair1/PHY/defs_common.h @@ -993,6 +993,9 @@ extern int sync_var; #define MBSFN_FDD_SF6 0x10 #define MBSFN_FDD_SF7 0x08 #define MBSFN_FDD_SF8 0x04 + +#define NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX 12 + typedef struct { pthread_mutex_t mutex_failure; bool failed; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index fb549d4734..abc700f9d2 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -53,30 +53,6 @@ typedef struct { int lut[MAX_PUCCH0_NID][160][14]; } NR_gNB_PUCCH0_LUT_t; -typedef struct { - /// Nfapi DLSCH PDU - nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu; - /// pointer to pdu from MAC interface (this is "a" in 36.212) - uint8_t *pdu; - /// Pointer to the payload - uint8_t *b; - /// Pointers to transport block segments - uint8_t **c; - /// Frame where current HARQ round was sent - uint32_t frame; - /// Interleaver outputs - uint8_t *f; - /// LDPC lifting size - uint32_t Z; - /// REs unavailable for DLSCH (overlapping with PTRS, CSIRS etc.) - uint32_t unav_res; -} NR_DL_gNB_HARQ_t; - -typedef struct { - uint8_t active; - nfapi_nr_dl_tti_csi_rs_pdu csirs_pdu; -} NR_gNB_CSIRS_t; - typedef struct { int dump_frame; int round_trials[8]; @@ -121,41 +97,20 @@ typedef struct { } NR_gNB_PHY_STATS_t; typedef struct { - /// Pointers to variables related to DLSCH harq process - NR_DL_gNB_HARQ_t harq_process; - /// Active flag for baseband transmitter processing - uint8_t active; - /// Number of soft channel bits - uint32_t G; + /// Nfapi DLSCH PDU + const nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu; + /// pointer to pdu from MAC interface (this is "a" in 36.212) + uint8_t *pdu; + /// Pointer to the payload + uint8_t *b; + /// Pointers to transport block segments + uint8_t **c; + /// Interleaver outputs + uint8_t *f; + /// REs unavailable for DLSCH (overlapping with PTRS, CSIRS etc.) + uint32_t unav_res; } NR_gNB_DLSCH_t; -typedef struct { - bool active; - nfapi_nr_dl_tti_ssb_pdu ssb_pdu; -} NR_gNB_SSB_t; - -typedef struct { - int frame; - int slot; - // identifier for concurrent beams - // prach duration in slots - int num_slots; - int *beam_nb; - nfapi_nr_prach_pdu_t pdu; -} gNB_PRACH_list_t; - -#define NUMBER_OF_NR_PRACH_MAX 8 - -typedef struct { - /// \brief ?. - /// second index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx. - /// third index: frequency-domain sample [0..ofdm_symbol_size*12[ - int16_t **rxsigF; - /// \brief local buffer to compute prach_ifft - int32_t *prach_ifft; - gNB_PRACH_list_t list[NUMBER_OF_NR_PRACH_MAX]; -} NR_gNB_PRACH; - typedef struct { uint8_t NumPRSResources; prs_config_t prs_cfg[NR_MAX_PRS_RESOURCES_PER_SET]; @@ -215,13 +170,6 @@ static inline int crcType(int nbSeg, int len) return len > NR_MAX_PDSCH_TBS ? CRC24_A : CRC16; } -typedef struct { - //! estimated rssi (dBm) - int rx_rssi_dBm; - /// Wideband CQI (sum of all RX antennas, in dB) - char wideband_cqi_tot; -} ulsch_measurements_gNB; - typedef struct { uint32_t frame; uint32_t slot; @@ -243,7 +191,6 @@ typedef struct { /// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around uint8_t handled; delay_t delay; - ulsch_measurements_gNB ulsch_measurements; } NR_gNB_ULSCH_t; typedef struct { @@ -438,7 +385,9 @@ typedef struct PHY_VARS_gNB_s { int max_nb_pusch; NR_gNB_COMMON common_vars; - NR_gNB_PRACH prach_vars; + prach_list_t prach_list; + // TODO: can we remove c from NR_gNB_DLSCH_t and put it on the stack? + NR_gNB_DLSCH_t *dlsch; NR_gNB_PRS prs_vars; NR_gNB_PUSCH *pusch_vars; NR_gNB_PUCCH_t *pucch; @@ -494,6 +443,9 @@ typedef struct PHY_VARS_gNB_s { bool enable_analog_das; + time_stats_t l1_tx_proc; + time_stats_t l1_rx_proc; + time_stats_t phy_proc_tx; time_stats_t phy_proc_rx; time_stats_t rx_prach; @@ -521,7 +473,6 @@ typedef struct PHY_VARS_gNB_s { time_stats_t rx_pusch_symbol_processing_stats; time_stats_t ul_indication_stats; time_stats_t slot_indication_stats; - time_stats_t schedule_response_stats; time_stats_t ulsch_decoding_stats; time_stats_t ts_deinterleave; time_stats_t ts_rate_unmatch; @@ -549,7 +500,6 @@ typedef struct PHY_VARS_gNB_s { int L1_rx_thread_core; pthread_t L1_tx_thread; int L1_tx_thread_core; - struct processingData_L1tx *msgDataTx; void *scopeData; } PHY_VARS_gNB; @@ -626,16 +576,6 @@ typedef struct processingData_L1tx { int slot_rx; openair0_timestamp timestamp_tx; PHY_VARS_gNB *gNB; - nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu[NFAPI_NR_MAX_NB_CORESETS]; - nfapi_nr_ul_dci_request_pdus_t ul_pdcch_pdu[NFAPI_NR_MAX_NB_CORESETS]; - NR_gNB_CSIRS_t csirs_pdu[NR_SYMBOLS_PER_SLOT]; - NR_gNB_DLSCH_t **dlsch; - NR_gNB_SSB_t ssb[64]; - uint16_t num_pdsch_slot; - int num_dl_pdcch; - int num_ul_pdcch; - /* a reference to the sched_response, to release it when not needed anymore */ - int sched_response_id; } processingData_L1tx_t; typedef struct processingData_L1rx { diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 0d1cab4045..23972fc9f2 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -38,6 +38,8 @@ #include "impl_defs_nr.h" #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" +#include + #define MAX_NUM_SUBCARRIER_SPACING 5 #define NR_MAX_OFDM_SYMBOL_SIZE 8192 @@ -133,6 +135,34 @@ typedef struct { int resource_type; } nr_srs_info_t; +#define NUMBER_OF_NR_PRACH_MAX 8 +typedef struct { + int frame; + int slot; + int num_slots; // prach duration in slots + int beams[NFAPI_MAX_NUM_BG_IF]; + nfapi_nr_prach_pdu_t pdu; + int rootSequenceIndex; + int numrootSequenceIndex; + int msg1_frequencystart; + int mu; + int prach_sequence_length; + int restricted_set; + int numerology_index; + int nb_rx; + c16_t rxsigF[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NB_ANTENNAS_RX][NR_PRACH_SEQ_LEN_L]; + c16_t (*Xu)[839]; + time_stats_t *rx_prach; +} prach_item_t; + +typedef struct { + /// prach commands + prach_item_t list[NUMBER_OF_NR_PRACH_MAX]; + /// mutex for prach_list access + pthread_mutex_t prach_list_mutex; +} prach_list_t; +void init_prach_list(prach_list_t *); + typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS; typedef uint32_t (*get_samples_per_slot_t)(int slot, const NR_DL_FRAME_PARMS *fp); @@ -284,7 +314,10 @@ typedef struct { int32_t sfn; int8_t slot; int8_t rxAnt_idx; - float dl_toa; + pthread_mutex_t dl_toa_mtx; // protect reading of max from write + // circular buffer to be able to read maximum of last estimations + float dl_toa[128]; // set through set_prs_dl_toa() + float *next_dl_toa; int32_t dl_aoa; float snr; float rsrp; diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 8303c510c7..a2011e1fa6 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -365,7 +365,7 @@ void nr_channel_level(const int symbol, int32_t avg[nb_rx * Nl], const uint32_t len); void nr_scale_channel(int size, int ch_estimates_ext[][size], int symb, uint32_t len, int nrOfLayers, int nb_rx, int shift_ch_ext); -bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, +bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms, c16_t **txdataF, uint16_t symbol_offset, int bwp_start, diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c index ba5d792428..9d91986b50 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c @@ -139,7 +139,7 @@ static int compute_n_b(frame_t frame_number, * See TS 38.211 - Section 6.4.1.4 Sounding reference signal * ***************************************************************************/ -bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, +bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms, c16_t **txdataF, uint16_t symbol_offset, int bwp_start, @@ -293,7 +293,7 @@ bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, } uint8_t k_l_offset = 0; // If the SRS is configured by the IE SRS-PosResource-r16, the quantity k_l_offset is // given by TS 38.211 - Table 6.4.1.4.3-2, otherwise k_l_offset = 0. - uint8_t k_0_overbar_p = (nr_srs_info->n_shift * NR_NB_SC_PER_RB + (K_TC_p + k_l_offset)) % K_TC; + uint8_t k_0_overbar_p = nr_srs_info->n_shift * NR_NB_SC_PER_RB + (K_TC_p + k_l_offset) % K_TC; uint8_t k_0_p = k_0_overbar_p + K_TC * M_sc_b_SRS * sum_n_b; nr_srs_info->k_0_p[p_index][l_line] = k_0_p; diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index d61f0d0548..5ddf2d3485 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -9,30 +9,12 @@ typedef struct pnf_p7_t pnf_p7_t; typedef struct vnf_t vnf_t; typedef struct vnf_p7_t vnf_p7_t; -void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){} - -void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){} - -void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, - nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, - uint8_t *sdu){ -} -void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, - int frame, int slot, - nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ - } int l1_north_init_gNB(void){return 0;} int slot_ahead = 6; //uint8_t nfapi_mode=0; NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;} -void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){} void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, @@ -41,18 +23,11 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu){} -void nr_fill_prach(PHY_VARS_gNB *gNB, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu){} -void nr_fill_prach_ru(RU_t *ru, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu){} - -void nr_phy_config_request(NR_PHY_Config_t *gNB){} +void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) +{ +} -void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} +void nr_phy_config_request(NR_PHY_Config_t *gNB){} void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} @@ -100,9 +75,6 @@ bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t * return false; } -void wls_vnf_set_p7_config(void *p7_config) -{ -} bool wls_vnf_nr_send_p5_message(vnf_t *vnf,uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len) { @@ -133,3 +105,27 @@ void wls_pnf_set_p7_config(void *p7_config) { } + +void wls_fapi_nr_pnf_stop() +{ +} + +void wls_pnf_close(pthread_t p5_thread) +{ +} + +void wls_vnf_send_stop_request() +{ +} + +void wls_vnf_stop() +{ +} + +void socket_nfapi_nr_pnf_stop() +{ +} + +void socket_nfapi_send_stop_request(vnf_t *vnf) +{ +} diff --git a/openair1/SCHED/nfapi_nr_dummy.c b/openair1/SCHED/nfapi_nr_dummy.c deleted file mode 100644 index 9c9ecea443..0000000000 --- a/openair1/SCHED/nfapi_nr_dummy.c +++ /dev/null @@ -1,54 +0,0 @@ -//Dummy NR defs to avoid linking errors - -#include "PHY/defs_gNB.h" -#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" -#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" -#include "openair1/PHY/LTE_TRANSPORT/transport_common.h" - -void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){} - -void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){} - -void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, - nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, - uint8_t *sdu){ -} -void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, - int frame, int slot, - nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ - } -int l1_north_init_gNB(void){return 0;} - -int slot_ahead = 6; -//uint8_t nfapi_mode=0; -NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;} - -void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){} -void nr_fill_ulsch(PHY_VARS_gNB *gNB, - int frame, - int slot, - nfapi_nr_pusch_pdu_t *ulsch_pdu){} -void nr_fill_pucch(PHY_VARS_gNB *gNB, - int frame, - int slot, - nfapi_nr_pucch_pdu_t *pucch_pdu){} -void nr_fill_prach(PHY_VARS_gNB *gNB, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu){} -void nr_fill_prach_ru(RU_t *ru, - int SFN, - int Slot, - nfapi_nr_prach_pdu_t *prach_pdu){} - -void nr_phy_config_request(NR_PHY_Config_t *gNB){} - -void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} - -//void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} - diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c deleted file mode 100644 index 74a2178982..0000000000 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ /dev/null @@ -1,248 +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 fapi_nr_l1.c - * \brief functions for FAPI L1 interface - * \author R. Knopp, WEI-TAI CHEN - * \date 2017, 2018 - * \version 0.1 - * \company Eurecom, NTUST - * \email: knopp@eurecom.fr, kroempa@gmail.com - * \note - * \warning - */ -#include "fapi_nr_l1.h" -#include "common/ran_context.h" -#include "PHY/NR_TRANSPORT/nr_transport_proto.h" -#include "PHY/NR_TRANSPORT/nr_dlsch.h" -#include "PHY/NR_TRANSPORT/nr_dci.h" -#include "nfapi/oai_integration/vendor_ext.h" -#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" -#include "nfapi/oai_integration/nfapi_vnf.h" - -void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot, - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu) -{ - - AssertFatal(dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag== 1, "bchPayloadFlat %d != 1\n", - dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag); - - uint8_t i_ssb = dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex; - - LOG_D(NR_PHY,"%d.%d : ssb index %d pbch_pdu: %x\n",frame,slot,i_ssb,dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload); - if (msgTx->ssb[i_ssb].active) - AssertFatal(1==0,"SSB PDU with index %d already active\n",i_ssb); - else { - msgTx->ssb[i_ssb].active = true; - memcpy((void*)&msgTx->ssb[i_ssb].ssb_pdu,&dl_tti_pdu->ssb_pdu,sizeof(dl_tti_pdu->ssb_pdu)); - } -} - -void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, int frame, int slot, nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu) -{ - int found = 0; - - for (int id = 0; id < NR_NUMBER_OF_SYMBOLS_PER_SLOT; id++) { - NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[id]; - if (csirs->active == 0) { - LOG_D(NR_PHY,"Frame %d Slot %d CSI_RS with ID %d is now active\n",frame,slot,id); - csirs->active = 1; - memcpy((void*)&csirs->csirs_pdu, (void*)csirs_pdu, sizeof(nfapi_nr_dl_tti_csi_rs_pdu)); - found = 1; - break; - } - } - if (found == 0) - LOG_E(MAC,"CSI-RS list is full\n"); -} - -void nr_schedule_dl_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_request_t *DL_req) -{ - DevAssert(gNB != NULL); - DevAssert(DL_req != NULL); - nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - - int frame = DL_req->SFN; - int slot = DL_req->Slot; - - int slot_type = nr_slot_select(cfg, frame, slot); - DevAssert(slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT); - - processingData_L1tx_t *msgTx = gNB->msgDataTx; - msgTx->slot = slot; - msgTx->frame = frame; - - uint8_t number_dl_pdu = DL_req->dl_tti_request_body.nPDUs; - - for (int i = 0; i < number_dl_pdu; i++) { - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i]; - LOG_D(NR_PHY, "NFAPI: dl_pdu %d : type %d\n", i, dl_tti_pdu->PDUType); - switch (dl_tti_pdu->PDUType) { - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - handle_nr_nfapi_ssb_pdu(msgTx, frame, slot, dl_tti_pdu); - break; - - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - LOG_D(NR_PHY, "frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n", frame, slot, DL_req->SFN, DL_req->Slot); - msgTx->pdcch_pdu[msgTx->num_dl_pdcch] = dl_tti_pdu->pdcch_pdu; - msgTx->num_dl_pdcch++; - break; - - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - LOG_D(NR_PHY, "frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n", frame, slot, DL_req->SFN, DL_req->Slot); - handle_nfapi_nr_csirs_pdu(msgTx, frame, slot, &dl_tti_pdu->csi_rs_pdu); - break; - - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - LOG_D(NR_PHY, "frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n", frame, slot, DL_req->SFN, DL_req->Slot); - nr_fill_dlsch_dl_tti_req(msgTx, &dl_tti_pdu->pdsch_pdu); - } - } -} - -void nr_schedule_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req) -{ - DevAssert(gNB != NULL); - DevAssert(UL_tti_req != NULL); - - int frame = UL_tti_req->SFN; - int slot = UL_tti_req->Slot; - - for (int i = 0; i < UL_tti_req->n_pdus; i++) { - switch (UL_tti_req->pdus_list[i].pdu_type) { - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - LOG_D(NR_PHY, - "frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", - frame, - slot, - UL_tti_req->SFN, - UL_tti_req->Slot); - nr_fill_ulsch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); - break; - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - LOG_D(NR_PHY, - "frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", - frame, - slot, - UL_tti_req->SFN, - UL_tti_req->Slot); - nr_fill_pucch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); - break; - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - LOG_D(NR_PHY, - "frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", - frame, - slot, - UL_tti_req->SFN, - UL_tti_req->Slot); - nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; - int id = nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - if (gNB->RU_list[0]->if_south == LOCAL_RF || gNB->RU_list[0]->if_south == REMOTE_IF5) - nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu, gNB->prach_vars.list[id].beam_nb); - break; - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: - LOG_D(NR_PHY, - "frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE for %d.%d\n", - frame, - slot, - UL_tti_req->SFN, - UL_tti_req->Slot); - nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu); - break; - } - } -} - -void nr_schedule_tx_req(PHY_VARS_gNB *gNB, nfapi_nr_tx_data_request_t *TX_req) -{ - DevAssert(gNB != NULL); - DevAssert(TX_req != NULL); - processingData_L1tx_t *msgTx = gNB->msgDataTx; - - for (int idx = 0; idx < TX_req->Number_of_PDUs; ++idx) { - uint8_t *sdu = (uint8_t *)TX_req->pdu_list[idx].TLVs[0].value.direct; - nr_fill_dlsch_tx_req(msgTx, idx, sdu); - } -} - -void nr_schedule_ul_dci_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_t *UL_dci_req) -{ - DevAssert(gNB != NULL); - DevAssert(UL_dci_req != NULL); - processingData_L1tx_t *msgTx = gNB->msgDataTx; - - msgTx->num_ul_pdcch = UL_dci_req->numPdus; - for (int i = 0; i < UL_dci_req->numPdus; i++) - msgTx->ul_pdcch_pdu[i] = UL_dci_req->ul_dci_pdu_list[i]; -} - -void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) -{ - // copy data from L2 interface into L1 structures - module_id_t Mod_id = Sched_INFO->module_id; - frame_t frame = Sched_INFO->frame; - slot_t slot = Sched_INFO->slot; - - AssertFatal(RC.gNB != NULL, "RC.gNB is null\n"); - AssertFatal(RC.gNB[Mod_id] != NULL, "RC.gNB[%d] is null\n", Mod_id); - - PHY_VARS_gNB *gNB = RC.gNB[Mod_id]; - start_meas(&gNB->schedule_response_stats); - - nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - - int slot_type = nr_slot_select(cfg, frame, slot); - - clear_slot_beamid(gNB, slot); // reset beam_id information for the slot to be processed - DevAssert(NFAPI_MODE == NFAPI_MONOLITHIC); - bool is_dl = slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT; - - processingData_L1tx_t *msgTx = gNB->msgDataTx; - /* store the sched_response_id for the TX thread to release it when done */ - msgTx->sched_response_id = Sched_INFO->sched_response_id; - - DevAssert(Sched_INFO->DL_req.SFN == frame); - DevAssert(Sched_INFO->DL_req.Slot == slot); - - if (is_dl) { - nr_schedule_dl_tti_req(gNB, &Sched_INFO->DL_req); - } - - nr_schedule_ul_tti_req(gNB, &Sched_INFO->UL_tti_req); - - if (is_dl) { - nr_schedule_tx_req(gNB, &Sched_INFO->TX_req); - - nr_schedule_ul_dci_req(gNB, &Sched_INFO->UL_dci_req); - /* Both the current thread and the TX thread will access the sched_info - * at the same time, so increase its reference counter, so that it is - * released only when both threads are done with it. - */ - inc_ref_sched_response(Sched_INFO->sched_response_id); - } - - /* this thread is done with the sched_info, decrease the reference counter */ - if ((slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) && NFAPI_MODE == NFAPI_MONOLITHIC) { - LOG_D(NR_PHY, "Calling dref_sched_response for id %d in %d.%d (sched_response)\n", Sched_INFO->sched_response_id, frame, slot); - deref_sched_response(Sched_INFO->sched_response_id); - } - stop_meas(&gNB->schedule_response_stats); -} diff --git a/openair1/SCHED_NR/fapi_nr_l1.h b/openair1/SCHED_NR/fapi_nr_l1.h deleted file mode 100644 index 59df4fb30d..0000000000 --- a/openair1/SCHED_NR/fapi_nr_l1.h +++ /dev/null @@ -1,69 +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 fapi_nr_l1.h - * \brief function prototypes for FAPI L1 interface - * \author R. Knopp, WEI-TAI CHEN - * \date 2017, 2018 - * \version 0.1 - * \company Eurecom, NTUST - * \email: knopp@eurecom.fr, kroempa@gmail.com - * \note - * \warning - */ - -#include "PHY/defs_gNB.h" -#include "SCHED_NR/sched_nr.h" -#include "nfapi_nr_interface_scf.h" - -// added -void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx, - int frame,int slot, - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu); - -void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO); - -void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, - int frame, int slot, - nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu); - -void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, - int frame, int subframe, - nfapi_nr_dl_tti_pdcch_pdu *dcl_dl_pdu); - -void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, - nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, - uint8_t *sdu); - -void nr_fill_indication(PHY_VARS_gNB *gNB, - int frame, - int slot_rx, - int UE_id, - uint8_t harq_pid, - uint8_t crc_flag, - int dtx_flag, - nfapi_nr_crc_t *crc, - nfapi_nr_rx_data_pdu_t *pdu); -//added - -void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu); diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index c56a37ca1d..d5d6a8860e 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -33,7 +33,6 @@ #include "PHY/defs_gNB.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "nfapi_nr_interface_scf.h" -#include "fapi_nr_l1.h" #include "nfapi_pnf.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -49,99 +48,86 @@ int get_nr_prach_duration(uint8_t prach_format) void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind) { - uint16_t max_preamble[4]={0},max_preamble_energy[4]={0},max_preamble_delay[4]={0}; - - RU_t *ru; - int aa=0; - int ru_aa; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1); rach_ind->sfn = frame; rach_ind->slot = slot; rach_ind->number_of_pdus = 0; - ru=gNB->RU_list[0]; + prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, SEARCH_EXIST); + if (!prach_id) { + return; + } - int prach_id = find_nr_prach(gNB, frame, slot, SEARCH_EXIST); - if (prach_id >= 0) { - LOG_D(NR_PHY,"%d.%d Got prach entry id %d\n",frame,slot,prach_id); - nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_vars.list[prach_id].pdu; - const int prach_start_slot = gNB->prach_vars.list[prach_id].slot; - uint8_t prachStartSymbol; - int N_dur = get_nr_prach_duration(prach_pdu->prach_format); + nfapi_nr_prach_pdu_t *prach_pdu = &prach_id->pdu; + LOG_D(NR_PHY_RACH, "%d.%d, prachstart slot %d prach entry occas %d\n", frame, slot, prach_id->slot, prach_pdu->num_prach_ocas); + const int prach_start_slot = prach_id->slot; + int N_dur = get_nr_prach_duration(prach_pdu->prach_format); - for(int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) { - for (ru_aa=0,aa=0;ru_aanb_rx;ru_aa++,aa++) { - gNB->prach_vars.rxsigF[aa] = ru->prach_rxsigF[prach_oc][ru_aa]; - } + for (int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) { + uint prachStartSymbol = prach_pdu->prach_start_symbol + prach_oc * N_dur; + // comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is + // given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots + // where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. + rx_prach_out_t res = rx_nr_prach(prach_id, prach_oc); + LOG_D(NR_PHY, + "[RAPROC] Frame %d, slot %d, occasion %d (prachStartSymbol %d) : Most likely preamble %d, energy %d.%d dB delay %d " + "(prach_energy counter %d)\n", + frame, + slot, + prach_oc, + prachStartSymbol, + res.max_preamble, + res.max_preamble_energy / 10, + res.max_preamble_energy % 10, + res.max_preamble_delay, + gNB->prach_energy_counter); - prachStartSymbol = prach_pdu->prach_start_symbol + prach_oc * N_dur; - //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. + if ((gNB->prach_energy_counter == NUM_PRACH_RX_FOR_NOISE_ESTIMATE) + && (res.max_preamble_energy > gNB->measurements.prach_I0 + gNB->prach_thres) + && (rach_ind->number_of_pdus < MAX_NUM_NR_RX_RACH_PDUS)) { + LOG_A(NR_PHY, + "[RAPROC] %d.%d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol " + "%u freq index %u\n", + frame, + prach_start_slot, + res.max_preamble, + res.max_preamble_energy / 10, + res.max_preamble_energy % 10, + gNB->measurements.prach_I0, + gNB->prach_thres, + res.max_preamble_delay, + prachStartSymbol, + prach_pdu->num_ra); - rx_nr_prach(gNB, - prach_pdu, - prach_oc, - frame, - slot, - &max_preamble[0], - &max_preamble_energy[0], - &max_preamble_delay[0]); - LOG_D(NR_PHY,"Freeing PRACH entry %d\n",prach_id); - free_nr_prach_entry(gNB,prach_id); - LOG_D(NR_PHY,"[RAPROC] Frame %d, slot %d, occasion %d (prachStartSymbol %d) : Most likely preamble %d, energy %d.%d dB delay %d (prach_energy counter %d)\n", - frame,slot,prach_oc,prachStartSymbol, - max_preamble[0], - max_preamble_energy[0]/10, - max_preamble_energy[0]%10, - max_preamble_delay[0], - gNB->prach_energy_counter); + T(T_ENB_PHY_INITIATE_RA_PROCEDURE, + T_INT(gNB->Mod_id), + T_INT(frame), + T_INT(slot), + T_INT(res.max_preamble), + T_INT(res.max_preamble_energy), + T_INT(res.max_preamble_delay)); - if ((gNB->prach_energy_counter == NUM_PRACH_RX_FOR_NOISE_ESTIMATE) - && (max_preamble_energy[0] > gNB->measurements.prach_I0 + gNB->prach_thres) - && (rach_ind->number_of_pdus < MAX_NUM_NR_RX_RACH_PDUS)) { - LOG_A(NR_PHY, - "[RAPROC] %d.%d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol " - "%u freq index %u\n", - frame, - prach_start_slot, - max_preamble[0], - max_preamble_energy[0] / 10, - max_preamble_energy[0] % 10, - gNB->measurements.prach_I0, - gNB->prach_thres, - max_preamble_delay[0], - prachStartSymbol, - prach_pdu->num_ra); - - T(T_ENB_PHY_INITIATE_RA_PROCEDURE, - T_INT(gNB->Mod_id), - T_INT(frame), - T_INT(slot), - T_INT(max_preamble[0]), - T_INT(max_preamble_energy[0]), - T_INT(max_preamble_delay[0])); - - nfapi_nr_prach_indication_pdu_t *ind = rach_ind->pdu_list + rach_ind->number_of_pdus; - ind->phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value; - ind->symbol_index = prachStartSymbol; - ind->slot_index = slot; - ind->freq_index = prach_pdu->num_ra; - ind->avg_rssi = (max_preamble_energy[0] < 631) ? (128 + (max_preamble_energy[0] / 5)) : 254; - ind->avg_snr = 0xff; // invalid for now - - ind->num_preamble = 1; - ind->preamble_list[0].preamble_index = max_preamble[0]; - ind->preamble_list[0].timing_advance = max_preamble_delay[0]; - ind->preamble_list[0].preamble_pwr = 0xffffffff; - rach_ind->number_of_pdus++; - } - gNB->measurements.prach_I0 = ((gNB->measurements.prach_I0*900)>>10) + ((max_preamble_energy[0]*124)>>10); - if (frame==0) LOG_I(PHY,"prach_I0 = %d.%d dB\n",gNB->measurements.prach_I0/10,gNB->measurements.prach_I0%10); - if (gNB->prach_energy_counter < NUM_PRACH_RX_FOR_NOISE_ESTIMATE) - gNB->prach_energy_counter++; - } //if prach_id>0 - rach_ind->slot = prach_start_slot; - } // for NUMBER_OF_NR_PRACH_OCCASION_MAX + nfapi_nr_prach_indication_pdu_t *ind = rach_ind->pdu_list + rach_ind->number_of_pdus; + *ind = (nfapi_nr_prach_indication_pdu_t){ + .phy_cell_id = gNB->gNB_config.cell_config.phy_cell_id.value, + .symbol_index = prachStartSymbol, + .slot_index = slot, + .freq_index = prach_pdu->num_ra, + .avg_rssi = (res.max_preamble_energy < 631) ? (128 + (res.max_preamble_energy / 5)) : 254, + .avg_snr = 0xff, // invalid for now + .num_preamble = 1, + .preamble_list = { + {.preamble_index = res.max_preamble, .timing_advance = res.max_preamble_delay, .preamble_pwr = 0xffffffff}}}; + rach_ind->number_of_pdus++; + } + gNB->measurements.prach_I0 = ((gNB->measurements.prach_I0 * 900) >> 10) + ((res.max_preamble_energy * 124) >> 10); + if (frame == 0) + LOG_I(PHY, "prach_I0 = %d.%d dB\n", gNB->measurements.prach_I0 / 10, gNB->measurements.prach_I0 % 10); + if (gNB->prach_energy_counter < NUM_PRACH_RX_FOR_NOISE_ESTIMATE) + gNB->prach_energy_counter++; + } // if prach_id>0 + rach_ind->slot = prach_start_slot; + LOG_D(NR_PHY_RACH, "Freeing PRACH entry\n"); + free_nr_prach_entry(&gNB->prach_list, prach_id); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0); } diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index 0546455e36..f121914f11 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -185,9 +185,6 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx) int txdataF_offset = slot_tx * fp->samples_per_slot_wCP; start_meas(&ru->precoding_stats); - if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT) - return; - if (gNB->common_vars.analog_bf) { for (int i = 0; i < ru->num_beams_period; i++) { memcpy((void*) &ru->common.beam_id[i][slot_tx * fp->symbols_per_slot], @@ -196,6 +193,9 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx) } } + if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT) + return; + // If there is no digital beamforming we just need to copy the data to RU if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) { for (int b = 0; b < ru->num_beams_period; b++) { diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 085ce8e087..9479e960a8 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -152,7 +152,7 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs } } -int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) +int nr_slot_select(const nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) { (void) nr_frame; diff --git a/openair1/SCHED_NR/phy_frame_config_nr.h b/openair1/SCHED_NR/phy_frame_config_nr.h index 11ae4bf5c6..687fd2bc51 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.h +++ b/openair1/SCHED_NR/phy_frame_config_nr.h @@ -53,7 +53,7 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs * @param nr_slot : slot number @returns int : downlink, uplink or mixed slot type*/ -int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot); +int nr_slot_select(const nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot); void do_tdd_config_sim(PHY_VARS_gNB *gNB, int mu); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 51e8c771e5..6ea1a197e2 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -27,7 +27,6 @@ #include "PHY/NR_TRANSPORT/nr_dci.h" #include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h" -#include "fapi_nr_l1.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "PHY/INIT/nr_phy_init.h" @@ -45,10 +44,29 @@ //#define DEBUG_RXDATA //#define SRS_IND_DEBUG +static void nr_fill_indication(PHY_VARS_gNB *gNB, + int frame, + int slot_rx, + int UE_id, + uint8_t harq_pid, + uint8_t crc_flag, + int dtx_flag, + nfapi_nr_crc_t *crc, + nfapi_nr_rx_data_pdu_t *pdu); + +static void nr_fill_indication(PHY_VARS_gNB *gNB, + int frame, + int slot_rx, + int ULSCH_id, + uint8_t harq_pid, + uint8_t crc_flag, + int dtx_flag, + nfapi_nr_crc_t *crc, + nfapi_nr_rx_data_pdu_t *pdu); int beam_index_allocation(bool das, int fapi_beam_index, - nfapi_nr_analog_beamforming_ve_t *analog_bf, + const nfapi_nr_analog_beamforming_ve_t *analog_bf, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, @@ -84,10 +102,10 @@ int beam_index_allocation(bool das, return idx; } -void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_dl_tti_ssb_pdu ssb_pdu) +void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu) { NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu.ssb_pdu_rel15; + const nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu->ssb_pdu_rel15; uint8_t ssb_index = pdu->SsbBlockIndex; LOG_D(PHY,"common_signal_procedures: frame %d, slot %d ssb index %d\n", frame, slot, ssb_index); @@ -135,7 +153,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n fp->ssb_start_subcarrier); LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n", frame, slot, ssb_start_symbol); - nfapi_nr_tx_precoding_and_beamforming_t *pb = &pdu->precoding_and_beamforming; + const nfapi_nr_tx_precoding_and_beamforming_t *pb = &pdu->precoding_and_beamforming; c16_t ***txdataF = gNB->common_vars.txdataF; int txdataF_offset = slot * fp->samples_per_slot_wCP; // beam number in a scenario with multiple concurrent beams @@ -173,7 +191,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n #endif nr_generate_pbch(gNB, - &ssb_pdu, + ssb_pdu, &txdataF[beam_nb][0][txdataF_offset], ssb_start_symbol, n_hf, @@ -186,24 +204,64 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot) { LOG_D(PHY, "Clearing beam_id structure for slot %d\n", slot); - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + int slot_sz = gNB->frame_parms.symbols_per_slot; for (int i = 0; i < gNB->common_vars.num_beams_period; i++) { if (gNB->common_vars.beam_id) - memset(&gNB->common_vars.beam_id[i][slot * fp->symbols_per_slot], -1, fp->symbols_per_slot * sizeof(int)); + memset(&gNB->common_vars.beam_id[i][slot * slot_sz], -1, slot_sz * sizeof(**gNB->common_vars.beam_id)); } } -void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, +static void nr_generate_csi_rs_gNB(PHY_VARS_gNB *gNB, + int slot, + const nfapi_nr_config_request_scf_t *cfg, + const nfapi_nr_dl_tti_csi_rs_pdu *csi_rs_pdu) +{ + const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csi_rs_pdu->csi_rs_pdu_rel15; + if (csi_params->csi_type == 2) // ZP-CSI + return; + + csi_mapping_parms_t mapping_parms = + get_csi_mapping_parms(csi_params->row, csi_params->freq_domain, csi_params->symb_l0, csi_params->symb_l1); + const nfapi_nr_tx_precoding_and_beamforming_t *pb = &csi_params->precodingAndBeamforming; + int csi_bitmap = 0; + int lprime_num = mapping_parms.lprime + 1; + for (int j = 0; j < mapping_parms.size; j++) + csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j]; + int beam_nb = beam_index_allocation(gNB->enable_analog_das, + pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, + &cfg->analog_beamforming_ve, + &gNB->common_vars, + slot, + gNB->frame_parms.symbols_per_slot, + csi_bitmap); + + nr_generate_csi_rs(&gNB->frame_parms, + &mapping_parms, + gNB->TX_AMP, + slot, + csi_params->freq_density, + csi_params->start_rb, + csi_params->nr_of_rbs, + csi_params->symb_l0, + csi_params->symb_l1, + csi_params->row, + csi_params->scramb_id, + csi_params->power_control_offset_ss, + csi_params->cdm_type, + gNB->common_vars.txdataF[beam_nb]); +} + +void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, + const nfapi_nr_dl_tti_request_t *DL_req, + const nfapi_nr_tx_data_request_t *TX_req, + const nfapi_nr_ul_dci_request_t *UL_dci_req, int frame, int slot, int do_meas) { - PHY_VARS_gNB *gNB = msgTx->gNB; - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - int slot_prs = 0; - int txdataF_offset = slot * fp->samples_per_slot_wCP; - prs_config_t *prs_config = NULL; + const int txdataF_offset = slot * fp->samples_per_slot_wCP; if ((cfg->cell_config.frame_duplex_type.value == TDD) && (nr_slot_select(cfg,frame,slot) == NR_UPLINK_SLOT)) return; @@ -213,101 +271,68 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, // clear the transmit data array and beam index for the current slot for (int i = 0; i < gNB->common_vars.num_beams_period; i++) { for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) { - memset(&gNB->common_vars.txdataF[i][aa][txdataF_offset], 0, fp->samples_per_slot_wCP * sizeof(int32_t)); + memset(&gNB->common_vars.txdataF[i][aa][txdataF_offset], 0, fp->samples_per_slot_wCP * sizeof(***gNB->common_vars.txdataF)); } } // Check for PRS slot - section 7.4.1.7.4 in 3GPP rel16 38.211 for(int rsc_id = 0; rsc_id < gNB->prs_vars.NumPRSResources; rsc_id++) { - prs_config = &gNB->prs_vars.prs_cfg[rsc_id]; + prs_config_t *prs_config = &gNB->prs_vars.prs_cfg[rsc_id]; for (int i = 0; i < prs_config->PRSResourceRepetition; i++) { if( (((frame*fp->slots_per_frame + slot) - (prs_config->PRSResourceSetPeriod[1] + prs_config->PRSResourceOffset)+prs_config->PRSResourceSetPeriod[0])%prs_config->PRSResourceSetPeriod[0]) == i*prs_config->PRSResourceTimeGap ) { - slot_prs = (slot - i*prs_config->PRSResourceTimeGap + fp->slots_per_frame)%fp->slots_per_frame; + int slot_prs = (slot - i * prs_config->PRSResourceTimeGap + fp->slots_per_frame) % fp->slots_per_frame; LOG_D(PHY,"gNB_TX: frame %d, slot %d, slot_prs %d, PRS Resource ID %d\n",frame, slot, slot_prs, rsc_id); nr_generate_prs(slot_prs, &gNB->common_vars.txdataF[0][0][txdataF_offset], AMP, prs_config, cfg, fp); } } } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1); - for (int i = 0; i < fp->Lmax; i++) { - if (msgTx->ssb[i].active) { - nr_common_signal_procedures(gNB, frame, slot, msgTx->ssb[i].ssb_pdu); - msgTx->ssb[i].active = false; + for (int i = 0; i < UL_dci_req->numPdus; ++i) + nr_generate_dci(gNB, &UL_dci_req->ul_dci_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot); + + int num_pdsch = 0; + for (int i = 0; i < DL_req->dl_tti_request_body.nPDUs; ++i) { + const nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i]; + switch (dl_tti_pdu->PDUType) { + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + nr_common_signal_procedures(gNB, frame, slot, &dl_tti_pdu->ssb_pdu); + break; + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + nr_generate_dci(gNB, &dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot); + break; + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + nr_generate_csi_rs_gNB(gNB, slot, cfg, &dl_tti_pdu->csi_rs_pdu); + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { + int tx_data_idx = dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15.pduIndex; + if (tx_data_idx < TX_req->Number_of_PDUs && TX_req->pdu_list[tx_data_idx].PDU_index == tx_data_idx) { + // reuse dlsch variables, as there are multiple very large memory + // buffers + gNB->dlsch[num_pdsch].pdsch_pdu = &dl_tti_pdu->pdsch_pdu; + gNB->dlsch[num_pdsch].pdu = (uint8_t *)TX_req->pdu_list[tx_data_idx].TLVs[0].value.direct; + DevAssert(num_pdsch < gNB->max_nb_pdsch); + num_pdsch++; + } else { + LOG_E(NR_PHY, + "%4d.%2d no corresponding tx_data.request for dl_tti.request index %d (out of %d)\n", + frame, + slot, + tx_data_idx, + TX_req->Number_of_PDUs); + } + } break; } } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0); - - int num_pdcch_pdus = msgTx->num_ul_pdcch + msgTx->num_dl_pdcch; - - if (num_pdcch_pdus > 0) { - LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL PDCCH PDUs %d/%d)\n", - gNB->Mod_id, frame, slot, msgTx->num_ul_pdcch, msgTx->num_dl_pdcch); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1); - - nr_generate_dci_top(msgTx, slot, txdataF_offset); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0); - } - msgTx->num_dl_pdcch = 0; - msgTx->num_ul_pdcch = 0; - if (msgTx->num_pdsch_slot > 0) { + if (num_pdsch > 0) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1); - LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", msgTx->num_pdsch_slot,frame,slot); - nr_generate_pdsch(msgTx, frame, slot); + LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", num_pdsch, frame, slot); + nr_generate_pdsch(gNB, num_pdsch, gNB->dlsch, frame, slot); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0); } - msgTx->num_pdsch_slot = 0; - - for (int i = 0; i < NR_SYMBOLS_PER_SLOT; i++){ - NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[i]; - if (csirs->active == 1) { - LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot); - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csirs->csirs_pdu.csi_rs_pdu_rel15; - if (csi_params->csi_type == 2) { // ZP-CSI - csirs->active = 0; - return; - } - csi_mapping_parms_t mapping_parms = get_csi_mapping_parms(csi_params->row, - csi_params->freq_domain, - csi_params->symb_l0, - csi_params->symb_l1); - nfapi_nr_tx_precoding_and_beamforming_t *pb = &csi_params->precodingAndBeamforming; - int csi_bitmap = 0; - int lprime_num = mapping_parms.lprime + 1; - for (int j = 0; j < mapping_parms.size; j++) - csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j]; - int beam_nb = beam_index_allocation(gNB->enable_analog_das, - pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, - &cfg->analog_beamforming_ve, - &gNB->common_vars, - slot, - fp->symbols_per_slot, - csi_bitmap); - - nr_generate_csi_rs(&gNB->frame_parms, - &mapping_parms, - gNB->TX_AMP, - slot, - csi_params->freq_density, - csi_params->start_rb, - csi_params->nr_of_rbs, - csi_params->symb_l0, - csi_params->symb_l1, - csi_params->row, - csi_params->scramb_id, - csi_params->power_control_offset_ss, - csi_params->cdm_type, - gNB->common_vars.txdataF[beam_nb]); - csirs->active = 0; - } - } //apply the OFDM symbol rotation here start_meas(&gNB->phase_comp_stats); @@ -537,24 +562,24 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo return ret_nr_ulsch_decoding; } -void nr_fill_indication(PHY_VARS_gNB *gNB, - int frame, - int slot_rx, - int ULSCH_id, - uint8_t harq_pid, - uint8_t crc_flag, - int dtx_flag, - nfapi_nr_crc_t *crc, - nfapi_nr_rx_data_pdu_t *pdu) +static void nr_fill_indication(PHY_VARS_gNB *gNB, + int frame, + int slot_rx, + int ULSCH_id, + uint8_t harq_pid, + uint8_t crc_flag, + int dtx_flag, + nfapi_nr_crc_t *crc, + nfapi_nr_rx_data_pdu_t *pdu) { - NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; - NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; - NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti); + NR_UL_gNB_HARQ_t *harq_process = gNB->ulsch[ULSCH_id].harq_process; + NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, gNB->ulsch[ULSCH_id].rnti); + NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id]; nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu; // Get estimated timing advance for MAC - int sync_pos = ulsch->delay.est_delay; + const int sync_pos = gNB->ulsch[ULSCH_id].delay.est_delay; // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; @@ -584,16 +609,15 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, timing_advance_update); // estimate UL_CQI for MAC - int SNRtimes10 = - dB_fixed_x10(gNB->pusch_vars[ULSCH_id].ulsch_power_tot) - dB_fixed_x10(gNB->pusch_vars[ULSCH_id].ulsch_noise_power_tot); + int SNRtimes10 = dB_fixed_x10(pusch->ulsch_power_tot) - dB_fixed_x10(pusch->ulsch_noise_power_tot); LOG_D(PHY, "%d.%d: Estimated SNR for PUSCH is = %f dB (ulsch_power %f, noise %f) delay %d\n", frame, slot_rx, SNRtimes10 / 10.0, - dB_fixed_x10(gNB->pusch_vars[ULSCH_id].ulsch_power_tot) / 10.0, - dB_fixed_x10(gNB->pusch_vars[ULSCH_id].ulsch_noise_power_tot) / 10.0, + dB_fixed_x10(pusch->ulsch_power_tot) / 10.0, + dB_fixed_x10(pusch->ulsch_noise_power_tot) / 10.0, sync_pos); int cqi; @@ -609,8 +633,7 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, crc->ul_cqi = cqi; crc->timing_advance = timing_advance_update; // in terms of dBFS range -128 to 0 with 0.1 step - crc->rssi = - (dtx_flag == 0) ? 1280 - (10 * dB_fixed(32767 * 32767) - dB_fixed_times10(gNB->pusch_vars[ULSCH_id].ulsch_power[0])) : 0; + crc->rssi = (dtx_flag == 0) ? 1280 - (10 * dB_fixed(32767 * 32767) - dB_fixed_times10(pusch->ulsch_power[0])) : 0; pdu->handle = pusch_pdu->handle; pdu->rnti = pusch_pdu->rnti; @@ -627,18 +650,18 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, } // Function to fill UL RB mask to be used for N0 measurements -static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32_t rb_mask_ul[14][9]) +static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, + int frame_rx, + int slot_rx, + uint32_t rb_mask_ul[14][9], + nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf) { - int rb = 0; - int rb2 = 0; - int prbpos = 0; - for (int symbol = 0; symbol < 14; symbol++) { for (int m = 0; m < 9; m++) { rb_mask_ul[symbol][m] = 0; for (int i = 0; i < 32; i++) { - prbpos = (m * 32) + i; - if (prbpos>gNB->frame_parms.N_RB_UL) + int prbpos = (m * 32) + i; + if (prbpos > gNB->frame_parms.N_RB_UL) break; rb_mask_ul[symbol][m] |= (gNB->ulprbbl[prbpos] > 0 ? 1U : 0) << i; } @@ -646,23 +669,27 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32 } for (int i = 0; i < gNB->max_nb_pucch; i++){ - NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; - if (pucch) { - if ((pucch->active == 1) && - (pucch->frame == frame_rx) && - (pucch->slot == slot_rx) ) { - nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; - LOG_D(PHY,"%d.%d pucch %d : start_symbol %d, nb_symbols %d, prb_size %d\n",frame_rx,slot_rx,i,pucch_pdu->start_symbol_index,pucch_pdu->nr_of_symbols,pucch_pdu->prb_size); - for (int symbol=pucch_pdu->start_symbol_index ; symbol<(pucch_pdu->start_symbol_index+pucch_pdu->nr_of_symbols);symbol++) { - if(gNB->frame_parms.frame_type == FDD || - (gNB->frame_parms.frame_type == TDD && gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol].slot_config.value==1)) { - for (rb=0; rbprb_size; rb++) { - rb2 = rb + pucch_pdu->bwp_start + - ((symbol < pucch_pdu->start_symbol_index+(pucch_pdu->nr_of_symbols>>1)) || (pucch_pdu->freq_hop_flag == 0) ? - pucch_pdu->prb_start : pucch_pdu->second_hop_prb); - rb_mask_ul[symbol][rb2>>5] |= (((uint32_t)1)<<(rb2&31)); - } - } + const NR_gNB_PUCCH_t *pucch = gNB->pucch + i; + if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx)) + continue; + const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; + const int start = pucch_pdu->start_symbol_index; + LOG_D(PHY, + "%d.%d pucch %d : start_symbol %d, nb_symbols %d, prb_size %d\n", + frame_rx, + slot_rx, + i, + start, + pucch_pdu->nr_of_symbols, + pucch_pdu->prb_size); + for (int symbol = start; symbol < (start + pucch_pdu->nr_of_symbols); symbol++) { + if (gNB->frame_parms.frame_type == FDD || (gNB->frame_parms.frame_type == TDD && slot_conf[symbol].slot_config.value == 1)) { + for (int rb = 0; rb < pucch_pdu->prb_size; rb++) { + int rb2 = + rb + pucch_pdu->bwp_start + + ((symbol < start + (pucch_pdu->nr_of_symbols >> 1)) || (pucch_pdu->freq_hop_flag == 0) ? pucch_pdu->prb_start + : pucch_pdu->second_hop_prb); + rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); } } } @@ -672,21 +699,16 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32 NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); - if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) { - uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; - uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; - for (int symbol = symbol_start; symbol < symbol_end; symbol++) { - if (gNB->frame_parms.frame_type == FDD - || (gNB->frame_parms.frame_type == TDD - && gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx] - .max_num_of_symbol_per_slot_list[symbol] - .slot_config.value - == 1)) { - LOG_D(PHY, "symbol %d Filling rb_mask_ul rb_size %d\n", symbol, ulsch_harq->ulsch_pdu.rb_size); - for (rb = 0; rb < ulsch_harq->ulsch_pdu.rb_size; rb++) { - rb2 = rb + ulsch_harq->ulsch_pdu.rb_start + ulsch_harq->ulsch_pdu.bwp_start; - rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); - } + if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled)) + continue; + uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; + uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; + for (int symbol = symbol_start; symbol < symbol_end; symbol++) { + if (gNB->frame_parms.frame_type == FDD || (gNB->frame_parms.frame_type == TDD && slot_conf[symbol].slot_config.value == 1)) { + LOG_D(PHY, "symbol %d Filling rb_mask_ul rb_size %d\n", symbol, ulsch_harq->ulsch_pdu.rb_size); + for (int rb = 0; rb < ulsch_harq->ulsch_pdu.rb_size; rb++) { + int rb2 = rb + ulsch_harq->ulsch_pdu.rb_start + ulsch_harq->ulsch_pdu.bwp_start; + rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); } } } @@ -694,52 +716,59 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32 for (int i = 0; i < gNB->max_nb_srs; i++) { NR_gNB_SRS_t *srs = &gNB->srs[i]; - if (srs) { - if ((srs->active == 1) && (srs->frame == frame_rx) && (srs->slot == slot_rx)) { - nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; - for(int symbol = 0; symbol < (1 << srs_pdu->num_symbols); symbol++) { - for(rb = srs_pdu->bwp_start; rb < (srs_pdu->bwp_start+srs_pdu->bwp_size); rb++) { - rb_mask_ul[srs_pdu->time_start_position + symbol][rb >> 5] |= 1U << (rb & 31); - } - } + if (!(srs && srs->active && srs->frame == frame_rx && srs->slot == slot_rx)) + continue; + nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + for (int symbol = 0; symbol < (1 << srs_pdu->num_symbols); symbol++) { + for (int rb = srs_pdu->bwp_start; rb < (srs_pdu->bwp_start + srs_pdu->bwp_size); rb++) { + rb_mask_ul[srs_pdu->time_start_position + symbol][rb >> 5] |= 1U << (rb & 31); } } } } -int fill_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *reported_symbol, - const nfapi_nr_srs_pdu_t *srs_pdu, - const int N_RB_UL, - const int16_t *snr_per_rb, - const int srs_est) { +static int fill_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *reported_symbol, + const nfapi_nr_srs_pdu_t *srs_pdu, + const int N_RB_UL, + const int16_t *snr_per_rb, + const int srs_est) +{ reported_symbol->num_prgs = srs_pdu->beamforming.num_prgs; for (int prg_idx = 0; prg_idx < reported_symbol->num_prgs; prg_idx++) { - if (srs_est<0) { - reported_symbol->prg_list[prg_idx].rb_snr = 0xFF; + uint8_t *snr = &reported_symbol->prg_list[prg_idx].rb_snr; + if (srs_est < 0) { + *snr = 0xFF; } else if (snr_per_rb[prg_idx] < -64) { - reported_symbol->prg_list[prg_idx].rb_snr = 0; + *snr = 0; } else if (snr_per_rb[prg_idx] > 63) { - reported_symbol->prg_list[prg_idx].rb_snr = 0xFE; + *snr = 0xFE; } else { - reported_symbol->prg_list[prg_idx].rb_snr = (snr_per_rb[prg_idx] + 64) << 1; + *snr = (snr_per_rb[prg_idx] + 64) << 1; } } return 0; } -int fill_srs_channel_matrix(uint8_t *channel_matrix, - const nfapi_nr_srs_pdu_t *srs_pdu, - const nr_srs_info_t *nr_srs_info, - const uint8_t normalized_iq_representation, - const uint16_t num_gnb_antenna_elements, - const uint16_t num_ue_srs_ports, - const uint16_t prg_size, - const uint16_t num_prgs, - const NR_DL_FRAME_PARMS *frame_parms, - const c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] - [frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) +static int fill_srs_channel_matrix( + nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_channel_iq_matrix, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const uint8_t normalized_iq_representation, + const uint16_t num_gnb_antenna_elements, + const uint16_t num_ue_srs_ports, + const uint16_t prg_size, + const uint16_t num_prgs, + const NR_DL_FRAME_PARMS *frame_parms, + const c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] + [frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) { + nr_srs_channel_iq_matrix->normalized_iq_representation = normalized_iq_representation; + nr_srs_channel_iq_matrix->num_gnb_antenna_elements = num_gnb_antenna_elements; + nr_srs_channel_iq_matrix->num_ue_srs_ports = num_ue_srs_ports; + nr_srs_channel_iq_matrix->prg_size = prg_size; + nr_srs_channel_iq_matrix->num_prgs = num_prgs; + uint8_t *channel_matrix = nr_srs_channel_iq_matrix->channel_matrix; const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*NR_NB_SC_PER_RB; const uint16_t step = prg_size*NR_NB_SC_PER_RB; @@ -837,75 +866,73 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N int pusch_decode_done = 0; int pusch_DTX = 0; + const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + const int symb_sz = frame_parms->ofdm_symbol_size; + const int nb_symb = frame_parms->symbols_per_slot; + const int ant = gNB->frame_parms.nb_antennas_rx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1); LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); - // Mask of occupied RBs, per symbol and PRB - uint32_t rb_mask_ul[14][9]; - fill_ul_rb_mask(gNB, frame_rx, slot_rx, rb_mask_ul); + { + // Mask of occupied RBs, per symbol and PRB + uint32_t rb_mask_ul[14][9]; + nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf = NULL; + if (frame_parms->frame_type == TDD) + slot_conf = gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list; + fill_ul_rb_mask(gNB, frame_rx, slot_rx, rb_mask_ul, slot_conf); - int first_symb=0,num_symb=0; - if (gNB->frame_parms.frame_type == TDD) - for(int symbol_count=0; symbol_countgNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1) { - if (num_symb==0) first_symb=symbol_count; - num_symb++; + int first_symb = 0, num_symb = 0; + if (frame_parms->frame_type == TDD) + for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + if (slot_conf[symbol_count].slot_config.value == 1) { + if (num_symb == 0) + first_symb = symbol_count; + num_symb++; + } } - } - else - num_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT; - gNB_I0_measurements(gNB, slot_rx, first_symb, num_symb, rb_mask_ul); + else + num_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT; + gNB_I0_measurements(gNB, slot_rx, first_symb, num_symb, rb_mask_ul); + } - const int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; + const int soffset = (slot_rx & 3) * nb_symb * symb_sz; start_meas(&gNB->phy_proc_rx); for (int i = 0; i < gNB->max_nb_pucch; i++) { NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; - if (pucch) { - if (pucch->active && (pucch->frame == frame_rx) && (pucch->slot == slot_rx)) { - c16_t **rxdataF = gNB->common_vars.rxdataF[pucch->beam_nb]; - pucch_decode_done = 1; - nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; - UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list; - nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list + UL_INFO->uci_ind.num_ucis; - switch (pucch_pdu->format_type) { - case 0: - UL_INFO->uci_ind.sfn = frame_rx; - UL_INFO->uci_ind.slot = slot_rx; - uci->pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE; - uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t); - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &uci->pucch_pdu_format_0_1; - - int offset = pucch_pdu->start_symbol_index * gNB->frame_parms.ofdm_symbol_size - + (gNB->frame_parms.first_carrier_offset + pucch_pdu->prb_start * 12); - LOG_D(NR_PHY, - "frame %d, slot %d: PUCCH signal energy %d\n", - frame_rx, - slot_rx, - signal_energy_nodc(&rxdataF[0][soffset + offset], 12)); - - nr_decode_pucch0(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format0, pucch_pdu); - - UL_INFO->uci_ind.num_ucis += 1; - pucch->active = false; - break; - case 2: - UL_INFO->uci_ind.sfn = frame_rx; - UL_INFO->uci_ind.slot = slot_rx; - uci->pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE; - uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t); - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &uci->pucch_pdu_format_2_3_4; - - LOG_D(PHY, "%d.%d Calling nr_decode_pucch2\n", frame_rx, slot_rx); - nr_decode_pucch2(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format2, pucch_pdu); - - UL_INFO->uci_ind.num_ucis += 1; - pucch->active = false; - break; - default: - AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n"); - } - } + if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx)) + continue; + c16_t **rxdataF = gNB->common_vars.rxdataF[pucch->beam_nb]; + pucch_decode_done = 1; + nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; + UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list; + nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list + UL_INFO->uci_ind.num_ucis; + UL_INFO->uci_ind.sfn = frame_rx; + UL_INFO->uci_ind.slot = slot_rx; + switch (pucch_pdu->format_type) { + case 0: + uci->pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE; + uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t); + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &uci->pucch_pdu_format_0_1; + int offset = pucch_pdu->start_symbol_index * symb_sz + (frame_parms->first_carrier_offset + pucch_pdu->prb_start * 12); + LOG_D(NR_PHY, + "frame %d, slot %d: PUCCH signal energy %d\n", + frame_rx, + slot_rx, + signal_energy_nodc(&rxdataF[0][soffset + offset], 12)); + nr_decode_pucch0(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format0, pucch_pdu); + break; + case 2: + uci->pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE; + uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t); + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &uci->pucch_pdu_format_2_3_4; + LOG_D(PHY, "%d.%d Calling nr_decode_pucch2\n", frame_rx, slot_rx); + nr_decode_pucch2(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format2, pucch_pdu); + break; + default: + AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n"); } + UL_INFO->uci_ind.num_ucis += 1; + pucch->active = false; } UL_INFO->crc_ind.sfn = frame_rx; @@ -915,104 +942,103 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N UL_INFO->rx_ind.slot = slot_rx; UL_INFO->rx_ind.pdu_list = UL_INFO->rx_pdu_list; bool ulsch_to_decode[gNB->max_nb_pusch]; - bzero((void *)ulsch_to_decode, sizeof(ulsch_to_decode)); + bzero(ulsch_to_decode, sizeof(ulsch_to_decode)); for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); - if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) { - LOG_D(PHY, "PUSCH ID %d with RNTI %x detection started in frame %d slot %d\n", ULSCH_id, ulsch->rnti, frame_rx, slot_rx); - nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; - int num_dmrs = count_bits64_with_mask(pdu->ul_dmrs_symb_pos, 0, NR_NUMBER_OF_SYMBOLS_PER_SLOT); + if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled)) + continue; + LOG_D(PHY, "PUSCH ID %d with RNTI %x detection started in frame %d slot %d\n", ULSCH_id, ulsch->rnti, frame_rx, slot_rx); + nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; + int num_dmrs = count_bits64_with_mask(pdu->ul_dmrs_symb_pos, 0, NR_NUMBER_OF_SYMBOLS_PER_SLOT); #ifdef DEBUG_RXDATA - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - RU_t *ru = gNB->RU_list[0]; - int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx, frame_parms, 0); - slot_offset -= ru->N_TA_offset; - int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset; - int16_t *buf = (int16_t *)&gNB->common_vars.debugBuff[offset]; - buf[0] = (int16_t)ulsch->rnti; - buf[1] = (int16_t)pdu->rb_size; - buf[2] = (int16_t)pdu->rb_start; - buf[3] = (int16_t)pdu->nr_of_symbols; - buf[4] = (int16_t)pdu->start_symbol_index; - buf[5] = (int16_t)pdu->mcs_index; - buf[6] = (int16_t)pdu->pusch_data.rv_index; - buf[7] = (int16_t)ulsch->harq_pid; - memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset + 4], - &ru->common.rxdata[0][slot_offset], - frame_parms->get_samples_per_slot(slot_rx, frame_parms) * sizeof(int32_t)); - gNB->common_vars.debugBuff_sample_offset += (frame_parms->get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4); - if (gNB->common_vars.debugBuff_sample_offset > ((frame_parms->get_samples_per_slot(slot_rx, frame_parms) + 1000 + 2) * 20)) { - FILE *f; - f = fopen("rxdata_buff.raw", "w"); - if (f == NULL) - exit(1); - fwrite((int16_t *)gNB->common_vars.debugBuff, - 2, - (frame_parms->get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4) * 20 * 2, - f); - fclose(f); - exit(-1); - } + RU_t *ru = gNB->RU_list[0]; + int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx, frame_parms, 0); + slot_offset -= ru->N_TA_offset; + int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset; + int16_t buf = (int16_t *)&gNB->common_vars.debugBuff[offset]; + buf[0] = (int16_t)ulsch->rnti; + buf[1] = (int16_t)pdu->rb_size; + buf[2] = (int16_t)pdu->rb_start; + buf[3] = (int16_t)pdu->nr_of_symbols; + buf[4] = (int16_t)pdu->start_symbol_index; + buf[5] = (int16_t)pdu->mcs_index; + buf[6] = (int16_t)pdu->pusch_data.rv_index; + buf[7] = (int16_t)ulsch->harq_pid; + memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset + 4], + &ru->common.rxdata[0][slot_offset], + frame_parms->get_samples_per_slot(slot_rx, frame_parms) * sizeof(int32_t)); + gNB->common_vars.debugBuff_sample_offset += (frame_parms->get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4); + if (gNB->common_vars.debugBuff_sample_offset > ((frame_parms->get_samples_per_slot(slot_rx, frame_parms) + 1000 + 2) * 20)) { + FILE *f; + f = fopen("rxdata_buff.raw", "w"); + if (f == NULL) + exit(1); + fwrite((int16_t *)gNB->common_vars.debugBuff, + 2, + (frame_parms->get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4) * 20 * 2, + f); + fclose(f); + exit(-1); + } #endif - pusch_decode_done = 1; + pusch_decode_done = 1; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 1); - start_meas(&gNB->rx_pusch_stats); - nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid, ulsch->beam_nb); - NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; - pusch_vars->ulsch_power_tot = 0; - pusch_vars->ulsch_noise_power_tot = 0; - for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx++) { - pusch_vars->ulsch_power[aarx] /= num_dmrs; - pusch_vars->ulsch_power_tot += pusch_vars->ulsch_power[aarx]; - pusch_vars->ulsch_noise_power[aarx] /= num_dmrs; - pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx]; - } - if (dB_fixed_x10(pusch_vars->ulsch_power_tot) < dB_fixed_x10(pusch_vars->ulsch_noise_power_tot) + gNB->pusch_thres) { - NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti); - - LOG_D(PHY, - "PUSCH not detected in %d.%d (%d,%d,%d)\n", - frame_rx, - slot_rx, - dB_fixed_x10(pusch_vars->ulsch_power_tot), - dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), - gNB->pusch_thres); - pusch_vars->ulsch_power_tot = pusch_vars->ulsch_noise_power_tot; - pusch_vars->DTX = 1; - if (stats) - stats->ulsch_stats.DTX++; - if (!get_softmodem_params()->phy_test) { - /* in case of phy_test mode, we still want to decode to measure execution time. - Therefore, we don't yet call nr_fill_indication, it will be called later */ - nfapi_nr_crc_t *crc = &UL_INFO->crc_ind.crc_list[UL_INFO->crc_ind.number_crcs++]; - nfapi_nr_rx_data_pdu_t *pdu = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++]; - nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1, crc, pdu); - pusch_DTX++; - gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX"); - continue; - } - } else { - LOG_D(PHY, - "PUSCH detected in %d.%d (%d,%d,%d)\n", - frame_rx, - slot_rx, - dB_fixed_x10(pusch_vars->ulsch_power_tot), - dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), - gNB->pusch_thres); - - pusch_vars->DTX = 0; - } - ulsch_to_decode[ULSCH_id] = true; - stop_meas(&gNB->rx_pusch_stats); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 0); - // LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); - // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 1); + start_meas(&gNB->rx_pusch_stats); + nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid, ulsch->beam_nb); + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; + pusch_vars->ulsch_power_tot = 0; + pusch_vars->ulsch_noise_power_tot = 0; + for (int aarx = 0; aarx < ant; aarx++) { + pusch_vars->ulsch_power[aarx] /= num_dmrs; + pusch_vars->ulsch_power_tot += pusch_vars->ulsch_power[aarx]; + pusch_vars->ulsch_noise_power[aarx] /= num_dmrs; + pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx]; } + if (dB_fixed_x10(pusch_vars->ulsch_power_tot) < dB_fixed_x10(pusch_vars->ulsch_noise_power_tot) + gNB->pusch_thres) { + NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti); + + LOG_D(PHY, + "PUSCH not detected in %d.%d (%d,%d,%d)\n", + frame_rx, + slot_rx, + dB_fixed_x10(pusch_vars->ulsch_power_tot), + dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), + gNB->pusch_thres); + pusch_vars->ulsch_power_tot = pusch_vars->ulsch_noise_power_tot; + pusch_vars->DTX = 1; + if (stats) + stats->ulsch_stats.DTX++; + if (!get_softmodem_params()->phy_test) { + /* in case of phy_test mode, we still want to decode to measure execution time. + Therefore, we don't yet call nr_fill_indication, it will be called later */ + nfapi_nr_crc_t *crc = &UL_INFO->crc_ind.crc_list[UL_INFO->crc_ind.number_crcs++]; + nfapi_nr_rx_data_pdu_t *pdu = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++]; + nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1, crc, pdu); + pusch_DTX++; + gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX"); + continue; + } + } else { + LOG_D(PHY, + "PUSCH detected in %d.%d (%d,%d,%d)\n", + frame_rx, + slot_rx, + dB_fixed_x10(pusch_vars->ulsch_power_tot), + dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), + gNB->pusch_thres); + + pusch_vars->DTX = 0; + } + ulsch_to_decode[ULSCH_id] = true; + stop_meas(&gNB->rx_pusch_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 0); + // LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); + // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); } /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 @@ -1033,251 +1059,298 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N * measurement per processed TB.*/ if (gNB->max_nb_pusch == 1) stop_meas(&gNB->ulsch_decoding_stats); + for (int i = 0; i < gNB->max_nb_srs; i++) { NR_gNB_SRS_t *srs = &gNB->srs[i]; - if (srs) { - if ((srs->active == true) && (srs->frame == frame_rx) && (srs->slot == slot_rx)) { - LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i); + if (!(srs && srs->active && srs->frame == frame_rx && srs->slot == slot_rx)) + continue; + LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i); - start_meas(&gNB->rx_srs_stats); + start_meas(&gNB->rx_srs_stats); - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; - uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; - c16_t srs_received_signal[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; - c16_t srs_received_noise[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; - c16_t srs_estimated_channel_freq[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] - [frame_parms->ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); - c16_t srs_estimated_channel_time[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size] - __attribute__((aligned(32))); - c16_t srs_estimated_channel_time_shifted[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] - [frame_parms->ofdm_symbol_size]; - int16_t snr_per_rb[srs_pdu->bwp_size]; + nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; + c16_t srs_received_signal[ant][symb_sz * N_symb_SRS]; + c16_t srs_received_noise[ant][symb_sz * N_symb_SRS]; + c16_t srs_estimated_channel_freq[ant][1 << srs_pdu->num_ant_ports][symb_sz * N_symb_SRS] __attribute__((aligned(32))); + c16_t srs_estimated_channel_time[ant][1 << srs_pdu->num_ant_ports][symb_sz] __attribute__((aligned(32))); + c16_t srs_estimated_channel_time_shifted[ant][1 << srs_pdu->num_ant_ports][symb_sz]; + int16_t snr_per_rb[srs_pdu->bwp_size]; - start_meas(&gNB->generate_srs_stats); + start_meas(&gNB->generate_srs_stats); - if (check_and_configure_srs_info(srs_pdu, gNB->nr_srs_info[i])) { - generate_srs_nr(frame_parms, - gNB->nr_srs_info[i]->srs_generated_signal, - 0, - srs_pdu->bwp_start, - gNB->nr_srs_info[i], - AMP, - frame_rx, - slot_rx); - } - stop_meas(&gNB->generate_srs_stats); - c16_t **rxdataF = gNB->common_vars.rxdataF[srs->beam_nb]; - start_meas(&gNB->get_srs_signal_stats); - int srs_est = nr_get_srs_signal(gNB, rxdataF, frame_rx, slot_rx, srs_pdu, gNB->nr_srs_info[i], srs_received_signal, srs_received_noise); - stop_meas(&gNB->get_srs_signal_stats); - - if (srs_est >= 0) { - start_meas(&gNB->srs_channel_estimation_stats); - nr_srs_channel_estimation(gNB, - frame_rx, - slot_rx, - srs_pdu, - gNB->nr_srs_info[i], - (const c16_t**)gNB->nr_srs_info[i]->srs_generated_signal, - srs_received_signal, - srs_received_noise, - srs_estimated_channel_freq, - srs_estimated_channel_time, - srs_estimated_channel_time_shifted, - snr_per_rb, - &gNB->srs->snr); - stop_meas(&gNB->srs_channel_estimation_stats); - } - - if ((gNB->srs->snr * 10) < gNB->srs_thres) { - srs_est = -1; - } - - T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, - T_INT(0), - T_INT(srs_pdu->rnti), - T_INT(frame_rx), - T_INT(0), - T_INT(0), - T_BUFFER(srs_estimated_channel_freq[0][0], frame_parms->ofdm_symbol_size * sizeof(int32_t))); - - T(T_GNB_PHY_UL_TIME_CHANNEL_ESTIMATE, - T_INT(0), - T_INT(srs_pdu->rnti), - T_INT(frame_rx), - T_INT(0), - T_INT(0), - T_BUFFER(srs_estimated_channel_time_shifted[0][0], frame_parms->ofdm_symbol_size * sizeof(int32_t))); - - T(T_GNB_PHY_UL_SNR_ESTIMATE, - T_INT(0), - T_INT(srs_pdu->rnti), - T_INT(frame_rx), - T_INT(0), - T_INT(0), - T_BUFFER(snr_per_rb, srs_pdu->bwp_size * sizeof(int16_t))); - - UL_INFO->srs_ind.sfn = frame_rx; - UL_INFO->srs_ind.slot = slot_rx; - - // data model difficult to understand, nfapi do malloc for this pointer - UL_INFO->srs_ind.pdu_list = UL_INFO->srs_pdu_list; - nfapi_nr_srs_indication_pdu_t *srs_indication = UL_INFO->srs_pdu_list + UL_INFO->srs_ind.number_of_pdus++; - srs_indication->handle = srs_pdu->handle; - srs_indication->rnti = srs_pdu->rnti; - start_meas(&gNB->srs_timing_advance_stats); - srs_indication->timing_advance_offset = srs_est >= 0 ? nr_est_timing_advance_srs(frame_parms, srs_estimated_channel_time[0]) : 0xFFFF; - stop_meas(&gNB->srs_timing_advance_stats); - srs_indication->timing_advance_offset_nsec = srs_est >= 0 ? (int16_t)((((int32_t)srs_indication->timing_advance_offset - 31) * ((int32_t)TC_NSEC_x32768)) >> 15) : 0xFFFF; - switch (srs_pdu->srs_parameters_v4.usage) { - case 0: - LOG_W(NR_PHY, "SRS report was not requested by MAC\n"); - return 0; - case 1 << NFAPI_NR_SRS_BEAMMANAGEMENT: - srs_indication->srs_usage = NFAPI_NR_SRS_BEAMMANAGEMENT; - break; - case 1 << NFAPI_NR_SRS_CODEBOOK: - srs_indication->srs_usage = NFAPI_NR_SRS_CODEBOOK; - break; - case 1 << NFAPI_NR_SRS_NONCODEBOOK: - srs_indication->srs_usage = NFAPI_NR_SRS_NONCODEBOOK; - break; - case 1 << NFAPI_NR_SRS_ANTENNASWITCH: - srs_indication->srs_usage = NFAPI_NR_SRS_ANTENNASWITCH; - break; - default: - LOG_E(NR_PHY, "Invalid srs_pdu->srs_parameters_v4.usage %i\n", srs_pdu->srs_parameters_v4.usage); - } - srs_indication->report_type = srs_pdu->srs_parameters_v4.report_type[0]; - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "UL_INFO->srs_ind.sfn = %i\n", UL_INFO->srs_ind.sfn); - LOG_I(NR_PHY, "UL_INFO->srs_ind.slot = %i\n", UL_INFO->srs_ind.slot); - LOG_I(NR_PHY, "srs_indication->rnti = %04x\n", srs_indication->rnti); - LOG_I(NR_PHY, "srs_indication->timing_advance = %i\n", srs_indication->timing_advance_offset); - LOG_I(NR_PHY, "srs_indication->timing_advance_offset_nsec = %i\n", srs_indication->timing_advance_offset_nsec); - LOG_I(NR_PHY, "srs_indication->srs_usage = %i\n", srs_indication->srs_usage); - LOG_I(NR_PHY, "srs_indication->report_type = %i\n", srs_indication->report_type); -#endif - - nfapi_srs_report_tlv_t *report_tlv = &srs_indication->report_tlv; - report_tlv->tag = 0; - report_tlv->length = 0; - - start_meas(&gNB->srs_report_tlv_stats); - switch (srs_indication->srs_usage) { - case NFAPI_NR_SRS_BEAMMANAGEMENT: { - start_meas(&gNB->srs_beam_report_stats); - nfapi_nr_srs_beamforming_report_t nr_srs_bf_report; - nr_srs_bf_report.prg_size = srs_pdu->beamforming.prg_size; - nr_srs_bf_report.num_symbols = 1 << srs_pdu->num_symbols; - nr_srs_bf_report.wide_band_snr = srs_est >= 0 ? (gNB->srs->snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid - nr_srs_bf_report.num_reported_symbols = 1 << srs_pdu->num_symbols; - AssertFatal(nr_srs_bf_report.num_reported_symbols == 1, - "nr_srs_bf_report.num_reported_symbols %i not handled yet!\n", - nr_srs_bf_report.num_reported_symbols); - fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, frame_parms->N_RB_UL, snr_per_rb, srs_est); - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "nr_srs_bf_report.prg_size = %i\n", nr_srs_bf_report.prg_size); - LOG_I(NR_PHY, "nr_srs_bf_report.num_symbols = %i\n", nr_srs_bf_report.num_symbols); - LOG_I(NR_PHY, "nr_srs_bf_report.wide_band_snr = %i (%i dB)\n", nr_srs_bf_report.wide_band_snr, (nr_srs_bf_report.wide_band_snr >> 1) - 64); - LOG_I(NR_PHY, "nr_srs_bf_report.num_reported_symbols = %i\n", nr_srs_bf_report.num_reported_symbols); - LOG_I(NR_PHY, "nr_srs_bf_report.reported_symbol_list[0].num_prgs = %i\n", nr_srs_bf_report.reported_symbol_list[0].num_prgs); - for (int prg_idx = 0; prg_idx < nr_srs_bf_report.reported_symbol_list[0].num_prgs; prg_idx++) { - LOG_I(NR_PHY, - "nr_srs_beamforming_report.reported_symbol_list[0].prg_list[%3i].rb_snr = %i (%i dB)\n", - prg_idx, - nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr, - (nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr >> 1) - 64); - } -#endif - - report_tlv->length = pack_nr_srs_beamforming_report(&nr_srs_bf_report, report_tlv->value, sizeof(report_tlv->value)); - stop_meas(&gNB->srs_beam_report_stats); - break; - } - - case NFAPI_NR_SRS_CODEBOOK: { - start_meas(&gNB->srs_iq_matrix_stats); - nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_channel_iq_matrix; - nr_srs_channel_iq_matrix.normalized_iq_representation = srs_pdu->srs_parameters_v4.iq_representation; - nr_srs_channel_iq_matrix.num_gnb_antenna_elements = gNB->frame_parms.nb_antennas_rx; - nr_srs_channel_iq_matrix.num_ue_srs_ports = srs_pdu->srs_parameters_v4.num_total_ue_antennas; - nr_srs_channel_iq_matrix.prg_size = srs_pdu->srs_parameters_v4.prg_size; - nr_srs_channel_iq_matrix.num_prgs = srs_pdu->srs_parameters_v4.srs_bandwidth_size / srs_pdu->srs_parameters_v4.prg_size; - fill_srs_channel_matrix(nr_srs_channel_iq_matrix.channel_matrix, - srs_pdu, - gNB->nr_srs_info[i], - nr_srs_channel_iq_matrix.normalized_iq_representation, - nr_srs_channel_iq_matrix.num_gnb_antenna_elements, - nr_srs_channel_iq_matrix.num_ue_srs_ports, - nr_srs_channel_iq_matrix.prg_size, - nr_srs_channel_iq_matrix.num_prgs, - &gNB->frame_parms, - srs_estimated_channel_freq); - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.normalized_iq_representation = %i\n", nr_srs_channel_iq_matrix.normalized_iq_representation); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_gnb_antenna_elements = %i\n", nr_srs_channel_iq_matrix.num_gnb_antenna_elements); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_ue_srs_ports = %i\n", nr_srs_channel_iq_matrix.num_ue_srs_ports); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.prg_size = %i\n", nr_srs_channel_iq_matrix.prg_size); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_prgs = %i\n", nr_srs_channel_iq_matrix.num_prgs); - c16_t *channel_matrix16 = (c16_t *)nr_srs_channel_iq_matrix.channel_matrix; - c8_t *channel_matrix8 = (c8_t *)nr_srs_channel_iq_matrix.channel_matrix; - for (int uI = 0; uI < nr_srs_channel_iq_matrix.num_ue_srs_ports; uI++) { - for (int gI = 0; gI < nr_srs_channel_iq_matrix.num_gnb_antenna_elements; gI++) { - for (int pI = 0; pI < nr_srs_channel_iq_matrix.num_prgs; pI++) { - uint16_t index = - uI * nr_srs_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_channel_iq_matrix.num_prgs + gI * nr_srs_channel_iq_matrix.num_prgs + pI; - LOG_I(NR_PHY, - "(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n", - uI, - gI, - pI, - nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].r : channel_matrix16[index].r, - nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].i : channel_matrix16[index].i); - } - } - } -#endif - - report_tlv->length = pack_nr_srs_normalized_channel_iq_matrix(&nr_srs_channel_iq_matrix, report_tlv->value, sizeof(report_tlv->value)); - stop_meas(&gNB->srs_iq_matrix_stats); - break; - } - - case NFAPI_NR_SRS_NONCODEBOOK: - case NFAPI_NR_SRS_ANTENNASWITCH: - LOG_W(NR_PHY, "PHY procedures for this SRS usage are not implemented yet!\n"); - break; - - default: - AssertFatal(1 == 0, "Invalid SRS usage\n"); - } - stop_meas(&gNB->srs_report_tlv_stats); - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "report_tlv->tag = %i\n", report_tlv->tag); - LOG_I(NR_PHY, "report_tlv->length = %i\n", report_tlv->length); - char *value = (char *)report_tlv->value; - for (int b = 0; b < report_tlv->length; b++) { - LOG_I(NR_PHY, "value[%i] = 0x%02x\n", b, value[b] & 0xFF); - } -#endif - srs->active = false; - stop_meas(&gNB->rx_srs_stats); - } + if (check_and_configure_srs_info(srs_pdu, gNB->nr_srs_info[i])) { + generate_srs_nr(frame_parms, + gNB->nr_srs_info[i]->srs_generated_signal, + 0, + srs_pdu->bwp_start, + gNB->nr_srs_info[i], + AMP, + frame_rx, + slot_rx); } + stop_meas(&gNB->generate_srs_stats); + c16_t **rxdataF = gNB->common_vars.rxdataF[srs->beam_nb]; + start_meas(&gNB->get_srs_signal_stats); + int srs_est = + nr_get_srs_signal(gNB, rxdataF, frame_rx, slot_rx, srs_pdu, gNB->nr_srs_info[i], srs_received_signal, srs_received_noise); + stop_meas(&gNB->get_srs_signal_stats); + + if (srs_est >= 0) { + start_meas(&gNB->srs_channel_estimation_stats); + nr_srs_channel_estimation(gNB, + frame_rx, + slot_rx, + srs_pdu, + gNB->nr_srs_info[i], + (const c16_t **)gNB->nr_srs_info[i]->srs_generated_signal, + srs_received_signal, + srs_received_noise, + srs_estimated_channel_freq, + srs_estimated_channel_time, + srs_estimated_channel_time_shifted, + snr_per_rb, + &gNB->srs->snr); + stop_meas(&gNB->srs_channel_estimation_stats); + } + + if ((gNB->srs->snr * 10) < gNB->srs_thres) { + srs_est = -1; + } + + T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, + T_INT(0), + T_INT(srs_pdu->rnti), + T_INT(frame_rx), + T_INT(0), + T_INT(0), + T_BUFFER(srs_estimated_channel_freq[0][0], symb_sz * sizeof(int32_t))); + + T(T_GNB_PHY_UL_TIME_CHANNEL_ESTIMATE, + T_INT(0), + T_INT(srs_pdu->rnti), + T_INT(frame_rx), + T_INT(0), + T_INT(0), + T_BUFFER(srs_estimated_channel_time_shifted[0][0], symb_sz * sizeof(int32_t))); + + T(T_GNB_PHY_UL_SNR_ESTIMATE, + T_INT(0), + T_INT(srs_pdu->rnti), + T_INT(frame_rx), + T_INT(0), + T_INT(0), + T_BUFFER(snr_per_rb, srs_pdu->bwp_size * sizeof(int16_t))); + + UL_INFO->srs_ind.sfn = frame_rx; + UL_INFO->srs_ind.slot = slot_rx; + + // data model difficult to understand, nfapi do malloc for this pointer + UL_INFO->srs_ind.pdu_list = UL_INFO->srs_pdu_list; + nfapi_nr_srs_indication_pdu_t *srs_indication = UL_INFO->srs_pdu_list + UL_INFO->srs_ind.number_of_pdus++; + srs_indication->handle = srs_pdu->handle; + srs_indication->rnti = srs_pdu->rnti; + start_meas(&gNB->srs_timing_advance_stats); + srs_indication->timing_advance_offset = + srs_est >= 0 ? nr_est_timing_advance_srs(frame_parms, srs_estimated_channel_time[0]) : 0xFFFF; + stop_meas(&gNB->srs_timing_advance_stats); + srs_indication->timing_advance_offset_nsec = + srs_est >= 0 ? (int16_t)((((int32_t)srs_indication->timing_advance_offset - 31) * ((int32_t)TC_NSEC_x32768)) >> 15) + : 0xFFFF; + switch (srs_pdu->srs_parameters_v4.usage) { + case 0: + LOG_W(NR_PHY, "SRS report was not requested by MAC\n"); + return 0; + case 1 << NFAPI_NR_SRS_BEAMMANAGEMENT: + srs_indication->srs_usage = NFAPI_NR_SRS_BEAMMANAGEMENT; + break; + case 1 << NFAPI_NR_SRS_CODEBOOK: + srs_indication->srs_usage = NFAPI_NR_SRS_CODEBOOK; + break; + case 1 << NFAPI_NR_SRS_NONCODEBOOK: + srs_indication->srs_usage = NFAPI_NR_SRS_NONCODEBOOK; + break; + case 1 << NFAPI_NR_SRS_ANTENNASWITCH: + srs_indication->srs_usage = NFAPI_NR_SRS_ANTENNASWITCH; + break; + default: + LOG_E(NR_PHY, "Invalid srs_pdu->srs_parameters_v4.usage %i\n", srs_pdu->srs_parameters_v4.usage); + } + srs_indication->report_type = srs_pdu->srs_parameters_v4.report_type[0]; + +#ifdef SRS_IND_DEBUG + LOG_I(NR_PHY, "UL_INFO->srs_ind.sfn = %i\n", UL_INFO->srs_ind.sfn); + LOG_I(NR_PHY, "UL_INFO->srs_ind.slot = %i\n", UL_INFO->srs_ind.slot); + LOG_I(NR_PHY, "srs_indication->rnti = %04x\n", srs_indication->rnti); + LOG_I(NR_PHY, "srs_indication->timing_advance = %i\n", srs_indication->timing_advance_offset); + LOG_I(NR_PHY, "srs_indication->timing_advance_offset_nsec = %i\n", srs_indication->timing_advance_offset_nsec); + LOG_I(NR_PHY, "srs_indication->srs_usage = %i\n", srs_indication->srs_usage); + LOG_I(NR_PHY, "srs_indication->report_type = %i\n", srs_indication->report_type); +#endif + + nfapi_srs_report_tlv_t *report_tlv = &srs_indication->report_tlv; + report_tlv->tag = 0; + report_tlv->length = 0; + + start_meas(&gNB->srs_report_tlv_stats); + switch (srs_indication->srs_usage) { + case NFAPI_NR_SRS_BEAMMANAGEMENT: { + start_meas(&gNB->srs_beam_report_stats); + nfapi_nr_srs_beamforming_report_t nr_srs_bf_report; + nr_srs_bf_report.prg_size = srs_pdu->beamforming.prg_size; + nr_srs_bf_report.num_symbols = 1 << srs_pdu->num_symbols; + nr_srs_bf_report.wide_band_snr = + srs_est >= 0 ? (gNB->srs->snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid + nr_srs_bf_report.num_reported_symbols = 1 << srs_pdu->num_symbols; + AssertFatal(nr_srs_bf_report.num_reported_symbols == 1, + "nr_srs_bf_report.num_reported_symbols %i not handled yet!\n", + nr_srs_bf_report.num_reported_symbols); + fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, frame_parms->N_RB_UL, snr_per_rb, srs_est); + +#ifdef SRS_IND_DEBUG + LOG_I(NR_PHY, "nr_srs_bf_report.prg_size = %i\n", nr_srs_bf_report.prg_size); + LOG_I(NR_PHY, "nr_srs_bf_report.num_symbols = %i\n", nr_srs_bf_report.num_symbols); + LOG_I(NR_PHY, + "nr_srs_bf_report.wide_band_snr = %i (%i dB)\n", + nr_srs_bf_report.wide_band_snr, + (nr_srs_bf_report.wide_band_snr >> 1) - 64); + LOG_I(NR_PHY, "nr_srs_bf_report.num_reported_symbols = %i\n", nr_srs_bf_report.num_reported_symbols); + LOG_I(NR_PHY, + "nr_srs_bf_report.reported_symbol_list[0].num_prgs = %i\n", + nr_srs_bf_report.reported_symbol_list[0].num_prgs); + for (int prg_idx = 0; prg_idx < nr_srs_bf_report.reported_symbol_list[0].num_prgs; prg_idx++) { + LOG_I(NR_PHY, + "nr_srs_beamforming_report.reported_symbol_list[0].prg_list[%3i].rb_snr = %i (%i dB)\n", + prg_idx, + nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr, + (nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr >> 1) - 64); + } +#endif + + report_tlv->length = pack_nr_srs_beamforming_report(&nr_srs_bf_report, report_tlv->value, sizeof(report_tlv->value)); + stop_meas(&gNB->srs_beam_report_stats); + break; + } + + case NFAPI_NR_SRS_CODEBOOK: { + start_meas(&gNB->srs_iq_matrix_stats); + nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_channel_iq_matrix; + fill_srs_channel_matrix(&nr_srs_channel_iq_matrix, + srs_pdu, + gNB->nr_srs_info[i], + srs_pdu->srs_parameters_v4.iq_representation, + ant, + srs_pdu->srs_parameters_v4.num_total_ue_antennas, + srs_pdu->srs_parameters_v4.prg_size, + srs_pdu->srs_parameters_v4.srs_bandwidth_size / srs_pdu->srs_parameters_v4.prg_size, + frame_parms, + srs_estimated_channel_freq); + +#ifdef SRS_IND_DEBUG + LOG_I(NR_PHY, + "nr_srs_channel_iq_matrix.normalized_iq_representation = %i\n", + nr_srs_channel_iq_matrix.normalized_iq_representation); + LOG_I(NR_PHY, + "nr_srs_channel_iq_matrix.num_gnb_antenna_elements = %i\n", + nr_srs_channel_iq_matrix.num_gnb_antenna_elements); + LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_ue_srs_ports = %i\n", nr_srs_channel_iq_matrix.num_ue_srs_ports); + LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.prg_size = %i\n", nr_srs_channel_iq_matrix.prg_size); + LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_prgs = %i\n", nr_srs_channel_iq_matrix.num_prgs); + c16_t *channel_matrix16 = (c16_t *)nr_srs_channel_iq_matrix.channel_matrix; + c8_t *channel_matrix8 = (c8_t *)nr_srs_channel_iq_matrix.channel_matrix; + for (int uI = 0; uI < nr_srs_channel_iq_matrix.num_ue_srs_ports; uI++) { + for (int gI = 0; gI < nr_srs_channel_iq_matrix.num_gnb_antenna_elements; gI++) { + for (int pI = 0; pI < nr_srs_channel_iq_matrix.num_prgs; pI++) { + uint16_t index = uI * nr_srs_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_channel_iq_matrix.num_prgs + + gI * nr_srs_channel_iq_matrix.num_prgs + pI; + LOG_I( + NR_PHY, + "(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n", + uI, + gI, + pI, + nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].r : channel_matrix16[index].r, + nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].i + : channel_matrix16[index].i); + } + } + } +#endif + + report_tlv->length = + pack_nr_srs_normalized_channel_iq_matrix(&nr_srs_channel_iq_matrix, report_tlv->value, sizeof(report_tlv->value)); + stop_meas(&gNB->srs_iq_matrix_stats); + break; + } + + case NFAPI_NR_SRS_NONCODEBOOK: + case NFAPI_NR_SRS_ANTENNASWITCH: + LOG_W(NR_PHY, "PHY procedures for this SRS usage are not implemented yet!\n"); + break; + + default: + AssertFatal(1 == 0, "Invalid SRS usage\n"); + } + stop_meas(&gNB->srs_report_tlv_stats); + +#ifdef SRS_IND_DEBUG + LOG_I(NR_PHY, "report_tlv->tag = %i\n", report_tlv->tag); + LOG_I(NR_PHY, "report_tlv->length = %i\n", report_tlv->length); + char *value = (char *)report_tlv->value; + for (int b = 0; b < report_tlv->length; b++) { + LOG_I(NR_PHY, "value[%i] = 0x%02x\n", b, value[b] & 0xFF); + } +#endif + srs->active = false; + stop_meas(&gNB->rx_srs_stats); } stop_meas(&gNB->phy_proc_rx); if (pucch_decode_done || pusch_decode_done) { - T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4)); + T(T_GNB_PHY_PUCCH_PUSCH_IQ, + T_INT(frame_rx), + T_INT(slot_rx), + T_BUFFER(&gNB->common_vars.rxdataF[0][0][0], nb_symb * symb_sz * 4)); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); return pusch_DTX; } + +void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req) +{ + DevAssert(gNB != NULL); + DevAssert(UL_tti_req != NULL); + + int frame = UL_tti_req->SFN; + int slot = UL_tti_req->Slot; + + for (int i = 0; i < UL_tti_req->n_pdus; i++) { + int type = UL_tti_req->pdus_list[i].pdu_type; + LOG_D(NR_PHY, + "frame %d, slot %d got %s for %d.%d\n", + frame, + slot, + txt_nfapi_nr_ul_config_pdu_type[type], + UL_tti_req->SFN, + UL_tti_req->Slot); + switch (type) { + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + nr_fill_ulsch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + nr_fill_pucch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { + nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; + prach_item_t *prach = nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); + if (!prach) + LOG_W(NR_PHY_RACH, "Error in scheduling rach\n"); + } break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu); + break; + } + } +} diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index 40c32c2199..da71809589 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -33,10 +33,17 @@ #include "phy_frame_config_nr.h" void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME_PARMS *fp); -void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, int frame_tx, int slot_tx, int do_meas); +void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, + const nfapi_nr_dl_tti_request_t *DL_req, + const nfapi_nr_tx_data_request_t *TX_req, + const nfapi_nr_ul_dci_request_t *UL_dci_req, + int frame, + int slot, + int do_meas); +void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req); int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO); void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind); -void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_dl_tti_ssb_pdu ssb_pdu); +void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu); void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa); void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx); @@ -49,7 +56,7 @@ void nr_phy_free_RU(RU_t *ru); void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot); int beam_index_allocation(bool das, int fapi_beam_index, - nfapi_nr_analog_beamforming_ve_t *analog_bf, + const nfapi_nr_analog_beamforming_ve_t *analog_bf, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index c7f0deb118..3ba5226542 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -92,7 +92,8 @@ */ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp); -int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data); +int pbch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data); +void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data); void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data); @@ -137,13 +138,22 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, void *typeSpecific, uint8_t *b); -int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue, +void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, - int32_t pdcch_est_size, - c16_t pdcch_dl_ch_estimates[][pdcch_est_size], + int symbol, nr_phy_data_t *phy_data, - int n_ss, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); + int llr_size_symbol, + int num_monitoring_occ, + int max_symb, + c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size], + c16_t pdcch_llr[phy_data->phy_pdcch_config.nb_search_space][num_monitoring_occ][max_symb * llr_size_symbol]); + +void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc, + int llr_size, + int max_monOcc, + PHY_VARS_NR_UE *ue, + nr_phy_data_t *phy_data, + c16_t llr[phy_data->phy_pdcch_config.nb_search_space][max_monOcc][llr_size]); void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index cbdd91c949..a3e86ce433 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -230,6 +230,88 @@ static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac, dl_config->number_pdus = 0; } +static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_ue_pusch_pdu_t *pusch_pdu) +{ + LOG_D(PHY, + "[UE %d] %d.%d ULSCH PDU pdu_bit_map %u " + "rnti %u " + "handle %u " + "bwp_size %u " + "bwp_start %u " + "subcarrier_spacing %u " + "cyclic_prefix %u " + "target_code_rate %u " + "qam_mod_order %u " + "mcs_index %u " + "mcs_table %u " + "transform_precoding %u " + "data_scrambling_id %u " + "nrOfLayers %u " + "Tpmi %u " + "ul_dmrs_symb_pos %u " + "dmrs_config_type %u " + "ul_dmrs_scrambling_id %u " + "scid %u " + "num_dmrs_cdm_grps_no_data %u " + "dmrs_ports %u " + "resource_alloc %u " + "rb_start %u " + "rb_size %u " + "vrb_to_prb_mapping %u " + "frequency_hopping %u " + "tx_direct_current_location %u " + "uplink_frequency_shift_7p5khz %u " + "start_symbol_index %u " + "nr_of_symbols %u " + "tbslbrm %u " + "ldpcBaseGraph %u " + "ulsch_indicator %u " + "pusch_data->rv_index %u " + "pusch_data->harq_process_id %u " + "pusch_data->new_data_indicator %u " + "pusch_data->num_cb %u\n", + instance, + frame, + slot, + pusch_pdu->pdu_bit_map, + pusch_pdu->rnti, + pusch_pdu->handle, + pusch_pdu->bwp_size, + pusch_pdu->bwp_start, + pusch_pdu->subcarrier_spacing, + pusch_pdu->cyclic_prefix, + pusch_pdu->target_code_rate, + pusch_pdu->qam_mod_order, + pusch_pdu->mcs_index, + pusch_pdu->mcs_table, + pusch_pdu->transform_precoding, + pusch_pdu->data_scrambling_id, + pusch_pdu->nrOfLayers, + pusch_pdu->Tpmi, + pusch_pdu->ul_dmrs_symb_pos, + pusch_pdu->dmrs_config_type, + pusch_pdu->ul_dmrs_scrambling_id, + pusch_pdu->scid, + pusch_pdu->num_dmrs_cdm_grps_no_data, + pusch_pdu->dmrs_ports, + pusch_pdu->resource_alloc, + pusch_pdu->rb_start, + pusch_pdu->rb_size, + pusch_pdu->vrb_to_prb_mapping, + pusch_pdu->frequency_hopping, + pusch_pdu->tx_direct_current_location, + pusch_pdu->uplink_frequency_shift_7p5khz, + pusch_pdu->start_symbol_index, + pusch_pdu->nr_of_symbols, + pusch_pdu->tbslbrm, + pusch_pdu->ldpcBaseGraph, + pusch_pdu->ulsch_indicator, + pusch_pdu->pusch_data.rv_index, + pusch_pdu->pusch_data.harq_process_id, + pusch_pdu->pusch_data.new_data_indicator, + pusch_pdu->pusch_data.num_cb); +} + static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_request_t *ul_config, nr_phy_data_tx_t *phy_data) { fapi_nr_ul_config_request_pdu_t *pdu = fapiLockIterator(ul_config, ul_config->frame, ul_config->slot); @@ -251,6 +333,7 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r pdu->pusch_config_pdu.num_dmrs_cdm_grps_no_data); memcpy(pusch_pdu, &pdu->pusch_config_pdu, sizeof(*pusch_pdu)); + dump_pusch_pdu(phy->Mod_id, ul_config->frame, ul_config->slot, pusch_pdu); if (pdu->pusch_config_pdu.tx_request_body.fapiTxPdu) { LOG_D(PHY, "%d.%d Copying %d bytes to harq_process_ul_ue->a (harq_pid %d)\n", diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index f22d13c5fc..43fef06ef7 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -278,8 +278,8 @@ static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs nr_srs_info->n_SRS_cs = srs_config_pdu->cyclic_shift; nr_srs_info->n_ID_SRS = srs_config_pdu->sequence_id; // It adjusts the SRS allocation to align with the common resource block grid in multiples of four - nr_srs_info->n_shift = srs_config_pdu->frequency_position; - nr_srs_info->n_RRC = srs_config_pdu->frequency_shift; + nr_srs_info->n_shift = srs_config_pdu->frequency_shift; + nr_srs_info->n_RRC = srs_config_pdu->frequency_position; nr_srs_info->groupOrSequenceHopping = srs_config_pdu->group_or_sequence_hopping; nr_srs_info->l_offset = srs_config_pdu->time_start_position; nr_srs_info->T_SRS = srs_config_pdu->t_srs; @@ -372,6 +372,9 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n AssertFatal(ue->CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN); +#if T_TRACER + T(T_UE_PHY_UL_TICK, T_INT(ue->Mod_id), T_INT(frame_tx % 1024), T_INT(slot_tx)); +#endif const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * ue->frame_parms.ofdm_symbol_size; c16_t txdataF_buf[ue->frame_parms.nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32))); @@ -440,7 +443,6 @@ static void nr_ue_measurement_procedures(uint16_t l, if(nr_slot_rx == 0) T(T_UE_PHY_MEAS, T_INT(gNB_id), - T_INT(ue->Mod_id), T_INT(proc->frame_rx % 1024), T_INT(nr_slot_rx), T_INT((int)(10 * log10(ue->measurements.rsrp[0]) - ue->rx_total_gain_dB)), @@ -448,7 +450,8 @@ static void nr_ue_measurement_procedures(uint16_t l, T_INT((int)(ue->measurements.rx_power_avg_dB[0] - ue->measurements.n0_power_avg_dB)), T_INT((int)ue->measurements.rx_power_avg_dB[0]), T_INT((int)ue->measurements.n0_power_avg_dB), - T_INT((int)ue->measurements.wideband_cqi_avg[0])); + T_INT((int)ue->measurements.wideband_cqi_avg[0]), + T_INT((int)ue->common_vars.freq_offset)); #endif } @@ -527,53 +530,6 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, return ret; } -int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - int32_t pdcch_est_size, - c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - nr_phy_data_t *phy_data, - int n_ss, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) -{ - int frame_rx = proc->frame_rx; - int nr_slot_rx = proc->nr_slot_rx; - NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; - - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[n_ss]; - - start_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); - - /// PDCCH/DCI e-sequence (input to rate matching). - int32_t pdcch_e_rx_size = NR_MAX_PDCCH_SIZE; - c16_t pdcch_e_rx[pdcch_e_rx_size]; - - nr_rx_pdcch(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, pdcch_e_rx, rel15, rxdataF); - - fapi_nr_dci_indication_t dci_ind; - nr_dci_decoding_procedure(ue, proc, pdcch_e_rx, &dci_ind, rel15); - - for (int i = 0; i < dci_ind.number_of_dcis; i++) { - LOG_D(PHY, - "[UE %d] AbsSubFrame %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n", - ue->Mod_id, - frame_rx % 1024, - nr_slot_rx, - i + 1, - dci_ind.number_of_dcis, - dci_ind.dci_list[i].rnti, - dci_ind.dci_list[i].dci_format); - } - - nr_downlink_indication_t dl_indication; - // fill dl_indication message - nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data); - // send to mac - ue->if_inst->dl_indication(&dl_indication); - stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT); - return (dci_ind.number_of_dcis); -} - static freq_alloc_bitmap_t set_start_end_from_bitmap(int size, int alloc_size, const uint8_t bitmap[alloc_size]) { freq_alloc_bitmap_t alloc = { @@ -1027,18 +983,87 @@ static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index) return ue->frame_parms.ssb_index == index; } -int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) +static int get_pdcch_max_rbs(NR_UE_PDCCH_CONFIG *phy_pdcch_config) +{ + int nb_rb = 0; + int rb_offset = 0; + for (int i = 0; i < phy_pdcch_config->nb_search_space; i++) { + int tmp = 0; + get_coreset_rballoc(phy_pdcch_config->pdcch_config[i].coreset.frequency_domain_resource, &tmp, &rb_offset); + if (tmp > nb_rb) + nb_rb = tmp; + } + return nb_rb; +} + +static int get_max_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config) +{ + int max_pdcch_symb = 0; + for (int i = 0; i < phy_pdcch_config->nb_search_space; i++) + if (phy_pdcch_config->pdcch_config[i].coreset.duration > max_pdcch_symb) + max_pdcch_symb = phy_pdcch_config->pdcch_config[i].coreset.duration; + + return max_pdcch_symb; +} + +void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) +{ + NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; + if (phy_pdcch_config->nb_search_space == 0) + return; + + TracyCZone(ctx, true); + /* process PDCCH */ + LOG_D(PHY, " ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", proc->frame_rx % 1024, proc->nr_slot_rx); + start_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); + int num_monitoring_occ = get_max_pdcch_monOcc(phy_pdcch_config); + int max_nb_symb_pdcch = get_max_pdcch_symb(phy_pdcch_config); + int llr_size_symbol = get_pdcch_max_rbs(phy_pdcch_config) * 9; + c16_t pdcch_llr[phy_pdcch_config->nb_search_space][num_monitoring_occ][max_nb_symb_pdcch * llr_size_symbol]; + + int start_symb_pdcch, last_symb_pdcch; + set_first_last_pdcch_symb(phy_pdcch_config, &start_symb_pdcch, &last_symb_pdcch); + + /* Temporarily loop over symbols in the slot, perform OFDM demod and process PDCCH. + When symbol based proc design is fully merged, this function will be called to process only one symbol + and OFDM demod will be removed from here. */ + const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP; + __attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; + + for (int symbol = start_symb_pdcch; symbol <= last_symb_pdcch; symbol++) { + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; + nr_slot_fep(ue, fp, proc->nr_slot_rx, symbol, rxdataF, link_type_dl, 0, ue->common_vars.rxdata); + __attribute__((aligned(32))) c16_t rxdataF_symb[fp->nb_antennas_rx][((fp->ofdm_symbol_size + 7) / 8) * 8]; + + for (int ant = 0; ant < fp->nb_antennas_rx; ant++) + memcpy(rxdataF_symb[ant], &rxdataF[ant][symbol * fp->ofdm_symbol_size], sizeof(c16_t) * fp->ofdm_symbol_size); + + nr_pdcch_generate_llr(ue, proc, symbol, phy_data, llr_size_symbol, num_monitoring_occ, max_nb_symb_pdcch, rxdataF_symb, pdcch_llr); + if (symbol == last_symb_pdcch) { + nr_pdcch_dci_indication(proc, llr_size_symbol * max_nb_symb_pdcch, num_monitoring_occ, ue, phy_data, pdcch_llr); + UEscopeCopy(ue, pdcchLlr, pdcch_llr, sizeof(c16_t), 1, sizeof(pdcch_llr) / sizeof(c16_t), 0); + } + } + stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); + TracyCZoneEnd(ctx); + if (ue->phy_sim_rxdataF) + memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * max_nb_symb_pdcch * ue->frame_parms.ofdm_symbol_size); +} + +int pbch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) { TracyCZone(ctx, true); int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; int gNB_id = proc->gNB_id; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; int sampleShift = INT_MAX; nr_ue_dlsch_init(phy_data->dlsch, NR_MAX_NB_LAYERS>4 ? 2:1, ue->max_ldpc_iterations); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); +#if T_TRACER + T(T_UE_PHY_DL_TICK, T_INT(ue->Mod_id), T_INT(frame_rx % 1024), T_INT(nr_slot_rx)); +#endif LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d ****** \n", frame_rx%1024, nr_slot_rx); @@ -1163,43 +1188,7 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ } // for i } // for rsc_id } // for gNB_id - - LOG_D(PHY," ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_IN); - - uint8_t nb_symb_pdcch = phy_pdcch_config->nb_search_space > 0 ? phy_pdcch_config->pdcch_config[0].coreset.duration : 0; - int first_symb_pdcch = phy_pdcch_config->nb_search_space > 0 ? phy_pdcch_config->pdcch_config[0].coreset.StartSymbolIndex : 0; - int last_symb_pdcch = first_symb_pdcch + nb_symb_pdcch; - for (int l = first_symb_pdcch; l < last_symb_pdcch; l++) { - nr_slot_fep(ue, fp, proc->nr_slot_rx, l, rxdataF, link_type_dl, 0, ue->common_vars.rxdata); - } - - // Hold the channel estimates in frequency domain. - int32_t pdcch_est_size = ((((fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH))+15)/16)*16); - __attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[4 * fp->nb_antennas_rx][pdcch_est_size]; - - uint8_t dci_cnt = 0; - for(int n_ss = 0; n_ssnb_search_space; n_ss++) { - for (int l = first_symb_pdcch; l < last_symb_pdcch; l++) { - // note: this only works if RBs for PDCCH are contigous! - nr_pdcch_channel_estimation(ue, - proc, - l, - &phy_pdcch_config->pdcch_config[n_ss].coreset, - fp->first_carrier_offset, - phy_pdcch_config->pdcch_config[n_ss].BWPStart, - pdcch_est_size, - pdcch_dl_ch_estimates, - rxdataF); - } - dci_cnt = dci_cnt + nr_ue_pdcch_procedures(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF); - } - LOG_D(PHY, "[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt); - phy_pdcch_config->nb_search_space = 0; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT); TracyCZoneEnd(ctx); - if (ue->phy_sim_rxdataF) - memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * nb_symb_pdcch * ue->frame_parms.ofdm_symbol_size); return sampleShift; } diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index c475bfc039..ea4a068b6e 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -439,10 +439,7 @@ int main(int argc, char **argv) nr_init_dl_harq_processes(UE->dl_harq_processes, 8, nb_rb); unsigned char harq_pid = 0; //dlsch->harq_ids[subframe]; - processingData_L1tx_t msgDataTx; - init_DLSCH_struct(gNB, &msgDataTx); - NR_gNB_DLSCH_t *dlsch = &msgDataTx.dlsch[0][0]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; + NR_gNB_DLSCH_t *dlsch = &gNB->dlsch[0]; //time_stats_t *rm_stats, *te_stats, *i_stats; unsigned int TBS = 8424; uint8_t nb_re_dmrs = 6; // No data in dmrs symbol @@ -459,19 +456,24 @@ int main(int argc, char **argv) TBS = nr_compute_tbs(mod_order,rate, nb_rb, nb_symb_sch, nb_re_dmrs*length_dmrs, 0, 0, Nl); printf("available bits %u TBS %u mod_order %d\n", available_bits, TBS, mod_order); //dlsch->harq_ids[subframe]= 0; - rel15->rbSize = nb_rb; - rel15->NrOfSymbols = nb_symb_sch; - rel15->qamModOrder[0] = mod_order; - rel15->nrOfLayers = Nl; - rel15->TBSize[0] = TBS>>3; - rel15->targetCodeRate[0] = rate; - rel15->NrOfCodewords = 1; - rel15->dmrsConfigType = NFAPI_NR_DMRS_TYPE1; - rel15->dlDmrsSymbPos = 4; - rel15->mcsIndex[0] = Imcs; - rel15->numDmrsCdmGrpsNoData = 1; - rel15->maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm; - rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, rate); + nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu = { + .pdsch_pdu_rel15 = { + .rbSize = nb_rb, + .NrOfSymbols = nb_symb_sch, + .qamModOrder[0] = mod_order, + .nrOfLayers = Nl, + .TBSize[0] = TBS >> 3, + .targetCodeRate[0] = rate, + .NrOfCodewords = 1, + .dmrsConfigType = NFAPI_NR_DMRS_TYPE1, + .dlDmrsSymbPos = 4, + .mcsIndex[0] = Imcs, + .numDmrsCdmGrpsNoData = 1, + .maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm, + .maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, rate), + }, + }; + dlsch->pdsch_pdu = &pdsch_pdu; double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc short channel_output_fixed[16 * 68 * 384]; //unsigned char *estimated_output; @@ -498,7 +500,7 @@ int main(int argc, char **argv) printf("harq process ue mcs = %d Qm = %d, symb %d\n", dlsch0_ue->dlsch_config.mcs, dlsch0_ue->dlsch_config.qamModOrder, nb_symb_sch); uint8_t test_input[TBS / 8 + 4]; // + 3 for CRC + 1 additional byte, see nr_dlsch_encoding() - dlsch->harq_process.pdu = test_input; + dlsch->pdu = test_input; //unsigned char test_input[TBS / 8] __attribute__ ((aligned(16))); for (i = 0; i < TBS / 8; i++) test_input[i] = (unsigned char) rand(); @@ -512,11 +514,10 @@ int main(int argc, char **argv) //printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32)); // generate signal - unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * NR_MAX_NB_LAYERS] __attribute__((aligned(64))); + unsigned char output[nb_rb * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * NR_MAX_NB_LAYERS] __attribute__((aligned(64))); bzero(output, sizeof(output)); if (input_fd == NULL) { - msgDataTx.num_pdsch_slot = 1; - nr_dlsch_encoding(gNB, &msgDataTx, frame, slot, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + nr_dlsch_encoding(gNB, 1, dlsch, frame, slot, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } for (SNR = snr0; SNR < snr1 && !stop; SNR += snr_step) { @@ -622,8 +623,6 @@ int main(int argc, char **argv) free_channel_desc_scm(gNB2UE); - reset_DLSCH_struct(gNB, &msgDataTx); - int nb_slots_to_set = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; for (int i = 0; i < nb_slots_to_set; ++i) free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 6329d5849f..82984657d3 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -62,7 +62,6 @@ #include "PHY/defs_nr_common.h" #include "PHY/impl_defs_nr.h" #include "PHY/phy_vars_nr_ue.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "SCHED_NR/sched_nr.h" #include "SCHED_NR_UE/defs.h" #include "SCHED_NR_UE/fapi_nr_ue_l1.h" @@ -182,13 +181,13 @@ extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration /* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs/nrOfLayers from command line of dlsim */ int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLayers = 1, g_pmi = 0; -void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) +void nr_dlsim_preprocessor(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pp_pdsch) { - NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.connected_ue_list[0]; - AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "Only single UE allowed in dlsim\n"); + NR_UE_info_t *UE_info = nr_mac->UE_info.connected_ue_list[0]; + AssertFatal(nr_mac->UE_info.connected_ue_list[1] == NULL, "Only single UE allowed in dlsim\n"); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP; - NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; + NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; uint8_t nr_of_candidates = 0; if (g_mcsIndex < 4) { @@ -201,8 +200,8 @@ void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) &nr_of_candidates, sched_ctrl->search_space,4); } - uint32_t Y = get_Y(sched_ctrl->search_space, slot, UE_info->rnti); - int CCEIndex = find_pdcch_candidate(RC.nrmac[module_id], + uint32_t Y = get_Y(sched_ctrl->search_space, pp_pdsch->slot, UE_info->rnti); + int CCEIndex = find_pdcch_candidate(nr_mac, /* CC_id = */ 0, sched_ctrl->aggregation_level, nr_of_candidates, @@ -210,49 +209,55 @@ void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) &sched_ctrl->sched_pdcch, sched_ctrl->coreset, Y); - AssertFatal(CCEIndex>=0, "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", frame, slot, 0, UE_info->rnti); + AssertFatal(CCEIndex >= 0, + "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", + pp_pdsch->frame, + pp_pdsch->slot, + 0, + UE_info->rnti); sched_ctrl->cce_index = CCEIndex; - NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; - sched_pdsch->rbStart = g_rbStart; - sched_pdsch->rbSize = g_rbSize; - sched_pdsch->bwp_info = get_pdsch_bwp_start_size(RC.nrmac[module_id], UE_info); - sched_pdsch->mcs = g_mcsIndex; - sched_pdsch->nrOfLayers = g_nrOfLayers; - sched_pdsch->pm_index = g_pmi; + NR_sched_pdsch_t sched_pdsch = { + .rbStart = g_rbStart, + .rbSize = g_rbSize, + .bwp_info = get_pdsch_bwp_start_size(nr_mac, UE_info), + .mcs = g_mcsIndex, + .nrOfLayers = g_nrOfLayers, + .pm_index = g_pmi, + }; /* the following might override the table that is mandated by RRC * configuration */ current_BWP->mcsTableIdx = g_mcsTableIdx; - sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], slot); - AssertFatal(sched_pdsch->time_domain_allocation >= 0,"Unable to find PDSCH time domain allocation in list\n"); + sched_pdsch.time_domain_allocation = get_dl_tda(nr_mac, pp_pdsch->slot); + AssertFatal(sched_pdsch.time_domain_allocation >= 0,"Unable to find PDSCH time domain allocation in list\n"); - sched_pdsch->tda_info = get_dl_tda_info(current_BWP, + sched_pdsch.tda_info = get_dl_tda_info(current_BWP, sched_ctrl->search_space->searchSpaceType->present, - sched_pdsch->time_domain_allocation, + sched_pdsch.time_domain_allocation, NR_MIB__dmrs_TypeA_Position_pos2, 1, TYPE_C_RNTI_, sched_ctrl->coreset->controlResourceSetId, false); - sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, + sched_pdsch.dmrs_parms = get_dl_dmrs_params(scc, current_BWP, - &sched_pdsch->tda_info, - sched_pdsch->nrOfLayers); + &sched_pdsch.tda_info, + sched_pdsch.nrOfLayers); - sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, current_BWP->mcsTableIdx); - sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, current_BWP->mcsTableIdx); - sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm, - sched_pdsch->R, - sched_pdsch->rbSize, - sched_pdsch->tda_info.nrOfSymbols, - sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT, + sched_pdsch.Qm = nr_get_Qm_dl(sched_pdsch.mcs, current_BWP->mcsTableIdx); + sched_pdsch.R = nr_get_code_rate_dl(sched_pdsch.mcs, current_BWP->mcsTableIdx); + sched_pdsch.tb_size = nr_compute_tbs(sched_pdsch.Qm, + sched_pdsch.R, + sched_pdsch.rbSize, + sched_pdsch.tda_info.nrOfSymbols, + sched_pdsch.dmrs_parms.N_PRB_DMRS * sched_pdsch.dmrs_parms.N_DMRS_SLOT, 0 /* N_PRB_oh, 0 for initialBWP */, 0 /* tb_scaling */, - sched_pdsch->nrOfLayers) >> 3; + sched_pdsch.nrOfLayers) >> 3; /* the simulator assumes the HARQ PID is equal to the slot number */ - sched_pdsch->dl_harq_pid = slot; + sched_pdsch.dl_harq_pid = pp_pdsch->slot; /* The scheduler uses lists to track whether a HARQ process is * free/busy/awaiting retransmission, and updates the HARQ process states. @@ -261,15 +266,17 @@ void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) * Therefore, below lines just "repair" everything so that the scheduler * won't remark that there is no HARQ feedback */ sched_ctrl->feedback_dl_harq.head = -1; // always overwrite feedback HARQ process - if (sched_ctrl->harq_processes[slot].round == 0) // depending on round set in simulation ... - add_front_nr_list(&sched_ctrl->available_dl_harq, slot); // ... make PID available + if (sched_ctrl->harq_processes[pp_pdsch->slot].round == 0) // depending on round set in simulation ... + add_front_nr_list(&sched_ctrl->available_dl_harq, pp_pdsch->slot); // ... make PID available else - add_front_nr_list(&sched_ctrl->retrans_dl_harq, slot); // ... make PID retransmission - sched_ctrl->harq_processes[slot].is_waiting = false; - AssertFatal(sched_pdsch->rbStart >= 0, "invalid rbStart %d\n", sched_pdsch->rbStart); - AssertFatal(sched_pdsch->rbSize > 0, "invalid rbSize %d\n", sched_pdsch->rbSize); - AssertFatal(sched_pdsch->mcs >= 0, "invalid mcs %d\n", sched_pdsch->mcs); + add_front_nr_list(&sched_ctrl->retrans_dl_harq, pp_pdsch->slot); // ... make PID retransmission + sched_ctrl->harq_processes[pp_pdsch->slot].is_waiting = false; + AssertFatal(sched_pdsch.rbStart >= 0, "invalid rbStart %d\n", sched_pdsch.rbStart); + AssertFatal(sched_pdsch.rbSize > 0, "invalid rbSize %d\n", sched_pdsch.rbSize); + AssertFatal(sched_pdsch.mcs >= 0, "invalid mcs %d\n", sched_pdsch.mcs); AssertFatal(current_BWP->mcsTableIdx >= 0 && current_BWP->mcsTableIdx <= 2, "invalid mcsTableIdx %d\n", current_BWP->mcsTableIdx); + + post_process_dlsch(nr_mac, pp_pdsch, UE_info, &sched_pdsch); } nrUE_params_t nrUE_params; @@ -278,7 +285,6 @@ nrUE_params_t *get_nrUE_params(void) { return &nrUE_params; } - void validate_input_pmi(nfapi_nr_config_request_scf_t *gNB_config, nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int nrOfLayers, @@ -966,13 +972,6 @@ int main(int argc, char **argv) int ret = 1; initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool"); initNotifiedFIFO(&gNB->L1_tx_out); - // we create 2 threads for L1 tx processing - processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t)); - init_DLSCH_struct(gNB, msgDataTx); - msgDataTx->slot = slot; - msgDataTx->frame = frame; - memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t)); - gNB->msgDataTx = msgDataTx; // Buffers to store internal memory of slot process int rx_size = (((14 * UE->frame_parms.N_RB_DL * 12 * sizeof(int32_t)) + 15) >> 4) << 4; @@ -1051,8 +1050,13 @@ int main(int argc, char **argv) n_false_positive = 0; if (n_trials== 1) num_rounds = 1; - NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; + NR_gNB_DLSCH_t *gNB_dlsch = &gNB->dlsch[0]; + memset(Sched_INFO, 0, sizeof(*Sched_INFO)); + Sched_INFO->sched_response_id = -1; + nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body; + // scheduler will place PDSCH second (after PDCCH), verification below + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1]; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; for (trial = 0; trial < n_trials && !stop; trial++) { @@ -1074,11 +1078,9 @@ int main(int argc, char **argv) UE_harq_process->DLround = round; UE_harq_process->first_rx = 1; - memset(Sched_INFO, 0, sizeof(*Sched_INFO)); - Sched_INFO->sched_response_id = -1; - while (round < num_rounds && !UE_harq_process->decodeResult && !stop) { - clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req); + reset_sched_response(Sched_INFO, frame, slot, 0, 0); + clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1); UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round; @@ -1086,18 +1088,13 @@ int main(int argc, char **argv) NR_SCHED_LOCK(&gNB_mac->sched_lock); nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req); NR_SCHED_UNLOCK(&gNB_mac->sched_lock); - Sched_INFO->module_id = 0; - Sched_INFO->CC_id = 0; - Sched_INFO->frame = frame; - Sched_INFO->slot = slot; - Sched_INFO->UL_dci_req.numPdus = 0; - nr_schedule_response(Sched_INFO); + + /* check that second message is indeed PDSCH */ + DevAssert(dl_tti_pdsch_pdu->PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE); /* PTRS values for DLSIM calculations */ - nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body; - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; pdu_bit_map = pdsch_pdu_rel15->pduBitmap; + // This is already in DL procedures?? if(pdu_bit_map & 0x1) { set_ptrs_symb_idx(&dlPtrsSymPos, pdsch_pdu_rel15->NrOfSymbols, @@ -1105,16 +1102,12 @@ int main(int argc, char **argv) 1<PTRSTimeDensity, pdsch_pdu_rel15->dlDmrsSymbPos); ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, pdsch_pdu_rel15->StartSymbolIndex, pdsch_pdu_rel15->NrOfSymbols); - ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity); + ptrsRePerSymb = ((pdsch_pdu_rel15->rbSize + pdsch_pdu_rel15->PTRSFreqDensity - 1) / pdsch_pdu_rel15->PTRSFreqDensity); LOG_D(PHY,"[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot, ptrsRePerSymb, ptrsSymbPerSlot * ptrsRePerSymb); } - msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234; - msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0; - msgDataTx->gNB = gNB; - start_meas(&gNB->phy_proc_tx); - phy_procedures_gNB_TX(msgDataTx,frame,slot,1); + phy_procedures_gNB_TX(gNB, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req, frame, slot, 1); stop_meas(&gNB->phy_proc_tx); int txdataF_offset = slot * frame_parms->samples_per_slot_wCP; @@ -1189,9 +1182,9 @@ int main(int argc, char **argv) double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); //Compute AWGN variance - sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR; + sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*pdsch_pdu_rel15->rbSize))) - SNR; sigma2 = pow(10, sigma2_dB/10); - if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize)); + if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*pdsch_pdu_rel15->rbSize)); for (aa = 0; aa < n_rx; aa++) { bzero(r_re[aa], slot_length * sizeof(double)); @@ -1216,9 +1209,8 @@ int main(int argc, char **argv) ue_dci_configuration(UE_mac, &dl_config, frame, slot); nr_ue_scheduled_response(&scheduled_response); - pbch_pdcch_processing(UE, - &UE_proc, - &phy_data); + pbch_processing(UE, &UE_proc, &phy_data); + pdcch_processing(UE, &UE_proc, &phy_data); pdsch_processing(UE, &UE_proc, &phy_data); @@ -1234,22 +1226,22 @@ int main(int argc, char **argv) int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr; - TBS = dlsch0->dlsch_config.TBS;//rel15->TBSize[0]; + TBS = dlsch0->dlsch_config.TBS; uint16_t length_dmrs = get_num_dmrs(dlsch0->dlsch_config.dlDmrsSymbPos); uint16_t nb_rb = dlsch0->dlsch_config.number_rbs; uint8_t nb_re_dmrs = dlsch0->dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups; uint8_t mod_order = dlsch0->dlsch_config.qamModOrder; uint8_t nb_symb_sch = dlsch0->dlsch_config.number_symbols; uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb; - available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, rel15->nrOfLayers); + available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, pdsch_pdu_rel15->nrOfLayers); if (pdu_bit_map & 0x1) { if (trial == 0 && round == 0) { - printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * rel15->nrOfLayers * mod_order)); + printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * pdsch_pdu_rel15->nrOfLayers * mod_order)); } } for (i = 0; i < available_bits; i++) { - const uint8_t current_bit = (gNB_dlsch->harq_process.f[i / 8] & (1 << (i & 7))) >> (i & 7); + const uint8_t current_bit = (gNB_dlsch->f[i / 8] & (1 << (i & 7))) >> (i & 7); if (((current_bit == 0) && (UE_llr[i] <= 0)) || ((current_bit == 1) && (UE_llr[i] >= 0))) { if (errors_scrambling[round] == 0) { LOG_D(PHY,"First bit in error in unscrambling = %d\n",i); @@ -1263,13 +1255,13 @@ int main(int argc, char **argv) } // round if (test_input_bit == NULL) { - test_input_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]); - estimated_output_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]); + test_input_bit = (unsigned char *)malloc16(8 * pdsch_pdu_rel15->TBSize[0]); + estimated_output_bit = (unsigned char *)malloc16(8 * pdsch_pdu_rel15->TBSize[0]); } for (i = 0; i < TBS; i++) { estimated_output_bit[i] = (UE->phy_sim_dlsch_b[i/8] & (1 << (i & 7))) >> (i & 7); - test_input_bit[i] = (gNB_dlsch->harq_process.b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments + test_input_bit[i] = (gNB_dlsch->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estimated_output_bit[i] != test_input_bit[i]) { if(errors_bit == 0) @@ -1313,7 +1305,7 @@ int main(int argc, char **argv) printf("), Channel BER (%e", berStats[0]); for (int r = 1; r < num_rounds; r++) printf(",%e", berStats[r]); - printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]); + printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / (8 * pdsch_pdu_rel15->TBSize[0]) * 100, 8 * pdsch_pdu_rel15->TBSize[0]); printf("*****************************************\n"); printf("\n"); // writing to csv file @@ -1321,7 +1313,7 @@ int main(int argc, char **argv) fprintf(csv_file,"%f,%d/%d,",SNR,n_false_positive,n_trials); for (int r = 0; r < num_rounds; r++) fprintf(csv_file,"%d/%d,%u/%u,%f,%e,",n_errors[r], round_trials[r], errors_scrambling[r], available_bits * round_trials[r],blerStats[r],berStats[r]); - fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]); + fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / (8 * pdsch_pdu_rel15->TBSize[0]) * 100, 8 * pdsch_pdu_rel15->TBSize[0]); } if (print_perf==1) { printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, C %d, block %d)\n", @@ -1329,7 +1321,7 @@ int main(int argc, char **argv) g_rbSize, g_mcsIndex, UE->dl_harq_processes[0][slot].C, - 8 * rel15->TBSize[0]); + 8 * pdsch_pdu_rel15->TBSize[0]); printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx"); printStatIndent2(&gNB->dci_generation_stats, "DCI encoding time"); printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time"); @@ -1371,8 +1363,8 @@ int main(int argc, char **argv) const uint32_t numReSym = (g_rbSize * 12 + 15) & (~15); for (int l = 0; l < g_nrOfLayers; l++) { for (int r = 0; r < n_rx; r++) { - const int s = rel15->StartSymbolIndex; - const int n = rel15->NrOfSymbols; + const int s = pdsch_pdu_rel15->StartSymbolIndex; + const int n = pdsch_pdu_rel15->NrOfSymbols; for (int i = s; i < s + n; i++) { const uint32_t dmrsBitMap = phy_data.dlsch[0].dlsch_config.dlDmrsSymbPos; const uint32_t dmrsCfg = phy_data.dlsch[0].dlsch_config.dmrsConfigType; @@ -1408,7 +1400,7 @@ int main(int argc, char **argv) break; } - if (effRate >= (eff_tp_check * 8 * rel15->TBSize[0])) { + if (effRate >= (eff_tp_check * 8 * pdsch_pdu_rel15->TBSize[0])) { printf("PDSCH test OK\n"); ret = 0; break; diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h index 74fbf1051b..a84e57aa7f 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h @@ -79,6 +79,16 @@ int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) return (0); } +void stop_nr_nfapi_vnf() +{ + abort(); +} + +void stop_nr_nfapi_pnf() +{ + abort(); +} + void fill_scc_sim(NR_ServingCellConfigCommon_t *scc, uint64_t *ssb_bitmap, int N_RB_DL, int N_RB_UL, int mu_dl, int mu_ul); void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap); void prepare_scc(NR_ServingCellConfigCommon_t *scc); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 6279663e74..c86744afaa 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -110,17 +110,6 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, { } -int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - int32_t pdcch_est_size, - c16_t pdcch_dl_ch_estimates[][pdcch_est_size], - nr_phy_data_t *phy_data, - int n_ss, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) -{ - return 0; -} - configmodule_interface_t *uniqCfg = NULL; int main(int argc, char **argv) { @@ -530,10 +519,10 @@ int main(int argc, char **argv) exit(-1); } - processingData_L1tx_t msgDataTx; // generate signal const uint32_t rxdataF_sz = UE->frame_parms.samples_per_slot_wCP; __attribute__ ((aligned(32))) c16_t rxdataF[UE->frame_parms.nb_antennas_rx][rxdataF_sz]; + nfapi_nr_dl_tti_ssb_pdu ssb_pdu[64] = {0}; if (input_fd==NULL) { for (i=0; iLmax; i++) { @@ -541,10 +530,10 @@ int main(int argc, char **argv) const int sc_offset = frame_parms->freq_range == FR1 ? ssb_subcarrier_offset<freq_range == FR1 ? gNB->gNB_config.ssb_table.ssb_offset_point_a.value<gNB_config.ssb_table.ssb_offset_point_a.value << (mu - 2); - msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33; - msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i; - msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset; - msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = prb_offset; + ssb_pdu[i].ssb_pdu_rel15.bchPayload = 0x55dd33; + ssb_pdu[i].ssb_pdu_rel15.SsbBlockIndex = i; + ssb_pdu[i].ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset; + ssb_pdu[i].ssb_pdu_rel15.ssbOffsetPointA = prb_offset; start_symbol = nr_get_ssb_start_symbol(frame_parms,i); int slot = start_symbol/14; @@ -552,7 +541,7 @@ int main(int argc, char **argv) for (aa=0; aaframe_parms.nb_antennas_tx; aa++) memset(gNB->common_vars.txdataF[0][aa], 0, frame_parms->samples_per_slot_wCP * sizeof(int32_t)); - nr_common_signal_procedures (gNB,frame,slot,msgDataTx.ssb[i].ssb_pdu); + nr_common_signal_procedures (gNB,frame,slot, &ssb_pdu[i]); int samp = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { @@ -755,7 +744,7 @@ int main(int argc, char **argv) gNB->gNB_config.ssb_table.ssb_subcarrier_offset.value, frame_parms->Lmax); int payload_ret = (result.xtra_byte == xtra_byte); - nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15; + nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu[ssb_index].ssb_pdu_rel15; for (int i = 0; i < 3; i++) payload_ret += (result.decoded_output[i] == ((pdu->bchPayload >> (8 * i)) & 0xff)); // printf("ret %d\n", payload_ret); diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 35e242cad3..aba532a80d 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -135,10 +135,11 @@ int main(int argc, char **argv){ double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs=-1, bw; int i, l, aa, aarx, trial, n_frames = 1, rx_prach_start; //, ntrials=1; c16_t **txdata; - int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0; + int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, + loglvl = OAILOG_INFO; uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0; uint8_t config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0; - uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format0, format1; + uint16_t Nid_cell = 0, preamble_tx = 0, format0, format1; uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB; uint64_t SSB_positions = 0x01; uint16_t RA_sfn_index; @@ -151,9 +152,7 @@ int main(int argc, char **argv){ NR_DL_FRAME_PARMS *frame_parms; nfapi_nr_prach_config_t *prach_config; - nfapi_nr_prach_pdu_t *prach_pdu; fapi_nr_prach_config_t *ue_prach_config; - fapi_nr_ul_config_prach_pdu *ue_prach_pdu; channel_desc_t *UE2gNB; SCM_t channel_model = Rayleigh1; @@ -417,7 +416,6 @@ int main(int argc, char **argv){ ru = RC.ru[0]; frame_parms = &gNB->frame_parms; prach_config = &gNB->gNB_config.prach_config; - prach_pdu = &gNB->prach_vars.list[0].pdu; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) s_re = malloc(2*sizeof(double*)); @@ -561,9 +559,6 @@ int main(int argc, char **argv){ prach_config->restricted_set_config.value = restrictedSetConfig; prach_config->prach_sequence_length.value = prach_sequence_length; prach_config->prach_sub_c_spacing.value = mu; - prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); - prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs)); - prach_pdu->prach_format = prach_format; memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); RC.nb_nr_L1_inst=1; @@ -573,6 +568,10 @@ int main(int argc, char **argv){ phy_init_nr_gNB(gNB); nr_phy_init_RU(ru); + nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_list.list[0].pdu; + prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); + prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs)); + prach_pdu->prach_format = prach_format; // Configure UE UE = malloc(sizeof(PHY_VARS_NR_UE)); @@ -588,7 +587,7 @@ int main(int argc, char **argv){ exit(-1); } - ue_prach_pdu = &UE->prach_vars[0]->prach_pdu; + fapi_nr_ul_config_prach_pdu *ue_prach_pdu = &UE->prach_vars[0]->prach_pdu; ue_prach_config = &UE->nrUE_config.prach_config; txdata = UE->common_vars.txData; @@ -716,9 +715,8 @@ int main(int argc, char **argv){ } rx_prach_start = subframe*frame_parms->samples_per_subframe; - if (n_frames==1) printf("slot %d, rx_prach_start %d\n",slot,rx_prach_start); - uint16_t preamble_rx, preamble_energy; - + if (n_frames == 1) + printf("slot %d, rx_prach_start %d\n", slot, rx_prach_start); for (SNR = snr0; SNR < snr1 && !stop; SNR += .1) { for (ue_speed = ue_speed0; ue_speed < ue_speed1 && !stop; ue_speed += 10) { @@ -729,8 +727,7 @@ int main(int argc, char **argv){ prach_errors=0; for (trial = 0; trial < n_frames && !stop; trial++) { - - if (input_fd==NULL) { + if (input_fd == NULL) { sigma2_dB = 10*log10((double)tx_lev) - SNR - 10*log10(N_RB_UL*12/N_ZC); if (n_frames==1) @@ -757,45 +754,67 @@ int main(int argc, char **argv){ tmp->i = (short)(.167 * (r_im[aa][i] + (iqim * r_re[aa][i]) + sqrt(sigma2 / 2) * gaussdouble(0.0, 1.0))); } } - } else { - n_bytes = fread(&ru->common.rxdata[0][rx_prach_start],sizeof(int32_t),frame_parms->samples_per_subframe,input_fd); - printf("fread %d bytes from file %s\n",n_bytes,input_file); - if (n_bytes!=frame_parms->samples_per_subframe) { - printf("expected %d bytes\n",frame_parms->samples_per_subframe); - exit(-1); - } - } + } else { + n_bytes = fread(&ru->common.rxdata[0][rx_prach_start], sizeof(int32_t), frame_parms->samples_per_subframe, input_fd); + printf("fread %d bytes from file %s\n", n_bytes, input_file); + if (n_bytes != frame_parms->samples_per_subframe) { + printf("expected %d bytes\n", frame_parms->samples_per_subframe); + exit(-1); + } + } - for (l = 0; l < frame_parms->symbols_per_slot; l++) { - for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - nr_slot_fep_ul(frame_parms, ru->common.rxdata[aa], ru->common.rxdataF[aa], l, slot, ru->N_TA_offset); - } - } + for (l = 0; l < frame_parms->symbols_per_slot; l++) { + for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + nr_slot_fep_ul(frame_parms, ru->common.rxdata[aa], ru->common.rxdataF[aa], l, slot, ru->N_TA_offset); + } + } - rx_nr_prach_ru(ru, prach_format, numRA, 0, prachStartSymbol, slot, prachOccasion, frame, slot); + nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; + nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; + prach_pdu->num_prach_ocas=1; + prach_item_t in = {.frame = frame, + .slot = slot, + .pdu = *prach_pdu, + .rootSequenceIndex = occ->prach_root_sequence_index.value, + .numrootSequenceIndex = occ->num_root_sequences.value, + .msg1_frequencystart = occ->k1.value, + .mu = cfg->prach_sub_c_spacing.value, + .prach_sequence_length = cfg->prach_sequence_length.value, + .restricted_set = cfg->restricted_set_config.value, + .numerology_index = gNB->frame_parms.numerology_index, + .nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value, + .Xu = gNB->X_u, + .rx_prach = &gNB->rx_prach}; + rx_nr_prach_ru(&in, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); + if (n_frames == 1) + LOG_I(PHY, + "ncs %d,num_seq %d\n", + prach_pdu->num_cs, + prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); + rx_prach_out_t out = rx_nr_prach(&in, prachOccasion); - for (int i = 0; i < ru->nb_rx; ++i) - gNB->prach_vars.rxsigF[i] = ru->prach_rxsigF[prachOccasion][i]; - if (n_frames == 1) printf("ncs %d,num_seq %d\n",prach_pdu->num_cs, prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); - rx_nr_prach(gNB, prach_pdu, prachOccasion, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay); + // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", out.max_preamble_energy, out.max_preamble, + // preamble_tx); - // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", preamble_energy, preamble_rx, preamble_tx); - - if (preamble_rx != preamble_tx) + if (out.max_preamble != preamble_tx) prach_errors++; else - delay_avg += (double)preamble_delay; + delay_avg += (double)out.max_preamble_delay; N_ZC = (prach_sequence_length) ? 139 : 839; - if (n_frames==1) { - printf("preamble %d (tx %d) : energy %d, delay %d\n",preamble_rx,preamble_tx,preamble_energy,preamble_delay); + if (n_frames == 1) { + printf("preamble %d (tx %d) : energy %d, delay %d\n", + out.max_preamble, + preamble_tx, + out.max_preamble_energy, + out.max_preamble_delay); #ifdef NR_PRACH_DEBUG LOG_M("prach0.m","prach0", &txdata[0][prach_start], frame_parms->samples_per_subframe, 1, 1); LOG_M("rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); LOG_M("ru_rxsigF0.m","rxsF0", ru->common.rxdataF[0], frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot, 1, 1); - LOG_M("ru_prach_rxsigF0.m","rxsF0", ru->prach_rxsigF[0][0], N_ZC, 1, 1); + LOG_M("ru_prach_rxsigF0.m", "rxsF0", in.rxsigF[0][0], N_ZC, 1, 1); LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1); LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1); #endif @@ -815,8 +834,7 @@ int main(int argc, char **argv){ } if (input_fd) break; - } //SNR loop - + } // SNR loop free_channel_desc_scm(UE2gNB); nr_phy_free_RU(ru); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index c4b2f854c2..85c165b00d 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -60,7 +60,6 @@ #include "PHY/defs_nr_common.h" #include "PHY/impl_defs_nr.h" #include "PHY/phy_vars_nr_ue.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "SCHED_NR/sched_nr.h" #include "SCHED_NR_UE/defs.h" #include "SCHED_NR_UE/fapi_nr_ue_l1.h" @@ -727,11 +726,6 @@ int main(int argc, char *argv[]) else initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool"); - processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t)); - msgDataTx->slot = -1; - gNB->msgDataTx = msgDataTx; - //gNB_config = &gNB->gNB_config; - NR_UL_IND_t UL_INFO = {0}; UL_INFO.crc_ind.crc_list = UL_INFO.crc_pdu_list; UL_INFO.rx_ind.pdu_list = UL_INFO.rx_pdu_list; @@ -1284,6 +1278,9 @@ int main(int argc, char *argv[]) srs_pdu->beamforming.prg_size = 1; } + /* load FAPI into RX of L1 */ + nr_save_ul_tti_req(gNB, &Sched_INFO->UL_tti_req); + /// UE UL PDUs UE->ul_harq_processes[harq_pid].round = round; @@ -1291,9 +1288,6 @@ int main(int argc, char *argv[]) UE_proc.frame_tx = frame; UE_proc.gNB_id = 0; - // prepare ULSCH/PUSCH reception - nr_schedule_response(Sched_INFO); - // --------- setting parameters for UE -------- nr_scheduled_response_t scheduled_response = {.ul_config = &ul_config, .phy_data = (void *)&phy_data}; @@ -1468,14 +1462,14 @@ int main(int argc, char *argv[]) } int offset = (slot & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { - apply_nr_rotation_RX(&gNB->frame_parms, - gNB->common_vars.rxdataF[0][aa], - gNB->frame_parms.symbol_rotation[1], - slot, - gNB->frame_parms.N_RB_UL, - offset, - 0, - gNB->frame_parms.Ncp == EXTENDED ? 12 : 14); + const unsigned int max_symb = (gNB->frame_parms.Ncp == EXTENDED) ? 12 : 14; + for (int sym = 0; sym < max_symb; sym++) + apply_nr_rotation_symbol_RX(&gNB->frame_parms, + gNB->common_vars.rxdataF[0][aa] + offset + sym * gNB->frame_parms.ofdm_symbol_size, + gNB->frame_parms.symbol_rotation[1], + gNB->frame_parms.N_RB_UL, + slot, + sym); } ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot, &UL_INFO); diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index 788236ca05..6906d54704 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -475,6 +475,14 @@ typedef struct pdu_session_to_mod_s { DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; } pdu_session_to_mod_t; +/** PDU Session Resource To Remove List (3GPP TS 38.463 clause 9.3.3.12) */ +typedef struct { + // PDU Session ID (M) + long sessionId; + // Cause (O) + e1ap_cause_t cause; +} pdu_session_to_remove_t; + /** * Bearer Context Setup Request message, clause 9.2.2.1 of 3GPP TS 38.463 */ @@ -534,6 +542,9 @@ typedef struct e1ap_bearer_mod_req_s { // NG-RAN PDU Session Resource To Modify List (O) int numPDUSessionsMod; pdu_session_to_mod_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; + // NG-RAN PDU Session Resource To Remove List (O) + int numPDUSessionsRem; + pdu_session_to_remove_t pduSessionRem[E1AP_MAX_NUM_PDU_SESSIONS]; } e1ap_bearer_mod_req_t; typedef struct e1ap_bearer_release_cmd_s { diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 2c4b0f8a0a..5be5e316ef 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -421,6 +421,8 @@ typedef struct ngap_nas_first_req_s { /* PLMN: Selected PLMN Identity (optional) * User Location Information (mandatory) */ plmn_id_t plmn; + // NR Cell ID for NR CGI (mandatory) + uint32_t nr_cell_id; // RRC Establishment Cause (mandatory) ngap_rrc_establishment_cause_t establishment_cause; // NAS-PDU (mandatory) @@ -434,6 +436,10 @@ typedef struct ngap_uplink_nas_s { uint32_t gNB_ue_ngap_id; /* NAS pdu */ byte_array_t nas_pdu; + /* UserLocationInformation (mandatory) */ + plmn_id_t plmn; // CGI and TAI + uint32_t nr_cell_id; // CGI + uint32_t tac; // TAI } ngap_uplink_nas_t; typedef struct target_cell_id_s { diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 1eff4ea529..168366f351 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -125,8 +125,8 @@ static void e1_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *s int e1ap_send_RESET(bool isCu, sctp_assoc_t assoc_id, E1AP_Reset_t *Reset) { AssertFatal(false, "Not implemented yet\n"); - E1AP_E1AP_PDU_t pdu = {0}; - return e1ap_encode_send(isCu, assoc_id, &pdu, 0, __func__); + E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + return e1ap_encode_send(isCu, assoc_id, pdu, 0, __func__); } int e1ap_send_RESET_ACKNOWLEDGE(instance_t instance, E1AP_Reset_t *Reset) @@ -304,9 +304,9 @@ static void fill_CONFIGURATION_UPDATE(E1AP_E1AP_PDU_t *pdu) void e1apCUUP_send_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id) { - E1AP_E1AP_PDU_t pdu = {0}; - fill_CONFIGURATION_UPDATE(&pdu); - e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__); + E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + fill_CONFIGURATION_UPDATE(pdu); + e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__); } int e1apCUCP_send_gNB_DU_CONFIGURATION_FAILURE(void) diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c index 330d29567a..e102c7e151 100644 --- a/openair2/E1AP/e1ap_common.c +++ b/openair2/E1AP/e1ap_common.c @@ -226,7 +226,7 @@ int e1ap_encode_send(E1_t type, sctp_assoc_t assoc_id, E1AP_E1AP_PDU_t *pdu, uin void *buffer = NULL; ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_E1AP_E1AP_PDU, 0, pdu, &buffer); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, pdu); + ASN_STRUCT_FREE(asn_DEF_E1AP_E1AP_PDU, pdu); if (encoded < 0) { LOG_E(E1AP, "%s: Failed to encode E1AP message\n", func); diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index 109b0008d3..f2593f103c 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -1631,6 +1631,20 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_mod_request(const e1ap_bearer_mod_req_ *ieC3_1 = e1_encode_pdu_session_to_mod_item(i); } } + + // NG-RAN PDU Session Resource To Remove List (O) + if (in->numPDUSessionsRem) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, remList); + E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = encode_ng_ran_to_mod(remList); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Remove_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Remove_List; + E1AP_PDU_Session_Resource_To_Remove_List_t *pdu2Remove = &msgNGRAN->value.choice.PDU_Session_Resource_To_Remove_List; + for (const pdu_session_to_remove_t *i = in->pduSessionRem; i < in->pduSessionRem + in->numPDUSessionsRem; i++) { + asn1cSequenceAdd(pdu2Remove->list, E1AP_PDU_Session_Resource_To_Remove_Item_t, ieC4_1); + ieC4_1->pDU_Session_ID = i->sessionId; + } + } return pdu; } @@ -1854,6 +1868,19 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare CHECK_E1AP_DEC(e1_decode_pdu_session_to_mod_item(out->pduSessionMod + i, modList->list.array[i])); } break; + case E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Remove_List: + /* PDU Session Resource To Remove List (see 9.3.3.12 of TS 38.463) */ + _E1_EQ_CHECK_INT(msgNGRAN->value.present, + E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Remove_List); + E1AP_PDU_Session_Resource_To_Remove_List_t *remList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Remove_List; + out->numPDUSessionsRem = remList->list.count; + // Loop through all PDU sessions to remove + for (int i = 0; i < remList->list.count; i++) { + E1AP_PDU_Session_Resource_To_Remove_Item_t *remItem = remList->list.array[i]; + pdu_session_to_remove_t *pduRem = &out->pduSessionRem[i]; + pduRem->sessionId = remItem->pDU_Session_ID; + } + break; default: PRINT_ERROR("Unknown msgNGRAN->id in E1 Setup Modification Request\n"); return false; @@ -1924,6 +1951,9 @@ e1ap_bearer_mod_req_t cp_bearer_context_mod_request(const e1ap_bearer_mod_req_t cp.pduSession[i] = cp_pdu_session_item(&msg->pduSession[i]); for (int i = 0; i < msg->numPDUSessionsMod; i++) cp.pduSessionMod[i] = cp_pdu_session_to_mod_item(&msg->pduSessionMod[i]); + // Copy PDU sessions to remove (simple struct copy, no deep copy needed) + for (int i = 0; i < msg->numPDUSessionsRem; i++) + cp.pduSessionRem[i] = msg->pduSessionRem[i]; return cp; } @@ -2037,6 +2067,15 @@ bool eq_bearer_context_mod_request(const e1ap_bearer_mod_req_t *a, const e1ap_be if (!eq_pdu_session_to_mod_item(&a->pduSessionMod[i], &b->pduSessionMod[i])) return false; } + // PDU Sessions to Remove + _E1_EQ_CHECK_INT(a->numPDUSessionsRem, b->numPDUSessionsRem); + for (int i = 0; i < a->numPDUSessionsRem; i++) { + const pdu_session_to_remove_t *pduRemA = &a->pduSessionRem[i]; + const pdu_session_to_remove_t *pduRemB = &b->pduSessionRem[i]; + _E1_EQ_CHECK_LONG(pduRemA->sessionId, pduRemB->sessionId); + _E1_EQ_CHECK_INT(pduRemA->cause.type, pduRemB->cause.type); + _E1_EQ_CHECK_INT(pduRemA->cause.value, pduRemB->cause.value); + } return true; } @@ -2114,129 +2153,129 @@ struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_response(const e1ap_bearer_mo ie2->criticality = E1AP_Criticality_reject; ie2->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; ie2->value.choice.GNB_CU_UP_UE_E1AP_ID = msg->gNB_cu_up_ue_id; - // NG-RAN PDU Session Resource Modified List (O) - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie3); - ie3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse; - ie3->criticality = E1AP_Criticality_ignore; - // CHOICE System (O) - ie3->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse; - E1AP_System_BearerContextModificationResponse_t *sys = &ie3->value.choice.System_BearerContextModificationResponse; - // NG-RAN - E1AP_ProtocolIE_Container_4932P29_t *ngran = calloc_or_fail(1, sizeof(*ngran)); - sys->present = E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse; - sys->choice.nG_RAN_BearerContextModificationResponse = (struct E1AP_ProtocolIE_Container *)ngran; - asn1cSequenceAdd(ngran->list, E1AP_NG_RAN_BearerContextModificationResponse_t, list); - // PDU Session Resource Modified List (O) - list->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List; - list->criticality = E1AP_Criticality_reject; - list->value.present = E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List; - E1AP_PDU_Session_Resource_Modified_List_t *pdu_mod_l = &list->value.choice.PDU_Session_Resource_Modified_List; - for (int i = 0; i < msg->numPDUSessionsMod; ++i) { - // PDU Session Resource Modified Item (1..maxnoofPDUSessionResource) - const pdu_session_modif_t *pdu = &msg->pduSessionMod[i]; - asn1cSequenceAdd(pdu_mod_l->list, E1AP_PDU_Session_Resource_Modified_Item_t, iePdu); - // PDU Session ID (M) - iePdu->pDU_Session_ID = pdu->id; - // Security Result (O) - if (pdu->confidentialityProtectionIndication || pdu->integrityProtectionIndication) { - iePdu->securityResult = calloc_or_fail(1, sizeof(*iePdu->securityResult)); - if (pdu->confidentialityProtectionIndication) - iePdu->securityResult->confidentialityProtectionResult = *pdu->confidentialityProtectionIndication; - if (pdu->integrityProtectionIndication) - iePdu->securityResult->integrityProtectionResult = *pdu->integrityProtectionIndication; - } - // NG DL UP Transport Layer Information (O) - if (pdu->ng_DL_UP_TL_info) { - iePdu->nG_DL_UP_TNL_Information = calloc_or_fail(1, sizeof(*iePdu->nG_DL_UP_TNL_Information)); - *iePdu->nG_DL_UP_TNL_Information = e1_encode_up_tnl_info(pdu->ng_DL_UP_TL_info); - } - // DRB Modified List (O) - if (pdu->numDRBModified > 0) { - iePdu->dRB_Modified_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Modified_List_NG_RAN)); - E1AP_DRB_Modified_List_NG_RAN_t *drb_mod_l = iePdu->dRB_Modified_List_NG_RAN; - for (int j = 0; j < pdu->numDRBModified; ++j) { - const DRB_nGRAN_modified_t *drb = &pdu->DRBnGRanModList[j]; - asn1cSequenceAdd(drb_mod_l->list, E1AP_DRB_Modified_Item_NG_RAN_t, drb_mod); - // DRB ID (M) - drb_mod->dRB_ID = drb->id; - // Flow Setup List (O) - if (drb->numQosFlowSetup) - drb_mod->flow_Setup_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Setup_List)); - for (int q = 0; q < drb->numQosFlowSetup; ++q) { - asn1cSequenceAdd(drb_mod->flow_Setup_List->list, E1AP_QoS_Flow_Item_t, qos_mod); - qos_mod->qoS_Flow_Identifier = drb->qosFlows[q].qfi; - } - // Flow Failed List (O) - if (drb->numQosFlowFailed) - drb_mod->flow_Failed_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Failed_List)); - for (int q = 0; q < drb->numQosFlowFailed; ++q) { - asn1cSequenceAdd(drb_mod->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); - encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); - } - - // PDCP Status Information (O) - if (drb->pdcp_status) { - asn1cCalloc(drb_mod->pDCP_SN_Status_Information, pdcp); - *pdcp = encode_pdcp_status_info(drb->pdcp_status); - } - - // UL UP Parameters (O) - if (drb->numUpParam) - drb_mod->uL_UP_Transport_Parameters = calloc_or_fail(1, sizeof(*drb_mod->uL_UP_Transport_Parameters)); - for (const up_params_t *k = drb->ul_UP_Params; k < drb->ul_UP_Params + drb->numUpParam; k++) { - asn1cSequenceAdd(drb_mod->uL_UP_Transport_Parameters->list, E1AP_UP_Parameters_Item_t, up); - up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); - up->cell_Group_ID = k->cell_group_id; + if (msg->numPDUSessionsMod > 0) { + // NG-RAN PDU Session Resource Modified List (O) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie3); + ie3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse; + ie3->criticality = E1AP_Criticality_ignore; + // CHOICE System (O) + ie3->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse; + E1AP_System_BearerContextModificationResponse_t *sys = &ie3->value.choice.System_BearerContextModificationResponse; + // NG-RAN + E1AP_ProtocolIE_Container_4932P29_t *ngran = calloc_or_fail(1, sizeof(*ngran)); + sys->present = E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse; + sys->choice.nG_RAN_BearerContextModificationResponse = (struct E1AP_ProtocolIE_Container *)ngran; + asn1cSequenceAdd(ngran->list, E1AP_NG_RAN_BearerContextModificationResponse_t, list); + // PDU Session Resource Modified List (O) + list->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List; + list->criticality = E1AP_Criticality_reject; + list->value.present = E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List; + E1AP_PDU_Session_Resource_Modified_List_t *pdu_mod_l = &list->value.choice.PDU_Session_Resource_Modified_List; + for (int i = 0; i < msg->numPDUSessionsMod; ++i) { + // PDU Session Resource Modified Item (1..maxnoofPDUSessionResource) + const pdu_session_modif_t *pdu = &msg->pduSessionMod[i]; + asn1cSequenceAdd(pdu_mod_l->list, E1AP_PDU_Session_Resource_Modified_Item_t, iePdu); + // PDU Session ID (M) + iePdu->pDU_Session_ID = pdu->id; + // Security Result (O) + if (pdu->confidentialityProtectionIndication || pdu->integrityProtectionIndication) { + iePdu->securityResult = calloc_or_fail(1, sizeof(*iePdu->securityResult)); + if (pdu->confidentialityProtectionIndication) + iePdu->securityResult->confidentialityProtectionResult = *pdu->confidentialityProtectionIndication; + if (pdu->integrityProtectionIndication) + iePdu->securityResult->integrityProtectionResult = *pdu->integrityProtectionIndication; + } + // NG DL UP Transport Layer Information (O) + if (pdu->ng_DL_UP_TL_info) { + iePdu->nG_DL_UP_TNL_Information = calloc_or_fail(1, sizeof(*iePdu->nG_DL_UP_TNL_Information)); + *iePdu->nG_DL_UP_TNL_Information = e1_encode_up_tnl_info(pdu->ng_DL_UP_TL_info); + } + // DRB Modified List (O) + if (pdu->numDRBModified > 0) { + iePdu->dRB_Modified_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Modified_List_NG_RAN)); + E1AP_DRB_Modified_List_NG_RAN_t *drb_mod_l = iePdu->dRB_Modified_List_NG_RAN; + for (int j = 0; j < pdu->numDRBModified; ++j) { + const DRB_nGRAN_modified_t *drb = &pdu->DRBnGRanModList[j]; + asn1cSequenceAdd(drb_mod_l->list, E1AP_DRB_Modified_Item_NG_RAN_t, drb_mod); + // DRB ID (M) + drb_mod->dRB_ID = drb->id; + // Flow Setup List (O) + if (drb->numQosFlowSetup) + drb_mod->flow_Setup_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Setup_List)); + for (int q = 0; q < drb->numQosFlowSetup; ++q) { + asn1cSequenceAdd(drb_mod->flow_Setup_List->list, E1AP_QoS_Flow_Item_t, qos_mod); + qos_mod->qoS_Flow_Identifier = drb->qosFlows[q].qfi; + } + // Flow Failed List (O) + if (drb->numQosFlowFailed) + drb_mod->flow_Failed_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Failed_List)); + for (int q = 0; q < drb->numQosFlowFailed; ++q) { + asn1cSequenceAdd(drb_mod->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); + encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); + } + // PDCP Status Information (O) + if (drb->pdcp_status) { + asn1cCalloc(drb_mod->pDCP_SN_Status_Information, pdcp); + *pdcp = encode_pdcp_status_info(drb->pdcp_status); + } + // UL UP Parameters (O) + if (drb->numUpParam) + drb_mod->uL_UP_Transport_Parameters = calloc_or_fail(1, sizeof(*drb_mod->uL_UP_Transport_Parameters)); + for (const up_params_t *k = drb->ul_UP_Params; k < drb->ul_UP_Params + drb->numUpParam; k++) { + asn1cSequenceAdd(drb_mod->uL_UP_Transport_Parameters->list, E1AP_UP_Parameters_Item_t, up); + up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); + up->cell_Group_ID = k->cell_group_id; + } } } - } - // DRB Failed To Modify List (O) - if (pdu->numDRBFailedToMod > 0) { - iePdu->dRB_Failed_To_Modify_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_To_Modify_List_NG_RAN)); - E1AP_DRB_Failed_To_Modify_List_NG_RAN_t *ngran = iePdu->dRB_Failed_To_Modify_List_NG_RAN; - for (int j = 0; j < pdu->numDRBFailedToMod; ++j) { - const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedModList[j]; - asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t, fail_to_mod); - encode_drb_failed_item((E1AP_DRB_Failed_Item_NG_RAN_t *)fail_to_mod, drb); - } - } - // DRB Setup List (O) - if (pdu->numDRBSetup > 0) { - iePdu->dRB_Setup_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Setup_List_NG_RAN)); - E1AP_DRB_Setup_List_NG_RAN_t *drb_setup = iePdu->dRB_Setup_List_NG_RAN; - for (int j = 0; j < pdu->numDRBModified; ++j) { - const DRB_nGRAN_setup_t *drb = &pdu->DRBnGRanSetupList[j]; - asn1cSequenceAdd(drb_setup->list, E1AP_DRB_Setup_Item_NG_RAN_t, item); - // DRB ID (M) - item->dRB_ID = drb->id; - // UL UP Parameters (M) - for (const up_params_t *k = drb->UpParamList; k < drb->UpParamList + drb->numUpParam; k++) { - asn1cSequenceAdd(item->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, up); - up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); - up->cell_Group_ID = drb->UpParamList->cell_group_id; - } - // Flow Setup List (M) - for (int q = 0; q < drb->numQosFlowSetup; ++q) { - asn1cSequenceAdd(item->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, qos); - qos->qoS_Flow_Identifier = drb->qosFlows[q].qfi; - } - // Flow Failed List (O) - if (drb->numQosFlowFailed) - item->flow_Failed_List = calloc_or_fail(1, sizeof(*item->flow_Failed_List)); - for (int q = 0; q < drb->numQosFlowFailed; ++q) { - asn1cSequenceAdd(item->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); - encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); + // DRB Failed To Modify List (O) + if (pdu->numDRBFailedToMod > 0) { + iePdu->dRB_Failed_To_Modify_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_To_Modify_List_NG_RAN)); + E1AP_DRB_Failed_To_Modify_List_NG_RAN_t *ngran = iePdu->dRB_Failed_To_Modify_List_NG_RAN; + for (int j = 0; j < pdu->numDRBFailedToMod; ++j) { + const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedModList[j]; + asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t, fail_to_mod); + encode_drb_failed_item((E1AP_DRB_Failed_Item_NG_RAN_t *)fail_to_mod, drb); } } - } - // DRB Failed List (O) - if (pdu->numDRBFailed) { - iePdu->dRB_Failed_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_List_NG_RAN)); - E1AP_DRB_Failed_List_NG_RAN_t *ngran = iePdu->dRB_Failed_List_NG_RAN; - for (int j = 0; j < pdu->numDRBFailed; ++j) { - const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedList[j]; - asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_Item_NG_RAN_t, fail); - encode_drb_failed_item(fail, drb); + // DRB Setup List (O) + if (pdu->numDRBSetup > 0) { + iePdu->dRB_Setup_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Setup_List_NG_RAN)); + E1AP_DRB_Setup_List_NG_RAN_t *drb_setup = iePdu->dRB_Setup_List_NG_RAN; + for (int j = 0; j < pdu->numDRBModified; ++j) { + const DRB_nGRAN_setup_t *drb = &pdu->DRBnGRanSetupList[j]; + asn1cSequenceAdd(drb_setup->list, E1AP_DRB_Setup_Item_NG_RAN_t, item); + // DRB ID (M) + item->dRB_ID = drb->id; + // UL UP Parameters (M) + for (const up_params_t *k = drb->UpParamList; k < drb->UpParamList + drb->numUpParam; k++) { + asn1cSequenceAdd(item->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, up); + up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); + up->cell_Group_ID = drb->UpParamList->cell_group_id; + } + // Flow Setup List (M) + for (int q = 0; q < drb->numQosFlowSetup; ++q) { + asn1cSequenceAdd(item->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, qos); + qos->qoS_Flow_Identifier = drb->qosFlows[q].qfi; + } + // Flow Failed List (O) + if (drb->numQosFlowFailed) + item->flow_Failed_List = calloc_or_fail(1, sizeof(*item->flow_Failed_List)); + for (int q = 0; q < drb->numQosFlowFailed; ++q) { + asn1cSequenceAdd(item->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); + encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); + } + } + } + // DRB Failed List (O) + if (pdu->numDRBFailed) { + iePdu->dRB_Failed_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_List_NG_RAN)); + E1AP_DRB_Failed_List_NG_RAN_t *ngran = iePdu->dRB_Failed_List_NG_RAN; + for (int j = 0; j < pdu->numDRBFailed; ++j) { + const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedList[j]; + asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_Item_NG_RAN_t, fail); + encode_drb_failed_item(fail, drb); + } } } } diff --git a/openair2/E1AP/lib/e1ap_lib_includes.h b/openair2/E1AP/lib/e1ap_lib_includes.h index 028993e6fd..adafbe0ae5 100644 --- a/openair2/E1AP/lib/e1ap_lib_includes.h +++ b/openair2/E1AP/lib/e1ap_lib_includes.h @@ -78,6 +78,7 @@ #include "E1AP_DRB-To-Modify-Item-NG-RAN.h" #include "E1AP_PDU-Session-Resource-To-Setup-Mod-Item.h" #include "E1AP_DRB-To-Setup-Mod-Item-NG-RAN.h" +#include "E1AP_PDU-Session-Resource-To-Remove-Item.h" // E1 Bearer Context Modification Response #include "E1AP_PDU-Session-Resource-Modified-Item.h" #include "E1AP_DRB-Modified-List-NG-RAN.h" diff --git a/openair2/E1AP/tests/e1ap_lib_test.c b/openair2/E1AP/tests/e1ap_lib_test.c index b168ff9e82..50116514fb 100644 --- a/openair2/E1AP/tests/e1ap_lib_test.c +++ b/openair2/E1AP/tests/e1ap_lib_test.c @@ -538,6 +538,14 @@ static void test_bearer_context_modification_request(void) .DRBnGRanList[0] = drb_to_setup, }; + // PDU Session to Remove + pdu_session_to_remove_t pdu_session_to_remove = { + .sessionId = 2, + // Note: cause is optional extension IE, currently encoding/decoding only handles sessionId + .cause.type = 0, + .cause.value = 0, + }; + // Initialize the Bearer Context Modification Request e1ap_bearer_mod_req_t orig = { .gNB_cu_cp_ue_id = 0x1234, @@ -548,6 +556,8 @@ static void test_bearer_context_modification_request(void) .pduSession[0] = pdusession_setup_item, .numPDUSessionsMod = 1, .pduSessionMod[0] = pdusession_mod_item, + .numPDUSessionsRem = 1, + .pduSessionRem[0] = pdu_session_to_remove, }; *orig.bearerContextStatus = BEARER_SUSPEND; *orig.inactivityTimer = 1000; diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c index a81a01d394..5d725f1df6 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_e2sm_ue_id.c @@ -38,13 +38,11 @@ ue_id_e2sm_t fill_e2sm_gnb_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context, __attr ue_id.gnb.amf_ue_ngap_id = auni < (1LL << 40) ? auni : 0; // Mandatory - //GUAMI 6.2.3.17 - ue_id.gnb.guami.plmn_id = (e2sm_plmn_t) { - .mcc = rrc_ue_context->ue_guami.mcc, - .mnc = rrc_ue_context->ue_guami.mnc, - .mnc_digit_len = rrc_ue_context->ue_guami.mnc_len - }; - + //GUAMI 6.2.3.17 + ue_id.gnb.guami.plmn_id = (e2sm_plmn_t){.mcc = rrc_ue_context->ue_guami.plmn.mcc, + .mnc = rrc_ue_context->ue_guami.plmn.mnc, + .mnc_digit_len = rrc_ue_context->ue_guami.plmn.mnc_digit_length}; + ue_id.gnb.guami.amf_region_id = rrc_ue_context->ue_guami.amf_region_id; ue_id.gnb.guami.amf_set_id = rrc_ue_context->ue_guami.amf_set_id; ue_id.gnb.guami.amf_ptr = rrc_ue_context->ue_guami.amf_pointer; diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index 02760c4984..8933b802a0 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -54,10 +54,12 @@ typedef struct { ue_id_e2sm_t* ue_id; // Optional - // only used to retreive MAC/RLC stats + // only used to retrieve MAC/RLC stats NR_UE_info_t** ue_info_list; }arr_ue_id_t; +static e2_node_level_stats_t node_stats[2] = {0}; // [0] node stats collected in previous reporting period; [1] current node stats + static meas_data_lst_t fill_kpm_meas_data_item(const meas_info_format_1_lst_t* meas_info_lst, const size_t len, const uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) { meas_data_lst_t data_item = {0}; @@ -74,7 +76,7 @@ static meas_data_lst_t fill_kpm_meas_data_item(const meas_info_format_1_lst_t* m char* meas_info_name_str = cp_ba_to_str(meas_info_lst[i].meas_type.name); - data_item.meas_record_lst[i] = get_kpm_meas_value(meas_info_name_str, gran_period_ms, ue_info, ue_idx); + data_item.meas_record_lst[i] = get_kpm_meas_value(meas_info_name_str, gran_period_ms, ue_info, ue_idx, node_stats); free(meas_info_name_str); } @@ -153,6 +155,8 @@ static kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3(arr_ue_id_t* arr_ue_id, con msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1(ue_info, i, act_def_fr_1); } + node_stats[0] = cp_node_level_stats(&node_stats[1]); + return msg_frm_3; } @@ -288,8 +292,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst const ngran_node_t node_type = get_e2_node_type(); + gNB_MAC_INST *mac = RC.nrmac[0]; + NR_SCHED_LOCK(&mac->sched_lock); // Take MAC info - UE_iterator(RC.nrmac[0]->UE_info.connected_ue_list, ue) { + UE_iterator(mac->UE_info.connected_ue_list, ue) { NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl; // UE matches if any of its DRBs matches for (size_t l = 0; l < seq_arr_size(&sched_ctrl->lc_config); ++l) { @@ -316,6 +322,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst AssertFatal(arr_ue_id.sz < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); } + node_stats[1].mac_stats.dl.total_prb_aggregate = mac->mac_stats.dl.total_prb_aggregate; + node_stats[1].mac_stats.ul.total_prb_aggregate = mac->mac_stats.ul.total_prb_aggregate; + NR_SCHED_UNLOCK(&mac->sched_lock); + free(sd); // if NULL, nothing happens return arr_ue_id; diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c index 80579e1754..d3381cadd3 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c @@ -23,6 +23,18 @@ #include +e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src) +{ + e2_node_level_stats_t dst = { + .mac_stats.dl.total_prb_aggregate = src->mac_stats.dl.total_prb_aggregate, + .mac_stats.dl.used_prb_aggregate = src->mac_stats.dl.used_prb_aggregate, + .mac_stats.ul.total_prb_aggregate = src->mac_stats.ul.total_prb_aggregate, + .mac_stats.ul.used_prb_aggregate = src->mac_stats.ul.used_prb_aggregate, + }; + + return dst; +} + /* measurements that need to store values from previous reporting period have a limitation when it comes to multiple subscriptions to the same UEs; ric_req_id is unique per subscription */ typedef struct uldlcounter { @@ -46,7 +58,7 @@ static nr_pdcp_statistics_t get_pdcp_stats_per_drb(const uint32_t rrc_ue_id, con /* 3GPP TS 28.522 - section 5.1.2.1.1.1 note: this measurement is calculated as per spec */ -static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -57,7 +69,7 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_ meas_record.value = INTEGER_MEAS_VALUE; // Get DL data volume delivered to PDCP layer - meas_record.int_val = (pdcp.rxsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].dl)*8/1000; // [kb] + meas_record.int_val = (pdcp.rxsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].dl)*8/1000000; // [Mb] last_pdcp_sdu_total_bytes[ue_idx].dl = pdcp.rxsdu_bytes; return meas_record; @@ -65,7 +77,7 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_ /* 3GPP TS 28.522 - section 5.1.2.1.2.1 note: this measurement is calculated as per spec */ -static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -76,7 +88,7 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_ meas_record.value = INTEGER_MEAS_VALUE; // Get UL data volume delivered from PDCP layer - meas_record.int_val = (pdcp.txsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].ul)*8/1000; // [kb] + meas_record.int_val = (pdcp.txsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].ul)*8/1000000; // [Mb] last_pdcp_sdu_total_bytes[ue_idx].ul = pdcp.txsdu_bytes; return meas_record; @@ -103,7 +115,7 @@ static nr_rlc_statistics_t get_rlc_stats_per_drb(const rnti_t rnti, const int rb /* 3GPP TS 28.522 - section 5.1.3.3.3 note: by default this measurement is calculated for previous 100ms (openair2/LAYER2/nr_rlc/nr_rlc_entity.c:118, 173, 213); please, update according to your needs */ -static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, __attribute__((unused))const size_t ue_idx) +static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, __attribute__((unused))const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -122,7 +134,7 @@ static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t /* 3GPP TS 28.522 - section 5.1.1.3.1 note: per spec, average UE throughput in DL (taken into consideration values from all UEs, and averaged) here calculated as: UE specific throughput in DL */ -static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -141,7 +153,7 @@ static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_ /* 3GPP TS 28.522 - section 5.1.1.3.3 note: per spec, average UE throughput in UL (taken into consideration values from all UEs, and averaged) here calculated as: UE specific throughput in UL */ -static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -159,32 +171,30 @@ static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_ } /* 3GPP TS 28.522 - section 5.1.1.2.1 - note: per spec, DL PRB usage [%] = (total used PRBs for DL traffic / total available PRBs for DL traffic) * 100 - here calculated as: aggregated DL PRBs (t) - aggregated DL PRBs (t-gran_period) */ -static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) + note: this measurement is calculated as per spec */ +static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; meas_record.value = INTEGER_MEAS_VALUE; // Get the number of DL PRBs - meas_record.int_val = ue_info.ue->mac_stats.dl.total_rbs - last_total_prbs[ue_idx].dl; // [PRBs] + meas_record.int_val = (ue_info.ue->mac_stats.dl.total_rbs - last_total_prbs[ue_idx].dl) * 100 / (node_stats[1].mac_stats.dl.total_prb_aggregate - node_stats[0].mac_stats.dl.total_prb_aggregate); // [%] last_total_prbs[ue_idx].dl = ue_info.ue->mac_stats.dl.total_rbs; return meas_record; } /* 3GPP TS 28.522 - section 5.1.1.2.2 - note: per spec, UL PRB usage [%] = (total used PRBs for UL traffic / total available PRBs for UL traffic) * 100 - here calculated as: aggregated UL PRBs (t) - aggregated UL PRBs (t-gran_period) */ -static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) + note: this measurement is calculated as per spec */ +static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; meas_record.value = INTEGER_MEAS_VALUE; // Get the number of UL PRBs - meas_record.int_val = ue_info.ue->mac_stats.ul.total_rbs - last_total_prbs[ue_idx].ul; // [PRBs] + meas_record.int_val = (ue_info.ue->mac_stats.ul.total_rbs - last_total_prbs[ue_idx].ul) * 100 / (node_stats[1].mac_stats.ul.total_prb_aggregate - node_stats[0].mac_stats.ul.total_prb_aggregate); // [%] last_total_prbs[ue_idx].ul = ue_info.ue->mac_stats.ul.total_rbs; return meas_record; @@ -217,7 +227,7 @@ void init_kpm_subs_data(void) } } -meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats) { assert(kpm_meas_name != NULL); @@ -226,7 +236,7 @@ meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_m assert(found_entry != NULL && "Unsupported KPM measurement name"); kv_measure_t *kv_found = (kv_measure_t *)found_entry->data; - meas_record_lst_t meas_record = kv_found->value(gran_period_ms, ue_info, ue_idx); + meas_record_lst_t meas_record = kv_found->value(gran_period_ms, ue_info, ue_idx, node_stats); return meas_record; } diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h index 7dbd807fa1..e612ca2bab 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h @@ -34,7 +34,13 @@ typedef struct { } cudu_ue_info_pair_t; -typedef meas_record_lst_t (*kpm_meas_fp)(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx); +typedef struct { + dlul_mac_stats_t mac_stats; +} e2_node_level_stats_t; + +e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src); + +typedef meas_record_lst_t (*kpm_meas_fp)(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats); typedef struct{ char* key; @@ -44,6 +50,6 @@ typedef struct{ void init_kpm_subs_data(void); -meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx); +meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats); #endif diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 7bc8f677d8..7be234262f 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -217,7 +217,7 @@ typedef enum { {CONFIG_STRING_RU_NUM_TP_CORES, HLP_RU_NUM_TP_CORES, 0, .uptr=NULL, .defintval=2, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_NUM_INTERFACES, HLP_RU_NUM_INTERFACES, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION, HLP_RU_HALF_SLOT_PARALLELIZATION, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \ - {CONFIG_STRING_RU_RU_THREAD_CORE, HLP_RU_RU_THREAD_CORE, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \ + {CONFIG_STRING_RU_RU_THREAD_CORE, HLP_RU_RU_THREAD_CORE, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ {CONFIG_STRING_RU_GPIO_CONTROL, HLP_RU_GPIO_CONTROL, 0, .strptr=NULL, .defstrval="generic", TYPE_STRING, 0}, \ } // clang-format on diff --git a/openair2/GNB_APP/L1_nr_paramdef.h b/openair2/GNB_APP/L1_nr_paramdef.h index b2b4ab93c1..d140275fa5 100644 --- a/openair2/GNB_APP/L1_nr_paramdef.h +++ b/openair2/GNB_APP/L1_nr_paramdef.h @@ -84,8 +84,8 @@ {CONFIG_STRING_L1_PUSCH_DTX_THRESHOLD, NULL, 0, .uptr=NULL, .defintval=50, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_SRS_DTX_THRESHOLD, NULL, 0, .uptr=NULL, .defintval=30, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_MAX_LDPC_ITERATIONS, NULL, 0, .uptr=NULL, .defintval=8, TYPE_UINT, 0}, \ - {CONFIG_STRING_L1_RX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \ - {CONFIG_STRING_L1_TX_THREAD_CORE, NULL, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \ + {CONFIG_STRING_L1_RX_THREAD_CORE, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ + {CONFIG_STRING_L1_TX_THREAD_CORE, NULL, 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0}, \ {CONFIG_STRING_L1_TX_AMP_BACKOFF_dB, HLP_L1TX_BO,0, .uptr=NULL, .defintval=36, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_PHASE_COMP, HLP_L1_PHASE_COMP,PARAMFLAG_BOOL, .uptr=NULL,.defintval=1, TYPE_UINT, 0}, \ {CONFIG_STRING_NUM_ANTENNAS_PER_THREAD, HLP_NUM_ARX,0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \ diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index a6299b10cc..6bd02cf74a 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -79,6 +79,7 @@ #define CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST "beam_weights" #define CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD "pusch_RSSI_Threshold" #define CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD "pucch_RSSI_Threshold" +#define CONFIG_STRING_MACRLC_STATS_MAX_UE "stats_max_ue" #define HLP_MACRLC_UL_PRBBLACK "SNR threshold to decide whether a PRB will be blacklisted or not" #define HLP_MACRLC_DL_BLER_UP "Upper threshold of BLER to decrease DL MCS" @@ -98,6 +99,7 @@ #define HLP_MACRLC_BEAMS_PERIOD "set of beams that can be simultaneously allocated in a period" #define HLP_MACRLC_PUSCH_RSSI_THRESHOLD "Limits PUSCH TPC commands based on RSSI to prevent ADC railing. Value range [-1280, 0], unit 0.1 dBm/dBFS" #define HLP_MACRLC_PUCCH_RSSI_THRESHOLD "Limits PUCCH TPC commands based on RSSI to prevent ADC railing. Value range [-1280, 0], unit 0.1 dBm/dBFS" +#define HLP_MACRLC_STATS_MAX_UE "Maximum number of UEs before disabling periodical output (0 to disable)" /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* MacRLC configuration parameters */ @@ -149,6 +151,7 @@ 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD, HLP_MACRLC_PUCCH_RSSI_THRESHOLD, \ 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ + {CONFIG_STRING_MACRLC_STATS_MAX_UE, HLP_MACRLC_STATS_MAX_UE, 0, .iptr=NULL, .defintval=8, TYPE_INT, 0}, \ } // clang-format off @@ -194,6 +197,7 @@ #define MACRLC_BEAMWEIGHTS_IDX 39 #define MACRLC_PUSCH_RSSI_THRES_IDX 40 #define MACRLC_PUCCH_RSSI_THRES_IDX 41 +#define MACRLC_STATS_MAX_UE_IDX 42 #define MACRLCPARAMS_CHECK { \ { .s5 = { NULL } }, \ @@ -238,6 +242,7 @@ { .s5 = { NULL } }, \ { .s2 = { config_check_intrange, {-1280, 0}} }, /* PUSCH RSSI threshold range */ \ { .s2 = { config_check_intrange, {-1280, 0}} }, /* PUCCH RSSI threshold range */ \ + { .s5 = { NULL } }, \ } /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 45532572cd..081ce8607f 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -707,7 +707,7 @@ void RCconfig_verify(configmodule_interface_t *cfg, ngran_node_t node_type) verify_gnb_param_notset(gnbp, GNB_DISABLE_HARQ_IDX, GNB_CONFIG_STRING_DISABLE_HARQ); verify_gnb_param_notset(gnbp, GNB_NUM_DL_HARQ_IDX, GNB_CONFIG_STRING_NUM_DL_HARQPROCESSES); verify_gnb_param_notset(gnbp, GNB_NUM_UL_HARQ_IDX, GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES); - verify_gnb_param_notset(gnbp, GNB_DO_SINR_IDX, GNB_CONFIG_STRING_DOSINR); + verify_gnb_param_notset(gnbp, GNB_CONFIG_REP_IDX, GNB_CONFIG_STRING_CONFIG_REP); // check for some general sections verify_section_notset(cfg, NULL, CONFIG_STRING_L1_LIST); @@ -1127,7 +1127,7 @@ f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCC sys_info->mib = calloc_or_fail(buf_len, sizeof(*sys_info->mib)); DevAssert(mib != NULL); - sys_info->mib_length = encode_MIB_NR(mib, 0, sys_info->mib, buf_len); + sys_info->mib_length = encode_MIB_NR_setup(mib->message.choice.mib, 0, sys_info->mib, buf_len); DevAssert(sys_info->mib_length == buf_len); DevAssert(sib1 != NULL); @@ -1356,6 +1356,18 @@ static void config_pdcp(configmodule_interface_t *cfg, nr_pdcp_configuration_t * pdcp_config->drb.discard_timer = config_get_processedint(cfg, &pdcp_params[CONFIG_NR_PDCP_DRB_DISCARD_TIMER_IDX]); } +void nfapi_stop_l1() +{ + if (NFAPI_MODE && (NFAPI_MODE == NFAPI_MODE_AERIAL || NFAPI_MODE == NFAPI_MODE_VNF)) { + stop_nr_nfapi_vnf(); + } else if (NFAPI_MODE && NFAPI_MODE == NFAPI_MODE_PNF) { + // PNF should just wait for the STOP.request to come from the L2 + // If instead it was stopped first, in some cases it makes sense for it to terminate itself (WLS) + // Sends a STOP.indication to the VNF + stop_nr_nfapi_pnf(); + } +} + static void get_bwp_config(nr_mac_config_t *configuration) { char path[MAX_OPTNAME_SIZE * 2 + 8]; @@ -1432,7 +1444,8 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) config.do_CSIRS = *GNBParamList.paramarray[0][GNB_DO_CSIRS_IDX].iptr; config.do_SRS = *GNBParamList.paramarray[0][GNB_DO_SRS_IDX].iptr; config.max_num_rsrp = *GNBParamList.paramarray[0][GNB_LIMIT_RSRP_REPORT_IDX].iptr; - config.do_SINR = *GNBParamList.paramarray[0][GNB_DO_SINR_IDX].iptr; + const char *report_type_s = *GNBParamList.paramarray[0][GNB_CONFIG_REP_IDX].strptr; + config.report_type = config_get_processedint(cfg, &GNBParamList.paramarray[0][GNB_CONFIG_REP_IDX]); config.force_256qam_off = *GNBParamList.paramarray[0][GNB_FORCE256QAMOFF_IDX].iptr; config.force_UL256qam_off = *GNBParamList.paramarray[0][GNB_FORCEUL256QAMOFF_IDX].iptr; config.use_deltaMCS = *GNBParamList.paramarray[0][GNB_USE_DELTA_MCS_IDX].iptr != 0; @@ -1443,10 +1456,11 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) if (config.disable_harq) LOG_W(GNB_APP, "\"disable_harq\" is a REL17 feature and is incompatible with REL15 and REL16 UEs!\n"); LOG_I(GNB_APP, - "CSI-RS %d, SRS %d, SINR:%d, 256 QAM %s, delta_MCS %s, maxMIMO_Layers %d, HARQ feedback %s, num DLHARQ:%d, num ULHARQ:%d\n", + "CSI-RS %d, SRS %d, report type %d (%s), 256 QAM %s, delta_MCS %s, maxMIMO_Layers %d, HARQ feedback %s, num DLHARQ:%d, num ULHARQ:%d\n", config.do_CSIRS, config.do_SRS, - config.do_SINR, + config.report_type, + report_type_s, config.force_256qam_off ? "force off" : "may be on", config.use_deltaMCS ? "on" : "off", config.maxMIMO_layers, @@ -1580,6 +1594,8 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) AssertFatal(1 == 0, "MACRLC %d: %s unknown southbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr)); } RC.nrmac[j]->ulsch_max_frame_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_FRAME_INACTIVITY].uptr); + RC.nrmac[j]->stats_max_ue = *MacRLC_ParamList.paramarray[j][MACRLC_STATS_MAX_UE_IDX].iptr; + RC.nrmac[j]->print_ue_stats = RC.nrmac[j]->stats_max_ue > 0; NR_bler_options_t *dl_bler_options = &RC.nrmac[j]->dl_bler; dl_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr); dl_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr); diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index 200400144b..96cf898ba0 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -64,7 +64,7 @@ f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCC int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update); MessageDef *RCconfig_NR_CU_E1(const E1_t *entity); ngran_node_t get_node_type(void); - +void nfapi_stop_l1(); #ifdef E2_AGENT #include "openair2/E2AP/e2_agent_arg.h" e2_agent_args_t RCconfig_NR_E2agent(void); diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index e4e4bc3d2a..4ec09d06f0 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -137,7 +137,7 @@ typedef enum { #define GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST "uess_agg_levels" #define GNB_CONFIG_STRING_CU_SIB_LIST "cu_sibs" #define GNB_CONFIG_STRING_DU_SIB_LIST "du_sibs" -#define GNB_CONFIG_STRING_DOSINR "do_SINR" +#define GNB_CONFIG_STRING_CONFIG_REP "CSI_report_type" #define GNB_CONFIG_STRING_1ST_ACTIVE_BWP "first_active_bwp" #define GNB_CONFIG_STRING_LIMIT_RSRP_REPORT "max_num_RSRP_reported" @@ -153,7 +153,7 @@ typedef enum { #define GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST "List of aggregation levels with number of candidates per level. Element 0 - aggregation level 1" #define GNB_CONFIG_HLP_CU_SIBS "List of CU generated SIBs to be transmitted" #define GNB_CONFIG_HLP_DU_SIBS "List of DU generated SIBs to be transmitted" -#define GNB_CONFIG_HLP_DOSINR "Enable CSI feedback using SINR measurements on SSB" +#define GNB_CONFIG_HLP_CONFIG_REP "Define quantity for CSI report (options: ssb_rsrp, ssb_sinr and cri_rsrp)" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ @@ -201,7 +201,7 @@ typedef enum { GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST, 0, .iptr=NULL, .defintarrayval=NULL, TYPE_INTARRAY, 0}, \ {GNB_CONFIG_STRING_CU_SIB_LIST, GNB_CONFIG_HLP_CU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ {GNB_CONFIG_STRING_DU_SIB_LIST, GNB_CONFIG_HLP_DU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \ -{GNB_CONFIG_STRING_DOSINR, GNB_CONFIG_HLP_DOSINR, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_CONFIG_REP, GNB_CONFIG_HLP_CONFIG_REP, 0, .strptr=NULL, .defstrval="ssb_rsrp", TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_1ST_ACTIVE_BWP, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ {GNB_CONFIG_STRING_LIMIT_RSRP_REPORT, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ } @@ -246,7 +246,7 @@ typedef enum { #define GNB_UESS_AGG_LEVEL_LIST_IDX 35 #define GNB_CU_SIBS_IDX 36 #define GNB_DU_SIBS_IDX 37 -#define GNB_DO_SINR_IDX 38 +#define GNB_CONFIG_REP_IDX 38 #define GNB_1ST_ACTIVE_BWP_IDX 39 #define GNB_LIMIT_RSRP_REPORT_IDX 40 @@ -293,7 +293,10 @@ typedef enum { { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ - { .s5 = { NULL } }, \ + { .s3a = { config_checkstr_assign_integer, \ + {"ssb_rsrp", "ssb_sinr", "cri_rsrp"}, \ + {SSB_RSRP, SSB_SINR, CRI_RSRP}, \ + 3 } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 1a5431bdd2..13f2eca955 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2246,7 +2246,6 @@ int32_t get_l_prime(uint8_t duration_in_symbols, // For PDSCH Mapping TypeA, ld is duration between first OFDM of the slot and last OFDM symbol of the scheduled PUSCH resources // For TypeB, ld is the duration of the scheduled PUSCH resources uint8_t ld = (mapping_type == typeA) ? (duration_in_symbols + start_symbol) : duration_in_symbols; - uint8_t l0 = (dmrs_typeA_position == NR_MIB__dmrs_TypeA_Position_pos2) ? 2 : 3 ; uint8_t colomn = additional_pos; @@ -2260,20 +2259,27 @@ int32_t get_l_prime(uint8_t duration_in_symbols, row = ld - 3; uint32_t l_prime; + int l0 = (dmrs_typeA_position == NR_MIB__dmrs_TypeA_Position_pos2) ? 2 : 3; + int l0_shift; if (pusch_maxLength == pusch_len1) { l_prime = table_6_4_1_1_3_3_pusch_dmrs_positions_l[row][colomn]; - l0 = 1 << l0; - } - else { + l0_shift = 1 << l0; + } else { l_prime = table_6_4_1_1_3_4_pusch_dmrs_positions_l[row][colomn]; - l0 = 1<= 0, "invalid l_prime < 0\n"); - LOG_D(NR_MAC, "PUSCH - l0:%d, ld:%d,row:%d, column:%d, addpos:%d, maxlen:%d\n", l0, ld, row, colomn, additional_pos, pusch_maxLength); - AssertFatal(l_prime>=0,"invalid l_prime < 0\n"); - - l_prime = (mapping_type == typeA) ? (l_prime | l0) : (l_prime << start_symbol); - LOG_D(MAC, " PUSCH DMRS MASK in HEX:%x\n", l_prime); + l_prime = (mapping_type == typeA) ? (l_prime | l0_shift) : (l_prime << start_symbol); + LOG_D(NR_MAC, + "PUSCH - l0:%d, ld:%d, row:%d, column:%d, addpos:%d, maxlen:%d DMRS MASK in HEX:%x\n", + (mapping_type == typeA) ? l0 : 0, + ld, + row, + colomn, + additional_pos, + pusch_maxLength, + l_prime); return l_prime; } @@ -2813,11 +2819,13 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP, dci_pdu->harq_pid.nbits = 4; dci_pdu->frequency_domain_assignment.nbits = (uint8_t)ceil(log2((N_RB * (N_RB + 1)) >>1)); // Freq domain assignment -- hopping scenario to be updated size += dci_pdu->frequency_domain_assignment.nbits; - if(alt_size >= size) - size += alt_size - size; // Padding to match 1_0 size - else if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) { - dci_pdu->frequency_domain_assignment.nbits -= (size - alt_size); - size = alt_size; + if (alt_size) { + if(alt_size >= size) + size += alt_size - size; // Padding to match 1_0 size + else if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) { + dci_pdu->frequency_domain_assignment.nbits -= (size - alt_size); + size = alt_size; + } } // UL/SUL indicator assumed to be 0 break; @@ -3127,7 +3135,7 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP, default: AssertFatal(1==0, "Invalid NR DCI format %d\n", format); } - LOG_D(NR_MAC, "DCI size: %d\n", size); + LOG_D(NR_MAC, "DCI format %d size: %d alt_size %d\n", format, size, alt_size); return size; } @@ -3163,13 +3171,21 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config, int dmrs_AdditionalPosition = 0; NR_DMRS_DownlinkConfig_t *dmrs_config = NULL; - LOG_D(MAC, "NrofSymbols:%d, startSymbol:%d, mappingtype:%d, dmrs_TypeA_Position:%d\n", NrOfSymbols, startSymbol, mappingtype, dmrs_TypeA_Position); + LOG_D(NR_MAC, + "NrofSymbols:%d, startSymbol:%d, mappingtype:%d, dmrs_TypeA_Position:%d\n", + NrOfSymbols, + startSymbol, + mappingtype, + dmrs_TypeA_Position); int l0 = 0; // type B if (mappingtype == typeA) { - if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2) l0 = 2; - else if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3) l0 = 3; - else AssertFatal(1==0,"Illegal dmrs_TypeA_Position %d\n",(int)dmrs_TypeA_Position); + if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2) + l0 = 2; + else if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3) + l0 = 3; + else + AssertFatal(false, "Illegal dmrs_TypeA_Position %d\n", (int)dmrs_TypeA_Position); } // in case of DCI FORMAT 1_0 or dedicated pdsch config not received additionposition = pos2, len1 should be used // referred to section 5.1.6.2 in 38.214 @@ -3177,14 +3193,16 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config, if (pdsch_Config != NULL) { if (mappingtype == typeA) { // Type A - if (dci_format != NR_DL_DCI_FORMAT_1_0 && - pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) + if (dci_format != NR_DL_DCI_FORMAT_1_0 + && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA + && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; } else if (mappingtype == typeB) { - if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) + if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB + && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup; } else { - AssertFatal(1==0,"Incorrect Mappingtype\n"); + AssertFatal(false, "Incorrect Mappingtype\n"); } // default values of additionalposition is pos2 @@ -3192,49 +3210,52 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config, dmrs_AdditionalPosition = *dmrs_config->dmrs_AdditionalPosition; } - uint8_t ld, row, column; - int32_t l_prime = -1; - // columns 0-3 for TypeA, 4-7 for TypeB - column = (mappingtype == typeA) ? dmrs_AdditionalPosition : (dmrs_AdditionalPosition + 4); + int column = (mappingtype == typeA) ? dmrs_AdditionalPosition : (dmrs_AdditionalPosition + 4); // Section 7.4.1.1.2 in Spec 38.211 // For PDSCH Mapping TypeA, ld is duration between first OFDM of the slot and last OFDM symbol of the scheduled PDSCH resources // For TypeB, ld is the duration of the scheduled PDSCH resources - ld = (mappingtype == typeA) ? (NrOfSymbols + startSymbol) : NrOfSymbols; + int ld = (mappingtype == typeA) ? (NrOfSymbols + startSymbol) : NrOfSymbols; AssertFatal(ld > 2 && ld < 15,"Illegal NrOfSymbols according to Table 5.1.2.1-1 Spec 38.214 %d\n",ld); AssertFatal((NrOfSymbols + startSymbol) < 15,"Illegal S+L according to Table 5.1.2.1-1 Spec 38.214 S:%d L:%d\n",startSymbol, NrOfSymbols); if (mappingtype == typeA) { - // Section 7.4.1.1.2 in Spec 38.211 AssertFatal((l0 == 2) || (l0 == 3 && dmrs_AdditionalPosition != 3),"Wrong config, If dmrs_TypeA_Position POS3, ADD POS cannot be POS3 \n"); - // Table 5.1.2.1-1 in Spec 38.214 AssertFatal(startSymbol <= l0, "Wrong config, Start symbol %d cannot be later than dmrs_TypeA_Position %d \n", startSymbol, l0); - // Section 7.4.1.1.2 in Spec 38.211 AssertFatal(l0 == 2 || (l0 == 3 && (ld != 3 && ld != 4)), "ld 3 or 4 symbols only possible with dmrs_TypeA_Position POS2 \n"); } // number of front loaded symbols + int l_prime, row, l0_shift; if (length == 1) { row = ld - 2; l_prime = table_7_4_1_1_2_3_pdsch_dmrs_positions_l[row][column]; - l0 = 1 << l0; - } - else { + l0_shift = 1 << l0; + } else { row = (ld < 4) ? 0 : (ld - 3); l_prime = table_7_4_1_1_2_4_pdsch_dmrs_positions_l[row][column]; - l0 = 1<= 0, + "ERROR in configuration. Check Time Domain allocation of this Grant. l_prime < 1. row:%d, column:%d\n", + row, + column); - LOG_D(MAC, "l0:%d, ld:%d,row:%d, column:%d, addpos:%d, maxlen:%d\n", l0, ld, row, column, dmrs_AdditionalPosition, length); - AssertFatal(l_prime>=0,"ERROR in configuration.Check Time Domain allocation of this Grant. l_prime < 1. row:%d, column:%d\n", row, column); - - l_prime = (mappingtype == typeA) ? (l_prime | l0) : (l_prime << startSymbol); - LOG_D(MAC, " PDSCH DMRS MASK in HEX:%x\n", l_prime); + l_prime = (mappingtype == typeA) ? (l_prime | l0_shift) : (l_prime << startSymbol); + LOG_D(NR_MAC, + "l0:%d, ld:%d, row:%d, column:%d, addpos:%d, maxlen:%d, DMRS MASK in HEX:%x\n", + (mappingtype == typeA) ? l0 : 0, + ld, + row, + column, + dmrs_AdditionalPosition, + length, + l_prime); return l_prime; } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index b7ebd5a651..b43937d362 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -307,8 +307,8 @@ typedef struct { NR_PUCCH_Resource_t *pucch_resource; uint32_t ack_payload; uint8_t sr_payload; - uint32_t csi_part1_payload; - uint32_t csi_part2_payload; + uint64_t csi_part1_payload; + uint64_t csi_part2_payload; int n_sr; int n_csi; int n_harq; @@ -431,6 +431,14 @@ typedef struct { float_t ssb_sinr_dB; } NR_SSB_meas_t; +typedef struct { + int rsrp_dBm; + uint8_t ri; + uint16_t i1; + uint8_t i2; + uint8_t cqi; +} NR_CSIRS_meas_t; + typedef enum ta_type { no_ta = 0, adjustment_ta, @@ -601,9 +609,6 @@ typedef struct NR_UE_MAC_INST_s { nr_csi_report_t csi_report_template[MAX_CSI_REPORTCONFIG]; - /// measurements from SS or CSI-RS - fapi_nr_l1_measurements_t l1_measurements; - //// FAPI-like interface message fapi_nr_ul_config_request_t *ul_config_request; fapi_nr_dl_config_request_t *dl_config_request; @@ -633,6 +638,7 @@ typedef struct NR_UE_MAC_INST_s { int ssb_start_subcarrier; NR_SSB_meas_t ssb_measurements[MAX_NB_SSB]; + NR_CSIRS_meas_t csirs_measurements; dci_pdu_rel15_t def_dci_pdu_rel15[NR_MAX_SLOTS_PER_FRAME][8]; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 1f35df5c4b..c78d2217b4 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -307,7 +307,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca release_ul_BWP(mac, i); memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); - memset(&mac->l1_measurements, 0, sizeof(mac->l1_measurements)); + memset(&mac->csirs_measurements, 0, sizeof(mac->csirs_measurements)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); for (int i = mac->TAG_list.count; i > 0 ; i--) asn_sequence_del(&mac->TAG_list, i - 1, 1); 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 218a513ec7..8a2074422e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -307,12 +307,7 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac, break; } - for (int i = 0; i < sps; i++) { - if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { - rel15->coreset.StartSymbolIndex = i; - break; - } - } + rel15->coreset.StartSymbolBitmap = monitoringSymbolsWithinSlot; uint32_t Y = 0; if (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) Y = get_Y(ss, slot, rel15->rnti); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 7818b08362..aeb15fe864 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1508,13 +1508,18 @@ nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t 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 CSI-RS measurements\n", frame, slot); - memcpy(&mac->l1_measurements, l1_measurements, sizeof(*l1_measurements)); + LOG_D(NR_MAC, "(%d.%d) Received measurements from L1\n", frame, slot); bool csi_meas = l1_measurements->meas_type == NFAPI_NR_CSI_MEAS; if (!csi_meas && !l1_measurements->is_neighboring_cell) { int ssb_index = l1_measurements->ssb_index; mac->ssb_measurements[ssb_index].ssb_rsrp_dBm = l1_measurements->rsrp_dBm; mac->ssb_measurements[ssb_index].ssb_sinr_dB = l1_measurements->sinr_dB; + } else if (csi_meas) { + mac->csirs_measurements.rsrp_dBm = l1_measurements->rsrp_dBm; + mac->csirs_measurements.i1 = l1_measurements->i1; + mac->csirs_measurements.i2 = l1_measurements->i2; + mac->csirs_measurements.cqi = l1_measurements->cqi; + mac->csirs_measurements.ri = l1_measurements->rank_indicator; } nr_mac_rrc_meas_ind_ue(mac->ue_id, l1_measurements->gNB_index, @@ -2790,13 +2795,13 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac, } else nb_meas = 2; - struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList SSB_resource; + struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList *SSB_resource = NULL; for (int csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) { if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId == *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { - SSB_resource = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList; + SSB_resource = &csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList; /// only one SSB resource set from spec 38.331 IE CSI-ResourceConfig - nb_ssb = SSB_resource.list.count; + nb_ssb = SSB_resource->list.count; break; } } @@ -2811,7 +2816,7 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac, for (int measured_ssb_idx = 0; measured_ssb_idx < MAX_NB_SSB; measured_ssb_idx++) { // searching for the SSB index in the SSB resource table for (int ssb_resource = 0; ssb_resource < nb_ssb; ssb_resource++) { - if (*SSB_resource.list.array[ssb_resource] == measured_ssb_idx) { + if (*SSB_resource->list.array[ssb_resource] == measured_ssb_idx) { sorted_sinr_measurements[sorted_idx].ssb_index = ssb_resource; sorted_sinr_measurements[sorted_idx].ssb_rsrp_dBm = mac->ssb_measurements[measured_ssb_idx].ssb_rsrp_dBm; sorted_sinr_measurements[sorted_idx].ssb_sinr_dB = mac->ssb_measurements[measured_ssb_idx].ssb_sinr_dB; @@ -2822,25 +2827,20 @@ static csi_payload_t get_ssb_sinr_payload(NR_UE_MAC_INST_t *mac, } qsort(sorted_sinr_measurements, nb_ssb, sizeof(NR_RSRP_meas_t), compare_ssb_sinr); - uint8_t ssbi; - // TS38.212 v16.5.0: Table 6.3.1.1.2-8A - if (ssbri_bits > 0) { - ssbi = sorted_sinr_measurements[0].ssb_index; - temp_payload = reverse_bits(ssbi, ssbri_bits); - bits += ssbri_bits; + for (int i = 0; i < nb_meas; i++) { + if (ssbri_bits > 0) { + uint8_t ssbi = sorted_sinr_measurements[i].ssb_index; + temp_payload |= (reverse_bits(ssbi, ssbri_bits) << bits); + bits += ssbri_bits; + } } uint8_t sinr_idx = get_sinr_index(sorted_sinr_measurements[0].ssb_sinr_dB); temp_payload |= (reverse_bits(sinr_idx, 7) << bits); bits += 7; // 7 bits for highest SINR - // from the second SSB, differential report for (int i = 1; i < nb_meas; i++) { - ssbi = sorted_sinr_measurements[i].ssb_index; - temp_payload |= (reverse_bits(ssbi, ssbri_bits) << bits); - bits += ssbri_bits; - sinr_idx = get_sinr_diff_index(sorted_sinr_measurements[0].ssb_sinr_dB, sorted_sinr_measurements[i].ssb_sinr_dB); temp_payload |= (reverse_bits(sinr_idx, 4) << bits); bits += 4; // 4 bits for differential SINR @@ -2931,13 +2931,13 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, } else nb_meas = 2; - struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList SSB_resource; + struct NR_CSI_SSB_ResourceSet__csi_SSB_ResourceList *SSB_resource = NULL; for (int csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) { if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId == *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ - SSB_resource = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList; + SSB_resource = &csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList; ///only one SSB resource set from spec 38.331 IE CSI-ResourceConfig - nb_ssb = SSB_resource.list.count; + nb_ssb = SSB_resource->list.count; break; } } @@ -2952,7 +2952,7 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, for (int measured_ssb_idx = 0; measured_ssb_idx < MAX_NB_SSB; measured_ssb_idx++) { // searching for the SSB index in the SSB resource table for (int ssb_resource = 0; ssb_resource < nb_ssb; ssb_resource++) { - if (*SSB_resource.list.array[ssb_resource] == measured_ssb_idx) { + if (*SSB_resource->list.array[ssb_resource] == measured_ssb_idx) { sorted_rsrp_measurements[sorted_idx].ssb_index = ssb_resource; sorted_rsrp_measurements[sorted_idx].ssb_rsrp_dBm = mac->ssb_measurements[measured_ssb_idx].ssb_rsrp_dBm; sorted_rsrp_measurements[sorted_idx].ssb_sinr_dB = mac->ssb_measurements[measured_ssb_idx].ssb_sinr_dB; @@ -2963,12 +2963,12 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, } qsort(sorted_rsrp_measurements, nb_ssb, sizeof(NR_RSRP_meas_t), compare_ssb_rsrp); - uint32_t ssbi; - - if (ssbri_bits > 0) { - ssbi = sorted_rsrp_measurements[0].ssb_index; - temp_payload = reverse_bits(ssbi, ssbri_bits); - bits += ssbri_bits; + for (int i = 0; i < nb_meas; i++) { + if (ssbri_bits > 0) { + uint32_t ssbi = sorted_rsrp_measurements[i].ssb_index; + temp_payload |= (reverse_bits(ssbi, ssbri_bits) << bits); + bits += ssbri_bits; + } } uint8_t rsrp_idx = get_rsrp_index(sorted_rsrp_measurements[0].ssb_rsrp_dBm); @@ -2977,15 +2977,11 @@ static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, // from the second SSB, differential report for (int i = 1; i < nb_meas; i++) { - ssbi = sorted_rsrp_measurements[i].ssb_index; - temp_payload |= (reverse_bits(ssbi, ssbri_bits) << bits); - bits += ssbri_bits; - rsrp_idx = get_rsrp_diff_index(sorted_rsrp_measurements[0].ssb_rsrp_dBm,sorted_rsrp_measurements[i].ssb_rsrp_dBm); temp_payload |= (reverse_bits(rsrp_idx, 4) << bits); bits += 4; // 4 bits for subsequent RSRP } - break; // resorce found + break; // resource found } } int max_bits = sizeof(((csi_payload_t *)0)->part1_payload) * 8; @@ -3026,28 +3022,28 @@ static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, AssertFatal(csi_report, "Couldn't find CSI report with ID %ld\n", csi_reportconfig->reportConfigId); int cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen; int ri_bitlen = csi_report->csi_meas_bitlen.ri_bitlen; - int pmi_x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[mac->l1_measurements.rank_indicator]; - int pmi_x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[mac->l1_measurements.rank_indicator]; - int cqi_bitlen = csi_report->csi_meas_bitlen.cqi_bitlen[mac->l1_measurements.rank_indicator]; + int pmi_x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[mac->csirs_measurements.ri]; + int pmi_x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[mac->csirs_measurements.ri]; + int cqi_bitlen = csi_report->csi_meas_bitlen.cqi_bitlen[mac->csirs_measurements.ri]; int padding_bitlen = 0; // TODO: Improvements will be needed to cri_bitlen>0 and pmi_x1_bitlen>0 if (mapping_type == ON_PUSCH) { p1_bits = cri_bitlen + ri_bitlen + cqi_bitlen; p2_bits = pmi_x1_bitlen + pmi_x2_bitlen; temp_payload_1 = (0/*mac->csi_measurements.cri*/ << (cqi_bitlen + ri_bitlen)) | - (mac->l1_measurements.rank_indicator << cqi_bitlen) | - (mac->l1_measurements.cqi); - temp_payload_2 = (mac->l1_measurements.i1 << pmi_x2_bitlen) | - mac->l1_measurements.i2; + (mac->csirs_measurements.ri << cqi_bitlen) | + (mac->csirs_measurements.cqi); + temp_payload_2 = (mac->csirs_measurements.i1 << pmi_x2_bitlen) | + mac->csirs_measurements.i2; } else { p1_bits = nr_get_csi_bitlen(csi_report); padding_bitlen = p1_bits - (cri_bitlen + ri_bitlen + pmi_x1_bitlen + pmi_x2_bitlen + cqi_bitlen); temp_payload_1 = (0/*mac->csi_measurements.cri*/ << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen + ri_bitlen)) | - (mac->l1_measurements.rank_indicator << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen)) | - (mac->l1_measurements.i1 << (cqi_bitlen + pmi_x2_bitlen)) | - (mac->l1_measurements.i2 << (cqi_bitlen)) | - (mac->l1_measurements.cqi); + (mac->csirs_measurements.ri << (cqi_bitlen + pmi_x2_bitlen + pmi_x1_bitlen + padding_bitlen)) | + (mac->csirs_measurements.i1 << (cqi_bitlen + pmi_x2_bitlen)) | + (mac->csirs_measurements.i2 << (cqi_bitlen)) | + (mac->csirs_measurements.cqi); } temp_payload_1 = reverse_bits(temp_payload_1, p1_bits); @@ -3106,7 +3102,7 @@ static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, } // TODO: Improvements will be needed to cri_ssbri_bitlen>0 - temp_payload = get_rsrp_index(mac->l1_measurements.rsrp_dBm); + temp_payload = get_rsrp_index(mac->csirs_measurements.rsrp_dBm); temp_payload = reverse_bits(temp_payload, n_bits); LOG_D(NR_MAC, "cri_ssbri_bitlen = %d\n", cri_ssbri_bitlen); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 3825a49fd2..bd9ea09041 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -555,6 +555,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->tbslbrm = 0; } else if (dci) { + pusch_config_pdu->subcarrier_spacing = scs; pusch_config_pdu->ulsch_indicator = dci->ulsch_indicator; if (dci->csi_request.nbits > 0 && dci->csi_request.val > 0) { AssertFatal(csi_report, "CSI report needs to be present in case of CSI request\n"); @@ -1918,7 +1919,6 @@ uint8_t set_csirs_measurement_bitmap(NR_CSI_MeasConfig_t *csi_measconfig, NR_CSI AssertFatal(false, "Unexpected measurement report type %d\n", report_config->reportQuantity.present); } } - AssertFatal(meas_bitmap > 0, "Expected to have at least 1 measurement configured for CSI-RS\n"); return meas_bitmap; } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index a0637ac107..893a94147e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -1099,6 +1099,13 @@ void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const plmn_id_t *plmn, uint64_t AssertFatal(cc->sib1_bcch_length > 0, "could not encode SIB1\n"); } +static bool process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl, const NR_RLC_BearerConfig_t *conf) +{ + int priority = conf->mac_LogicalChannelConfig->ul_SpecificParameters->priority; + nr_lc_config_t c = {.lcid = conf->logicalChannelIdentity, .priority = priority}; + return nr_mac_add_lcid(sched_ctrl, &c); +} + bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) { /* ideally, instead of this function, "users" of this function should call @@ -1120,7 +1127,9 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t } int ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; configure_UE_BWP(nrmac, nrmac->common_channels[0].ServingCellConfigCommon, UE, false, ss_type, -1, -1); - process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, CellGroup->rlc_BearerToAddModList); + const struct NR_CellGroupConfig__rlc_BearerToAddModList *l = CellGroup->rlc_BearerToAddModList; + for (int i = 0; l != NULL && i < l->list.count; ++i) + process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, CellGroup->rlc_BearerToAddModList->list.array[i]); AssertFatal(CellGroup->rlc_BearerToReleaseList == NULL, "cannot release bearers while adding new UEs\n"); NR_SCHED_UNLOCK(&nrmac->sched_lock); LOG_I(NR_MAC, "Added new UE %x with initial CellGroup\n", rnti); @@ -1139,14 +1148,23 @@ void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE) uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count; ra->preambles.num_preambles = num_preamble; NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; + char buf[200]; + int idx = 0; for (int i = 0; i < cc->num_active_ssb; i++) { for (int j = 0; j < num_preamble; j++) { if (cc->ssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) { // one dedicated preamble for each beam ra->preambles.preamble_list[i] = cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ra_PreambleIndex; + if (idx < sizeof(buf) - 1) + idx += snprintf(buf + idx, sizeof(buf) - idx, " %d", ra->preambles.preamble_list[i]); break; } } } - LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", UE->rnti); + LOG_I(NR_MAC, + "Added new %s process for UE RNTI %04x with initial CellGroup and %d preamble(s): %s\n", + ra->cfra ? "CFRA" : "CBRA", + UE->rnti, + num_preamble, + buf); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 46ad8069da..6a9cce656a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -59,13 +59,7 @@ uint8_t nr_get_rv(int rel_round) return nr_rv_round_map[rel_round]; } -void clear_nr_nfapi_information(gNB_MAC_INST *gNB, - int CC_idP, - frame_t frameP, - slot_t slotP, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req, - nfapi_nr_ul_dci_request_t *UL_dci_req) +void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, frame_t frameP, slot_t slotP) { /* called below and in simulators, so we assume a lock but don't require it */ const int num_slots = gNB->frame_structure.numb_slots_frame; @@ -75,16 +69,8 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB, gNB->pdu_index[CC_idP] = 0; - DL_req[CC_idP].SFN = frameP; - DL_req[CC_idP].Slot = slotP; - DL_req[CC_idP].dl_tti_request_body.nPDUs = 0; - DL_req[CC_idP].dl_tti_request_body.nGroup = 0; memset(pdcch, 0, sizeof(*pdcch) * MAX_NUM_CORESET); - UL_dci_req[CC_idP].SFN = frameP; - UL_dci_req[CC_idP].Slot = slotP; - UL_dci_req[CC_idP].numPdus = 0; - /* advance last round's future UL_tti_req to be ahead of current frame/slot */ const int size = gNB->UL_tti_req_ahead_size; const int prev_slot = frameP * num_slots + slotP + size - 1; @@ -100,8 +86,6 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB, future_ul_tti_req->n_ulsch = 0; future_ul_tti_req->n_ulcch = 0; future_ul_tti_req->n_group = 0; - - TX_req[CC_idP].Number_of_PDUs = 0; } static void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slot, int slots_per_frame) @@ -191,14 +175,27 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL[i]; memcpy(&vrb_map_UL[prev_slot % size * MAX_BWP_SIZE], &gNB->ulprbbl, sizeof(uint16_t) * MAX_BWP_SIZE); } - clear_nr_nfapi_information(gNB, CC_id, frame, slot, &sched_info->DL_req, &sched_info->TX_req, &sched_info->UL_dci_req); + clear_nr_nfapi_information(gNB, CC_id, frame, slot); } bool wait_prach_completed = gNB->num_scheduled_prach_rx >= NUM_PRACH_RX_FOR_NOISE_ESTIMATE; - if ((wait_prach_completed || get_softmodem_params()->phy_test) && (slot == 0) && (frame & 127) == 0) { + if (gNB->print_ue_stats && (wait_prach_completed || get_softmodem_params()->phy_test) && (slot == 0) && (frame & 127) == 0) { char stats_output[32656] = {0}; dump_mac_stats(gNB, stats_output, sizeof(stats_output), true); LOG_I(NR_MAC, "Frame.Slot %d.%d\n%s\n", frame, slot, stats_output); + + // TODO: this should be replaced with a size() operation on connected_ue_list + int num_ue = 0; + UE_iterator(gNB->UE_info.connected_ue_list, it) { + (void) it; // not used + num_ue++; + } + if (gNB->print_ue_stats && num_ue > gNB->stats_max_ue) { + gNB->print_ue_stats = false; + LOG_W(NR_MAC, + "periodical UE stats deactivated after reaching %d UEs, please check nrMAC_stats.log, or increase MACRLCs.[0].stats_max_ue\n", + gNB->stats_max_ue); + } } nr_measgap_scheduling(gNB, frame, slot); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 5e9cd47a79..f8df95f679 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -60,7 +60,7 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &gNB->common_channels[0]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; + nfapi_nr_config_request_scf_t *cfg = &gNB->config[0]; NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; uint8_t config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; @@ -351,10 +351,10 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) msgacc = initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; int slots_frame = gNB->frame_structure.numb_slots_frame; int index = ul_buffer_index(frameP, slotP, slots_frame, gNB->UL_tti_req_ahead_size); - nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index]; - nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; + nfapi_nr_ul_tti_request_t *UL_tti_req = &gNB->UL_tti_req_ahead[0][index]; + nfapi_nr_config_request_scf_t *cfg = &gNB->config[0]; - if (is_ul_slot(slotP, &RC.nrmac[module_idP]->frame_structure)) { + if (is_ul_slot(slotP, &gNB->frame_structure)) { const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric; uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex; int slot_index = 0; @@ -390,16 +390,15 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) uint32_t N_t_slot = cc->prach_info.N_t_slot; uint32_t start_symb = cc->prach_info.start_symbol; for (int fdm_index = 0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion - AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]), - "Invalid UL_tti_req->n_pdus %d\n", - UL_tti_req->n_pdus); - - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t); - nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu; - memset(prach_pdu, 0, sizeof(nfapi_nr_prach_pdu_t)); + AssertFatal(UL_tti_req->n_pdus < sizeofArray(UL_tti_req->pdus_list), "Invalid UL_tti_req->n_pdus %d\n", UL_tti_req->n_pdus); + nfapi_nr_ul_tti_request_number_of_pdus_t *newpdu = UL_tti_req->pdus_list + UL_tti_req->n_pdus; + *newpdu = (nfapi_nr_ul_tti_request_number_of_pdus_t){ + .pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE, + .pdu_size = sizeof(nfapi_nr_prach_pdu_t), + }; UL_tti_req->n_pdus += 1; int num_td_occ = 0; + nfapi_nr_prach_pdu_t *prach_pdu = &newpdu->prach_pdu; for (int td_index = 0; td_index < N_t_slot; td_index++) { uint32_t config_period = cc->prach_info.x; prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) + @@ -786,6 +785,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_RA_t *ra = UE->ra; + DevAssert(!ra->cfra); NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; @@ -1123,7 +1123,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ const uint16_t mask = SL_to_bitmap(ra->msg3_startsymb, ra->msg3_nbSymb); int slots_frame = mac->frame_structure.numb_slots_frame; int buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, slots_frame, mac->vrb_map_UL_size); - uint16_t *vrb_map_UL = &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_beam.idx][buffer_index * MAX_BWP_SIZE]; + uint16_t *vrb_map_UL = &mac->common_channels[CC_id].vrb_map_UL[ra->Msg3_beam.idx][buffer_index * MAX_BWP_SIZE]; for (int i = 0; i < ra->msg3_nb_rb; ++i) { AssertFatal(!(vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] & mask), "RB %d in %4d.%2d is already taken, cannot allocate Msg3!\n", @@ -1135,7 +1135,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ LOG_D(NR_MAC, "UE %04x: %d.%d RA is active, Msg3 in (%d,%d)\n", UE->rnti, frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, slots_frame, mac->UL_tti_req_ahead_size); - nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][buffer_index]; + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &mac->UL_tti_req_ahead[CC_id][buffer_index]; AssertFatal(future_ul_tti_req->SFN == ra->Msg3_frame && future_ul_tti_req->Slot == ra->Msg3_slot, "future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", @@ -1431,7 +1431,12 @@ static void nr_generate_Msg2(module_id_t module_idP, scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow; const int n_slots_frame = nr_mac->frame_structure.numb_slots_frame; if (!msg2_in_response_window(ra->preamble_frame, ra->preamble_slot, n_slots_frame, rrc_ra_ResponseWindow, frameP, slotP)) { - LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: exceeded RA window, cannot schedule Msg2\n", ra->RA_rnti, UE->rnti); + LOG_E(NR_MAC, + "sfn: %d.%d UE RA-RNTI %04x TC-RNTI %04x: exceeded RA window, cannot schedule Msg2\n", + frameP, + slotP, + ra->RA_rnti, + UE->rnti); nr_release_ra_UE(nr_mac, UE->rnti); return; } @@ -1447,6 +1452,11 @@ static void nr_generate_Msg2(module_id_t module_idP, return; const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + // check the feasibility of Msg3, the actual Msg3 allocation + // is further below. In the case of CFRA, we don't need Msg3, but 38.321 + // §5.1.4 does not clearly exclude Msg3, and UL TA might still be useful. + // Before the change in this commit, we used CFRA but required Msg3, which + // COTS UE would often (but not always) send. bool ret = get_feasible_msg3_tda(scc, get_delta_for_k2(ul_bwp->scs), ul_bwp->tdaList_Common, @@ -1519,6 +1529,7 @@ static void nr_generate_Msg2(module_id_t module_idP, return; } + // get an actual Msg3 allocation in CBRA bool msg3_ret = nr_get_Msg3alloc(nr_mac, CC_id, slotP, frameP, UE); if (!msg3_ret) { reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); @@ -1605,27 +1616,31 @@ static void nr_generate_Msg2(module_id_t module_idP, // DL TX request nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; - // Program UL processing for Msg3 + // If CFRA: 38.321 §5.1.4 does not clearly say (to me) if UL grant should be + // dropped or not, and COTS UE would often send Msg3 if we configured CFRA + // but required Msg3. Also, "if RAR includes a MAC subPDU with RAPID: [...] + // indicate the reception of an acknowledgement for SI request to upper + // layers." which is not the case here. nr_add_msg3(module_idP, CC_id, frameP, slotP, UE, (uint8_t *)&tx_req->TLVs[0].value.direct[0]); - // Start RA contention resolution timer in Msg3 transmission slot (current slot + K2) - // 3GPP TS 38.321 Section 5.1.5 Contention Resolution - start_ra_contention_resolution_timer( - ra, - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer, - *ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc), - ul_bwp->scs); + if (!ra->cfra) { + LOG_D(NR_MAC, + "UE %04x: %d.%d: Setting RA-Msg3 reception for SFN.Slot %d.%d\n", + UE->rnti, + frameP, + slotP, + ra->Msg3_frame, + ra->Msg3_slot); - LOG_D(NR_MAC, - "UE %04x: %d.%d: Setting RA-Msg3 reception (%s) for SFN.Slot %d.%d\n", - UE->rnti, - frameP, - slotP, - ra->cfra ? "CFRA" : "CBRA", - ra->Msg3_frame, - ra->Msg3_slot); + // Start RA contention resolution timer in Msg3 transmission slot (current slot + K2) + // 3GPP TS 38.321 Section 5.1.5 Contention Resolution + start_ra_contention_resolution_timer( + ra, + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer, + *ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc), + ul_bwp->scs); - LOG_A(NR_MAC, "%d.%d Send RAR to RA-RNTI %04x\n", frameP, slotP, ra->RA_rnti); + } tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; @@ -1650,6 +1665,7 @@ static void nr_generate_Msg2(module_id_t module_idP, vrb_map[bwp_info.bwpStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); } + // In CFRA: in Msg3 handling, will unconditionally mark succeeded ra->ra_state = nrRA_WAIT_Msg3; } @@ -1671,6 +1687,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_SearchSpace_t *ss = sched_ctrl->search_space; NR_RA_t *ra = UE->ra; + DevAssert(!ra->cfra); const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; AssertFatal(coreset != NULL, "Coreset cannot be null for RA %s\n", ra_type_str); @@ -2115,10 +2132,9 @@ static void nr_fill_rar(uint8_t Mod_idP, NR_UE_info_t *UE, uint8_t *dlsch_buffer * The corresponding function to add is add_new_UE_RA(). */ void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti) { + NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); NR_UEs_t *UE_info = &mac->UE_info; - NR_SCHED_LOCK(&UE_info->mutex); NR_UE_info_t *UE = remove_UE_from_list(NR_NB_RA_PROC_MAX, UE_info->access_ue_list, rnti); - NR_SCHED_UNLOCK(&UE_info->mutex); if (UE) { delete_nr_ue_data(UE, mac->common_channels, &UE_info->uid_allocator); } else { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 8a81d8ae4f..1f6fb64181 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -274,35 +274,32 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi } } -static uint32_t get_tbs_bch(NR_sched_pdsch_t *pdsch, - uint32_t num_total_bytes, - uint16_t *vrb_map) +static void update_rb_mcs_tbs(NR_sched_pdsch_t *pdsch, uint32_t num_total_bytes, uint16_t *vrb_map) { - NR_tda_info_t *tda_info = &pdsch->tda_info; + const NR_tda_info_t *tda_info = &pdsch->tda_info; // Calculate number of PRB_DMRS uint8_t N_PRB_DMRS = pdsch->dmrs_parms.N_PRB_DMRS; LOG_D(MAC, "dlDmrsSymbPos %x\n", pdsch->dmrs_parms.dl_dmrs_symb_pos); int mcsTableIdx = 0; - uint32_t TBS = 0; const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); int bwpSize = pdsch->bwp_info.bwpSize; int bwpStart = pdsch->bwp_info.bwpStart; int rbStop = bwpSize - 1; - int rbStart = 0; - uint16_t rbSize = 0; - while (rbStart < rbStop) { - if (vrb_map[rbStart + bwpStart] & slbitmap) - rbStart++; + while (pdsch->rbStart < rbStop) { + if (vrb_map[pdsch->rbStart + bwpStart] & slbitmap) + pdsch->rbStart++; else { int max_rbSize = 0; - while (rbStart + max_rbSize <= rbStop && !(vrb_map[rbStart + max_rbSize + bwpStart] & slbitmap)) + while (pdsch->rbStart + max_rbSize <= rbStop && !(vrb_map[pdsch->rbStart + max_rbSize + bwpStart] & slbitmap)) max_rbSize++; bool res = false; while (res == false && pdsch->mcs < 10) { - res = nr_find_nb_rb(nr_get_Qm_dl(pdsch->mcs, mcsTableIdx), - nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx), + pdsch->Qm = nr_get_Qm_dl(pdsch->mcs, mcsTableIdx); + pdsch->R = nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx); + res = nr_find_nb_rb(pdsch->Qm, + pdsch->R, 1, // no transform precoding for DL 1, // single layer tda_info->nrOfSymbols, @@ -310,59 +307,56 @@ static uint32_t get_tbs_bch(NR_sched_pdsch_t *pdsch, num_total_bytes, 1, // min_rbSize max_rbSize, - &TBS, - &rbSize); + &pdsch->tb_size, + &pdsch->rbSize); if (!res) pdsch->mcs++; } break; } } - AssertFatal(TBS >= num_total_bytes, + AssertFatal(pdsch->tb_size >= num_total_bytes, "Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d)\n", num_total_bytes, - rbStart, - rbSize, + pdsch->rbStart, + pdsch->rbSize, bwpSize); - pdsch->rbSize = rbSize; - pdsch->rbStart = rbStart; - LOG_D(NR_MAC, "mcs=%i, startSymbolIndex = %i, nrOfSymbols = %i, rbSize = %i, TBS = %i, dmrs_length %d, N_PRB_DMRS = %d, mappingtype = %d\n", pdsch->mcs, tda_info->startSymbolIndex, tda_info->nrOfSymbols, - rbSize, - TBS, + pdsch->rbSize, + pdsch->tb_size, pdsch->dmrs_parms.N_DMRS_SLOT, N_PRB_DMRS, tda_info->mapping_type); - return TBS; } -static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, - int CC_id, - NR_sched_pdcch_t *pdcch, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - int time_domain_allocation, - NR_pdsch_dmrs_t *dmrs_parms, - NR_tda_info_t *tda_info, - uint8_t candidate_idx, - int beam, - uint16_t num_total_bytes) +static NR_sched_pdsch_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, + int CC_id, + NR_sched_pdcch_t *pdcch, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + int time_domain_allocation, + NR_pdsch_dmrs_t *dmrs_parms, + NR_tda_info_t *tda_info, + uint8_t candidate_idx, + int beam, + uint16_t num_total_bytes) { AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n"); NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; uint16_t *vrb_map = cc->vrb_map[beam]; - NR_sched_pdsch_t *pdsch = &gNB_mac->sched_ctrlCommon->sched_pdsch; - pdsch->bwp_info = get_pdsch_bwp_start_size(gNB_mac, NULL); - pdsch->time_domain_allocation = time_domain_allocation; - pdsch->dmrs_parms = *dmrs_parms; - pdsch->tda_info = *tda_info; - pdsch->nrOfLayers = 1; - pdsch->pm_index = 0; - pdsch->mcs = 0; // starting from mcs 0 + NR_sched_pdsch_t pdsch = { + .bwp_info = get_pdsch_bwp_start_size(gNB_mac, NULL), + .time_domain_allocation = time_domain_allocation, + .dmrs_parms = *dmrs_parms, + .tda_info = *tda_info, + .nrOfLayers = 1, + .pm_index = 0, + .mcs = 0, // starting from mcs 0 + }; gNB_mac->sched_ctrlCommon->num_total_bytes = num_total_bytes; uint8_t nr_of_candidates = 0; @@ -383,12 +377,7 @@ static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n"); - uint32_t TBS = get_tbs_bch(&gNB_mac->sched_ctrlCommon->sched_pdsch, - gNB_mac->sched_ctrlCommon->num_total_bytes, - vrb_map); - - pdsch->R = nr_get_code_rate_dl(pdsch->mcs, 0); - pdsch->Qm = nr_get_Qm_dl(pdsch->mcs, 0); + update_rb_mcs_tbs(&pdsch, gNB_mac->sched_ctrlCommon->num_total_bytes, vrb_map); // Mark the corresponding RBs as used fill_pdcch_vrb_map(gNB_mac, @@ -397,10 +386,10 @@ static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, gNB_mac->sched_ctrlCommon->cce_index, gNB_mac->sched_ctrlCommon->aggregation_level, beam); - for (int rb = 0; rb < pdsch->rbSize; rb++) { + for (int rb = 0; rb < pdsch.rbSize; rb++) { vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); } - return TBS; + return pdsch; } static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, @@ -578,22 +567,21 @@ void schedule_nr_sib1(module_id_t module_idP, NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0]; // Configure sched_ctrlCommon for SIB1 - uint32_t TBS = schedule_control_sib1(gNB_mac, - CC_id, - &sched_pdcch, - type0_PDCCH_CSS_config, - time_domain_allocation, - &dmrs_parms, - &tda_info, - candidate_idx, - beam.idx, - cc->sib1_bcch_length); + NR_sched_pdsch_t sched_pdsch = schedule_control_sib1(gNB_mac, + CC_id, + &sched_pdcch, + type0_PDCCH_CSS_config, + time_domain_allocation, + &dmrs_parms, + &tda_info, + candidate_idx, + beam.idx, + cc->sib1_bcch_length); - gNB_mac->sched_ctrlCommon->sched_pdsch.tb_size = TBS; nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; int pdu_index = gNB_mac->pdu_index[0]++; nr_fill_nfapi_dl_SIB_pdu(gNB_mac, - &gNB_mac->sched_ctrlCommon->sched_pdsch, + &sched_pdsch, &sched_pdcch, gNB_mac->sched_ctrlCommon->search_space, gNB_mac->sched_ctrlCommon->coreset, @@ -609,11 +597,11 @@ void schedule_nr_sib1(module_id_t module_idP, nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; // Data to be transmitted - memcpy(tx_req->TLVs[0].value.direct, cc->sib1_bcch_pdu, TBS); + memcpy(tx_req->TLVs[0].value.direct, cc->sib1_bcch_pdu, sched_pdsch.tb_size); tx_req->PDU_index = pdu_index; tx_req->num_TLV = 1; - tx_req->TLVs[0].length = TBS; + tx_req->TLVs[0].length = sched_pdsch.tb_size; tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length); TX_req->Number_of_PDUs++; TX_req->SFN = frameP; @@ -718,9 +706,7 @@ static void other_sib_sched_control(module_id_t module_idP, uint16_t *vrb_map = cc->vrb_map[beam.idx]; uint8_t *sib_bcch_pdu = cc->other_sib_bcch_pdu[payload_idx]; int num_total_bytes = cc->other_sib_bcch_length[payload_idx]; - sched_pdsch_otherSI.tb_size = get_tbs_bch(&sched_pdsch_otherSI, num_total_bytes, vrb_map); - sched_pdsch_otherSI.R = nr_get_code_rate_dl(sched_pdsch_otherSI.mcs, 0); - sched_pdsch_otherSI.Qm = nr_get_Qm_dl(sched_pdsch_otherSI.mcs, 0); + update_rb_mcs_tbs(&sched_pdsch_otherSI, num_total_bytes, vrb_map); for (int rb = 0; rb < sched_pdsch_otherSI.rbSize; rb++) { vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); @@ -747,10 +733,10 @@ static void other_sib_sched_control(module_id_t module_idP, // Data to be transmitted memcpy(tx_req->TLVs[0].value.direct, sib_bcch_pdu, sched_pdsch_otherSI.tb_size); - tx_req->PDU_length = sched_pdsch_otherSI.tb_size; tx_req->PDU_index = pdu_index; tx_req->num_TLV = 1; - tx_req->TLVs[0].length = sched_pdsch_otherSI.tb_size + 2; + tx_req->TLVs[0].length = sched_pdsch_otherSI.tb_size; + tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length); TX_req->Number_of_PDUs++; TX_req->SFN = frame; TX_req->Slot = slot; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 348c32d599..a1814d5715 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -26,6 +26,7 @@ * \email: guido.casati@iis.fraunhofe.de * \version 1.0 * @ingroup _mac + */ #include "common/utils/nr/nr_common.h" @@ -320,46 +321,41 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, return offset; } -static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, slot_t slot) +static uint32_t update_dlsch_buffer(frame_t frame, slot_t slot, NR_UE_info_t *UE) { - UE_iterator(RC.nrmac[module_id]->UE_info.connected_ue_list, UE) { - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - sched_ctrl->num_total_bytes = 0; - sched_ctrl->dl_pdus_total = 0; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + sched_ctrl->num_total_bytes = 0; + sched_ctrl->dl_pdus_total = 0; - /* loop over all activated logical channels */ - // Note: DL_SCH_LCID_DCCH, DL_SCH_LCID_DCCH1, DL_SCH_LCID_DTCH - for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); ++i) { - const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); - const int lcid = c->lcid; - const uint16_t rnti = UE->rnti; - LOG_D(NR_MAC, "In %s: UE %x: LCID %d\n", __FUNCTION__, rnti, lcid); - memset(&sched_ctrl->rlc_status[lcid], 0, sizeof(sched_ctrl->rlc_status[lcid])); - if (c->suspended) - continue; - if (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt)) - continue; - sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid); + /* loop over all activated logical channels */ + for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); ++i) { + const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); + const int lcid = c->lcid; + const uint16_t rnti = UE->rnti; + LOG_D(NR_MAC, "UE %x: LCID %d\n", rnti, lcid); + memset(&sched_ctrl->rlc_status[lcid], 0, sizeof(sched_ctrl->rlc_status[lcid])); + if (c->suspended) + continue; + if (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt)) + continue; + sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid); - if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) - continue; + if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) + continue; - sched_ctrl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer; - sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; - LOG_D(MAC, - "[gNB %d][%4d.%2d] %s%d->DLSCH, RLC status for UE %d: %d bytes in buffer, total DL buffer size = %d bytes, %d total PDU bytes, %s TA command\n", - module_id, - frame, - slot, - lcid < 4 ? "DCCH":"DTCH", - lcid, - UE->rnti, - sched_ctrl->rlc_status[lcid].bytes_in_buffer, - sched_ctrl->num_total_bytes, - sched_ctrl->dl_pdus_total, - sched_ctrl->ta_apply ? "send":"do not send"); - } + sched_ctrl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer; + sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; + LOG_D(MAC, + "%4d.%2d UE %04x LCID %d status: %d bytes, total buffer %d bytes %d PDUs\n", + frame, + slot, + UE->rnti, + lcid, + sched_ctrl->rlc_status[lcid].bytes_in_buffer, + sched_ctrl->num_total_bytes, + sched_ctrl->dl_pdus_total); } + return sched_ctrl->num_total_bytes; } void finish_nr_dl_harq(NR_UE_sched_ctrl_t *sched_ctrl, int harq_pid) @@ -421,29 +417,30 @@ bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) return bwp_info; } -static bool allocate_dl_retransmission(module_id_t module_id, - frame_t frame, - slot_t slot, +static bool allocate_dl_retransmission(gNB_MAC_INST *nr_mac, + post_process_pdsch_t *pp_pdsch, int *n_rb_sched, NR_UE_info_t *UE, int beam_idx, int current_harq_pid) { - + frame_t frame = pp_pdsch->frame; + slot_t slot = pp_pdsch->slot; int CC_id = 0; - gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + const NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels->ServingCellConfigCommon; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; - NR_sched_pdsch_t *retInfo = &sched_ctrl->harq_processes[current_harq_pid].sched_pdsch; - NR_sched_pdsch_t *curInfo = &sched_ctrl->sched_pdsch; + NR_sched_pdsch_t new_sched = sched_ctrl->harq_processes[current_harq_pid].sched_pdsch; + int layers = get_dl_nrOfLayers(sched_ctrl, dl_bwp->dci_format); + int pm_index = get_pm_index(nr_mac, UE, dl_bwp->dci_format, layers, nr_mac->radio_config.pdsch_AntennaPorts.XP); // If the RI changed between current rtx and a previous transmission // we need to verify if it is not decreased // othwise it wouldn't be possible to transmit the same TBS - int layers = (curInfo->nrOfLayers < retInfo->nrOfLayers) ? curInfo->nrOfLayers : retInfo->nrOfLayers; - int pm_index = (curInfo->nrOfLayers < retInfo->nrOfLayers) ? curInfo->pm_index : retInfo->pm_index; + layers = (layers < new_sched.nrOfLayers) ? layers : new_sched.nrOfLayers; + pm_index = (layers < new_sched.nrOfLayers) ? pm_index : new_sched.pm_index; const int coresetid = sched_ctrl->coreset->controlResourceSetId; const int tda = get_dl_tda(nr_mac, slot); @@ -462,11 +459,11 @@ static bool allocate_dl_retransmission(module_id_t module_id, if (!temp_tda.valid_tda) return false; - bool reuse_old_tda = (retInfo->tda_info.startSymbolIndex == temp_tda.startSymbolIndex) && (retInfo->tda_info.nrOfSymbols <= temp_tda.nrOfSymbols); + bool reuse_old_tda = (new_sched.tda_info.startSymbolIndex == temp_tda.startSymbolIndex) && (new_sched.tda_info.nrOfSymbols <= temp_tda.nrOfSymbols); LOG_D(NR_MAC, "[UE %x] %s old TDA, %s number of layers\n", UE->rnti, reuse_old_tda ? "reuse" : "do not reuse", - layers == retInfo->nrOfLayers ? "same" : "different"); + layers == new_sched.nrOfLayers ? "same" : "different"); uint16_t *rballoc_mask = nr_mac->common_channels[CC_id].vrb_map[beam_idx]; @@ -475,13 +472,13 @@ static bool allocate_dl_retransmission(module_id_t module_id, int rbStop = bwp_info.bwpStart + bwp_info.bwpSize - 1; int rbSize = 0; - if (reuse_old_tda && layers == retInfo->nrOfLayers) { + if (reuse_old_tda && layers == new_sched.nrOfLayers) { /* Check that there are enough resources for retransmission */ - while (rbSize < retInfo->rbSize) { + while (rbSize < new_sched.rbSize) { rbStart += rbSize; /* last iteration rbSize was not enough, skip it */ rbSize = 0; - const uint16_t slbitmap = SL_to_bitmap(retInfo->tda_info.startSymbolIndex, retInfo->tda_info.nrOfSymbols); + const uint16_t slbitmap = SL_to_bitmap(new_sched.tda_info.startSymbolIndex, new_sched.tda_info.nrOfSymbols); while (rbStart < rbStop && (rballoc_mask[rbStart] & slbitmap)) rbStart++; @@ -490,8 +487,9 @@ static bool allocate_dl_retransmission(module_id_t module_id, return false; } - while (rbStart + rbSize <= rbStop && !(rballoc_mask[rbStart + rbSize] & slbitmap) && rbSize < retInfo->rbSize) + while (rbStart + rbSize <= rbStop && !(rballoc_mask[rbStart + rbSize] & slbitmap) && rbSize < new_sched.rbSize) rbSize++; + DevAssert(rbSize > 0); } } else { /* the retransmission will use a different time domain allocation, check @@ -502,42 +500,48 @@ static bool allocate_dl_retransmission(module_id_t module_id, while (rbStart < rbStop && (rballoc_mask[rbStart] & slbitmap)) rbStart++; + if (rbStart >= rbStop) { + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not allocate DL retransmission: no resources\n", UE->rnti, frame, slot); + return false; + } + while (rbStart + rbSize <= rbStop && !(rballoc_mask[rbStart + rbSize] & slbitmap)) rbSize++; + DevAssert(rbSize > 0); uint32_t new_tbs; uint16_t new_rbSize; - bool success = nr_find_nb_rb(retInfo->Qm, - retInfo->R, + bool success = nr_find_nb_rb(new_sched.Qm, + new_sched.R, 1, // no transform precoding for DL layers, temp_tda.nrOfSymbols, temp_dmrs.N_PRB_DMRS * temp_dmrs.N_DMRS_SLOT, - retInfo->tb_size, + new_sched.tb_size, 1, /* minimum of 1RB: need to find exact TBS, don't preclude any number */ rbSize, &new_tbs, &new_rbSize); - if (!success || new_tbs != retInfo->tb_size) { + if (!success || new_tbs != new_sched.tb_size) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] allocation of DL retransmission failed: new TBS %d of new TDA does not match old TBS %d\n", UE->rnti, frame, slot, new_tbs, - retInfo->tb_size); + new_sched.tb_size); return false; /* the maximum TBsize we might have is smaller than what we need */ } /* we can allocate it. Overwrite the time_domain_allocation, the number * of RBs, and the new TB size. The rest is done below */ - retInfo->tb_size = new_tbs; - retInfo->rbSize = new_rbSize; - retInfo->time_domain_allocation = tda; - retInfo->nrOfLayers = layers; - retInfo->pm_index = pm_index; - retInfo->dmrs_parms = temp_dmrs; - retInfo->tda_info = temp_tda; + new_sched.tb_size = new_tbs; + new_sched.rbSize = new_rbSize; + new_sched.time_domain_allocation = tda; + new_sched.nrOfLayers = layers; + new_sched.pm_index = pm_index; + new_sched.dmrs_parms = temp_dmrs; + new_sched.tda_info = temp_tda; } /* Find a free CCE */ @@ -572,24 +576,26 @@ static bool allocate_dl_retransmission(module_id_t module_id, sched_ctrl->cce_index = CCEIndex; fill_pdcch_vrb_map(nr_mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, beam_idx); - /* just reuse from previous scheduling opportunity, set new start RB */ - sched_ctrl->sched_pdsch = *retInfo; - sched_ctrl->sched_pdsch.rbStart = rbStart - bwp_info.bwpStart; - sched_ctrl->sched_pdsch.pucch_allocation = alloc; - sched_ctrl->sched_pdsch.bwp_info = bwp_info; - /* retransmissions: directly allocate */ - *n_rb_sched -= sched_ctrl->sched_pdsch.rbSize; - for (int rb = rbStart; rb < sched_ctrl->sched_pdsch.rbSize; rb++) - rballoc_mask[rb] |= SL_to_bitmap(retInfo->tda_info.startSymbolIndex, retInfo->tda_info.nrOfSymbols); + new_sched.rbStart = rbStart - bwp_info.bwpStart; + new_sched.pucch_allocation = alloc; + new_sched.bwp_info = bwp_info; + + post_process_dlsch(nr_mac, pp_pdsch, UE, &new_sched); + + /* retransmissions: directly allocate */ + *n_rb_sched -= new_sched.rbSize; + + for (int rb = rbStart; rb < new_sched.rbSize; rb++) + rballoc_mask[rb] |= SL_to_bitmap(new_sched.tda_info.startSymbolIndex, new_sched.tda_info.nrOfSymbols); return true; } -static uint32_t pf_tbs[3][29]; // pre-computed, approximate TBS values for PF coefficient typedef struct UEsched_s { float coef; NR_UE_info_t * UE; + int selected_mcs; } UEsched_t; static int comparator(const void *p, const void *q) @@ -603,15 +609,16 @@ static int comparator(const void *p, const void *q) return 0; } -static void pf_dl(module_id_t module_id, - frame_t frame, - slot_t slot, +static void pf_dl(gNB_MAC_INST *mac, + post_process_pdsch_t *pp_pdsch, NR_UE_info_t **UE_list, int max_num_ue, int num_beams, int n_rb_sched[num_beams]) { - gNB_MAC_INST *mac = RC.nrmac[module_id]; + frame_t frame = pp_pdsch->frame; + slot_t slot = pp_pdsch->slot; + NR_ServingCellConfigCommon_t *scc=mac->common_channels[0].ServingCellConfigCommon; // UEs that could be scheduled UEsched_t UE_sched[MAX_MOBILES_PER_GNB + 1] = {0}; @@ -630,16 +637,22 @@ static void pf_dl(module_id_t module_id, if (!nr_mac_ue_is_active(UE)) continue; - const NR_mac_dir_stats_t *stats = &UE->mac_stats.dl; - NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; + NR_mac_dir_stats_t *stats = &UE->mac_stats.dl; /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ - sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head; + int harq_pid = sched_ctrl->retrans_dl_harq.head; /* Calculate Throughput */ const float a = 0.01f; - const uint32_t b = UE->mac_stats.dl.current_bytes; + const uint32_t b = stats->current_bytes; UE->dl_thr_ue = (1 - a) * UE->dl_thr_ue + a * b; + stats->current_bytes = 0; + stats->current_rbs = 0; + + /* Check if this UE should get TA. If we add the CE, ta_apply will be reset */ + if (frame == sched_ctrl->ta_frame) + sched_ctrl->ta_apply = true; + int total_rem_ues = 0; for (int i = 0; i < num_beams; i++) total_rem_ues += remainUEs[i]; @@ -647,12 +660,12 @@ static void pf_dl(module_id_t module_id, continue; /* retransmission */ - if (sched_pdsch->dl_harq_pid >= 0) { + if (harq_pid >= 0) { NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame); bool sch_ret = beam.idx >= 0; /* Allocate retransmission */ if (sch_ret) - sch_ret = allocate_dl_retransmission(module_id, frame, slot, &n_rb_sched[beam.idx], UE, beam.idx, sched_pdsch->dl_harq_pid); + sch_ret = allocate_dl_retransmission(mac, pp_pdsch, &n_rb_sched[beam.idx], UE, beam.idx, harq_pid); if (!sch_ret) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] DL retransmission could not be allocated\n", UE->rnti, frame, slot); reset_beam_status(&mac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame, beam.new_beam); @@ -673,25 +686,26 @@ static void pf_dl(module_id_t module_id, continue; } + update_dlsch_buffer(pp_pdsch->frame, pp_pdsch->slot, UE); + /* Check DL buffer and skip this UE if no bytes and no TA necessary */ - if (sched_ctrl->num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 100) % 1024) + if (sched_ctrl->num_total_bytes == 0 && sched_ctrl->ta_apply == false) continue; /* Calculate coeff */ const NR_bler_options_t *bo = &mac->dl_bler; const int max_mcs_table = current_BWP->mcsTableIdx == 1 ? 27 : 28; const int max_mcs = min(sched_ctrl->dl_max_mcs, max_mcs_table); + int selected_mcs; if (bo->harq_round_max == 1) { int new_mcs = min(bo->max_mcs, max_mcs); - sched_pdsch->mcs = max(bo->min_mcs, new_mcs); - sched_ctrl->dl_bler_stats.mcs = sched_pdsch->mcs; + selected_mcs = max(bo->min_mcs, new_mcs); + sched_ctrl->dl_bler_stats.mcs = selected_mcs; } else - sched_pdsch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->dl_bler_stats, max_mcs, frame); - sched_pdsch->nrOfLayers = get_dl_nrOfLayers(sched_ctrl, current_BWP->dci_format); - sched_pdsch->pm_index = - get_pm_index(mac, UE, current_BWP->dci_format, sched_pdsch->nrOfLayers, mac->radio_config.pdsch_AntennaPorts.XP); - const uint8_t Qm = nr_get_Qm_dl(sched_pdsch->mcs, current_BWP->mcsTableIdx); - const uint16_t R = nr_get_code_rate_dl(sched_pdsch->mcs, current_BWP->mcsTableIdx); + selected_mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->dl_bler_stats, max_mcs, frame); + int l = get_dl_nrOfLayers(sched_ctrl, current_BWP->dci_format); + const uint8_t Qm = nr_get_Qm_dl(selected_mcs, current_BWP->mcsTableIdx); + const uint16_t R = nr_get_code_rate_dl(selected_mcs, current_BWP->mcsTableIdx); uint32_t tbs = nr_compute_tbs(Qm, R, 1, /* rbSize */ @@ -699,7 +713,7 @@ static void pf_dl(module_id_t module_id, 0, /* N_PRB_DMRS * N_DMRS_SLOT */ 0 /* N_PRB_oh, 0 for initialBWP */, 0 /* tb_scaling */, - sched_pdsch->nrOfLayers) >> 3; + l) >> 3; float coeff_ue = (float) tbs / UE->dl_thr_ue; LOG_D(NR_MAC, "[UE %04x][%4d.%2d] b %d, thr_ue %f, tbs %d, coeff_ue %f\n", UE->rnti, @@ -712,6 +726,7 @@ static void pf_dl(module_id_t module_id, /* Create UE_sched list for UEs eligible for new transmission*/ UE_sched[numUE].coef = coeff_ue; UE_sched[numUE].UE = UE; + UE_sched[numUE].selected_mcs = selected_mcs; numUE++; } } @@ -719,7 +734,7 @@ static void pf_dl(module_id_t module_id, qsort(UE_sched, numUE, sizeof(UEsched_t), comparator); UEsched_t *iterator = UE_sched; - const int min_rbSize = 10; + const int min_rbSize = 5; /* Loop UE_sched to find max coeff and allocate transmission */ while (iterator->UE != NULL) { @@ -752,41 +767,36 @@ static void pf_dl(module_id_t module_id, continue; } - NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; - sched_pdsch->dl_harq_pid = sched_ctrl->available_dl_harq.head; - /* MCS has been set above */ - sched_pdsch->time_domain_allocation = get_dl_tda(mac, slot); - AssertFatal(sched_pdsch->time_domain_allocation>=0,"Unable to find PDSCH time domain allocation in list\n"); + int tda = get_dl_tda(mac, slot); + AssertFatal(tda >= 0,"Unable to find PDSCH time domain allocation in list\n"); const int coresetid = sched_ctrl->coreset->controlResourceSetId; - sched_pdsch->tda_info = get_dl_tda_info(dl_bwp, + NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp, sched_ctrl->search_space->searchSpaceType->present, - sched_pdsch->time_domain_allocation, + tda, scc->dmrs_TypeA_Position, 1, TYPE_C_RNTI_, coresetid, false); - AssertFatal(sched_pdsch->tda_info.valid_tda, "Invalid TDA from get_dl_tda_info\n"); + AssertFatal(tda_info.valid_tda, "Invalid TDA from get_dl_tda_info\n"); - NR_tda_info_t *tda_info = &sched_pdsch->tda_info; - - const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); + const uint16_t slbitmap = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); uint16_t *rballoc_mask = mac->common_channels[CC_id].vrb_map[beam.idx]; - sched_pdsch->bwp_info = get_pdsch_bwp_start_size(mac, iterator->UE); + bwp_info_t bwp_info = get_pdsch_bwp_start_size(mac, iterator->UE); int rbStart = 0; // WRT BWP start - int rbStop = sched_pdsch->bwp_info.bwpSize - 1; - int bwp_start = sched_pdsch->bwp_info.bwpStart; + int rbStop = bwp_info.bwpSize - 1; + int bwp_start = bwp_info.bwpStart; // Freq-demain allocation while (rbStart < rbStop && (rballoc_mask[rbStart + bwp_start] & slbitmap)) rbStart++; - uint16_t max_rbSize = 1; // used to be 1 - - while (rbStart + max_rbSize <= rbStop && !(rballoc_mask[rbStart + max_rbSize + bwp_start] & slbitmap)) - max_rbSize++; + uint16_t max_rbSize = 5; + + /* while (rbStart + max_rbSize <= rbStop && !(rballoc_mask[rbStart + max_rbSize + bwp_start] & slbitmap)) */ + /* max_rbSize++; */ if (max_rbSize < min_rbSize) { LOG_D(NR_MAC, @@ -824,7 +834,7 @@ static void pf_dl(module_id_t module_id, * allocation after CCE alloc fail would be more complex) */ int alloc = -1; - if (!get_FeedbackDisabled(iterator->UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) { + if (!get_FeedbackDisabled(iterator->UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_ctrl->available_dl_harq.head)) { int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, ul_bwp->pucch_Config, CCEIndex); alloc = nr_acknack_scheduling(mac, iterator->UE, frame, slot, iterator->UE->UE_beam_index, r_pucch, 0); if (alloc < 0) { @@ -838,46 +848,57 @@ static void pf_dl(module_id_t module_id, sched_ctrl->cce_index = CCEIndex; fill_pdcch_vrb_map(mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, beam.idx); - sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, tda_info, sched_pdsch->nrOfLayers); - sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx); - sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx); - sched_pdsch->pucch_allocation = alloc; - uint32_t TBS = 0; - uint16_t rbSize; + int l = get_dl_nrOfLayers(sched_ctrl, dl_bwp->dci_format); + NR_sched_pdsch_t sched_pdsch = { + // rbSize below + .rbStart = rbStart, + .mcs = iterator->selected_mcs, + .R = nr_get_code_rate_dl(iterator->selected_mcs, dl_bwp->mcsTableIdx), + .Qm = nr_get_Qm_dl(iterator->selected_mcs, dl_bwp->mcsTableIdx), + // tb_size below + .dl_harq_pid = sched_ctrl->available_dl_harq.head, + .pucch_allocation = alloc, + .pm_index = get_pm_index(mac, iterator->UE, dl_bwp->dci_format, l, mac->radio_config.pdsch_AntennaPorts.XP), + .nrOfLayers = l, + .bwp_info = bwp_info, + .dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, &tda_info, l), + .time_domain_allocation = tda, + .tda_info = tda_info, + }; + // Fix me: currently, the RLC does not give us the total number of PDUs // awaiting. Therefore, for the time being, we put a fixed overhead of 12 // (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of // PDUs, we replace with 3 * numPDUs - const int oh = 3 * 4 + 2 * (frame == (sched_ctrl->ta_frame + 100) % 1024); - //const int oh = 3 * sched_ctrl->dl_pdus_total + 2 * (frame == (sched_ctrl->ta_frame + 100) % 1024); - nr_find_nb_rb(sched_pdsch->Qm, - sched_pdsch->R, + const int oh = 3 * 4 + (sched_ctrl->ta_apply ? 2 : 0); + //const int oh = 3 * sched_ctrl->dl_pdus_total + (sched_ctrl->ta_apply ? 2 : 0); + nr_find_nb_rb(sched_pdsch.Qm, + sched_pdsch.R, 1, // no transform precoding for DL - sched_pdsch->nrOfLayers, - tda_info->nrOfSymbols, - sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT, + sched_pdsch.nrOfLayers, + tda_info.nrOfSymbols, + sched_pdsch.dmrs_parms.N_PRB_DMRS * sched_pdsch.dmrs_parms.N_DMRS_SLOT, sched_ctrl->num_total_bytes + oh, min_rbSize, max_rbSize, - &TBS, - &rbSize); - sched_pdsch->rbSize = rbSize; - sched_pdsch->rbStart = rbStart; - sched_pdsch->tb_size = TBS; - /* transmissions: directly allocate */ - n_rb_sched[beam.idx] -= sched_pdsch->rbSize; + &sched_pdsch.tb_size, + &sched_pdsch.rbSize); - for (int rb = bwp_start; rb < sched_pdsch->rbSize; rb++) - rballoc_mask[rb + sched_pdsch->rbStart] |= slbitmap; + post_process_dlsch(mac, pp_pdsch, iterator->UE, &sched_pdsch); + + /* transmissions: directly allocate */ + n_rb_sched[beam.idx] -= sched_pdsch.rbSize; + + for (int rb = bwp_start; rb < sched_pdsch.rbSize; rb++) + rballoc_mask[rb + sched_pdsch.rbStart] |= slbitmap; remainUEs[beam.idx]--; iterator++; } } -static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) +static void nr_dlsch_preprocessor(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) { - gNB_MAC_INST *mac = RC.nrmac[module_id]; NR_UEs_t *UE_info = &mac->UE_info; if (UE_info->connected_ue_list[0] == NULL) @@ -890,9 +911,6 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s for (int i = 0; i < num_beams; i++) n_rb_sched[i] = bw; - /* Retrieve amount of data to send for this UE */ - nr_store_dlsch_buffer(module_id, frame, slot); - int average_agg_level = 4; // TODO find a better estimation int max_sched_ues = bw / (average_agg_level * NR_NB_REG_PER_CCE); @@ -900,35 +918,11 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET); /* proportional fair scheduling algorithm */ - pf_dl(module_id, frame, slot, UE_info->connected_ue_list, max_sched_ues, num_beams, n_rb_sched); + pf_dl(mac, pp_pdsch, UE_info->connected_ue_list, max_sched_ues, num_beams, n_rb_sched); } -nr_pp_impl_dl nr_init_dlsch_preprocessor(int CC_id) { - /* during initialization: no mutex needed */ - /* in the PF algorithm, we have to use the TBsize to compute the coefficient. - * This would include the number of DMRS symbols, which in turn depends on - * the time domain allocation. In case we are in a mixed slot, we do not want - * to recalculate all these values just, and therefore we provide a look-up - * table which should approximately give us the TBsize */ - for (int mcsTableIdx = 0; mcsTableIdx < 3; ++mcsTableIdx) { - for (int mcs = 0; mcs < 29; ++mcs) { - if (mcs > 27 && mcsTableIdx == 1) - continue; - - const uint8_t Qm = nr_get_Qm_dl(mcs, mcsTableIdx); - const uint16_t R = nr_get_code_rate_dl(mcs, mcsTableIdx); - pf_tbs[mcsTableIdx][mcs] = nr_compute_tbs(Qm, - R, - 1, /* rbSize */ - 10, /* hypothetical number of slots */ - 0, /* N_PRB_DMRS * N_DMRS_SLOT */ - 0 /* N_PRB_oh, 0 for initialBWP */, - 0 /* tb_scaling */, - 1 /* nrOfLayers */ - ) >> 3; - } - } - +nr_pp_impl_dl nr_init_dlsch_preprocessor(int CC_id) +{ return nr_dlsch_preprocessor; } @@ -1010,6 +1004,377 @@ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu return pdsch_pdu; } +void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE_info_t *UE, NR_sched_pdsch_t *sched_pdsch) +{ + int CC_id = 0; + int module_id = nr_mac->Mod_id; + frame_t frame = pdsch->frame; + slot_t slot = pdsch->slot; + + const NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[CC_id].ServingCellConfigCommon; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP; + + const rnti_t rnti = UE->rnti; + + /* POST processing */ + const uint8_t nrOfLayers = sched_pdsch->nrOfLayers; + const uint32_t TBS = sched_pdsch->tb_size; + int8_t current_harq_pid = sched_pdsch->dl_harq_pid; + + if (current_harq_pid < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + current_harq_pid = sched_ctrl->available_dl_harq.head; + AssertFatal(current_harq_pid >= 0, + "no free HARQ process available for UE %04x\n", + UE->rnti); + remove_front_nr_list(&sched_ctrl->available_dl_harq); + sched_pdsch->dl_harq_pid = current_harq_pid; + } else { + /* PP selected a specific HARQ process. Check whether it will be a new + * transmission or a retransmission, and remove from the corresponding + * list */ + if (sched_ctrl->harq_processes[current_harq_pid].round == 0) + remove_nr_list(&sched_ctrl->available_dl_harq, current_harq_pid); + else + remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); + } + + NR_tda_info_t *tda_info = &sched_pdsch->tda_info; + NR_pdsch_dmrs_t *dmrs_parms = &sched_pdsch->dmrs_parms; + NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; + NR_sched_pucch_t *pucch = NULL; + DevAssert(!harq->is_waiting); + if (sched_pdsch->pucch_allocation < 0) { + finish_nr_dl_harq(sched_ctrl, current_harq_pid); + } else { + pucch = &sched_ctrl->sched_pucch[sched_pdsch->pucch_allocation]; + add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); + harq->feedback_frame = pucch->frame; + harq->feedback_slot = pucch->ul_slot; + harq->is_waiting = true; + } + UE->mac_stats.dl.rounds[harq->round]++; + LOG_D(NR_MAC, + "%4d.%2d [DLSCH/PDSCH/PUCCH] RNTI %04x DCI L %d start %3d RBs %3d startSymbol %2d nb_symbol %2d dmrspos %x MCS %2d nrOfLayers %d TBS %4d HARQ PID %2d round %d RV %d NDI %d dl_data_to_ULACK %d (%d.%d) PUCCH allocation %d TPC %d\n", + frame, + slot, + rnti, + sched_ctrl->aggregation_level, + sched_pdsch->rbStart, + sched_pdsch->rbSize, + tda_info->startSymbolIndex, + tda_info->nrOfSymbols, + dmrs_parms->dl_dmrs_symb_pos, + sched_pdsch->mcs, + nrOfLayers, + TBS, + current_harq_pid, + harq->round, + nr_get_rv(harq->round % 4), + harq->ndi, + pucch ? pucch->timing_indicator : 0, + pucch ? pucch->frame : 0, + pucch ? pucch->ul_slot : 0, + sched_pdsch->pucch_allocation, + sched_ctrl->tpc1); + DevAssert(sched_pdsch->rbSize > 0); + + const int bwp_id = current_BWP->bwp_id; + const int coresetid = sched_ctrl->coreset->controlResourceSetId; + + /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it */ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = nr_mac->pdcch_pdu_idx[CC_id][coresetid]; + + if (!pdcch_pdu) { + LOG_D(NR_MAC, "creating pdcch pdu, pdcch_pdu = NULL. \n"); + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &pdsch->dl_req->dl_tti_pdu_list[pdsch->dl_req->nPDUs]; + memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + pdsch->dl_req->nPDUs += 1; + pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + LOG_D(NR_MAC,"Trying to configure DL pdcch for UE %04x, bwp %d, cs %d\n", UE->rnti, bwp_id, coresetid); + NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; + nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch); + nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu; + } + + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &pdsch->dl_req->dl_tti_pdu_list[pdsch->dl_req->nPDUs]; + memset(dl_tti_pdsch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; + dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + pdsch->dl_req->nPDUs += 1; + + /* SCF222: PDU index incremented for each PDSCH PDU sent in TX control + * message. This is used to associate control information to data and is + * reset every slot. */ + const int pduindex = nr_mac->pdu_index[CC_id]++; + // TODO: verify the case where maxMIMO_Layers is NULL, in which case + // in principle maxMIMO_layers should be given by the maximum number of layers + // for PDSCH supported by the UE for the serving cell (5.4.2.1 of 38.212) + long ue_supp_nl = ue_supported_dl_layers(scc, UE->capability); + long maxMIMO_Layers = UE->sc_info.maxMIMO_Layers_PDSCH ? *UE->sc_info.maxMIMO_Layers_PDSCH : ue_supp_nl; + if (maxMIMO_Layers < 1) { + LOG_D(NR_MAC, "Both maxMIMO_Layers_PDSCH and UE supported layers are not present, defaulting to 1\n"); + maxMIMO_Layers = 1; + } + const int nl_tbslbrm = min(maxMIMO_Layers, 4); + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = prepare_pdsch_pdu(dl_tti_pdsch_pdu, + nr_mac, + UE, + sched_pdsch, + current_BWP->pdsch_Config, + false, + harq->round, + rnti, + UE->UE_beam_index, + nl_tbslbrm, + pduindex); + + + LOG_D(NR_MAC,"Configuring DCI/PDCCH in %d.%d at CCE %d, rnti %x\n", frame,slot,sched_ctrl->cce_index,rnti); + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu, + scc, + sched_ctrl->search_space, + sched_ctrl->coreset, + sched_ctrl->aggregation_level, + sched_ctrl->cce_index, + UE->UE_beam_index, + rnti); + pdcch_pdu->numDlDci++; + + /* DCI payload */ + const int rnti_type = TYPE_C_RNTI_; + dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(nr_mac, + UE, + rnti_type, + sched_ctrl->search_space->searchSpaceType->present, + pdsch_pdu, + sched_pdsch, + pucch, + current_harq_pid, + 0, + false); + + // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR + sched_ctrl->tpc1 = 1; + NR_PDSCH_Config_t *pdsch_Config = current_BWP->pdsch_Config; + AssertFatal(pdsch_Config == NULL + || pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1, + "Only frequency resource allocation type 1 is currently supported\n"); + + LOG_D(NR_MAC, + "%4d.%2d DCI type 1 payload: freq_alloc %d (%d,%d,%d), " + "nrOfLayers %d, time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d tpc %d ti %d\n", + frame, + slot, + dci_payload.frequency_domain_assignment.val, + pdsch_pdu->rbStart, + pdsch_pdu->rbSize, + pdsch_pdu->BWPSize, + pdsch_pdu->nrOfLayers, + dci_payload.time_domain_assignment.val, + dci_payload.vrb_to_prb_mapping.val, + dci_payload.mcs, + dci_payload.tb_scaling, + dci_payload.ndi, + dci_payload.rv, + dci_payload.tpc, + pucch ? pucch->timing_indicator : 0); + + fill_dci_pdu_rel15(&UE->sc_info, + current_BWP, + &UE->current_UL_BWP, + dci_pdu, + &dci_payload, + current_BWP->dci_format, + rnti_type, + bwp_id, + sched_ctrl->search_space, + sched_ctrl->coreset, + UE->pdsch_HARQ_ACK_Codebook, + nr_mac->cset0_bwp_size); + + LOG_D(NR_MAC, + "coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", + (unsigned long long)pdcch_pdu->FreqDomainResource, + pdcch_pdu->StartSymbolIndex, + pdcch_pdu->DurationSymbols); + + if (harq->round != 0) { /* retransmission */ + /* we do not have to do anything, since we do not require to get data + * from RLC or encode MAC CEs. The TX_req structure is filled below + * or copy data to FAPI structures */ + LOG_D(NR_MAC, + "%d.%2d DL retransmission RNTI %04x HARQ PID %d round %d NDI %d\n", + frame, + slot, + rnti, + current_harq_pid, + harq->round, + harq->ndi); + if (!get_softmodem_params()->phy_test) + AssertFatal(harq->sched_pdsch.tb_size == TBS, + "UE %04x mismatch between scheduled TBS and buffered TB for HARQ PID %d\n", + UE->rnti, + current_harq_pid); + else if (harq->sched_pdsch.tb_size != TBS) + LOG_E(NR_MAC, + "Mismatch between scheduled TBS and buffered TB for HARQ PID %d. No RTX control in phy-test mode. " + "Possible causes: presence of CSI-RS or DLSCH scheduled in the mixed slot.\n", + current_harq_pid); + T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), + T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock.buf, TBS)); + UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize; + nr_mac->mac_stats.dl.used_prb_aggregate += sched_pdsch->rbSize; + } else { /* initial transmission */ + LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot); + uint8_t *buf = allocate_transportBlock_buffer(&harq->transportBlock, TBS); + /* first, write all CEs that might be there */ + int written = nr_write_ce_dlsch_pdu(module_id, + sched_ctrl, + (unsigned char *)buf, + 255, // no drx + NULL); // contention res id + buf += written; + uint8_t *bufEnd = buf + TBS - written; + DevAssert(TBS > written); + int dlsch_total_bytes = 0; + /* next, get RLC data */ + start_meas(&nr_mac->rlc_data_req); + int sdus = 0; + + if (sched_ctrl->num_total_bytes > 0) { + /* loop over all activated logical channels */ + for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); ++i) { + const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); + const int lcid = c->lcid; + + if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) + continue; // no data for this LC tbs_size_t len = 0; + + int lcid_bytes=0; + while (bufEnd-buf > sizeof(NR_MAC_SUBHEADER_LONG) + 1 ) { + // we do not know how much data we will get from RLC, i.e., whether it + // will be longer than 256B or not. Therefore, reserve space for long header, then + // fetch data, then fill real length + NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; + /* limit requested number of bytes to what preprocessor specified, or + * such that TBS is full */ + const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, + bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); + tbs_size_t len = nr_mac_rlc_data_req(module_id, + rnti, + true, + lcid, + ndata, + (char *)buf+sizeof(NR_MAC_SUBHEADER_LONG)); + LOG_D(NR_MAC, + "%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %ld)\n", + frame, + slot, + rnti, + len, + lcid < 4 ? "DCCH" : "DTCH", + lcid, + ndata, + bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); + + if (len == 0) + break; + + T(T_GNB_MAC_LCID_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(lcid), T_INT(len * 8), T_INT(nr_rlc_tx_list_occupancy(rnti, lcid))); + header->R = 0; + header->F = 1; + header->LCID = lcid; + header->L = htons(len); + buf += len+sizeof(NR_MAC_SUBHEADER_LONG); + dlsch_total_bytes += len; + lcid_bytes += len; + sdus += 1; + } + + UE->mac_stats.dl.lc_bytes[lcid] += lcid_bytes; + } + } else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) { + /* we will need the large header, phy-test typically allocates all + * resources and fills to the last byte below */ + LOG_D(NR_MAC, "Configuring DL_TX in %d.%d: TBS %d of random data\n", frame, slot, TBS); + + if (bufEnd-buf > sizeof(NR_MAC_SUBHEADER_LONG) ) { + NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; + // fill dlsch_buffer with random data + header->R = 0; + header->F = 1; + header->LCID = DL_SCH_LCID_PADDING; + buf += sizeof(NR_MAC_SUBHEADER_LONG); + header->L = htons(bufEnd-buf); + + for (; ((intptr_t)buf) % 4; buf++) + *buf = lrand48() & 0xff; + for (; buf < bufEnd - 3; buf += 4) { + uint32_t *buf32 = (uint32_t *)buf; + *buf32 = lrand48(); + } + for (; buf < bufEnd; buf++) + *buf = lrand48() & 0xff; + sdus +=1; + } + } + + stop_meas(&nr_mac->rlc_data_req); + + // Add padding header and zero rest out if there is space left + if (bufEnd-buf > 0) { + NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) buf; + padding->R = 0; + padding->LCID = DL_SCH_LCID_PADDING; + buf += 1; + memset(buf,0,bufEnd-buf); + buf=bufEnd; + } + + UE->mac_stats.dl.total_bytes += TBS; + UE->mac_stats.dl.current_bytes = TBS; + UE->mac_stats.dl.total_rbs += sched_pdsch->rbSize; + UE->mac_stats.dl.num_mac_sdu += sdus; + UE->mac_stats.dl.current_rbs = sched_pdsch->rbSize; + UE->mac_stats.dl.total_sdu_bytes += dlsch_total_bytes; + nr_mac->mac_stats.dl.used_prb_aggregate += sched_pdsch->rbSize; + + /* save retransmission information */ + harq->sched_pdsch = *sched_pdsch; + /* save which time allocation has been used, to be used on + * retransmissions */ + harq->sched_pdsch.time_domain_allocation = sched_pdsch->time_domain_allocation; + + // ta command is sent, values are reset + if (sched_ctrl->ta_apply) { + sched_ctrl->ta_apply = false; + sched_ctrl->ta_update = 31; + sched_ctrl->ta_frame = (frame + 100) % MAX_FRAME_NUMBER; + LOG_D(NR_MAC, "%d.%2d UE %04x TA scheduled, setting next TA frame to %d\n", frame, slot, UE->rnti, sched_ctrl->ta_frame); + } + + T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), + T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock.buf, TBS)); + T(T_GNB_MAC_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(sched_pdsch->mcs), T_INT(TBS)); + } + + const int ntx_req = pdsch->TX_req->Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &pdsch->TX_req->pdu_list[ntx_req]; + tx_req->PDU_index = pduindex; + tx_req->num_TLV = 1; + tx_req->TLVs[0].length = TBS; + tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length); + memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock.buf, TBS); + pdsch->TX_req->Number_of_PDUs++; + pdsch->TX_req->SFN = frame; + pdsch->TX_req->Slot = slot; +} + void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, slot_t slot, @@ -1017,6 +1382,8 @@ void nr_schedule_ue_spec(module_id_t module_id, nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; + int CC_id = 0; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ AssertFatal(pthread_mutex_trylock(&gNB_mac->sched_lock) == EBUSY, "this function should be called with the scheduler mutex locked\n"); @@ -1024,391 +1391,13 @@ void nr_schedule_ue_spec(module_id_t module_id, if (!is_dl_slot(slot, &gNB_mac->frame_structure)) return; - /* PREPROCESSOR */ - gNB_mac->pre_processor_dl(module_id, frame, slot); - const int CC_id = 0; NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; - NR_UEs_t *UE_info = &gNB_mac->UE_info; + int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + gNB_mac->mac_stats.dl.total_prb_aggregate += bw; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; + post_process_pdsch_t pdsch = { frame, slot, dl_req, TX_req }; - const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; - gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE); - - UE_iterator(UE_info->connected_ue_list, UE) { - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP; - - if (!nr_mac_ue_is_active(UE) && !get_softmodem_params()->phy_test) - continue; - - NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; - UE->mac_stats.dl.current_bytes = 0; - UE->mac_stats.dl.current_rbs = 0; - - /* update TA and set ta_apply every 100 frames. - * Possible improvement: take the periodicity from input file. - * If such UE is not scheduled now, it will be by the preprocessor later. - * If we add the CE, ta_apply will be reset */ - if (frame == ((sched_ctrl->ta_frame + 100) % 1024) && !nr_timer_is_active(&sched_ctrl->transm_interrupt)) { - sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */ - LOG_D(NR_MAC, "[UE %04x][%d.%d] UL timing alignment procedures: setting flag for Timing Advance command\n", UE->rnti, frame, slot); - } - - if (sched_pdsch->rbSize <= 0) - continue; - - const rnti_t rnti = UE->rnti; - - /* POST processing */ - const uint8_t nrOfLayers = sched_pdsch->nrOfLayers; - const uint32_t TBS = sched_pdsch->tb_size; - int8_t current_harq_pid = sched_pdsch->dl_harq_pid; - - if (current_harq_pid < 0) { - /* PP has not selected a specific HARQ Process, get a new one */ - current_harq_pid = sched_ctrl->available_dl_harq.head; - AssertFatal(current_harq_pid >= 0, - "no free HARQ process available for UE %04x\n", - UE->rnti); - remove_front_nr_list(&sched_ctrl->available_dl_harq); - sched_pdsch->dl_harq_pid = current_harq_pid; - } else { - /* PP selected a specific HARQ process. Check whether it will be a new - * transmission or a retransmission, and remove from the corresponding - * list */ - if (sched_ctrl->harq_processes[current_harq_pid].round == 0) - remove_nr_list(&sched_ctrl->available_dl_harq, current_harq_pid); - else - remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); - } - - NR_tda_info_t *tda_info = &sched_pdsch->tda_info; - NR_pdsch_dmrs_t *dmrs_parms = &sched_pdsch->dmrs_parms; - NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; - NR_sched_pucch_t *pucch = NULL; - DevAssert(!harq->is_waiting); - if (sched_pdsch->pucch_allocation < 0) { - finish_nr_dl_harq(sched_ctrl, current_harq_pid); - } else { - pucch = &sched_ctrl->sched_pucch[sched_pdsch->pucch_allocation]; - add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); - harq->feedback_frame = pucch->frame; - harq->feedback_slot = pucch->ul_slot; - harq->is_waiting = true; - } - UE->mac_stats.dl.rounds[harq->round]++; - LOG_D(NR_MAC, - "%4d.%2d [DLSCH/PDSCH/PUCCH] RNTI %04x DCI L %d start %3d RBs %3d startSymbol %2d nb_symbol %2d dmrspos %x MCS %2d nrOfLayers %d TBS %4d HARQ PID %2d round %d RV %d NDI %d dl_data_to_ULACK %d (%d.%d) PUCCH allocation %d TPC %d\n", - frame, - slot, - rnti, - sched_ctrl->aggregation_level, - sched_pdsch->rbStart, - sched_pdsch->rbSize, - tda_info->startSymbolIndex, - tda_info->nrOfSymbols, - dmrs_parms->dl_dmrs_symb_pos, - sched_pdsch->mcs, - nrOfLayers, - TBS, - current_harq_pid, - harq->round, - nr_get_rv(harq->round % 4), - harq->ndi, - pucch ? pucch->timing_indicator : 0, - pucch ? pucch->frame : 0, - pucch ? pucch->ul_slot : 0, - sched_pdsch->pucch_allocation, - sched_ctrl->tpc1); - - const int bwp_id = current_BWP->bwp_id; - const int coresetid = sched_ctrl->coreset->controlResourceSetId; - - /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it */ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][coresetid]; - - if (!pdcch_pdu) { - LOG_D(NR_MAC, "creating pdcch pdu, pdcch_pdu = NULL. \n"); - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; - memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - dl_req->nPDUs += 1; - pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - LOG_D(NR_MAC,"Trying to configure DL pdcch for UE %04x, bwp %d, cs %d\n", UE->rnti, bwp_id, coresetid); - NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; - nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch); - gNB_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu; - } - - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; - memset(dl_tti_pdsch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; - dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdsch_pdu)); - dl_req->nPDUs += 1; - /* SCF222: PDU index incremented for each PDSCH PDU sent in TX control - * message. This is used to associate control information to data and is - * reset every slot. */ - const int pduindex = gNB_mac->pdu_index[CC_id]++; - // TODO: verify the case where maxMIMO_Layers is NULL, in which case - // in principle maxMIMO_layers should be given by the maximum number of layers - // for PDSCH supported by the UE for the serving cell (5.4.2.1 of 38.212) - long maxMIMO_Layers = UE->sc_info.maxMIMO_Layers_PDSCH ? *UE->sc_info.maxMIMO_Layers_PDSCH : 1; - const int nl_tbslbrm = min(maxMIMO_Layers, 4); - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = prepare_pdsch_pdu(dl_tti_pdsch_pdu, - gNB_mac, - UE, - sched_pdsch, - current_BWP->pdsch_Config, - false, - harq->round, - rnti, - UE->UE_beam_index, - nl_tbslbrm, - pduindex); - - - LOG_D(NR_MAC,"Configuring DCI/PDCCH in %d.%d at CCE %d, rnti %x\n", frame,slot,sched_ctrl->cce_index,rnti); - /* Fill PDCCH DL DCI PDU */ - nfapi_nr_dl_dci_pdu_t *dci_pdu = prepare_dci_pdu(pdcch_pdu, - scc, - sched_ctrl->search_space, - sched_ctrl->coreset, - sched_ctrl->aggregation_level, - sched_ctrl->cce_index, - UE->UE_beam_index, - rnti); - pdcch_pdu->numDlDci++; - - /* DCI payload */ - const int rnti_type = TYPE_C_RNTI_; - dci_pdu_rel15_t dci_payload = prepare_dci_dl_payload(gNB_mac, - UE, - rnti_type, - sched_ctrl->search_space->searchSpaceType->present, - pdsch_pdu, - sched_pdsch, - pucch, - current_harq_pid, - 0, - false); - - // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR - sched_ctrl->tpc1 = 1; - NR_PDSCH_Config_t *pdsch_Config = current_BWP->pdsch_Config; - AssertFatal(pdsch_Config == NULL - || pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1, - "Only frequency resource allocation type 1 is currently supported\n"); - - LOG_D(NR_MAC, - "%4d.%2d DCI type 1 payload: freq_alloc %d (%d,%d,%d), " - "nrOfLayers %d, time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d tpc %d ti %d\n", - frame, - slot, - dci_payload.frequency_domain_assignment.val, - pdsch_pdu->rbStart, - pdsch_pdu->rbSize, - pdsch_pdu->BWPSize, - pdsch_pdu->nrOfLayers, - dci_payload.time_domain_assignment.val, - dci_payload.vrb_to_prb_mapping.val, - dci_payload.mcs, - dci_payload.tb_scaling, - dci_payload.ndi, - dci_payload.rv, - dci_payload.tpc, - pucch ? pucch->timing_indicator : 0); - - fill_dci_pdu_rel15(&UE->sc_info, - current_BWP, - &UE->current_UL_BWP, - dci_pdu, - &dci_payload, - current_BWP->dci_format, - rnti_type, - bwp_id, - sched_ctrl->search_space, - sched_ctrl->coreset, - UE->pdsch_HARQ_ACK_Codebook, - gNB_mac->cset0_bwp_size); - - LOG_D(NR_MAC, - "coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", - (unsigned long long)pdcch_pdu->FreqDomainResource, - pdcch_pdu->StartSymbolIndex, - pdcch_pdu->DurationSymbols); - - if (harq->round != 0) { /* retransmission */ - /* we do not have to do anything, since we do not require to get data - * from RLC or encode MAC CEs. The TX_req structure is filled below - * or copy data to FAPI structures */ - LOG_D(NR_MAC, - "%d.%2d DL retransmission RNTI %04x HARQ PID %d round %d NDI %d\n", - frame, - slot, - rnti, - current_harq_pid, - harq->round, - harq->ndi); - if (!get_softmodem_params()->phy_test) - AssertFatal(harq->sched_pdsch.tb_size == TBS, - "UE %04x mismatch between scheduled TBS and buffered TB for HARQ PID %d\n", - UE->rnti, - current_harq_pid); - else if (harq->sched_pdsch.tb_size != TBS) - LOG_E(NR_MAC, - "Mismatch between scheduled TBS and buffered TB for HARQ PID %d. No RTX control in phy-test mode. " - "Possible causes: presence of CSI-RS or DLSCH scheduled in the mixed slot.\n", - current_harq_pid); - T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), - T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock.buf, TBS)); - UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize; - gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize; - } else { /* initial transmission */ - LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot); - uint8_t *buf = allocate_transportBlock_buffer(&harq->transportBlock, TBS); - /* first, write all CEs that might be there */ - int written = nr_write_ce_dlsch_pdu(module_id, - sched_ctrl, - (unsigned char *)buf, - 255, // no drx - NULL); // contention res id - buf += written; - uint8_t *bufEnd = buf + TBS - written; - DevAssert(TBS > written); - int dlsch_total_bytes = 0; - /* next, get RLC data */ - start_meas(&gNB_mac->rlc_data_req); - int sdus = 0; - - if (sched_ctrl->num_total_bytes > 0) { - /* loop over all activated logical channels */ - for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); ++i) { - const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); - const int lcid = c->lcid; - - if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) - continue; // no data for this LC tbs_size_t len = 0; - - int lcid_bytes=0; - while (bufEnd-buf > sizeof(NR_MAC_SUBHEADER_LONG) + 1 ) { - // we do not know how much data we will get from RLC, i.e., whether it - // will be longer than 256B or not. Therefore, reserve space for long header, then - // fetch data, then fill real length - NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; - /* limit requested number of bytes to what preprocessor specified, or - * such that TBS is full */ - const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, - bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); - tbs_size_t len = nr_mac_rlc_data_req(module_id, - rnti, - true, - lcid, - ndata, - (char *)buf+sizeof(NR_MAC_SUBHEADER_LONG)); - LOG_D(NR_MAC, - "%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %ld)\n", - frame, - slot, - rnti, - len, - lcid < 4 ? "DCCH" : "DTCH", - lcid, - ndata, - bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); - - if (len == 0) - break; - - T(T_GNB_MAC_LCID_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(lcid), T_INT(len * 8), T_INT(nr_rlc_tx_list_occupancy(rnti, lcid))); - header->R = 0; - header->F = 1; - header->LCID = lcid; - header->L = htons(len); - buf += len+sizeof(NR_MAC_SUBHEADER_LONG); - dlsch_total_bytes += len; - lcid_bytes += len; - sdus += 1; - } - - UE->mac_stats.dl.lc_bytes[lcid] += lcid_bytes; - } - } else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) { - /* we will need the large header, phy-test typically allocates all - * resources and fills to the last byte below */ - LOG_D(NR_MAC, "Configuring DL_TX in %d.%d: TBS %d of random data\n", frame, slot, TBS); - - if (bufEnd-buf > sizeof(NR_MAC_SUBHEADER_LONG) ) { - NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; - // fill dlsch_buffer with random data - header->R = 0; - header->F = 1; - header->LCID = DL_SCH_LCID_PADDING; - buf += sizeof(NR_MAC_SUBHEADER_LONG); - header->L = htons(bufEnd-buf); - - for (; ((intptr_t)buf) % 4; buf++) - *buf = lrand48() & 0xff; - for (; buf < bufEnd - 3; buf += 4) { - uint32_t *buf32 = (uint32_t *)buf; - *buf32 = lrand48(); - } - for (; buf < bufEnd; buf++) - *buf = lrand48() & 0xff; - sdus +=1; - } - } - - stop_meas(&gNB_mac->rlc_data_req); - - // Add padding header and zero rest out if there is space left - if (bufEnd-buf > 0) { - NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) buf; - padding->R = 0; - padding->LCID = DL_SCH_LCID_PADDING; - buf += 1; - memset(buf,0,bufEnd-buf); - buf=bufEnd; - } - - // mac_stats - UE->mac_stats.dl.total_bytes += TBS; - UE->mac_stats.dl.current_bytes = TBS; - UE->mac_stats.dl.total_rbs += sched_pdsch->rbSize; - UE->mac_stats.dl.num_mac_sdu += sdus; - UE->mac_stats.dl.current_rbs = sched_pdsch->rbSize; - UE->mac_stats.dl.total_sdu_bytes += dlsch_total_bytes; - gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize; - - /* save retransmission information */ - harq->sched_pdsch = *sched_pdsch; - /* save which time allocation has been used, to be used on - * retransmissions */ - harq->sched_pdsch.time_domain_allocation = sched_pdsch->time_domain_allocation; - - // ta command is sent, values are reset - if (sched_ctrl->ta_apply) { - sched_ctrl->ta_apply = false; - sched_ctrl->ta_frame = frame; - LOG_D(NR_MAC, "%d.%2d UE %04x TA scheduled, resetting TA frame\n", frame, slot, UE->rnti); - } - - T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), - T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock.buf, TBS)); - T(T_GNB_MAC_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(sched_pdsch->mcs), T_INT(TBS)); - } - - const int ntx_req = TX_req->Number_of_PDUs; - nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; - tx_req->PDU_index = pduindex; - tx_req->num_TLV = 1; - tx_req->TLVs[0].length = TBS; - tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length); - memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock.buf, TBS); - TX_req->Number_of_PDUs++; - TX_req->SFN = frame; - TX_req->Slot = slot; - /* mark UE as scheduled */ - sched_pdsch->rbSize = 0; - } + /* PREPROCESSOR */ + gNB_mac->pre_processor_dl(gNB_mac, &pdsch); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 5ec7bf781d..f9121b3125 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -55,9 +55,11 @@ uint32_t target_dl_bw = 50; uint64_t dlsch_slot_bitmap = (1<<1); /* schedules whole bandwidth for first user, all the time */ -void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) +void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) { - gNB_MAC_INST *mac = RC.nrmac[module_id]; + frame_t frame = pp_pdsch->frame; + slot_t slot = pp_pdsch->slot; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ int slot_period = slot % mac->frame_structure.numb_slots_period; if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot_period)) @@ -86,9 +88,6 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) if(!tda_info.valid_tda) return; - sched_ctrl->sched_pdsch.tda_info = tda_info; - sched_ctrl->sched_pdsch.time_domain_allocation = tda; - /* find largest unallocated chunk */ const int bwpSize = dl_bwp->BWPSize; const int BWPStart = dl_bwp->BWPStart; @@ -142,12 +141,11 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) 0); AssertFatal(CCEIndex >= 0, "Could not find CCE for UE %04x\n", UE->rnti); - NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; - if (sched_pdsch->dl_harq_pid == -1) - sched_pdsch->dl_harq_pid = sched_ctrl->available_dl_harq.head; - int alloc = -1; - if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) { + int harq_pid = sched_ctrl->retrans_dl_harq.head; + if (harq_pid < 0) + harq_pid = sched_ctrl->available_dl_harq.head; + if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, harq_pid)) { int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, UE->current_UL_BWP.pucch_Config, CCEIndex); alloc = nr_acknack_scheduling(mac, UE, frame, slot, 0, r_pucch, 0); if (alloc < 0) { @@ -165,42 +163,38 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) sched_ctrl->aggregation_level, beam); - //AssertFatal(alloc, - // "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n", - // rnti, frame, slot); - - sched_pdsch->pucch_allocation = alloc; - sched_pdsch->rbStart = rbStart; - sched_pdsch->rbSize = rbSize; - sched_pdsch->bwp_info = get_pdsch_bwp_start_size(mac, UE); - sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, - dl_bwp, - &tda_info, - target_dl_Nl); - - sched_pdsch->mcs = target_dl_mcs; - sched_pdsch->nrOfLayers = target_dl_Nl; - sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx); - sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx); + NR_sched_pdsch_t sched_pdsch = { + .rbSize = rbSize, + .rbStart = rbStart, + .mcs = target_dl_mcs, + .R = nr_get_code_rate_dl(target_dl_mcs, dl_bwp->mcsTableIdx), + .Qm = nr_get_Qm_dl(target_dl_mcs, dl_bwp->mcsTableIdx), + // tbSize further below + .dl_harq_pid = sched_ctrl->retrans_dl_harq.head, // PID of HARQ awaiting retransmission, or -1 otherwise + .pucch_allocation = alloc, + .pm_index = 0, + .nrOfLayers = target_dl_Nl, + .bwp_info = get_pdsch_bwp_start_size(mac, UE), + .dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, &tda_info, target_dl_Nl), + .time_domain_allocation = tda, + .tda_info = tda_info, + }; sched_ctrl->dl_bler_stats.mcs = target_dl_mcs; /* for logging output */ - sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm, - sched_pdsch->R, - sched_pdsch->rbSize, - tda_info.nrOfSymbols, - sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT, - 0 /* N_PRB_oh, 0 for initialBWP */, - 0 /* tb_scaling */, - sched_pdsch->nrOfLayers) - >> 3; + sched_pdsch.tb_size = nr_compute_tbs(sched_pdsch.Qm, + sched_pdsch.R, + sched_pdsch.rbSize, + tda_info.nrOfSymbols, + sched_pdsch.dmrs_parms.N_PRB_DMRS * sched_pdsch.dmrs_parms.N_DMRS_SLOT, + 0 /* N_PRB_oh, 0 for initialBWP */, + 0 /* tb_scaling */, + target_dl_Nl) + >> 3; - /* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */ - sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head; + post_process_dlsch(mac, pp_pdsch, UE, &sched_pdsch); /* mark the corresponding RBs as used */ - for (int rb = 0; rb < sched_pdsch->rbSize; rb++) - vrb_map[rb + sched_pdsch->rbStart + BWPStart] = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); - - if ((frame&127) == 0) LOG_D(MAC,"phytest: %d.%d DL mcs %d, DL rbStart %d, DL rbSize %d\n", frame, slot, sched_pdsch->mcs, rbStart,rbSize); + for (int rb = 0; rb < sched_pdsch.rbSize; rb++) + vrb_map[rb + sched_pdsch.rbStart + BWPStart] = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); } uint32_t target_ul_mcs = 9; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 4e55941420..a68c12092b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -125,6 +125,8 @@ static const uint16_t cqi_table3[16][2] = {{0, 0}, static void determine_aggregation_level_search_order(int agg_level_search_order[NUM_PDCCH_AGG_LEVELS], float pdcch_cl_adjust); +static int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots, int slots_per_frame); + uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format) { // TODO check this but it should be enough for now @@ -2974,9 +2976,6 @@ NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroup NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; sched_ctrl->ta_update = 31; - /* set illegal time domain allocation to force recomputation of all fields */ - sched_ctrl->sched_pdsch.time_domain_allocation = -1; - /* Set default BWPs */ AssertFatal(UE->sc_info.n_ul_bwp <= NR_MAX_NUM_BWP, "uplinkBWP_ToAddModList has %d BWP!\n", UE->sc_info.n_ul_bwp); @@ -3033,18 +3032,17 @@ bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) * To remove the UE, use mac_remove_nr_ue(). */ bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) { + NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); + LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", UE->rnti); NR_UEs_t *UE_info = &nr_mac->UE_info; dump_nr_list(UE_info->connected_ue_list); AssertFatal(!UE->ra, "UE in connected cannot have RA process\n"); - NR_SCHED_LOCK(&UE_info->mutex); - bool success = add_UE_to_list(MAX_MOBILES_PER_GNB, UE_info->connected_ue_list, UE); if (!success) { LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", UE->rnti); delete_nr_ue_data(UE, NULL, &UE_info->uid_allocator); - NR_SCHED_UNLOCK(&UE_info->mutex); return false; } @@ -3057,7 +3055,6 @@ bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame); init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame); - NR_SCHED_UNLOCK(&UE_info->mutex); dump_nr_list(UE_info->connected_ue_list); return true; } @@ -3110,9 +3107,7 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) /* already mutex protected */ NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); NR_UEs_t *UE_info = &nr_mac->UE_info; - NR_SCHED_LOCK(&UE_info->mutex); NR_UE_info_t *UE = remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, UE_info->connected_ue_list, rnti); - NR_SCHED_UNLOCK(&UE_info->mutex); if (UE) delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); else @@ -3442,7 +3437,7 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot continue; const int slots_frame = nr_mac->frame_structure.numb_slots_frame; - const frame_t f = (frame + (slot + mgc->n_slots_advance) / slots_frame) % 1024; + const frame_t f = (frame + (slot + mgc->n_slots_advance) / slots_frame) % MAX_FRAME_NUMBER; const slot_t s = (slot + mgc->n_slots_advance) % slots_frame; // TS 38 331 - Section 5.5.2.9 Measurement gap configuration @@ -3453,7 +3448,7 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot // start a timer to stop scheduling UE during MeasGap, or extend timer for // duration of measGap with existing follow-up action if (!nr_timer_is_active(t) || nr_timer_remaining_time(t) < mgc->mgl_slots) { - nr_mac_interrupt_ue_transmission(nr_mac, UE, mgc->mgl_slots); + nr_mac_interrupt_ue_transmission(nr_mac, UE, mgc->mgl_slots, slots_frame); } } } @@ -3537,7 +3532,7 @@ int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs) return (delay_ms << scs) + sl_ahead; } -int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots) +static int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots, int slots_per_frame) { DevAssert(mac != NULL); DevAssert(UE != NULL); @@ -3546,11 +3541,11 @@ int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int sl nr_timer_setup(&UE->UE_sched_ctrl.transm_interrupt, slots, 1); nr_timer_start(&UE->UE_sched_ctrl.transm_interrupt); - // it might happen that timing advance command should be sent during the UE - // inactivity time. To prevent this, set a variable as if we would have just - // sent it. This way, another TA command will for sure be sent in some - // frames, after the inactivity of the UE. - UE->UE_sched_ctrl.ta_frame = (mac->frame - 1 + 1024) % 1024; + // it might happen that timing advance command should be sent during the UE inactivity time. + // To prevent this, delay next TA command just after the UE inactivity time. + const int inactive_frames = slots / slots_per_frame + 1; + if ((UE->UE_sched_ctrl.ta_frame - mac->frame + MAX_FRAME_NUMBER) % MAX_FRAME_NUMBER < inactive_frames) + UE->UE_sched_ctrl.ta_frame = (mac->frame + inactive_frames) % MAX_FRAME_NUMBER; LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots)\n", UE->rnti, slots); return 0; @@ -3968,23 +3963,6 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_ free_cellGroupConfig(cellGroup_for_UE); } -/* \brief add bearers from CellGroupConfig. - * - * This is a kind of hack, as this should be processed through a F1 UE Context - * setup request, but some modes do not use that (NSA/do-ra/phy_test). */ -void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl, const struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod) -{ - if (addmod == NULL) - return; /* nothing to do */ - - for (int i = 0; i < addmod->list.count; ++i) { - const NR_RLC_BearerConfig_t *conf = addmod->list.array[i]; - int lcid = conf->logicalChannelIdentity; - nr_lc_config_t c = {.lcid = lcid}; - nr_mac_add_lcid(sched_ctrl, &c); - } -} - long get_lcid_from_drbid(int drb_id) { return drb_id + 3; /* LCID is DRB + 3 */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index f3de970683..27ecbdcbd0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -589,11 +589,13 @@ static void evaluate_rsrp_report(gNB_MAC_INST *nrmac, rsrp_report->nr_reports = csi_report->CSI_report_bitlen.nb_ssbri_cri; int bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen; - uint8_t curr_payload = pickandreverse_bits(payload, bitlen, *cumul_bits); - rsrp_report->resource_id[0] = *(index_list[bitlen > 0 ? ((curr_payload) & ~(~1U << (bitlen - 1))) : bitlen]); - *cumul_bits += bitlen; + for (int i = 0; i < rsrp_report->nr_reports; i++) { + uint8_t idx_payload = pickandreverse_bits(payload, bitlen, *cumul_bits); + rsrp_report->resource_id[i] = *(index_list[bitlen > 0 ? ((idx_payload) & ~(~1U << (bitlen - 1))) : bitlen]); + *cumul_bits += bitlen; + } - curr_payload = pickandreverse_bits(payload, 7, *cumul_bits); + uint8_t curr_payload = pickandreverse_bits(payload, 7, *cumul_bits); int rsrp = curr_payload & 0x7f; *cumul_bits += 7; csi_report->nb_of_csi_ssb_report++; @@ -605,10 +607,6 @@ static void evaluate_rsrp_report(gNB_MAC_INST *nrmac, } for (int i = 1; i < rsrp_report->nr_reports; i++) { - curr_payload = pickandreverse_bits(payload, bitlen, *cumul_bits); - rsrp_report->resource_id[i] = *(index_list[bitlen > 0 ? ((curr_payload) & ~(~1U << (bitlen - 1))) : bitlen]); - *cumul_bits += bitlen; - curr_payload = pickandreverse_bits(payload, 4, *cumul_bits); csi_report->nb_of_csi_ssb_report++; rsrp_report->RSRP[i] = get_diff_rsrp(curr_payload & 0x0f, rsrp_report->RSRP[0]); @@ -680,6 +678,8 @@ static void evaluate_cqi_report(uint8_t *payload, const int cqi_idx = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb; const int mcs_table = UE->current_DL_BWP.mcsTableIdx; sched_ctrl->dl_max_mcs = get_mcs_from_cqi(mcs_table, cqi_Table, cqi_idx); + + LOG_D(MAC, "Reported CQI = %d, dl_max_mcs %d\n", temp_cqi, sched_ctrl->dl_max_mcs); } static uint8_t evaluate_pmi_report(uint8_t *payload, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index d86efb6160..90e2e502a8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -725,13 +725,6 @@ static void handle_nr_ul_harq(gNB_MAC_INST *nrmac, static void handle_msg3_failed_rx(gNB_MAC_INST *mac, NR_RA_t *ra, rnti_t rnti, int harq_round_max) { - // for CFRA (NSA) do not schedule retransmission of msg3 - if (ra->cfra) { - LOG_W(NR_MAC, "UE %04x RA failed at state %s (NSA msg3 reception failed)\n", rnti, nrra_text[ra->ra_state]); - nr_release_ra_UE(mac, rnti); - return; - } - if (ra->msg3_round >= harq_round_max - 1) { LOG_W(NR_MAC, "UE %04x RA failed at state %s (Reached msg3 max harq rounds)\n", rnti, nrra_text[ra->ra_state]); nr_release_ra_UE(mac, rnti); @@ -756,6 +749,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, const uint16_t rssi) { gNB_MAC_INST *mac = RC.nrmac[mod_id]; + NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; NR_UE_info_t *UE = find_ra_UE(&mac->UE_info, rnti); if (!UE) { LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", rnti); @@ -768,8 +762,36 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, return; } + // CFRA: we scheduled Msg3 (which does not exist in CFRA, see also + // nr_generate_Msg2()). We did not mark RA as complete right away, as the + // DLSCH scheduler might schedule in the same slot as Msg2 if RLC has data + // (which can only happen in do-ra), so we mark it as complete now. + bool cfra = ra->cfra; + if (ra->cfra) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + nr_mac_reset_ul_failure(sched_ctrl); + reset_dl_harq_list(sched_ctrl); + reset_ul_harq_list(sched_ctrl); + // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration in SA + // in NSA (or do-ra) there is no reconfiguration in NR + int ss_type = IS_SA_MODE(get_softmodem_params()) ? NR_SearchSpace__searchSpaceType_PR_common + : NR_SearchSpace__searchSpaceType_PR_ue_Specific; + configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1); + // initialize ta_frame in case there is no Msg3 received + UE->UE_sched_ctrl.ta_frame = (frame + 100) % MAX_FRAME_NUMBER; + if (!transition_ra_connected_nr_ue(mac, UE)) { + LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); + delete_nr_ue_data(UE, NULL, &mac->UE_info.uid_allocator); + } else { + LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti); + } + } + const int target_snrx10 = mac->pusch_target_snrx10; if (!sdu) { // NACK + if (cfra) // no Msg3 on CFRA, no problem + return; + if (ra->ra_state != nrRA_WAIT_Msg3) return; @@ -799,10 +821,11 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, if (no_sig) { LOG_W(NR_MAC, "MSG3 ULSCH with no signal\n"); - handle_msg3_failed_rx(mac, ra, rnti, mac->ul_bler.harq_round_max); + if (!cfra) + handle_msg3_failed_rx(mac, ra, rnti, mac->ul_bler.harq_round_max); return; } - if (ra->ra_type == RA_2_STEP) { + if (!cfra && ra->ra_type == RA_2_STEP) { // random access pusch with RA-RNTI if (ra->RA_rnti != rnti) { LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, rnti); @@ -811,7 +834,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, } // re-initialize ta update variables after RA procedure completion - UE->UE_sched_ctrl.ta_frame = frame; + UE->UE_sched_ctrl.ta_frame = (frame + 100) % MAX_FRAME_NUMBER; LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frame, slot, rnti); @@ -826,94 +849,76 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, UE_scheduling_control->ta_update = timing_advance; UE_scheduling_control->raw_rssi = rssi; LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update); - NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; - if (ra->cfra) { - LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti); - nr_mac_reset_ul_failure(UE_scheduling_control); - reset_dl_harq_list(UE_scheduling_control); - reset_ul_harq_list(UE_scheduling_control); - process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList); - int ss_type; - // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration in SA - // in NSA (or do-ra) there is no reconfiguration in NR - if (IS_SA_MODE(get_softmodem_params())) - ss_type = NR_SearchSpace__searchSpaceType_PR_common; - else - ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1); - if (!transition_ra_connected_nr_ue(mac, UE)) { - LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); - delete_nr_ue_data(UE, NULL, &mac->UE_info.uid_allocator); - return; - } - } else { - LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3"); - for (uint32_t k = 0; k < sdu_len; k++) { - LOG_D(NR_MAC, "(%i): 0x%x\n", k, sdu[k]); - } - // 3GPP TS 38.321 Section 5.4.3 Multiplexing and assembly - // Logical channels shall be prioritised in accordance with the following order (highest priority listed first): - // - MAC CE for C-RNTI, or data from UL-CCCH; - // This way, we need to process MAC CE for C-RNTI if RA is active and it is present in the MAC PDU - // Search for MAC CE for C-RNTI - rnti_t crnti = lcid_crnti_lookahead(sdu, sdu_len); - if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A - // Replace the current UE by the UE identified by C-RNTI - NR_UE_info_t *old_UE = find_nr_UE(&mac->UE_info, crnti); - if (!old_UE) { - // The UE identified by C-RNTI no longer exists at the gNB - // Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better - // solution may be implemented - LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", UE->rnti); - nr_release_ra_UE(mac, rnti); - return; - } - // in case UE beam has changed - old_UE->UE_beam_index = UE->UE_beam_index; - // Reset UL failure for old UE - nr_mac_reset_ul_failure(&old_UE->UE_sched_ctrl); - // Reset HARQ processes - reset_dl_harq_list(&old_UE->UE_sched_ctrl); - reset_ul_harq_list(&old_UE->UE_sched_ctrl); + LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3"); + for (uint32_t k = 0; k < sdu_len; k++) { + LOG_D(NR_MAC, "(%i): 0x%x\n", k, sdu[k]); + } - // Only trigger RRCReconfiguration if UE is not performing RRCReestablishment - // The RRCReconfiguration will be triggered by the RRCReestablishmentComplete - if (!old_UE->reconfigSpCellConfig) { - LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti); - // Trigger RRCReconfiguration - nr_mac_trigger_reconfiguration(mac, old_UE, -1); - // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration - configure_UE_BWP(mac, scc, old_UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); - } + // 3GPP TS 38.321 Section 5.4.3 Multiplexing and assembly + // Logical channels shall be prioritised in accordance with the following order (highest priority listed first): + // - MAC CE for C-RNTI, or data from UL-CCCH; + // This way, we need to process MAC CE for C-RNTI if RA is active and it is present in the MAC PDU + // Search for MAC CE for C-RNTI + rnti_t crnti = lcid_crnti_lookahead(sdu, sdu_len); + if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A + // Replace the current UE by the UE identified by C-RNTI + NR_UE_info_t *old_UE = find_nr_UE(&mac->UE_info, crnti); + if (!old_UE) { + // The UE identified by C-RNTI no longer exists at the gNB + // Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better + // solution may be implemented + LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", UE->rnti); nr_release_ra_UE(mac, rnti); - LOG_A(NR_MAC, "%4d.%2d RA with C-RNTI %04x complete\n", frame, slot, crnti); - - // Decode the entire MAC PDU - // It may have multiple MAC subPDUs, for example, a MAC subPDU with LCID 1 caring a RRCReestablishmentComplete - nr_process_mac_pdu(mod_id, old_UE, CC_id, frame, slot, sdu, sdu_len, -1); return; } + // in case UE beam has changed + old_UE->UE_beam_index = UE->UE_beam_index; + // Reset UL failure for old UE + nr_mac_reset_ul_failure(&old_UE->UE_sched_ctrl); + // Reset HARQ processes + reset_dl_harq_list(&old_UE->UE_sched_ctrl); + reset_ul_harq_list(&old_UE->UE_sched_ctrl); - // UE Contention Resolution Identity - // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4 - // First byte corresponds to R/LCID MAC sub-header - memcpy(ra->cont_res_id, &sdu[1], sizeof(uint8_t) * 6); + // Only trigger RRCReconfiguration if UE is not performing RRCReestablishment + // The RRCReconfiguration will be triggered by the RRCReestablishmentComplete + if (!old_UE->reconfigSpCellConfig) { + LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti); + // Trigger RRCReconfiguration + nr_mac_trigger_reconfiguration(mac, old_UE, -1); + // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration + configure_UE_BWP(mac, scc, old_UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); + } + nr_release_ra_UE(mac, rnti); + LOG_A(NR_MAC, "%4d.%2d RA with C-RNTI %04x complete\n", frame, slot, crnti); - // Decode MAC PDU - // the function is only called to decode the contention resolution sub-header - // harq_pid set a non-valid value because it is not used in this call - nr_process_mac_pdu(mod_id, UE, CC_id, frame, slot, sdu, sdu_len, -1); - - LOG_I(NR_MAC, - "Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n", - ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4", - UE->rnti, - nrra_text[ra->ra_state]); - ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4; - LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]); + // Decode the entire MAC PDU + // It may have multiple MAC subPDUs, for example, a MAC subPDU with LCID 1 caring a RRCReestablishmentComplete + nr_process_mac_pdu(mod_id, old_UE, CC_id, frame, slot, sdu, sdu_len, -1); return; } + + if (cfra) + return; // rest not relevant for CFRA + + // UE Contention Resolution Identity + // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4 + // First byte corresponds to R/LCID MAC sub-header + memcpy(ra->cont_res_id, &sdu[1], sizeof(uint8_t) * 6); + + // Decode MAC PDU + // the function is only called to decode the contention resolution sub-header + // harq_pid set a non-valid value because it is not used in this call + nr_process_mac_pdu(mod_id, UE, CC_id, frame, slot, sdu, sdu_len, -1); + + LOG_I(NR_MAC, + "Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n", + ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4", + UE->rnti, + nrra_text[ra->ra_state]); + ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4; + LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]); + return; } static void _nr_rx_sdu(const module_id_t gnb_mod_idP, @@ -1834,6 +1839,10 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); while (rbStart < bwpSize && (rballoc_mask[rbStart + bwpStart] & slbitmap)) rbStart++; + if (rbStart >= bwpSize) { + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not allocate UL retransmission: no resources\n", UE->rnti, frame, slot); + return false; + } int rbSize = 0; while (rbStart + rbSize < bwpSize && !(rballoc_mask[rbStart + bwpStart + rbSize] & slbitmap)) rbSize++; @@ -1909,7 +1918,6 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, return true; } -static uint32_t ul_pf_tbs[5][29]; // pre-computed, approximate TBS values for PF coefficient typedef struct UEsched_s { float coef; bool sched_inactive; @@ -2065,8 +2073,8 @@ static int pf_ul(gNB_MAC_INST *nrmac, const int max_mcs_table = (current_BWP->mcs_table == 0 || current_BWP->mcs_table == 2) ? 28 : 27; const int max_mcs = min(bo->max_mcs, max_mcs_table); /* no per-user maximum MCS yet */ int selected_mcs; + int nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); if (bo->harq_round_max == 1) { - int nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); selected_mcs = get_mcs_from_SINRx10(current_BWP->mcs_table, sched_ctrl->pusch_snrx10, nrOfLayers); selected_mcs = min(max_mcs, selected_mcs); selected_mcs = max(bo->min_mcs, selected_mcs); @@ -2078,7 +2086,17 @@ static int pf_ul(gNB_MAC_INST *nrmac, /* Create UE_sched for UEs eligibale for new data transmission*/ /* Calculate coefficient*/ - const uint32_t tbs = ul_pf_tbs[current_BWP->mcs_table][selected_mcs]; + const uint8_t Qm = nr_get_Qm_ul(selected_mcs, current_BWP->mcs_table); + const uint16_t R = nr_get_code_rate_ul(selected_mcs, current_BWP->mcs_table); + const uint32_t tbs = nr_compute_tbs(Qm, + R, + 1, /* rbSize */ + 10, /* hypothetical number of slots */ + 0, /* N_PRB_DMRS * N_DMRS_SLOT */ + 0 /* N_PRB_oh, 0 for initialBWP */, + 0 /* tb_scaling */, + nrOfLayers) + >> 3; float coeff_ue = (float) tbs / UE->ul_thr_ue; bool sched_inactive = B == 0 && do_sched; LOG_D(NR_MAC, "[UE %04x][%4d.%2d] b %d, ul_thr_ue %f, tbs %d, coeff_ue %f, sched_inactive %d\n", @@ -2155,13 +2173,16 @@ static int pf_ul(gNB_MAC_INST *nrmac, bwp_info_t bi = get_pusch_bwp_start_size(iterator->UE); while (rbStart < bi.bwpSize && (rballoc_mask[rbStart + bi.bwpStart] & slbitmap)) rbStart++; + /* if it's for inactivity, min_grant_prb is enough, otherwise check what * would be the maximum */ - uint16_t max_rbSize = iterator->sched_inactive ? min_rb : bi.bwpSize; - /* uint16_t max_rbSize = 10; */ + /* uint16_t max_rbSize = iterator->sched_inactive ? min_rb : bi.bwpSize; */ + uint16_t max_rbSize = min_rb; uint16_t available_rb = 1; while (rbStart + available_rb < bi.bwpSize && !(rballoc_mask[rbStart + bi.bwpStart + available_rb] & slbitmap) && available_rb < max_rbSize) - available_rb++; + available_rb++; + + /* LOG_I(NR_MAC, "[UE %04x] RB size: %u\n", iterator->UE->rnti, available_rb); */ if (rbStart + min_rb > bi.bwpSize || available_rb < min_rb) { reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, slots_per_frame, dci_beam.new_beam); @@ -2363,10 +2384,9 @@ nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti long *maxMIMO_Layers = UE->sc_info.maxMIMO_Layers_PUSCH; if (!maxMIMO_Layers && ul_bwp && ul_bwp->pusch_Config) maxMIMO_Layers = ul_bwp->pusch_Config->maxRank; + long lbrm_layers = maxMIMO_Layers ? *maxMIMO_Layers : ue_supported_ul_layers(UE->capability); AssertFatal (maxMIMO_Layers != NULL,"Option with max MIMO layers not configured is not supported\n"); - pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(ul_bwp->mcs_table, - UE->sc_info.ul_bw_tbslbrm, - *maxMIMO_Layers); + pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(ul_bwp->mcs_table, UE->sc_info.ul_bw_tbslbrm, lbrm_layers); } /* PUSCH PTRS */ if (sched_pusch->dmrs_info.ptrsConfig) { @@ -2443,6 +2463,7 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE } UE->mac_stats.ul.current_bytes = sched_pusch->tb_size; UE->mac_stats.ul.current_rbs = sched_pusch->rbSize; + nr_mac->mac_stats.ul.used_prb_aggregate += sched_pusch->rbSize; sched_ctrl->last_ul_frame = sched_pusch->frame; sched_ctrl->last_ul_slot = sched_pusch->slot; @@ -2685,6 +2706,7 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp int tda = seq_arr_dist(&nr_mac->ul_tda, seq_arr_front(&nr_mac->ul_tda), tda_info); AssertFatal(tda >= 0 && tda < 16, "illegal TDA index %d\n", tda); + nr_mac->mac_stats.ul.total_prb_aggregate += bw; int len[num_beams]; for (int i = 0; i < num_beams; i++) len[i] = rb_len; @@ -2704,32 +2726,6 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp nr_pp_impl_ul nr_init_ulsch_preprocessor(int CC_id) { - /* during initialization: no mutex needed */ - /* in the PF algorithm, we have to use the TBsize to compute the coefficient. - * This would include the number of DMRS symbols, which in turn depends on - * the time domain allocation. In case we are in a mixed slot, we do not want - * to recalculate all these values, and therefore we provide a look-up table - * which should approximately(!) give us the TBsize. In particular, the - * number of symbols, the number of DMRS symbols, and the exact Qm and R, are - * not correct*/ - for (int mcsTableIdx = 0; mcsTableIdx < 5; ++mcsTableIdx) { - for (int mcs = 0; mcs < 29; ++mcs) { - if (mcs > 27 && (mcsTableIdx == 1 || mcsTableIdx == 3 || mcsTableIdx == 4)) - continue; - const uint8_t Qm = nr_get_Qm_ul(mcs, mcsTableIdx); - const uint16_t R = nr_get_code_rate_ul(mcs, mcsTableIdx); - /* note: we do not update R/Qm based on low MCS or pi2BPSK */ - ul_pf_tbs[mcsTableIdx][mcs] = nr_compute_tbs(Qm, - R, - 1, /* rbSize */ - 10, /* hypothetical number of slots */ - 0, /* N_PRB_DMRS * N_DMRS_SLOT */ - 0 /* N_PRB_oh, 0 for initialBWP */, - 0 /* tb_scaling */, - 1 /* nrOfLayers */) - >> 3; - } - } return nr_ulsch_preprocessor; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index f04b28b8da..e280a8cbe2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -65,16 +65,9 @@ void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE); bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs); -int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots); int nr_transmission_action_indicator_stop(gNB_MAC_INST *mac, NR_UE_info_t *UE_info); -void clear_nr_nfapi_information(gNB_MAC_INST *gNB, - int CC_idP, - frame_t frameP, - slot_t slotP, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req, - nfapi_nr_ul_dci_request_t *UL_dci_req); +void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, frame_t frameP, slot_t slotP); void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot); @@ -145,7 +138,7 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs); /* \brief preprocessor for phytest: schedules UE_id 0 with fixed MCS on all * freq resources */ -void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot); +void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch); /* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a * fixed set of resources */ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch); @@ -487,9 +480,6 @@ bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t * void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE, int new_bwp_id); -void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl, - const struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod); - bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c); nr_lc_config_t *nr_mac_get_lc_config(NR_UE_sched_ctrl_t* sched_ctrl, int lcid); bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid); @@ -504,5 +494,6 @@ void prepare_du_configuration_update(gNB_MAC_INST *mac, void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group); +void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE_info_t *UE, NR_sched_pdsch_t *sched_pdsch); void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE_info_t *UE, NR_sched_pusch_t *sched_pusch); #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index debc0d5530..8f98aabbee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -329,7 +329,7 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, *rlc_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size12; *rlc_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size12; } - + AssertFatal(rlc_BearerConfig->rlc_Config, "We expect rlc-Config to be always present when we configure a DRB\n"); nr_rlc_add_drb(UE->rnti, drb->id, rlc_BearerConfig); nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nr.nssai}; @@ -381,12 +381,9 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, { DevAssert(req_drbs != NULL && cellGroupConfig != NULL); instance_t f1inst = get_f1_gtp_instance(); - cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList)); AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n"); - /* Note: the actual GTP tunnels are already removed in the F1AP message - * decoding */ for (int i = 0; i < drbs_len; i++) { const f1ap_drb_to_release_t *drb = &req_drbs[i]; @@ -401,7 +398,7 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { nr_mac_remove_lcid(&UE->UE_sched_ctrl, lcid); nr_rlc_release_entity(UE->rnti, lcid); - if (f1inst >= 0) + if (f1inst >= 0) /* Delete F1 tunnel */ newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->id); asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1); long *plcid = malloc(sizeof(*plcid)); @@ -684,11 +681,9 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) /* new UE: tell the UE to reestablish RLC */ struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod = new_CellGroup->rlc_BearerToAddModList; for (int i = 0; i < addmod->list.count; ++i) { - asn1cCallocOne(addmod->list.array[i]->reestablishRLC, NR_RLC_BearerConfig__reestablishRLC_true); - for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) { - nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i); - nr_rlc_reestablish_entity(UE->rnti, lc_config->lcid); - } + NR_RLC_BearerConfig_t *bc = addmod->list.array[i]; + asn1cCallocOne(bc->reestablishRLC, NR_RLC_BearerConfig__reestablishRLC_true); + nr_rlc_reestablish_entity(UE->rnti, bc->logicalChannelIdentity); } } @@ -967,6 +962,8 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = oldUE->CellGroup; oldUE->CellGroup = NULL; + UE->capability = oldUE->capability; + oldUE->capability = NULL; UE->mac_stats = oldUE->mac_stats; UE->measgap_config = oldUE->measgap_config; /* 38.331 5.3.7.2 says that the UE releases the spCellConfig, so we drop it @@ -978,8 +975,15 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) pthread_mutex_unlock(&mac->sched_lock); nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id); nr_rlc_update_id(*dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id); - /* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */ - nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL); + /* 38.331 clause 5.3.7.4: apply gNB RLC configuration for SRB1 to match the UE RLC configuration defined in 9.2.1 */ + nr_rlc_configuration_t rlc_configuration = mac->rlc_config; // use configuration file values for timers t_poll_retransmit, t_reassembly and t_status_prohibit + rlc_configuration.srb.poll_pdu = -1; + rlc_configuration.srb.poll_byte = -1; + rlc_configuration.srb.max_retx_threshold = 8; + rlc_configuration.srb.sn_field_length = 12; + NR_RLC_Config_t *rlc_Config = nr_srb_config(&rlc_configuration); + nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, rlc_Config); + ASN_STRUCT_FREE(asn_DEF_NR_RLC_Config, rlc_Config); instance_t f1inst = get_f1_gtp_instance(); if (f1inst >= 0) // we actually use F1-U gtpv1u_update_ue_id(f1inst, *dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index fa66125bf7..f3f070b0e7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -87,7 +87,6 @@ void *nrmac_stats_thread(void *arg) { char *p = output; NR_SCHED_LOCK(&gNB->sched_lock); p += dump_mac_stats(gNB, p, end - p, false); - NR_SCHED_UNLOCK(&gNB->sched_lock); p += snprintf(p, end - p, "\n"); p += print_meas_log(&gNB->gNB_scheduler, "gNB_scheduler", NULL, NULL, p, end - p); p += print_meas_log(&gNB->rx_ulsch_sdu, "rx_ulsch_sdu", NULL, NULL, p, end - p); @@ -97,10 +96,17 @@ void *nrmac_stats_thread(void *arg) { p += print_meas_log(&gNB->rlc_data_req, "rlc_data_req", NULL, NULL, p, end - p); p += print_meas_log(&gNB->nr_srs_ri_computation_timer, "UL-RI computation time", NULL, NULL, p, end - p); p += print_meas_log(&gNB->nr_srs_tpmi_computation_timer, "UL-TPMI computation time", NULL, NULL, p, end - p); - fwrite(output, p - output, 1, file); - fflush(file); + NR_SCHED_UNLOCK(&gNB->sched_lock); + size_t len = p - output; + if (fwrite(output, len, 1, file) != 1 || fflush(file) != 0) { + LOG_E(NR_MAC, "error while writing nrMAC_stats.log: %d, %s\n", errno, strerror(errno)); + break; + } sleep(1); - fseek(file,0,SEEK_SET); + if (ftruncate(fileno(file), 0) != 0 || fseek(file, 0, SEEK_SET) != 0) { + LOG_E(NR_MAC, "error while writing nrMAC_stats.log: %d, %s\n", errno, strerror(errno)); + break; + } } fclose(file); return NULL; @@ -112,6 +118,19 @@ void clear_mac_stats(gNB_MAC_INST *gNB) { } } +static char *st_append(char *start, const char *end, const char *format, ...) +{ + size_t space = end - start; + va_list args; + va_start(args, format); + size_t written = vsnprintf(start, space, format, args); + va_end(args); + if (written <= space) + return start + written; + else + return (char *)end; +} + size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp) { const char *begin = output; @@ -121,46 +140,45 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset * scheduler to be locked*/ NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock); - NR_SCHED_LOCK(&gNB->UE_info.mutex); UE_iterator(gNB->UE_info.connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_mac_stats_t *stats = &UE->mac_stats; const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0; const int avg_sinrx10 = stats->num_sinr_meas > 0 ? stats->cumul_sinrx10 / stats->num_sinr_meas : 0; - output += snprintf(output, end - output, "UE RNTI %04x CU-UE-ID ", UE->rnti); + output = st_append(output, end, "UE RNTI %04x CU-UE-ID ", UE->rnti); if (du_exists_f1_ue_data(UE->rnti)) { f1_ue_data_t ued = du_get_f1_ue_data(UE->rnti); - output += snprintf(output, end - output, "%d", ued.secondary_ue); + output = st_append(output, end, "%d", ued.secondary_ue); } else { - output += snprintf(output, end - output, "(none)"); + output = st_append(output, end, "(none)"); } bool in_sync = !sched_ctrl->ul_failure; - output += snprintf(output, - end - output, + output = st_append(output, + end, " %s PH %d dB PCMAX %d dBm", in_sync ? "in-sync" : "out-of-sync", sched_ctrl->ph, sched_ctrl->pcmax); if (stats->num_rsrp_meas) - output += snprintf(output, end - output, ", average RSRP %d (%d meas)", avg_rsrp, stats->num_rsrp_meas); + output = st_append(output, end, ", average RSRP %d (%d meas)", avg_rsrp, stats->num_rsrp_meas); if (stats->num_sinr_meas) { - output += snprintf(output, - end - output, + output = st_append(output, + end, ", average SINR %d.%d (%d meas)", avg_sinrx10 / 10, avg_sinrx10 % 10, stats->num_sinr_meas); } - output += snprintf(output, end - output, "\n"); + output = st_append(output, end, "\n"); if(sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.print_report) - output += snprintf(output, - end - output, + output = st_append(output, + end, "UE %04x: CQI %d, RI %d, PMI (%d,%d)\n", UE->rnti, sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb, @@ -169,18 +187,18 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2); if (stats->srs_stats[0] != '\0') { - output += snprintf(output, end - output, "UE %04x: %s\n", UE->rnti, stats->srs_stats); + output = st_append(output, end, "UE %04x: %s\n", UE->rnti, stats->srs_stats); } - output += snprintf(output, - end - output, + output = st_append(output, + end, "UE %04x: dlsch_rounds ", UE->rnti); - output += snprintf(output, end - output, "%"PRIu64, stats->dl.rounds[0]); + output = st_append(output, end, "%"PRIu64, stats->dl.rounds[0]); for (int i = 1; i < gNB->dl_bler.harq_round_max; i++) - output += snprintf(output, end - output, "/%"PRIu64, stats->dl.rounds[i]); + output = st_append(output, end, "/%"PRIu64, stats->dl.rounds[i]); - output += snprintf(output, - end - output, + output = st_append(output, + end, ", dlsch_errors %"PRIu64", pucch0_DTX %d, BLER %.5f MCS (%d) %d CCE fail %d\n", stats->dl.errors, stats->pucch0_DTX, @@ -194,15 +212,15 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset stats->num_sinr_meas = 0; stats->cumul_sinrx10 = 0; } - output += snprintf(output, - end - output, + output = st_append(output, + end, "UE %04x: ulsch_rounds ", UE->rnti); - output += snprintf(output, end - output, "%"PRIu64, stats->ul.rounds[0]); + output = st_append(output, end, "%"PRIu64, stats->ul.rounds[0]); for (int i = 1; i < gNB->ul_bler.harq_round_max; i++) - output += snprintf(output, end - output, "/%"PRIu64, stats->ul.rounds[i]); + output = st_append(output, end, "/%"PRIu64, stats->ul.rounds[i]); - output += snprintf(output, - end - output, + output = st_append(output, + end, ", ulsch_errors %"PRIu64", ulsch_DTX %d, BLER %.5f MCS (%d) %d (Qm %d deltaMCS %d dB) NPRB %d SNR %d.%d dB CCE fail %d\n", stats->ul.errors, stats->ulsch_DTX, @@ -215,15 +233,15 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset sched_ctrl->pusch_snrx10 / 10, sched_ctrl->pusch_snrx10 % 10, sched_ctrl->ul_cce_fail); - output += snprintf(output, - end - output, + output = st_append(output, + end, "UE %04x: MAC: TX %14"PRIu64" RX %14"PRIu64" bytes\n", UE->rnti, stats->dl.total_bytes, stats->ul.total_bytes); for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); i++) { const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); - output += snprintf(output, - end - output, + output = st_append(output, + end, "UE %04x: LCID %d: TX %14"PRIu64" RX %14"PRIu64" bytes\n", UE->rnti, c->lcid, @@ -231,7 +249,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset stats->ul.lc_bytes[c->lcid]); } } - NR_SCHED_UNLOCK(&gNB->UE_info.mutex); + DevAssert(output <= end); return output - begin; } @@ -296,9 +314,10 @@ void mac_top_init_gNB(ngran_node_t node_type, RC.nrmac[i]->cset0_bwp_start = 0; RC.nrmac[i]->cset0_bwp_size = 0; + RC.nrmac[i]->print_ue_stats = true; + pthread_mutex_init(&RC.nrmac[i]->sched_lock, NULL); - pthread_mutex_init(&RC.nrmac[i]->UE_info.mutex, NULL); uid_linear_allocator_init(&RC.nrmac[i]->UE_info.uid_allocator); if (get_softmodem_params()->phy_test) { diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 026d8d563e..aa8b2b8644 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -179,6 +179,12 @@ typedef struct { int location_and_bw; } nr_bwp_config_t; +typedef enum { + SSB_RSRP, + CRI_RSRP, + SSB_SINR, +} nr_config_report_type_t; + typedef struct nr_mac_config_t { int sib1_tda; nr_pdsch_AntennaPorts_t pdsch_AntennaPorts; @@ -207,7 +213,7 @@ typedef struct nr_mac_config_t { int num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; nr_redcap_config_t *redcap; nr_ptrs_config_t *ptrs; - bool do_SINR; + nr_config_report_type_t report_type; } nr_mac_config_t; typedef struct NR_preamble_ue { @@ -633,8 +639,6 @@ typedef struct { /// PHR info: nominal UE transmit power levels (dBm) int pcmax; - /// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI - NR_sched_pdsch_t sched_pdsch; /// UE-estimated maximum MCS (from CSI-RS) uint8_t dl_max_mcs; @@ -797,7 +801,6 @@ typedef struct { typedef struct { /// scheduling control info // last element always NULL - pthread_mutex_t mutex; NR_UE_info_t *connected_ue_list[MAX_MOBILES_PER_GNB + 1]; NR_UE_info_t *access_ue_list[NR_NB_RA_PROC_MAX + 1]; // bitmap of CSI-RS already scheduled in current slot @@ -820,7 +823,18 @@ typedef struct { nr_beam_mode_t beam_mode; } NR_beam_info_t; -#define UE_iterator(BaSe, VaR) NR_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++))) +#define UE_iterator(BaSe, VaR) for (NR_UE_info_t **VaR##pptr=BaSe, *VaR=*VaR##pptr; VaR; VaR=*(++VaR##pptr)) + +typedef struct { + /// current frame + frame_t frame; + /// current slot + slot_t slot; + /// FAPI DL req in which allocations are made + nfapi_nr_dl_tti_request_body_t *dl_req; + /// TX_data request holds the actual data + nfapi_nr_tx_data_request_t *TX_req; +} post_process_pdsch_t; typedef struct { /// current frame for DCI @@ -837,7 +851,7 @@ typedef struct { struct gNB_MAC_INST_s; typedef struct gNB_MAC_INST_s gNB_MAC_INST; -typedef void (*nr_pp_impl_dl)(module_id_t mod_id, frame_t frame, slot_t slot); +typedef void (*nr_pp_impl_dl)(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pp_pdsch); typedef void (*nr_pp_impl_ul)(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch); typedef struct f1_config_t { @@ -856,6 +870,11 @@ typedef struct { uint64_t used_prb_aggregate; } mac_stats_t; +typedef struct dlul_mac_stats { + mac_stats_t dl; + mac_stats_t ul; +} dlul_mac_stats_t; + /// helper type to encapsulate a frame/slot combination in a single type. /// Currently only used in the UL preprocessor. Note: if you use this type /// further, please refactor it into a common type first. @@ -975,9 +994,14 @@ typedef struct gNB_MAC_INST_s { f1_config_t f1_config; int16_t frame; + /// number of UEs to exceed to disable stats + int stats_max_ue; + /// if stats are currently enabled + bool print_ue_stats; + pthread_mutex_t sched_lock; - mac_stats_t mac_stats; + dlul_mac_stats_t mac_stats; uint64_t num_scheduled_prach_rx; } gNB_MAC_INST; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 2749e44978..a9e53b6d32 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -585,22 +585,13 @@ static void config_csiim(int do_csirs, } -void set_dl_maxmimolayers(NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig, - const NR_ServingCellConfigCommon_t *scc, - const NR_UE_NR_Capability_t *uecap, - int maxMIMO_layers) +long ue_supported_dl_layers(const NR_ServingCellConfigCommon_t *scc, const NR_UE_NR_Capability_t *uecap) { - if(!pdsch_servingcellconfig->ext1) - pdsch_servingcellconfig->ext1=calloc(1,sizeof(*pdsch_servingcellconfig->ext1)); - if(!pdsch_servingcellconfig->ext1->maxMIMO_Layers) - pdsch_servingcellconfig->ext1->maxMIMO_Layers = calloc(1,sizeof(*pdsch_servingcellconfig->ext1->maxMIMO_Layers)); - NR_SCS_SpecificCarrier_t *scs_carrier = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]; int band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; const frequency_range_t freq_range = get_freq_range_from_band(band); const int scs = scs_carrier->subcarrierSpacing; const int bw_size = scs_carrier->carrierBandwidth; - NR_FeatureSets_t *fs = uecap ? uecap->featureSets : NULL; if (fs) { const int bw_mhz = get_supported_bw_mhz(freq_range, get_supported_band_index(scs, freq_range, bw_size)); @@ -610,16 +601,29 @@ void set_dl_maxmimolayers(NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig, if (scs == dl_fs->supportedSubcarrierSpacingDL && supported_bw_comparison(bw_mhz, &dl_fs->supportedBandwidthDL, dl_fs->channelBW_90mhz) && dl_fs->maxNumberMIMO_LayersPDSCH) { - long ue_supported_layers = (2 << *dl_fs->maxNumberMIMO_LayersPDSCH); - if (maxMIMO_layers == -1) - *pdsch_servingcellconfig->ext1->maxMIMO_Layers = NR_MAX_SUPPORTED_DL_LAYERS < ue_supported_layers ? NR_MAX_SUPPORTED_DL_LAYERS : ue_supported_layers; - else - *pdsch_servingcellconfig->ext1->maxMIMO_Layers = maxMIMO_layers < ue_supported_layers ? maxMIMO_layers : ue_supported_layers; - return; + return (2 << *dl_fs->maxNumberMIMO_LayersPDSCH); } } } - *pdsch_servingcellconfig->ext1->maxMIMO_Layers = 2; + return -1; +} + +static void set_dl_maxmimolayers(NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig, + const NR_ServingCellConfigCommon_t *scc, + const NR_UE_NR_Capability_t *uecap, + int maxMIMO_layers) +{ + if(!pdsch_servingcellconfig->ext1) + pdsch_servingcellconfig->ext1 = calloc(1, sizeof(*pdsch_servingcellconfig->ext1)); + if(!pdsch_servingcellconfig->ext1->maxMIMO_Layers) + pdsch_servingcellconfig->ext1->maxMIMO_Layers = calloc(1, sizeof(*pdsch_servingcellconfig->ext1->maxMIMO_Layers)); + + long l = ue_supported_dl_layers(scc, uecap); + long ue_supported_layers = l > 1 ? l : 2; // min UE supported layers = 2 + if (maxMIMO_layers == -1) + *pdsch_servingcellconfig->ext1->maxMIMO_Layers = min(NR_MAX_SUPPORTED_DL_LAYERS, ue_supported_layers); + else + *pdsch_servingcellconfig->ext1->maxMIMO_Layers = min(maxMIMO_layers, ue_supported_layers); } // TODO: Implement to b_SRS = 1 and b_SRS = 2 @@ -2144,7 +2148,7 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, 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->csi_RS_ResourceSetList.present == NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB) { - if (configuration->do_CSIRS && num_antenna_ports < 4) { + if (configuration->report_type == CRI_RSRP && configuration->do_CSIRS && num_antenna_ports < 4) { if (csires->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList) resource_id = csires->csi_ResourceConfigId; } else { @@ -2166,20 +2170,19 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic)); set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, true); asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires); - if (configuration->do_CSIRS && num_antenna_ports < 4) { + if (configuration->report_type == SSB_SINR) { + csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_none; + csirep->reportQuantity.choice.none = (NULL_t)0; + csirep->ext2 = calloc(1, sizeof(*csirep->ext2)); + csirep->ext2->reportQuantity_r16 = calloc(1, sizeof(*csirep->ext2->reportQuantity_r16)); + csirep->ext2->reportQuantity_r16->present = NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16; + csirep->ext2->reportQuantity_r16->choice.ssb_Index_SINR_r16 = (NULL_t)0; + } else if (configuration->report_type == CRI_RSRP && configuration->do_CSIRS && num_antenna_ports < 4) { csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP; csirep->reportQuantity.choice.cri_RSRP = (NULL_t)0; } else { csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP; csirep->reportQuantity.choice.ssb_Index_RSRP = (NULL_t)0; - if (configuration->do_SINR) { - csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_none; - csirep->reportQuantity.choice.none = (NULL_t)0; - csirep->ext2 = calloc(1, sizeof(*csirep->ext2)); - csirep->ext2->reportQuantity_r16 = calloc(1, sizeof(*csirep->ext2->reportQuantity_r16)); - csirep->ext2->reportQuantity_r16->present = NR_CSI_ReportConfig__ext2__reportQuantity_r16_PR_ssb_Index_SINR_r16; - csirep->ext2->reportQuantity_r16->choice.ssb_Index_SINR_r16 = (NULL_t)0; - } } csirep->groupBasedBeamReporting.present = NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled; csirep->groupBasedBeamReporting.choice.disabled = calloc(1, sizeof(*csirep->groupBasedBeamReporting.choice.disabled)); @@ -3539,6 +3542,24 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, return SpCellConfig; } +struct NR_RLC_Config *nr_srb_config(const nr_rlc_configuration_t *default_rlc_config) +{ + NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); + rlc_Config->present = NR_RLC_Config_PR_am; + rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am)); + rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length); + rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = encode_t_reassembly(default_rlc_config->srb.t_reassembly); + rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = encode_t_status_prohibit(default_rlc_config->srb.t_status_prohibit); + rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length); + rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = encode_t_poll_retransmit(default_rlc_config->srb.t_poll_retransmit); + rlc_Config->choice.am->ul_AM_RLC.pollPDU = encode_poll_pdu(default_rlc_config->srb.poll_pdu); + rlc_Config->choice.am->ul_AM_RLC.pollByte = encode_poll_byte(default_rlc_config->srb.poll_byte); + rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = encode_max_retx_threshold(default_rlc_config->srb.max_retx_threshold); + return rlc_Config; +} + NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, long priority, long bucketSizeDuration, @@ -3552,20 +3573,7 @@ NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, rlc_BearerConfig->servedRadioBearer->choice.srb_Identity = channelId; rlc_BearerConfig->reestablishRLC = NULL; - NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); - rlc_Config->present = NR_RLC_Config_PR_am; - rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am)); - rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); - *(rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length); - rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = encode_t_reassembly(default_rlc_config->srb.t_reassembly); - rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = encode_t_status_prohibit(default_rlc_config->srb.t_status_prohibit); - rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); - *(rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length); - rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = encode_t_poll_retransmit(default_rlc_config->srb.t_poll_retransmit); - rlc_Config->choice.am->ul_AM_RLC.pollPDU = encode_poll_pdu(default_rlc_config->srb.poll_pdu); - rlc_Config->choice.am->ul_AM_RLC.pollByte = encode_poll_byte(default_rlc_config->srb.poll_byte); - rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = encode_max_retx_threshold(default_rlc_config->srb.max_retx_threshold); - rlc_BearerConfig->rlc_Config = rlc_Config; + rlc_BearerConfig->rlc_Config = nr_srb_config(default_rlc_config); NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t)); logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters)); @@ -3585,10 +3593,9 @@ NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, return rlc_BearerConfig; } -static void nr_drb_config(struct NR_RLC_Config *rlc_Config, - NR_RLC_Config_PR rlc_config_pr, - const nr_rlc_configuration_t *default_rlc_config) +struct NR_RLC_Config *nr_drb_config(NR_RLC_Config_PR rlc_config_pr, const nr_rlc_configuration_t *default_rlc_config) { + NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); switch (rlc_config_pr) { case NR_RLC_Config_PR_um_Bi_Directional: // RLC UM Bi-directional Bearer configuration @@ -3621,6 +3628,7 @@ static void nr_drb_config(struct NR_RLC_Config *rlc_Config, break; } rlc_Config->present = rlc_config_pr; + return rlc_Config; } NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, @@ -3636,9 +3644,7 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, rlc_BearerConfig->servedRadioBearer->choice.drb_Identity = drbId; rlc_BearerConfig->reestablishRLC = NULL; - NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); - nr_drb_config(rlc_Config, rlc_conf, default_rlc_config); - rlc_BearerConfig->rlc_Config = rlc_Config; + rlc_BearerConfig->rlc_Config = nr_drb_config(rlc_conf, default_rlc_config); NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t)); logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters)); @@ -3733,10 +3739,11 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, return cellGroupConfig; } -static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_NR_Capability_t *uecap) +long ue_supported_ul_layers(const NR_UE_NR_Capability_t *uecap) { long ul_max_layers = 1; - if (uecap && uecap->featureSets + if (uecap + && uecap->featureSets && uecap->featureSets->featureSetsUplinkPerCC && uecap->featureSets->featureSetsUplinkPerCC->list.count > 0) { NR_FeatureSetUplinkPerCC_t *ul_feature_setup_per_cc = uecap->featureSets->featureSetsUplinkPerCC->list.array[0]; @@ -3752,11 +3759,15 @@ static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_ ul_max_layers = 1; } } - ul_max_layers = min(ul_max_layers, configuration->pusch_AntennaPorts); } return ul_max_layers; } +static long set_ul_max_layers(const nr_mac_config_t *configuration, const NR_UE_NR_Capability_t *uecap) +{ + return min(ue_supported_ul_layers(uecap), configuration->pusch_AntennaPorts); +} + NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t *cellGroupConfig, const nr_mac_config_t *configuration, const NR_UE_NR_Capability_t *uecap, @@ -3867,8 +3878,15 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CSI_MeasConfig_t *csi_MeasConfig = spCellConfigDedicated->csi_MeasConfig->choice.setup; for (int report = 0; report < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; report++) { NR_CSI_ReportConfig_t *csirep = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[report]; - if(csirep->codebookConfig) + if (csirep->codebookConfig) config_csi_codebook(&configuration->pdsch_AntennaPorts, *pdsch_servingcellconfig->ext1->maxMIMO_Layers, csirep->codebookConfig); + if (csirep->groupBasedBeamReporting.present == NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled + && csirep->groupBasedBeamReporting.choice.disabled + && csirep->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + *csirep->groupBasedBeamReporting.choice.disabled->nrofReportedRS = config_nrofReportedRS(uecap, + get_ssb_bitmap(scc), + scc, + configuration->max_num_rsrp); } NR_UplinkConfig_t *uplinkConfig = spCellConfigDedicated->uplinkConfig; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index 89ce03e7f5..270aed4b71 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -112,6 +112,9 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc, int frame); +struct NR_RLC_Config *nr_srb_config(const nr_rlc_configuration_t *default_rlc_config); +struct NR_RLC_Config *nr_drb_config(NR_RLC_Config_PR rlc_config_pr, const nr_rlc_configuration_t *default_rlc_config); + NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, long priority, long bucketSizeDuration, @@ -131,5 +134,6 @@ NR_CellGroupConfig_t * update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_ NR_MeasurementTimingConfiguration_t *get_nr_mtc(uint8_t *buf, uint32_t len); measgap_config_t create_measgap_config(const NR_MeasurementTimingConfiguration_t *mtc, int scs, int min_rxtxtime); int encode_measgap_config(const measgap_config_t *c, uint8_t *buf); - +long ue_supported_ul_layers(const NR_UE_NR_Capability_t *uecap); +long ue_supported_dl_layers(const NR_ServingCellConfigCommon_t *scc, const NR_UE_NR_Capability_t *uecap); #endif diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index b19ccceb22..ecdf3dfd72 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -141,6 +141,24 @@ static instance_t get_f1_gtp_instance(void) return inst->gtpInst; } +/** @brief Add bearer in PDCP/SDAP for 5GC association (SA) */ +static void e1_add_bearers(const int ue_id, const NR_DRB_ToAddModList_t *addMod, const nr_pdcp_entity_security_keys_and_algos_t *sp) +{ + for (int i = 0; i < addMod->list.count; i++) { + NR_DRB_ToAddMod_t *drb = addMod->list.array[i]; + DevAssert(drb->cnAssociation); + DevAssert(drb->cnAssociation->present != NR_DRB_ToAddMod__cnAssociation_PR_NOTHING); + DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config); + DevAssert(drb->cnAssociation->choice.sdap_Config); + // get SDAP config + sdap_config_t sdap = nr_sdap_get_config(GNB_FLAG_YES, drb->cnAssociation->choice.sdap_Config, drb->drb_Identity); + // add SDAP entity + nr_sdap_addmod_entity(GNB_FLAG_YES, ue_id, &sdap); + // add PDCP entity + nr_pdcp_add_drb(GNB_FLAG_YES, ue_id, drb->pdcp_Config, &sdap, sp); + } +} + void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) { bool need_ue_id_mgmt = e1_used(); @@ -208,11 +226,10 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) security_parameters.integrity_algorithm = req->secInfo.integrityProtectionAlgorithm; memcpy(security_parameters.ciphering_key, req->secInfo.encryptionKey, NR_K_KEY_SIZE); memcpy(security_parameters.integrity_key, req->secInfo.integrityProtectionKey, NR_K_KEY_SIZE); - nr_pdcp_add_drbs(true, // set this to notify PDCP that his not UE - cu_up_ue_id, - &DRB_configList, - &security_parameters); + + e1_add_bearers(cu_up_ue_id, &DRB_configList, &security_parameters); ASN_STRUCT_RESET(asn_DEF_NR_DRB_ToAddModList, &DRB_configList.list); + if (f1inst >= 0) { /* we have F1(-U) */ teid_t dummy_teid = 0xffff; // we will update later with answer from DU in_addr_t dummy_address = {0}; // IPv4, updated later with answer from DU @@ -242,17 +259,58 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) get_e1_if()->bearer_setup_response(&resp); } +static void release_gtpu_tunnel(uint32_t ue_id, int pdusession_id) +{ + instance_t n3inst = get_n3_gtp_instance(); + + // Handle N3 tunnel (1 tunnel per PDU session) + if (n3inst >= 0) { + LOG_I(E1AP, "UE %u: Deleting N3 tunnel for PDU session %d\n", ue_id, pdusession_id); + int result = newGtpuDeleteOneTunnel(n3inst, ue_id, pdusession_id); + if (result == GTPNOK) { + LOG_E(E1AP, "UE %u: Failed to delete N3 tunnel for PDU session %d\n", ue_id, pdusession_id); + } + } +} + +static void release_f1_drbs(uint32_t ue_id, int pdusession_id) +{ + instance_t f1inst = get_f1_gtp_instance(); + // Handle F1 tunnels (1 tunnel per DRB, fetch PDCP entities and get DRB IDs) + int drb_ids[MAX_DRBS_PER_UE]; + int n_drbs = nr_pdcp_get_drb_ids_for_pdusession(ue_id, pdusession_id, drb_ids); + if (n_drbs > 0) { + LOG_I(E1AP, "UE %u: Deleting %d F1 tunnels for PDU session %d\n", ue_id, n_drbs, pdusession_id); + // Delete each F1 tunnel using the DRB IDs + for (int i = 0; i < n_drbs; i++) { + int drb_id = drb_ids[i]; + if (f1inst >= 0) { + int result = newGtpuDeleteOneTunnel(f1inst, ue_id, drb_id); + if (result == GTPNOK) { + LOG_E(E1AP, "UE %u: Failed to delete F1 tunnel for DRB %d\n", ue_id, drb_id); + } + } + // Release PDCP entity + nr_pdcp_release_drb(ue_id, drb_id); + } + } else { + LOG_W(E1AP, "UE %u: No DRBs found for PDU session %d\n", ue_id, pdusession_id); + } +} + /** * @brief Fill Bearer Context Modification Response and send to callback */ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { - AssertFatal(req->numPDUSessionsMod > 0, "need at least one PDU session to modify\n"); + AssertFatal(req->numPDUSessionsMod > 0 || req->numPDUSessionsRem > 0, + "need at least one PDU session to modify or release (mod=%u, rel=%u)\n", + req->numPDUSessionsMod, + req->numPDUSessionsRem); e1ap_bearer_modif_resp_t modif = { .gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id, .gNB_cu_up_ue_id = req->gNB_cu_up_ue_id, - .numPDUSessionsMod = req->numPDUSessionsMod, }; instance_t f1inst = get_f1_gtp_instance(); @@ -267,6 +325,7 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) req->pduSessionMod[i].numDRB2Modify); modif.pduSessionMod[i].id = req->pduSessionMod[i].sessionId; modif.pduSessionMod[i].numDRBModified = req->pduSessionMod[i].numDRB2Modify; + modif.numPDUSessionsMod++; /* DRBs to modify */ for (int j = 0; j < req->pduSessionMod[i].numDRB2Modify; j++) { const DRB_nGRAN_to_mod_t *to_modif = &req->pduSessionMod[i].DRBnGRanModList[j]; @@ -330,6 +389,15 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) } } + /* PDU Session Resource To Remove List (see 9.3.3.12 of TS 38.463) */ + for (int i = 0; i < req->numPDUSessionsRem; i++) { + modif.pduSessionMod[i].id = req->pduSessionRem[i].sessionId; + modif.numPDUSessionsMod++; + release_gtpu_tunnel(req->gNB_cu_up_ue_id, req->pduSessionRem[i].sessionId); + release_f1_drbs(req->gNB_cu_up_ue_id, req->pduSessionRem[i].sessionId); + nr_sdap_delete_entity(req->gNB_cu_up_ue_id, req->pduSessionRem[i].sessionId); + } + get_e1_if()->bearer_modif_response(&modif); } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index ce885b6b33..3fd4c4bdd4 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -575,75 +575,32 @@ void add_srb(int is_gnb, nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -void add_drb(int is_gnb, - ue_id_t UEid, - struct NR_DRB_ToAddMod *s, - const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) +void nr_pdcp_add_drb(int is_gnb, + const ue_id_t UEid, + const NR_PDCP_Config_t *pdcp, + const sdap_config_t *sdap, + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { - nr_pdcp_entity_t *pdcp_drb; nr_pdcp_ue_t *ue; - int drb_id = s->drb_Identity; - if (!s->pdcp_Config || !s->pdcp_Config->drb) { - LOG_E(PDCP, "DRB field mandatory present at setup. DRB %d not configured.\n", drb_id); + if (!pdcp->drb) { + LOG_E(PDCP, "Missing PDCP config. DRB %d not configured.\n", sdap->drb_id); return; } - struct NR_PDCP_Config__drb *drb = s->pdcp_Config->drb; + struct NR_PDCP_Config__drb *drb = pdcp->drb; int sn_size_ul = decode_sn_size_ul(*drb->pdcp_SN_SizeUL); int sn_size_dl = decode_sn_size_dl(*drb->pdcp_SN_SizeDL); int discard_timer = decode_discard_timer(*drb->discardTimer); - int has_integrity; - int has_ciphering; - /* if pdcp_Config->t_Reordering is not present, it means infinity (-1) */ int t_reordering = -1; - if (s->pdcp_Config->t_Reordering != NULL) { - t_reordering = decode_t_reordering(*s->pdcp_Config->t_Reordering); + if (pdcp->t_Reordering != NULL) { + t_reordering = decode_t_reordering(*pdcp->t_Reordering); } - if (drb->integrityProtection != NULL) - has_integrity = 1; - else - has_integrity = 0; - - if (s->pdcp_Config->ext1 != NULL && s->pdcp_Config->ext1->cipheringDisabled != NULL) - has_ciphering = 0; - else - has_ciphering = 1; - - if ((!s->cnAssociation) || s->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_NOTHING) { - LOG_E(PDCP, "fatal, cnAssociation is missing or present is NR_DRB_ToAddMod__cnAssociation_PR_NOTHING\n"); - exit(-1); - } - - int pdusession_id; - bool has_sdap_rx = false; - bool has_sdap_tx = false; - bool is_sdap_DefaultDRB = false; - NR_QFI_t *mappedQFIs2Add = NULL; - uint8_t mappedQFIs2AddCount=0; - if (s->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity) - pdusession_id = s->cnAssociation->choice.eps_BearerIdentity; - else { - if (!s->cnAssociation->choice.sdap_Config) { - LOG_E(PDCP,"fatal, sdap_Config is null"); - exit(-1); - } - pdusession_id = s->cnAssociation->choice.sdap_Config->pdu_Session; - has_sdap_rx = is_sdap_rx(is_gnb, s->cnAssociation->choice.sdap_Config); - has_sdap_tx = is_sdap_tx(is_gnb, s->cnAssociation->choice.sdap_Config); - is_sdap_DefaultDRB = s->cnAssociation->choice.sdap_Config->defaultDRB == true ? 1 : 0; - mappedQFIs2Add = (NR_QFI_t*)s->cnAssociation->choice.sdap_Config->mappedQoS_FlowsToAdd->list.array[0]; - mappedQFIs2AddCount = s->cnAssociation->choice.sdap_Config->mappedQoS_FlowsToAdd->list.count; - LOG_D(SDAP, "Captured mappedQoS_FlowsToAdd from RRC: %ld \n", *mappedQFIs2Add); - } - /* TODO(?): accept different UL and DL SN sizes? */ - if (sn_size_ul != sn_size_dl) { - LOG_E(PDCP, "fatal, bad SN sizes, must be same. ul=%d, dl=%d\n", sn_size_ul, sn_size_dl); - exit(1); - } + int has_integrity = (drb->integrityProtection != NULL) ? 1 : 0; + int has_ciphering = (pdcp->ext1 != NULL && pdcp->ext1->cipheringDisabled != NULL) ? 0 : 1; /* get actual ciphering and integrity algorithm based on pdcp_Config */ nr_pdcp_entity_security_keys_and_algos_t actual_security_parameters = *security_parameters; @@ -652,29 +609,33 @@ void add_drb(int is_gnb, nr_pdcp_manager_lock(nr_pdcp_ue_manager); ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, UEid); - if (nr_pdcp_get_rb(ue, drb_id, false) != NULL) { - LOG_W(PDCP, "warning DRB %d already exist for UE ID %ld, do nothing\n", drb_id, UEid); + if (nr_pdcp_get_rb(ue, sdap->drb_id, false) != NULL) { + LOG_W(PDCP, "warning DRB %d already exist for UE ID %ld, do nothing\n", sdap->drb_id, UEid); } else { - pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id, pdusession_id, - has_sdap_rx, has_sdap_tx, deliver_sdu_drb, ue, - is_gnb ? - deliver_pdu_drb_gnb : deliver_pdu_drb_ue, - ue, - sn_size_dl, t_reordering, discard_timer, - &actual_security_parameters); - nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb); + // code assumption: same SN size for both DL and UL + if (sn_size_ul != sn_size_dl) { + LOG_E(PDCP, "fatal, bad SN sizes, must be same. ul=%d, dl=%d\n", sn_size_ul, sn_size_dl); + exit(1); + } - LOG_I(PDCP, "added drb %d to UE ID %ld\n", drb_id, UEid); - /* add new SDAP entity for the PDU session the DRB belongs to */ - new_nr_sdap_entity(is_gnb, - has_sdap_rx, - has_sdap_tx, - UEid, - pdusession_id, - is_sdap_DefaultDRB, - drb_id, - mappedQFIs2Add, - mappedQFIs2AddCount); + // add PDCP entity + nr_pdcp_entity_t *pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, + is_gnb, + sdap->drb_id, + sdap->pdusession_id, + (sdap->role & (SDAP_UL_RX | SDAP_DL_RX)) != 0, + (sdap->role & (SDAP_UL_TX | SDAP_DL_TX)) != 0, + deliver_sdu_drb, + ue, + is_gnb ? deliver_pdu_drb_gnb : deliver_pdu_drb_ue, + ue, + sn_size_dl, + t_reordering, + discard_timer, + &actual_security_parameters); + nr_pdcp_ue_add_drb_pdcp_entity(ue, sdap->drb_id, pdcp_drb); + + LOG_I(PDCP, "Added DRB %d to UE ID %ld\n", sdap->drb_id, UEid); } nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } @@ -692,20 +653,28 @@ void nr_pdcp_add_srbs(eNB_flag_t enb_flag, LOG_W(PDCP, "nr_pdcp_add_srbs() with void list\n"); } -void nr_pdcp_add_drbs(eNB_flag_t enb_flag, - ue_id_t UEid, - NR_DRB_ToAddModList_t *const drb2add_list, - const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) +/** @brief Get DRB IDs for a specific PDU session */ +int nr_pdcp_get_drb_ids_for_pdusession(ue_id_t ue_id, long pdusession_id, int *drb_ids) { - if (drb2add_list != NULL) { - for (int i = 0; i < drb2add_list->list.count; i++) { - add_drb(enb_flag, - UEid, - drb2add_list->list.array[i], - security_parameters); + int num_found = 0; + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); + if (ue) { + for (int i = 0; i < MAX_DRBS_PER_UE; i++) { + nr_pdcp_entity_t *drb = ue->drb[i]; + if (drb && drb->pdusession_id == pdusession_id) { + if (num_found < MAX_DRBS_PER_UE) { + drb_ids[num_found] = drb->rb_id; + num_found++; + } else { + LOG_W(PDCP, "Found more DRBs than MAX_DRBS_PER_UE=%d\n", MAX_DRBS_PER_UE); + break; + } + } } - } else - LOG_W(PDCP, "nr_pdcp_add_drbs() with void list\n"); + } + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return num_found; } uint64_t get_pdcp_optmask(void) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index 375bd27458..75435ed695 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -33,6 +33,7 @@ #include "nr_pdcp_ue_manager.h" struct NR_DRB_ToAddMod; struct NR_SRB_ToAddMod; +struct sdap_configuration_s; void nr_pdcp_layer_init(void); @@ -42,20 +43,16 @@ bool nr_pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, const sdu_size_t sdu_buffer_size, uint8_t *const sdu_buffer); -void nr_pdcp_add_drbs(eNB_flag_t enb_flag, - ue_id_t UEid, - NR_DRB_ToAddModList_t *const drb2add_list, - const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); - void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t UEid, NR_SRB_ToAddModList_t *const srb2add_list, const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); -void add_drb(int is_gnb, - ue_id_t UEid, - struct NR_DRB_ToAddMod *s, - const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); +void nr_pdcp_add_drb(int is_gnb, + const ue_id_t UEid, + const NR_PDCP_Config_t *pdcp, + const struct sdap_configuration_s *sdap, + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); void nr_pdcp_remove_UE(ue_id_t ue_id); void nr_pdcp_reestablishment(ue_id_t ue_id, @@ -69,6 +66,7 @@ void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering); void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, NR_PDCP_Config_t *pdcp_config); void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id); void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id); +int nr_pdcp_get_drb_ids_for_pdusession(ue_id_t ue_id, long pdusession_id, int *drb_ids); void add_srb(int is_gnb, ue_id_t UEid, diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c index 07edfb5814..f4dc5c1d5d 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c @@ -178,7 +178,7 @@ void nr_pdcp_ue_add_srb_pdcp_entity(nr_pdcp_ue_t *ue, int srb_id, nr_pdcp_entity /* must be called with lock acquired */ void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity_t *entity) { - if (drb_id < 1 || drb_id > 5) { + if (drb_id < 1 || drb_id > MAX_DRBS_PER_UE) { LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index e187541fd5..126f9fb51c 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -672,7 +672,7 @@ void nr_rlc_reconfigure_entity(int ue_id, int lc_id, NR_RLC_Config_t *rlc_Config void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig) { - struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; + NR_RLC_Config_t *r = rlc_BearerConfig->rlc_Config; int t_status_prohibit; int t_poll_retransmit; int poll_pdu; @@ -682,8 +682,7 @@ void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_Bear int sn_field_length; LOG_D(RLC, "Trying to add SRB %d\n", srb_id); - AssertFatal(srb_id > 0 && srb_id < 4, - "Invalid srb id %d\n", srb_id); + AssertFatal(srb_id > 0 && srb_id < 4, "Invalid srb id %d\n", srb_id); if (r && r->present == NR_RLC_Config_PR_am) { struct NR_RLC_Config__am *am; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 2352870ace..18944a8099 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -41,7 +41,6 @@ #include "nfapi/oai_integration/gnb_ind_vars.h" #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi_interface.h" -#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #include "openair2/PHY_INTERFACE/queue_t.h" #include "utils.h" #include "nfapi/oai_integration/nfapi_pnf.h" @@ -379,52 +378,25 @@ static void match_crc_rx_pdu(nfapi_nr_rx_data_indication_t *rx_ind, nfapi_nr_crc } } -extern void handle_nr_slot_ind(uint16_t sfn, uint16_t slot); -static void pnf_send_slot_ind(module_id_t module_id, int CC_id, int frame, int slot) +extern void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, NR_Sched_Rsp_t *sched_response); +static void pnf_send_slot_ind(const nfapi_nr_slot_indication_scf_t *ind, NR_Sched_Rsp_t *rsp) { - (void)module_id; - (void)CC_id; - handle_nr_slot_ind(frame, slot); + module_id_t module_id = 0; + int CC_id = 0; + reset_sched_response(rsp, ind->sfn, ind->slot, module_id, CC_id); + handle_nr_slot_ind(ind->sfn, ind->slot, rsp); } -static void run_scheduler_monolithic(module_id_t module_id, int CC_id, int frame, int slot) +static void run_scheduler_monolithic(const nfapi_nr_slot_indication_scf_t *ind, NR_Sched_Rsp_t *rsp) { - NR_IF_Module_t *ifi = nr_if_inst[module_id]; - - LOG_D(NR_MAC, "Calling scheduler for %d.%d\n", frame, slot); - NR_Sched_Rsp_t *sched_info = allocate_sched_response(); - - // clear UL DCI prior to handling ULSCH - sched_info->UL_dci_req.numPdus = 0; - gNB_dlsch_ulsch_scheduler(module_id, frame, slot, sched_info); - ifi->CC_mask = 0; - sched_info->module_id = module_id; - sched_info->CC_id = CC_id; - sched_info->frame = frame; - sched_info->slot = slot; - /* - sched_info->DL_req = &mac->DL_req[CC_id]; - sched_info->UL_dci_req = &mac->UL_dci_req[CC_id]; - - sched_info->UL_tti_req = mac->UL_tti_req[CC_id]; - - sched_info->TX_req = &mac->TX_req[CC_id]; - */ -#ifdef DUMP_FAPI - dump_dl(sched_info); -#endif - - AssertFatal(ifi->NR_Schedule_response != NULL, "nr_schedule_response is null (mod %d, cc %d)\n", module_id, CC_id); - ifi->NR_Schedule_response(sched_info); - - LOG_D(NR_PHY, - "NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n", - sched_info->frame, - sched_info->slot, - sched_info->DL_req.dl_tti_request_body.nPDUs); + module_id_t module_id = 0; + int CC_id = 0; + reset_sched_response(rsp, ind->sfn, ind->slot, module_id, CC_id); + gNB_dlsch_ulsch_scheduler(rsp->module_id, ind->sfn, ind->slot, rsp); } -void NR_UL_indication(NR_UL_IND_t *UL_info) { +static void NR_UL_indication(NR_UL_IND_t *UL_info) +{ AssertFatal(UL_info!=NULL,"UL_info is null\n"); module_id_t module_id = UL_info->module_id; int CC_id = UL_info->CC_id; @@ -501,17 +473,47 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { nr_if_inst[Mod_id]->CC_mask=0; nr_if_inst[Mod_id]->NR_UL_indication = NR_UL_indication; - if (NFAPI_MODE == NFAPI_MONOLITHIC) + if (NFAPI_MODE == NFAPI_MONOLITHIC) { nr_if_inst[Mod_id]->NR_slot_indication = run_scheduler_monolithic; - else if (NFAPI_MODE == NFAPI_MODE_PNF) + } else if (NFAPI_MODE == NFAPI_MODE_PNF) { nr_if_inst[Mod_id]->NR_slot_indication = pnf_send_slot_ind; - else // NFAPI_MODE_VNF - NULL; + } else { // NFAPI_MODE_VNF + DevAssert(NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL); + nr_if_inst[Mod_id]->NR_slot_indication = run_scheduler_monolithic; + } AssertFatal(pthread_mutex_init(&nr_if_inst[Mod_id]->if_mutex,NULL)==0, "allocation of nr_if_inst[%d]->if_mutex fails\n",Mod_id); } - init_sched_response(); - return nr_if_inst[Mod_id]; } + +void reset_sched_response(NR_Sched_Rsp_t *sched_response, int frame, int slot, int module_id, int CC_id) +{ + sched_response->module_id = module_id; + sched_response->CC_id = CC_id; + sched_response->frame = frame; + sched_response->slot = slot; + + + nfapi_nr_dl_tti_request_t *DL_req = &sched_response->DL_req; + DL_req->SFN = frame; + DL_req->Slot = slot; + DL_req->dl_tti_request_body.nPDUs = 0; + DL_req->dl_tti_request_body.nGroup = 0; + + nfapi_nr_ul_dci_request_t *UL_dci_req = &sched_response->UL_dci_req; + UL_dci_req->SFN = frame; + UL_dci_req->Slot = slot; + UL_dci_req->numPdus = 0; + + nfapi_nr_ul_tti_request_t *UL_tti_req = &sched_response->UL_tti_req; + UL_tti_req->SFN = frame; + UL_tti_req->Slot = slot; + UL_tti_req->n_pdus = 0; + + nfapi_nr_tx_data_request_t *TX_req = &sched_response->TX_req; + TX_req->SFN = frame; + TX_req->Slot = slot; + TX_req->Number_of_PDUs = 0; +} diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h index 52a0f28871..49219a0af1 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h @@ -91,7 +91,7 @@ typedef struct { // Downlink slot P7 -typedef struct { +typedef struct NR_Sched_Rsp { /// the ID of this sched_response - used by sched_reponse memory management int sched_response_id; /// Module ID @@ -111,6 +111,7 @@ typedef struct { /// Pointers to DL SDUs nfapi_nr_tx_data_request_t TX_req; } NR_Sched_Rsp_t; +void reset_sched_response(NR_Sched_Rsp_t *sched_response, int frame, int slot, int module_id, int CC_id); typedef struct { uint8_t Mod_id; @@ -121,8 +122,7 @@ typedef struct { typedef struct NR_IF_Module_s { //define the function pointer void (*NR_UL_indication)(NR_UL_IND_t *UL_INFO); - void (*NR_Schedule_response)(NR_Sched_Rsp_t *Sched_INFO); - void (*NR_slot_indication)(module_id_t module_idP, int CC_id, int frame, int slot); + void (*NR_slot_indication)(const nfapi_nr_slot_indication_scf_t *ind, NR_Sched_Rsp_t *rsp); void (*NR_PHY_config_req)(NR_PHY_Config_t *config_INFO); uint32_t CC_mask; uint16_t current_frame; @@ -136,9 +136,4 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id); void NR_IF_Module_kill(int Mod_id); -void NR_UL_indication(NR_UL_IND_t *UL_INFO); - -/*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/ -void NR_Schedule_Response(NR_Sched_Rsp_t *Sched_INFO); - #endif /*_NFAPI_INTERFACE_NR_H_*/ diff --git a/openair2/NR_PHY_INTERFACE/nr_sched_response.c b/openair2/NR_PHY_INTERFACE/nr_sched_response.c deleted file mode 100644 index 9c66b21536..0000000000 --- a/openair2/NR_PHY_INTERFACE/nr_sched_response.c +++ /dev/null @@ -1,157 +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 - */ - -/* sched response memory management */ - -/* A system with reference counting is implemented. - * It is needed because several threads will access the structure, - * which has to be released only when all the threads are done with it. - * So the main thread allocates a sched_response with allocate_sched_response() - * which allocates a sched_response with a reference counter == 1 - * and then for each other thread that will access sched_response, a - * call to inc_ref_sched_response() is done. When a thread has finished - * using the sched_response, it calls deref_sched_response() which will - * in turn call release_sched_response() when the reference counter becomes 0. - * - * The several threads in question are accessing the _same_ sched_response, - * it has not to be confused with the various TX processes that may run in - * parallel and which are accessing _different_ sched_response (the maximum - * number of parallel processes is N_RESP). - */ - -#include "nr_sched_response.h" -#include -#include -#include -#include "NR_PHY_INTERFACE/NR_IF_Module.h" -#include "common/utils/LOG/log.h" -#include "common/utils/assertions.h" - -#define N_RESP 3 -static NR_Sched_Rsp_t resp[N_RESP]; -static int resp_refcount[N_RESP]; -static int resp_freelist_next[N_RESP]; -static int resp_freelist_head; -static pthread_mutex_t resp_mutex = PTHREAD_MUTEX_INITIALIZER; -static bool resp_freelist_inited = false; - -void init_sched_response(void) -{ - /* init only once */ - if (pthread_mutex_lock(&resp_mutex)) - AssertFatal(0, "pthread_mutex_lock failed\n"); - if (resp_freelist_inited) { - if (pthread_mutex_unlock(&resp_mutex)) - AssertFatal(0, "pthread_mutex_unlock failed\n"); - return; - } - resp_freelist_inited = true; - if (pthread_mutex_unlock(&resp_mutex)) - AssertFatal(0, "pthread_mutex_unlock failed\n"); - - int i; - for (i = 0; i < N_RESP - 1; i++) - resp_freelist_next[i] = i + 1; - resp_freelist_next[N_RESP - 1] = -1; - resp_freelist_head = 0; -} - -NR_Sched_Rsp_t *allocate_sched_response(void) -{ - NR_Sched_Rsp_t *ret; - int new_head; - - if (pthread_mutex_lock(&resp_mutex)) - AssertFatal(0, "pthread_mutex_lock failed\n"); - - AssertFatal(resp_freelist_inited, "sched_response used before init\n"); - - if (resp_freelist_head == -1) { - LOG_E(PHY, "fatal: sched_response cannot be allocated, increase N_RESP\n"); - exit(1); - } - - ret = &resp[resp_freelist_head]; - ret->sched_response_id = resp_freelist_head; - resp_refcount[resp_freelist_head] = 1; - - new_head = resp_freelist_next[resp_freelist_head]; - resp_freelist_next[resp_freelist_head] = -1; - resp_freelist_head = new_head; - - if (pthread_mutex_unlock(&resp_mutex)) - AssertFatal(0, "pthread_mutex_unlock failed\n"); - - return ret; -} - -static void release_sched_response(int sched_response_id) -{ - LOG_D(NR_MAC,"Releasing sched_response %d\n",sched_response_id); - resp_freelist_next[sched_response_id] = resp_freelist_head; - resp_freelist_head = sched_response_id; -} - -void deref_sched_response(int sched_response_id) -{ - /* simulators (ulsim/dlsim) deal with their own sched_response but call - * functions that call this one, let's handle this case with a special - * value -1 where we do nothing (yes it's a hack) - */ - if (sched_response_id == -1) - return; - - if (pthread_mutex_lock(&resp_mutex)) - AssertFatal(0, "pthread_mutex_lock failed\n"); - - AssertFatal(resp_freelist_inited, "sched_response used before init\n"); - AssertFatal(resp_refcount[sched_response_id] > 0, "sched_reponse decreased too much\n"); - - LOG_D(NR_MAC,"resp_refcount[%d] %d\n",sched_response_id,resp_refcount[sched_response_id]); - resp_refcount[sched_response_id]--; - if (resp_refcount[sched_response_id] == 0) - release_sched_response(sched_response_id); - - if (pthread_mutex_unlock(&resp_mutex)) - AssertFatal(0, "pthread_mutex_unlock failed\n"); -} - -void inc_ref_sched_response(int sched_response_id) -{ - /* simulators (ulsim/dlsim) deal with their own sched_response but call - * functions that call this one, let's handle this case with a special - * value -1 where we do nothing (yes it's a hack) - */ - if (sched_response_id == -1) - return; - - LOG_D(NR_MAC,"Incrementing sched_resp resp_refounct[%d] = %d\n", - sched_response_id,resp_refcount[sched_response_id]); - if (pthread_mutex_lock(&resp_mutex)) - AssertFatal(0, "pthread_mutex_lock failed\n"); - - AssertFatal(resp_freelist_inited, "sched_response used before init\n"); - - resp_refcount[sched_response_id]++; - - if (pthread_mutex_unlock(&resp_mutex)) - AssertFatal(0, "pthread_mutex_unlock failed\n"); -} diff --git a/openair2/NR_PHY_INTERFACE/nr_sched_response.h b/openair2/NR_PHY_INTERFACE/nr_sched_response.h deleted file mode 100644 index 33a0af93d0..0000000000 --- a/openair2/NR_PHY_INTERFACE/nr_sched_response.h +++ /dev/null @@ -1,32 +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 - */ - -#ifndef OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H -#define OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H - -#include "NR_IF_Module.h" - -void init_sched_response(void); -NR_Sched_Rsp_t *allocate_sched_response(void); -void deref_sched_response(int sched_response_id); -void inc_ref_sched_response(int sched_response_id); - -#endif /* OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H */ diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 23cd60b25f..0939b52c7a 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -82,7 +82,7 @@ void print_ue_mac_stats(const module_id_t mod, const int frame_rx, const int slo for (int i = 1; i < nb + 1; i++) cur += snprintf(cur, end - cur, "/%lu", mac->stats.dl.rounds[i]); - cur += snprintf(cur, end - cur, "\n Ul harq: %lu", mac->stats.ul.rounds[0]); + cur += snprintf(cur, end - cur, "\n UL harq: %lu", mac->stats.ul.rounds[0]); for (nb = NR_MAX_HARQ_ROUNDS_FOR_STATS - 1; nb > 1; nb--) if (mac->stats.ul.rounds[nb]) break; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 35b21a9722..585b1e48e2 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -519,7 +519,13 @@ static NR_RRCReconfiguration_IEs_t *build_RRCReconfiguration_IEs(const nr_rrc_re cfg->drb_ToAddModList = params->drb_config_list; cfg->securityConfig = params->security_config; cfg->srb3_ToRelease = NULL; - cfg->drb_ToReleaseList = params->drb_release_list; + if (params->n_drb_rel) { + asn1cCalloc(cfg->drb_ToReleaseList, to_release); + for (int i = 0; i < params->n_drb_rel; i++) { + asn1cSequenceAdd(to_release->list, NR_DRB_Identity_t, DRB_release); + *DRB_release = params->drb_rel[i]; + } + } } /* measConfig */ @@ -1020,7 +1026,7 @@ int do_RRCReestablishment(int8_t nh_ncc, uint8_t *const buffer, size_t buffer_si rrcReestablishment->criticalExtensions.choice.rrcReestablishment = CALLOC(1, sizeof(NR_RRCReestablishment_IEs_t)); // 3GPP TS 33.501 Section 6.11 Security handling for RRC connection re-establishment procedure - rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount = nh_ncc >= 0 ? nh_ncc : 0; + rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount = nh_ncc; rrcReestablishment->criticalExtensions.choice.rrcReestablishment->lateNonCriticalExtension = NULL; rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nonCriticalExtension = NULL; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 48a0ea734b..eb8da91c2a 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -64,7 +64,8 @@ typedef struct { uint8_t transaction_id; NR_SRB_ToAddModList_t *srb_config_list; NR_DRB_ToAddModList_t *drb_config_list; - NR_DRB_ToReleaseList_t *drb_release_list; + int *drb_rel; + int n_drb_rel; NR_SecurityConfig_t *security_config; NR_MeasConfig_t *meas_config; byte_array_t dedicated_NAS_msg_list[MAX_DRBS_PER_UE]; diff --git a/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp b/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp index 1f92c5aae5..025978218e 100644 --- a/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp +++ b/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp @@ -88,7 +88,6 @@ TEST(nr_asn1, paging) void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params) { ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, params.meas_config); - ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, params.drb_release_list); ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, params.drb_config_list); ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, params.srb_config_list); ASN_STRUCT_FREE(asn_DEF_NR_SecurityConfig, params.security_config); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index e76802338c..4d24a771c0 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -97,7 +97,6 @@ typedef enum pdu_session_satus_e { PDU_SESSION_STATUS_TOMODIFY, // ENDC NSA PDU_SESSION_STATUS_FAILED, PDU_SESSION_STATUS_TORELEASE, // to release DRB between eNB and UE - PDU_SESSION_STATUS_RELEASED } pdu_session_status_t; typedef struct pdusession_s { @@ -149,6 +148,12 @@ typedef enum { RRC_UECAPABILITY_ENQUIRY, } rrc_action_t; +/* Small state for delaying NG-triggered actions (setup/release) */ +typedef struct { + int max_delays; + bool ongoing_transaction; +} delayed_action_state_t; + typedef struct nr_redcap_ue_cap { bool support_of_redcap_r17; bool support_of_16drb_redcap_r17; @@ -167,8 +172,6 @@ typedef struct nr_handover_context_s nr_handover_context_t; typedef struct gNB_RRC_UE_s { time_t last_seen; // last time this UE has been accessed - NR_DRB_ToReleaseList_t *DRB_ReleaseList; - NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB]; NR_MeasConfig_t *measConfig; nr_handover_context_t *ho_context; @@ -188,7 +191,6 @@ typedef struct gNB_RRC_UE_s { /* KgNB as derived from KASME received from EPC */ uint8_t kgnb[32]; - int8_t kgnb_ncc; uint8_t nh[32]; int8_t nh_ncc; @@ -209,6 +211,8 @@ typedef struct gNB_RRC_UE_s { uint64_t amf_ue_ngap_id; // Globally Unique AMF Identifier nr_guami_t ue_guami; + // Serving PLMN of the UE + plmn_id_t serving_plmn; ngap_security_capabilities_t security_capabilities; //NSA block @@ -243,8 +247,7 @@ typedef struct gNB_RRC_UE_s { byte_array_t nas_pdu; /* hack, see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() for more info */ - int max_delays_pdu_session; - bool ongoing_pdusession_setup_request; + delayed_action_state_t delayed_action; nr_redcap_ue_cap_t *redcap_cap; } gNB_RRC_UE_t; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 777ea9a8d1..a36a0778c6 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -66,12 +66,6 @@ void *rrc_gnb_task(void *args_p); int nr_rrc_reconfiguration_req(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p, const int dl_bwp_id, const int ul_bwp_id); -void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, - gNB_RRC_UE_t *ue_p, - uint8_t xid, - uint32_t nas_length, - uint8_t *nas_buffer); - NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cellid); bool ue_associated_to_cuup(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue); @@ -128,5 +122,6 @@ NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish); NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish, bool do_integrity, bool do_ciphering); void activate_srb(gNB_RRC_UE_t *UE, int srb_id); void e1_notify_pdcp_status(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const ngap_drb_status_t *drb_status); +void init_delayed_action(delayed_action_state_t *delayed_action); #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index c2734c755a..e1d2dbe841 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -115,6 +115,97 @@ mui_t rrc_gNB_mui = 0; +/* Per-transaction max_delays counter to limit retry attempts */ +#define MAX_DELAYS 100 + +/** @brief clone and re-enqueue an NGAP message after delaying + * delays the ongoing transaction (in msg_p) by setting a timer to wait + * 10ms; upon expiry, delivers to RRC, which sends the message to itself */ +static void delay_transaction(MessageDef *msg_p, int wait_us) +{ + MessagesIds id = ITTI_MSG_ID(msg_p); + AssertFatal(id == NGAP_PDUSESSION_SETUP_REQ || id == NGAP_PDUSESSION_RELEASE_COMMAND, + "delay_transaction(): unsupported message id %d\n", + id); + + MessageDef *new = itti_alloc_new_message(TASK_RRC_GNB, 0, id); + + // Copy only the specific message struct, not the entire union. + // The union (msg_t) contains all message types and is much larger than + // the allocated space (which is sized for the specific message type only). + if (id == NGAP_PDUSESSION_SETUP_REQ) { + NGAP_PDUSESSION_SETUP_REQ(new) = NGAP_PDUSESSION_SETUP_REQ(msg_p); + } else if (id == NGAP_PDUSESSION_RELEASE_COMMAND) { + NGAP_PDUSESSION_RELEASE_COMMAND(new) = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p); + } + + int instance = msg_p->ittiMsgHeader.originInstance; + long timer_id; + timer_setup(0, wait_us, TASK_RRC_GNB, instance, TIMER_ONE_SHOT, new, &timer_id); +} + +static void reset_delayed_action(delayed_action_state_t *delayed_action) +{ + delayed_action->ongoing_transaction = false; + delayed_action->max_delays = 0; +} + +void init_delayed_action(delayed_action_state_t *delayed_action) +{ + delayed_action->ongoing_transaction = true; + delayed_action->max_delays = MAX_DELAYS; +} + +/* \brief checks if any transaction is ongoing for any xid of this UE */ +static bool transaction_ongoing(const gNB_RRC_UE_t *UE) +{ + for (int xid = 0; xid < NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; ++xid) { + if (UE->xids[xid] != RRC_ACTION_NONE) + return true; + } + return false; +} + +/** @brief delay control: returns true if delayed, false if should proceed + * This is a hack. We observed that with some UEs, PDU session requests might + * come in quick succession, faster than the RRC reconfiguration for the PDU + * session requests can be carried out (UE is doing reconfig, and second PDU + * session request arrives). We don't have currently the means to "queue up" + * these transactions, which would probably involve some rework of the RRC. + * To still allow these requests to come in and succeed, we below check and delay transactions + * for 10ms. However, to not accidentally end up in infinite loops, the + * maximum number is capped on a per-UE basis as indicated in variable + * max_delays_pdu_session. See commit 277f8da0 for more details. */ +static bool rrc_delay_transaction(instance_t instance, MessageDef *msg_p) +{ + uint32_t cu_ue_id = 0; + if (ITTI_MSG_ID(msg_p) == NGAP_PDUSESSION_SETUP_REQ) { + cu_ue_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id; + } else if (ITTI_MSG_ID(msg_p) == NGAP_PDUSESSION_RELEASE_COMMAND) { + cu_ue_id = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id; + } + AssertFatal(cu_ue_id > 0, "cu_ue_id not found in message %s\n", ITTI_MSG_NAME(msg_p)); + + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], cu_ue_id); + DevAssert(ue_context_p); + + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + bool delay = UE->delayed_action.ongoing_transaction && UE->delayed_action.max_delays > 0; + /* Check if any PDU session action is ongoing */ + if (delay || transaction_ongoing(UE)) { + int wait_us = 10000; + LOG_I(NR_RRC, + "UE %d: ongoing transaction, delaying incoming transaction by %d us\n", + UE->rrc_ue_id, + wait_us); + delay_transaction(msg_p, wait_us); + UE->delayed_action.max_delays--; + return true; /* delayed */ + } + LOG_D(NR_RRC, "UE %d: no delayed action ongoing, proceeding with incoming transaction\n", UE->rrc_ue_id); + return false; /* not delayed */ +} + typedef struct deliver_ue_ctxt_release_data_t { gNB_RRC_INST *rrc; f1ap_ue_context_rel_cmd_t *release_cmd; @@ -366,6 +457,10 @@ NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish, bool do LOG_D(NR_RRC, "PDU Session %d not found, skip\n", drb->pdusession_id); continue; } + if (pduSession->status > PDU_SESSION_STATUS_TOMODIFY) { + LOG_D(NR_RRC, "PDU Session %d is not to add/mod\n", drb->pdusession_id); + continue; + } pdusession_t *session = &pduSession->param; NR_DRB_ToAddMod_t *drb_ToAddMod = calloc_or_fail(1, sizeof(*drb_ToAddMod)); drb_ToAddMod->drb_Identity = drb->drb_id; @@ -625,10 +720,10 @@ static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params) { - ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, params.drb_release_list); ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, params.drb_config_list); ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, params.srb_config_list); ASN_STRUCT_FREE(asn_DEF_NR_SecurityConfig, params.security_config); + free(params.drb_rel); for (int i = 0; i < params.num_nas_msg; i++) FREE_AND_ZERO_BYTE_ARRAY(params.dedicated_NAS_msg_list[i]); } @@ -706,19 +801,37 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC nr_rrc_reconfig_param_t params = {.cell_group_config = UE->masterCellGroup, .transaction_id = xid, .drb_config_list = DRBs, - .drb_release_list = UE->DRB_ReleaseList, .meas_config = UE->measConfig, .srb_config_list = SRBs}; - UE->DRB_ReleaseList = NULL; // pointer transferred to params FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &UE->pduSessions) { pdusession_t *session = &item->param; + // Collect NAS PDUs if (session->nas_pdu.len > 0) { params.dedicated_NAS_msg_list[params.num_nas_msg++] = session->nas_pdu; session->nas_pdu.buf = NULL; session->nas_pdu.len = 0; LOG_D(NR_RRC, "Transfer NAS info with size %ld to RRCReconfiguration params\n", session->nas_pdu.len); } + // Collect DRBs to release for PDU sessions marked for release + if (item->status == PDU_SESSION_STATUS_TORELEASE) { + if (!params.drb_rel) + params.drb_rel = calloc_or_fail(MAX_DRBS_PER_UE, sizeof(int)); + FOR_EACH_SEQ_ARR (drb_t *, drb, &UE->drbs) { + if (drb->pdusession_id == session->pdusession_id) { + if (params.n_drb_rel >= MAX_DRBS_PER_UE) { + LOG_E(NR_RRC, "UE %d: Too many DRBs to release (max %d)\n", UE->rrc_ue_id, MAX_DRBS_PER_UE); + break; + } + params.drb_rel[params.n_drb_rel++] = drb->drb_id; + LOG_D(NR_RRC, + "UE %d: Added DRB %d to release list for PDU session %d\n", + UE->rrc_ue_id, + drb->drb_id, + session->pdusession_id); + } + } + } } if (UE->nas_pdu.len > 0) { @@ -746,21 +859,24 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_ { /* do not re-establish PDCP for any bearer */ nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, ue_p, 0, false); - ue_p->xids[params.transaction_id] = RRC_PDUSESSION_ESTABLISH; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { + if (item->status == PDU_SESSION_STATUS_NEW) { + item->status = PDU_SESSION_STATUS_DONE; + continue; + } + // Set xid for all PDU sessions + item->xid = params.transaction_id; + } + + // Set xid for RRC transaction + ue_p->xids[params.transaction_id] = params.n_drb_rel > 0 ? RRC_PDUSESSION_RELEASE : RRC_PDUSESSION_ESTABLISH; + byte_array_t msg = rrc_gNB_encode_RRCReconfiguration(rrc, ue_p, params); if (msg.len <= 0) { LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id); return; } - FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { - if (item->param.nas_pdu.buf) - item->xid = params.transaction_id; - if (item->status < PDU_SESSION_STATUS_ESTABLISHED) { - item->status = PDU_SESSION_STATUS_DONE; - } - } - LOG_UE_DL_EVENT(ue_p, "Generate RRCReconfiguration (bytes %ld, xid %d)\n", msg.len, params.transaction_id); const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len); @@ -831,44 +947,27 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t free_byte_array(msg); } -//----------------------------------------------------------------------------- -void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, - gNB_RRC_UE_t *ue_p, - uint8_t xid, - uint32_t nas_length, - uint8_t *nas_buffer) -//----------------------------------------------------------------------------- +static void rrc_gNB_send_f1_drb_release_request(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p, int *drb_to_release, int n_drb_to_release) { - nr_rrc_reconfig_param_t params = {.transaction_id = xid}; + f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); + f1ap_ue_context_mod_req_t req = { + .gNB_CU_ue_id = ue_p->rrc_ue_id, + .gNB_DU_ue_id = ue_data.secondary_ue, + .servCellIndex = 0, + }; + req.plmn = malloc_or_fail(sizeof(*req.plmn)); + *req.plmn = rrc->configuration.plmn[0]; + req.nr_cellid = malloc_or_fail(sizeof(*req.nr_cellid)); + *req.nr_cellid = rrc->nr_cellid; + req.drbs_rel = malloc_or_fail(sizeof(*req.drbs_rel)); + req.drbs_rel_len = n_drb_to_release; + memcpy(req.drbs_rel, drb_to_release, n_drb_to_release * sizeof(int)); - NR_DRB_ToReleaseList_t *to_release = CALLOC(sizeof(*to_release), 1); - FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { - if ((item->status != PDU_SESSION_STATUS_TORELEASE) && item->xid != xid) - continue; - FOR_EACH_SEQ_ARR(drb_t *, drb, &ue_p->drbs) { - if (drb->pdusession_id == item->param.pdusession_id) { - asn1cSequenceAdd(to_release->list, NR_DRB_Identity_t, DRB_release); - *DRB_release = drb->drb_id; // DRB ID - } - } - } - params.drb_release_list = to_release; - - if (nas_length > 0) { - params.dedicated_NAS_msg_list[params.num_nas_msg].buf = nas_buffer; - params.dedicated_NAS_msg_list[params.num_nas_msg++].len = nas_length; - } - byte_array_t msg = do_RRCReconfiguration(¶ms); - if (msg.len <= 0) { - LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id); - return; - } - LOG_DUMPMSG(NR_RRC, DEBUG_RRC, msg.buf, msg.len, "[MSG] RRC Reconfiguration\n"); - LOG_I(NR_RRC, "UE %d: Generate NR_RRCReconfiguration (bytes %ld)\n", ue_p->rrc_ue_id, msg.len); - const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; - nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len); - free_RRCReconfiguration_params(params); - free_byte_array(msg); + /* send UE Context Modification to DU without attaching any RRC container */ + rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &req); + LOG_I(NR_RRC, "UE %d: send F1 UE Context Modification Request with DRB release (%d DRBs)\n", ue_p->rrc_ue_id, req.drbs_rel_len); + free_ue_context_mod_req(&req); } static void fill_security_info(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, security_information_t *secInfo) @@ -964,15 +1063,10 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) } } -#if 0 - /* According to current understanding of E1 specifications, it is not needed - * to send security information because this does not change. - * But let's keep the code here in case it's needed. - */ - // Always send security information + /* During reestablishment, for DRB integrity protection security keys change (KgNB* is derived), + * so security information MUST be sent to CU-UP to update DRB security keys. */ req.secInfo = malloc_or_fail(sizeof(*req.secInfo)); fill_security_info(rrc, ue_p, req.secInfo); -#endif /* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */ sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p); @@ -998,8 +1092,7 @@ 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); - ue_p->kgnb_ncc = 0; + 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); 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); @@ -1284,6 +1377,20 @@ static rrc_gNB_ue_context_t *rrc_gNB_get_ue_context_source_cell(gNB_RRC_INST *rr return NULL; } +/** + * @brief Rollback F1-U DL TL and TEID in RRC + */ +static void f1u_dl_gtp_rollback(gNB_RRC_UE_t *UE) +{ + DevAssert(UE != NULL); + DevAssert(UE->ho_context->source != NULL); + + FOR_EACH_SEQ_ARR(drb_t *, drb, &UE->drbs) { + drb->du_tunnel_config = UE->ho_context->source->old_du_tunnel_config; + LOG_W(NR_RRC, "DRB id %d rollback to tunnel TEID %x\n", drb->drb_id, drb->du_tunnel_config.teid); + } +} + static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id, const NR_RRCReestablishmentRequest_IEs_t *req, @@ -1362,6 +1469,7 @@ static void rrc_handle_RRCReestablishmentRequest(gNB_RRC_INST *rrc, } source_ctx->ho_cancel(rrc, UE); + f1u_dl_gtp_rollback(UE); /* we need the original CellGroupConfig */ ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); @@ -1833,10 +1941,8 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U switch (UE->xids[xid]) { case RRC_PDUSESSION_RELEASE: { - gtpv1u_gnb_delete_tunnel_req_t req = {0}; - gtpv1u_delete_ngu_tunnel(rrc->module_id, &req); - // NGAP_PDUSESSION_RELEASE_RESPONSE rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(rrc, UE, xid); + reset_delayed_action(&UE->delayed_action); } break; case RRC_PDUSESSION_ESTABLISH: if (UE->n_initial_pdu > 0) { @@ -1851,6 +1957,7 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U LOG_W(NR_RRC, "UE %d: RRC Reconfiguration Complete for PDU session establishment, but no PDU sessions were setup\n", UE->rrc_ue_id); + reset_delayed_action(&UE->delayed_action); break; case RRC_PDUSESSION_MODIFY: rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(rrc, UE, xid); @@ -1867,9 +1974,6 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U break; } - if (UE->xids[xid] == RRC_PDUSESSION_ESTABLISH) - UE->ongoing_pdusession_setup_request = false; - UE->xids[xid] = RRC_ACTION_NONE; for (int i = 0; i < NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; ++i) { if (UE->xids[i] != RRC_ACTION_NONE) { @@ -2714,15 +2818,19 @@ void rrc_gNB_process_e1_bearer_context_setup_failure(e1ap_bearer_context_setup_f */ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t *resp) { + LOG_I(NR_RRC, "Received E1AP Bearer Context Modification Response for UE CU-CP ID %d\n", resp->gNB_cu_cp_ue_id); gNB_RRC_INST *rrc = RC.nrrrc[0]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_cu_cp_ue_id); if (ue_context_p == NULL) { LOG_E(RRC, "no UE with CU-CP UE ID %d found\n", resp->gNB_cu_cp_ue_id); return; } + gNB_RRC_UE_t *ue = &ue_context_p->ue_context; int n_drb_mod = 0; int drb_ids[MAX_DRBS_PER_UE] = {0}; + int drb_to_release[MAX_DRBS_PER_UE] = {0}; + int n_drb_to_release = 0; e1_pdcp_status_info_t pdcp_status[MAX_DRBS_PER_UE] = {0}; for (int i = 0; i < resp->numPDUSessionsMod; ++i) { const pdu_session_modif_t *pdu = &resp->pduSessionMod[i]; @@ -2735,13 +2843,32 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t pdcp_status[n_drb_mod++] = *pdu->DRBnGRanModList[j].pdcp_status; } } + // Collect DRBs to release for PDU sessions marked for release + rrc_pdu_session_param_t *pdu_session = find_pduSession(&ue->pduSessions, pdu->id); + if (pdu_session && pdu_session->status == PDU_SESSION_STATUS_TORELEASE) { + FOR_EACH_SEQ_ARR(drb_t *, drb, &ue->drbs) { + if (drb->pdusession_id == pdu->id) { + DevAssert(n_drb_to_release < MAX_DRBS_PER_UE); + drb_to_release[n_drb_to_release++] = drb->drb_id; + } + } + if (n_drb_to_release == 0) { + LOG_E(NR_RRC, "UE %d: no DRBs to release for PDU session %ld\n", ue->rrc_ue_id, pdu->id); + } + } } + if (n_drb_mod) { LOG_I(NR_RRC, "UE %d: received PDU Status Info - send UL RAN Status Transfer\n", resp->gNB_cu_cp_ue_id); - gNB_RRC_UE_t *ue = &ue_context_p->ue_context; if (ue->ho_context && ue->ho_context->source) ue->ho_context->source->ho_status_transfer(rrc, ue, n_drb_mod, drb_ids, pdcp_status); } + + // Send F1 UE Context Modification Request with DRB release + if (n_drb_to_release) { + LOG_I(NR_RRC, "Send F1 UE Context Modification Request with DRB to release\n"); + rrc_gNB_send_f1_drb_release_request(rrc, ue, drb_to_release, n_drb_to_release); + } } /** @brief E1AP Bearer Context Modification Failure processing on CU-CP */ @@ -2838,7 +2965,6 @@ static const char *get_pdusession_status_text(pdu_session_status_t status) case PDU_SESSION_STATUS_TOMODIFY: return "to-modify"; case PDU_SESSION_STATUS_FAILED: return "failed"; case PDU_SESSION_STATUS_TORELEASE: return "to-release"; - case PDU_SESSION_STATUS_RELEASED: return "released"; default: AssertFatal(false, "illegal PDU status code %d\n", status); return "illegal"; } return "illegal"; @@ -2964,7 +3090,8 @@ void *rrc_gnb_task(void *args_p) { break; case NGAP_PDUSESSION_SETUP_REQ: - rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(msg_p, instance); + if (!rrc_delay_transaction(instance, msg_p)) + rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(msg_p, instance); break; case NGAP_PDUSESSION_MODIFY_REQ: @@ -2972,7 +3099,8 @@ void *rrc_gnb_task(void *args_p) { break; case NGAP_PDUSESSION_RELEASE_COMMAND: - rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(msg_p, instance); + if (!rrc_delay_transaction(instance, msg_p)) + rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(&NGAP_PDUSESSION_RELEASE_COMMAND(msg_p), RC.nrrrc[instance]); break; case NGAP_DL_RAN_STATUS_TRANSFER: @@ -3274,26 +3402,7 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, } nr_rrc_du_container_t *du = get_du_for_ue((gNB_RRC_INST *)rrc, ue_p->rrc_ue_id); - byte_array_t *meas_timing_config = NULL; - if (du->mtc && ue_p->measConfig && ue_p->measConfig->measObjectToAddModList) { - NR_MeasObjectToAddModList_t *mo_list = ue_p->measConfig->measObjectToAddModList; - NR_ARFCN_ValueNR_t ssbFrequency0; - for (int i = 0; i < mo_list->list.count; i++) { - NR_MeasObjectToAddMod_t *mo = mo_list->list.array[i]; - if (mo->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) { - NR_MeasObjectNR_t *monr = mo->measObject.choice.measObjectNR; - if (i == 0) { - ssbFrequency0 = *monr->ssbFrequency; - } else if (ssbFrequency0 != *monr->ssbFrequency) { - meas_timing_config = calloc_or_fail(1, sizeof(*meas_timing_config)); - meas_timing_config->buf = calloc_or_fail(1, NR_RRC_BUF_SIZE); - meas_timing_config->len = do_NR_MeasurementTimingConfiguration(du->mtc, meas_timing_config->buf, NR_RRC_BUF_SIZE); - cu2du.meas_timing_config = meas_timing_config; - break; - } - } - } - } + cu2du.meas_timing_config = get_meas_timing_config(du->mtc, ue_p->measConfig); int nb_srb = 1; f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs)); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 7d75384a9b..979fe0ac5e 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -110,6 +110,24 @@ static const uint16_t NGAP_INTEGRITY_NIA3_MASK = 0x2000; static void set_UE_security_algos(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const ngap_security_capabilities_t *cap); +/** @brief Validates PLMN against allowed PLMN list and returns pointer to matching PLMN + * @param rrc RRC instance + * @param plmn PLMN to validate + * @return pointer to matching PLMN in configuration, or NULL if not found */ +static const plmn_id_t *get_serving_plmn(gNB_RRC_INST *rrc, const plmn_id_t *plmn) +{ + // Find matching PLMN in configuration + for (int idx = 0; idx < rrc->configuration.num_plmn; idx++) { + const plmn_id_t *allowed = &rrc->configuration.plmn[idx]; + if (allowed->mcc == plmn->mcc && allowed->mnc == plmn->mnc && allowed->mnc_digit_length == plmn->mnc_digit_length) { + LOG_D(NR_RRC, "PLMN (MCC:%d, MNC:%*d) matched with allowed PLMN[%d]\n", plmn->mcc, plmn->mnc_digit_length, plmn->mnc, idx); + return allowed; + } + } + LOG_W(NR_RRC, "PLMN (MCC:%d, MNC:%*d) not found in allowed PLMN list\n", plmn->mcc, plmn->mnc_digit_length, plmn->mnc); + return NULL; +} + /*! *\brief save security key. *\param UE UE context. @@ -122,7 +140,9 @@ static void set_UE_security_key(gNB_RRC_UE_t *UE, uint8_t *security_key_pP) /* Saves the security key */ memcpy(UE->kgnb, security_key_pP, SECURITY_KEY_LENGTH); memset(UE->nh, 0, SECURITY_KEY_LENGTH); - UE->nh_ncc = -1; + /* 3GPP TS 33.501 §6.9.2.1.1: On Initial Context Setup, AMF does not send NH; + * gNB shall initialize NCC to 0. */ + UE->nh_ncc = 0; char ascii_buffer[65]; for (i = 0; i < 32; i++) { @@ -165,9 +185,7 @@ static nr_guami_t get_guami(const uint32_t amf_Id, const plmn_id_t plmn) guami.amf_region_id = (amf_Id >> 16) & 0xff; guami.amf_set_id = (amf_Id >> 6) & 0x3ff; guami.amf_pointer = amf_Id & 0x3f; - guami.mcc = plmn.mcc; - guami.mnc = plmn.mnc; - guami.mnc_len = plmn.mnc_digit_length; + guami.plmn = plmn; return guami; } @@ -223,17 +241,22 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC req->nas_pdu = create_byte_array(rrcSetupComplete->dedicatedNAS_Message.size, rrcSetupComplete->dedicatedNAS_Message.buf); /* Selected PLMN Identity (Optional) - * selectedPLMN-Identity in RRCSetupComplete: Index of the PLMN selected by the UE from the plmn-IdentityInfoList (SIB1) - * Selected PLMN Identity in INITIAL UE MESSAGE: Indicates the selected PLMN id for the non-3GPP access.*/ - if (rrcSetupComplete->selectedPLMN_Identity > rrc->configuration.num_plmn) { + * selectedPLMN-Identity in RRCSetupComplete: Index of the PLMN selected by the UE from the plmn-IdentityInfoList (SIB1) */ + int idx = rrcSetupComplete->selectedPLMN_Identity - 1; // Convert 1-based PLMN Identity IE to 0-based index + if (idx < 0 || idx >= rrc->configuration.num_plmn) { LOG_E(NGAP, - "Failed to send Initial UE Message: selected PLMN (%ld) identity is out of bounds (%d)\n", - rrcSetupComplete->selectedPLMN_Identity, + "Failed to send Initial UE Message: selected PLMN index (%d) is out of bounds [0..%d)\n", + idx, rrc->configuration.num_plmn); return; } - int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1; // Convert 1-based PLMN Identity IE to 0-based index - req->plmn = rrc->configuration.plmn[selected_plmn_identity]; // Select from the stored list + req->plmn = rrc->configuration.plmn[idx]; // Select from the stored list + /* UE is connected to only one PLMN at a time: store this as the serving PLMN */ + UE->serving_plmn = req->plmn; + + // Cell ID (NR CGI) + req->nr_cell_id = UE->nr_cellid; + // PLMN (NR CGI and TAI) plmn_id_t *p = &req->plmn; LOG_I(NGAP, "Selected PLMN in the NG Initial UE Message: MCC=%03d MNC=%0*d\n", p->mcc, p->mnc_digit_length, p->mnc); @@ -721,6 +744,10 @@ void rrc_gNB_send_NGAP_UPLINK_NAS(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_ NGAP_UPLINK_NAS(msg_p).gNB_ue_ngap_id = UE->rrc_ue_id; NGAP_UPLINK_NAS(msg_p).nas_pdu.len = nas->size; NGAP_UPLINK_NAS(msg_p).nas_pdu.buf = buf; + /* Fill PLMN and location info: use serving PLMN of the UE */ + NGAP_UPLINK_NAS(msg_p).plmn = UE->serving_plmn; + NGAP_UPLINK_NAS(msg_p).nr_cell_id = rrc->nr_cellid; + NGAP_UPLINK_NAS(msg_p).tac = rrc->configuration.tac; itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p); } @@ -762,29 +789,6 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE return; } -/* \brief checks if any transaction is ongoing for any xid of this UE */ -static bool transaction_ongoing(const gNB_RRC_UE_t *UE) -{ - for (int xid = 0; xid < NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; ++xid) { - if (UE->xids[xid] != RRC_ACTION_NONE) - return true; - } - return false; -} - -/* \brief delays the ongoing transaction (in msg_p) by setting a timer to wait - * 10ms; upon expiry, delivers to RRC, which sends the message to itself */ -static void delay_transaction(MessageDef *msg_p, int wait_us) -{ - MessageDef *new = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_REQ); - ngap_pdusession_setup_req_t *n = &NGAP_PDUSESSION_SETUP_REQ(new); - *n = NGAP_PDUSESSION_SETUP_REQ(msg_p); - - int instance = msg_p->ittiMsgHeader.originInstance; - long timer_id; - timer_setup(0, wait_us, TASK_RRC_GNB, instance, TIMER_ONE_SHOT, new, &timer_id); -} - /** * @brief Fill PDU Session Resource Setup Response with a list of PDU Session Resources Failed to Setup * and send ITTI message to TASK_NGAP @@ -856,25 +860,6 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins UE->amf_ue_ngap_id = msg->amf_ue_ngap_id; - /* This is a hack. We observed that with some UEs, PDU session requests might - * come in quick succession, faster than the RRC reconfiguration for the PDU - * session requests can be carried out (UE is doing reconfig, and second PDU - * session request arrives). We don't have currently the means to "queue up" - * these transactions, which would probably involve some rework of the RRC. - * To still allow these requests to come in and succeed, we below check and delay transactions - * for 10ms. However, to not accidentally end up in infinite loops, the - * maximum number is capped on a per-UE basis as indicated in variable - * max_delays_pdu_session. */ - if (!UE->ongoing_pdusession_setup_request) - UE->max_delays_pdu_session = 100; - - if (UE->max_delays_pdu_session > 0 && (transaction_ongoing(UE) || UE->ongoing_pdusession_setup_request)) { - int wait_us = 10000; - LOG_I(RRC, "UE %d: delay PDU session setup by %d us, pending %d retries\n", UE->rrc_ue_id, wait_us, UE->max_delays_pdu_session); - delay_transaction(msg_p, wait_us); - UE->max_delays_pdu_session--; - return; - } pdusession_t to_setup[NGAP_MAX_PDU_SESSION] = {0}; for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) @@ -889,7 +874,8 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins send_ngap_pdu_session_setup_resp_fail(instance, msg, cause); rrc_forward_ue_nas_message(rrc, UE); } else { - UE->ongoing_pdusession_setup_request = true; + // Set ongoing_transaction flag to true + init_delayed_action(&UE->delayed_action); } } @@ -1154,6 +1140,20 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga rrc_gNB_send_NGAP_HANDOVER_FAILURE(rrc, &fail); return -1; } + + // Validate PLMN from GUAMI against allowed PLMN list + const plmn_id_t *serving_plmn = get_serving_plmn(rrc, &msg->guami.plmn); + if (!serving_plmn) { + LOG_E(NR_RRC, "PLMN from GUAMI not supported - rejecting handover\n"); + ngap_handover_failure_t fail = { + .amf_ue_ngap_id = msg->amf_ue_ngap_id, + .cause.type = NGAP_CAUSE_RADIO_NETWORK, + .cause.value = NGAP_CAUSE_RADIO_NETWORK_HO_TARGET_NOT_ALLOWED, + }; + rrc_gNB_send_NGAP_HANDOVER_FAILURE(rrc, &fail); + return -1; + } + uint16_t pci = du->setup_req->cell[0].info.nr_pci; LOG_I(NR_RRC, "Received Handover Request (on NR Cell ID=%lu, PCI=%u) \n", msg->nr_cell_id, pci); @@ -1169,6 +1169,9 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga // Store IDs in UE context UE->amf_ue_ngap_id = msg->amf_ue_ngap_id; UE->ue_guami = msg->guami; + // Store the serving PLMN + UE->serving_plmn = *serving_plmn; + UE->ho_context->target->ue_ho_prep_info = copy_byte_array(msg->ue_ho_prep_info); // store the received UE Security Capabilities in the UE context FREE_AND_ZERO_BYTE_ARRAY(UE->ue_cap_buffer); @@ -1189,7 +1192,11 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga // Activate SRBs activate_srb(UE, SRB1); activate_srb(UE, SRB2); - nr_rrc_pdcp_config_security(UE, false); + // During N2 handover, the UE continues using the old security context from the source gNB + // until it receives and processes the RRC Reconfiguration with masterKeyUpdate. The first + // PDUs sent after CFRA are still ciphered with the old keys. The target gNB must enable + // ciphering during handover setup to correctly decipher and verify integrity of these PDUs. + nr_rrc_pdcp_config_security(UE, true); // Process all PDU Session Resource Setup items from handover request DevAssert(msg->nb_of_pdusessions <= NGAP_MAX_PDU_SESSION); @@ -1518,68 +1525,75 @@ void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE DevAssert(resp->nb_of_pdusessions_released < NGAP_MAX_PDU_SESSION); resp->pdusession_release[resp->nb_of_pdusessions_released++].pdusession_id = pdusession->pdusession_id; } - session->status = PDU_SESSION_STATUS_RELEASED; } } + for (int i = 0; i < resp->nb_of_pdusessions_released; ++i) { + rm_pduSession(&UE->pduSessions, &UE->drbs, resp->pdusession_release[i].pdusession_id); + } + LOG_I(NR_RRC, "NGAP PDUSESSION RELEASE RESPONSE: rrc_ue_id %u release_pdu_sessions %d\n", resp->gNB_ue_ngap_id, resp->nb_of_pdusessions_released); itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p); } -//------------------------------------------------------------------------------ -int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance) -//------------------------------------------------------------------------------ +/** @brief Process NG PDU Session Resource Release command (8.2.2 of 3GPP TS 38.413) + * upon reception the NG-RAN node shall execute the release of the requested PDU sessions. + * For each PDU session to be released the NG-RAN node shall release the corresponding + * resources over Uu and over NG, if any. */ +int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(ngap_pdusession_release_command_t *cmd, gNB_RRC_INST *rrc) { - uint32_t gNB_ue_ngap_id; - ngap_pdusession_release_command_t *cmd = &NGAP_PDUSESSION_RELEASE_COMMAND(msg_p); - gNB_ue_ngap_id = cmd->gNB_ue_ngap_id; - gNB_RRC_INST *rrc = RC.nrrrc[instance]; + uint32_t gNB_ue_ngap_id = cmd->gNB_ue_ngap_id; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, gNB_ue_ngap_id); if (!ue_context_p) { - LOG_E(NR_RRC, "[gNB %ld] not found ue context gNB_ue_ngap_id %u \n", instance, gNB_ue_ngap_id); + LOG_E(NR_RRC, "[gNB %d] UE context not found for gNB_ue_ngap_id %u \n", rrc->module_id, gNB_ue_ngap_id); return -1; } - LOG_I(NR_RRC, "[gNB %ld] gNB_ue_ngap_id %u \n", instance, gNB_ue_ngap_id); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - LOG_I( - NR_RRC, "PDU Session Release Command: AMF_UE_NGAP_ID %lu rrc_ue_id %u release_pdusessions %d \n", cmd->amf_ue_ngap_id, gNB_ue_ngap_id, cmd->nb_pdusessions_torelease); - bool found = false; - uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); - UE->xids[xid] = RRC_PDUSESSION_RELEASE; + LOG_I(NR_RRC, "NG PDU Session Release command: AMF_UE_NGAP_ID=%lu, rrc_ue_id=%u, nb_pdusessions_torelease=%d \n", + cmd->amf_ue_ngap_id, + gNB_ue_ngap_id, + cmd->nb_pdusessions_torelease); + e1ap_bearer_mod_req_t req = {0}; for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) { rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_release_params[pdusession].pdusession_id); if (!pduSession) { LOG_E(NR_RRC, "Failed to release non-existing PDU Session %d\n", cmd->pdusession_release_params[pdusession].pdusession_id); continue; } - if (pduSession->status == PDU_SESSION_STATUS_FAILED) { - pduSession->xid = xid; + if (pduSession->status == PDU_SESSION_STATUS_TORELEASE) { + LOG_W(NR_RRC, "PDU Session %d already set to be released\n", pduSession->param.pdusession_id); continue; } - if (pduSession->status == PDU_SESSION_STATUS_ESTABLISHED) { - found = true; - LOG_I(NR_RRC, "RELEASE pdusession %d \n", pduSession->param.pdusession_id); - pduSession->status = PDU_SESSION_STATUS_TORELEASE; - pduSession->xid = xid; - } + // Set PDU session to release, regardless of the status + LOG_I(NR_RRC, "Set PDU Session %d to release\n", pduSession->param.pdusession_id); + pdu_session_to_remove_t *release = &req.pduSessionRem[req.numPDUSessionsRem++]; + release->sessionId = pduSession->param.pdusession_id; + release->cause.type = E1AP_CAUSE_RADIO_NETWORK; + release->cause.value = E1AP_RADIO_CAUSE_NORMAL_RELEASE; + pduSession->status = PDU_SESSION_STATUS_TORELEASE; } - if (found) { - // TODO RRCReconfiguration To UE - LOG_I(NR_RRC, "Send RRCReconfiguration To UE \n"); - rrc_gNB_generate_dedicatedRRCReconfiguration_release(rrc, UE, xid, cmd->nas_pdu.len, cmd->nas_pdu.buf); + if (req.numPDUSessionsRem == 0) { + LOG_E(NR_RRC, "Received NG PDU Session Release Command but no PDU Sessions to release\n"); + return -1; + } else if (!ue_associated_to_cuup(rrc, UE)) { + LOG_E(NR_RRC, "UE %d is not associated to CU-UP\n", UE->rrc_ue_id); + // TODO handle, e.g., only trigger F1 release + return 0; } else { - // gtp tunnel delete - LOG_I(NR_RRC, "gtp tunnel delete all tunnels for UE %04x\n", UE->rnti); - gtpv1u_gnb_delete_tunnel_req_t req = {0}; - req.ue_id = UE->rnti; - gtpv1u_delete_ngu_tunnel(rrc->module_id, &req); - // NGAP_PDUSESSION_RELEASE_RESPONSE - rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(rrc, UE, xid); - LOG_I(NR_RRC, "Send PDU Session Release Response \n"); + /* If present, store NAS-PDU in the UE context for later inclusion in RRCReconfiguration */ + if (cmd->nas_pdu.len > 0) { + UE->nas_pdu = copy_byte_array(cmd->nas_pdu); + } + LOG_I(NR_RRC, "Send F1 Bearer Context Modification Request with PDU Session release \n"); + req.gNB_cu_cp_ue_id = UE->rrc_ue_id; + req.gNB_cu_up_ue_id = UE->rrc_ue_id; + sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE); + rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); } + init_delayed_action(&UE->delayed_action); return 0; } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 91c7722c52..c3f692ff5f 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -78,7 +78,7 @@ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_UECapabilityInformation_t *const ue_cap_info); -int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance); +int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(ngap_pdusession_release_command_t *cmd, gNB_RRC_INST *rrc); void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t xid); diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index 9a2c3fb6f6..86838927ab 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -218,8 +218,6 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id, ue->rrc_ue_id); bool success = cu_add_f1_ue_data(ue->rrc_ue_id, &ue_data); DevAssert(success); - ue->max_delays_pdu_session = 20; /* see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() */ - ue->ongoing_pdusession_setup_request = false; // Initialise setup PDU Sessions list seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t)); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 552cc881d6..e570682ce8 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -160,6 +160,12 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, ho_ctx->source->du_ue_id = ue_data.secondary_ue; ho_ctx->source->old_rnti = ue->rnti; + // Save the GTP-U tunnel info for source DU before process UE context setup request/response + // since tunnel info will be updated by calling store_du_f1u_tunnel() in rrc_CU_process_ue_context_setup_response() + FOR_EACH_SEQ_ARR(drb_t *, drb, &ue->drbs) { + ho_ctx->source->old_du_tunnel_config = drb->du_tunnel_config; + } + int result = asn_copy(&asn_DEF_NR_CellGroupConfig, (void **)&ho_ctx->source->old_cellGroupConfig, ue->masterCellGroup); AssertFatal(result == 0, "error during asn_copy() of CellGroupConfig\n"); } @@ -186,12 +192,7 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, meas_config->buf = calloc_or_fail(1, NR_RRC_BUF_SIZE); meas_config->len = do_NR_MeasConfig(ue->measConfig, meas_config->buf, NR_RRC_BUF_SIZE); - byte_array_t *meas_timing_config = NULL; - if (target_du->mtc) { - meas_timing_config = calloc_or_fail(1, sizeof(*meas_timing_config)); - meas_timing_config->buf = calloc_or_fail(1, NR_RRC_BUF_SIZE); - meas_timing_config->len = do_NR_MeasurementTimingConfiguration(target_du->mtc, meas_timing_config->buf, NR_RRC_BUF_SIZE); - } + byte_array_t *meas_timing_config = get_meas_timing_config(target_du->mtc, ue->measConfig); byte_array_t *hpi = malloc_or_fail(sizeof(*hpi)); *hpi = copy_byte_array(*ho_prep_info); @@ -612,3 +613,31 @@ void nr_HO_N2_trigger_telnet(gNB_RRC_INST *rrc, uint32_t neighbour_pci, uint32_t nr_rrc_trigger_n2_ho(rrc, UE, scell_du->nr_pci, neighbour); } + +// This function detects if there are at least two different ssbFrequency values, and if so, returns meas_timing_config; +// otherwise, it returns NULL. When you return NULL, the measurement gaps will not be configured. +byte_array_t *get_meas_timing_config(const NR_MeasurementTimingConfiguration_t *mtc, const NR_MeasConfig_t *measConfig) +{ + if (!mtc || !measConfig || !measConfig->measObjectToAddModList) + return NULL; + + byte_array_t *meas_timing_config = NULL; + NR_MeasObjectToAddModList_t *mo_list = measConfig->measObjectToAddModList; + NR_ARFCN_ValueNR_t ssbFrequency0 = 0; + for (int i = 0; i < mo_list->list.count; i++) { + NR_MeasObjectToAddMod_t *mo = mo_list->list.array[i]; + if (mo->measObject.present != NR_MeasObjectToAddMod__measObject_PR_measObjectNR) + continue; + NR_MeasObjectNR_t *monr = mo->measObject.choice.measObjectNR; + if (i == 0) { + ssbFrequency0 = *monr->ssbFrequency; + } else if (ssbFrequency0 != *monr->ssbFrequency) { + meas_timing_config = calloc_or_fail(1, sizeof(*meas_timing_config)); + meas_timing_config->buf = calloc_or_fail(1, NR_RRC_BUF_SIZE); + meas_timing_config->len = do_NR_MeasurementTimingConfiguration(mtc, meas_timing_config->buf, NR_RRC_BUF_SIZE); + break; + } + } + + return meas_timing_config; +} diff --git a/openair2/RRC/NR/rrc_gNB_mobility.h b/openair2/RRC/NR/rrc_gNB_mobility.h index 7010cc83ba..88e3548220 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.h +++ b/openair2/RRC/NR/rrc_gNB_mobility.h @@ -56,6 +56,8 @@ typedef struct nr_ho_source_cu { ho_cancel_t ho_cancel; /// status transfer ho_status_transfer_t ho_status_transfer; + /// old (source) downlink tunnel + gtpu_tunnel_t old_du_tunnel_config; } nr_ho_source_cu_t; /* acknowledgement of handover request. buf+len is the RRC Reconfiguration */ @@ -106,4 +108,6 @@ void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_RRC_UE_ void nr_rrc_trigger_n2_ho_target(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue); +byte_array_t *get_meas_timing_config(const NR_MeasurementTimingConfiguration_t *mtc, const NR_MeasConfig_t *measConfig); + #endif /* RRC_GNB_MOBILITY_H_ */ diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index f0f7201517..3e3c462145 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -161,6 +161,28 @@ static NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id, return rbconfig; } +static void rrc_nsa_add_drb(const int ue_id, + const NR_DRB_ToAddModList_t *addMod, + const nr_pdcp_entity_security_keys_and_algos_t *sp) +{ + for (int i = 0; i < addMod->list.count; i++) { + NR_DRB_ToAddMod_t *drb = addMod->list.array[i]; + DevAssert(drb->cnAssociation); + DevAssert(drb->cnAssociation->present != NR_DRB_ToAddMod__cnAssociation_PR_NOTHING); + DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity); + // get SDAP config + sdap_config_t sdap = {0}; + // EPC association + sdap.pdusession_id = drb->cnAssociation->choice.eps_BearerIdentity; + sdap.drb_id = drb->drb_Identity; + sdap.defaultDRB = true; + // add SDAP entity (terminated at gNB, since it's EPC) + nr_sdap_addmod_entity(GNB_FLAG_YES, ue_id, &sdap); + // add PDCP entity + nr_pdcp_add_drb(GNB_FLAG_YES, ue_id, drb->pdcp_Config, &sdap, sp); + } +} + /* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */ RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries, rrc_gNB_compare_ue_rnti_id); @@ -304,10 +326,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ } DevAssert(UE->rb_config != NULL); - nr_pdcp_add_drbs(GNB_FLAG_YES, - UE->rrc_ue_id, - UE->rb_config->drb_ToAddModList, - &security_parameters); + rrc_nsa_add_drb(UE->rrc_ue_id, UE->rb_config->drb_ToAddModList, &security_parameters); /* assumption: only a single bearer, see above */ NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList; diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 5af84f0399..c636e9e639 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -141,6 +141,62 @@ rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusessio return added; } +static bool eq_drb_pdu_session_id(const void *vval, const void *vit) +{ + const int *id = (const int *)vval; + const drb_t *elem = (const drb_t *)vit; + return elem->pdusession_id == *id; +} + +/** @brief Finds the first DRB with the given PDU session ID. + * @return Pointer to matching drb_t or NULL if not found. */ +static drb_t *find_drb_by_pdusession_id(seq_arr_t *seq, int pdusession_id) +{ + DevAssert(seq); + DevAssert(pdusession_id > 0 && pdusession_id <= NGAP_MAX_PDU_SESSION); + elm_arr_t elm = find_if(seq, &pdusession_id, eq_drb_pdu_session_id); + if (elm.found) + return (drb_t *)elm.it; + return NULL; +} + +/** @brief Removes a DRB from the list + * @param drbs The DRB list + * @param drb Pointer to the DRB to remove */ +static void nr_rrc_rm_drb(seq_arr_t *drbs, drb_t *drb) +{ + DevAssert(drbs); + DevAssert(drb); + LOG_I(NR_RRC, "Removing DRB ID %d (PDU Session ID=%d)\n", drb->drb_id, drb->pdusession_id); + seq_arr_erase_deep(drbs, drb, free_drb); +} + +/** @brief Removes a PDU Session from the list by ID + * Also removes all associated DRBs for this PDU session. + * @return true if successfully removed, false if not found */ +bool rm_pduSession(seq_arr_t *sessions, seq_arr_t *drbs, int pdusession_id) +{ + DevAssert(sessions); + DevAssert(drbs); + + rrc_pdu_session_param_t *session = find_pduSession(sessions, pdusession_id); + + if (session) { + LOG_I(NR_RRC, "Removing PDU Session %d from RRC setup list\n", pdusession_id); + // Remove all associated DRBs first + drb_t *drb; + while ((drb = find_drb_by_pdusession_id(drbs, pdusession_id))) { + nr_rrc_rm_drb(drbs, drb); + } + // Then remove the PDU session + seq_arr_erase_deep(sessions, session, free_pdusession); + return true; + } + + LOG_W(NR_RRC, "pdusession_id=%d not found to remove\n", pdusession_id); + return false; +} + /** @brief Add drb_t item in the UE context list for @param pdusession_id */ drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id, nr_pdcp_configuration_t *pdcp) { diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index f6821e314b..a1b09a5b02 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -39,6 +39,10 @@ rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusessio /// @brief get PDU session of UE ue through the DRB drb_id rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id); +/// @brief Remove PDU Session from RRC list +/// Also removes all associated DRBs for this PDU session. +bool rm_pduSession(seq_arr_t *sessions, seq_arr_t *drbs, int pdusession_id); + /// @brief set PDCP configuration in E1 Bearer Context Management message bearer_context_pdcp_config_t set_bearer_context_pdcp_config(const nr_pdcp_configuration_t pdcp, bool um_on_default_drb, diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index d23dd14c58..27e1dc0bb1 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -210,7 +210,7 @@ static void get_epochtime_from_sib19scheduling(NR_UE_RRC_SI_INFO *SI_info, int * slot); } -static int eval_epoch_time(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int frame) +static int eval_epoch_time(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int frame, bool is_targetcell) { int epoch_frame = 0, epoch_subframe = 0; int diff_frames = 0; @@ -229,11 +229,19 @@ static int eval_epoch_time(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntnc ntncfg->epochTime_r17->sfn_r17 = epoch_frame; ntncfg->epochTime_r17->subFrameNR_r17 = epoch_subframe; } - // For serving cell, the field sfn indicates the current SFN or the next upcoming SFN - // after the frame where the message indicating the epochTime is received - // i.e. Epochframe can be present or future SFN - diff_frames = (epoch_frame - frame + 1024) % 1024; // According to 38.331 Epochtime is defined for serving cell like this - LOG_I(NR_RRC, "Epoch frame %d, ahead by %d frames\n", epoch_frame, diff_frames); + if (is_targetcell) { + // For Target cell,the SFN nearest to the frame needs to be considered + // i.e. Epochframe can be in the past or future + int diff1 = (frame - epoch_frame + 1024) % 1024; + int diff2 = (epoch_frame - frame + 1024) % 1024; + diff_frames = (diff1 < diff2) ? -diff1 : diff2; + } else { + // For serving cell, the field sfn indicates the current SFN or the next upcoming SFN + // after the frame where the message indicating the epochTime is received + // i.e. Epochframe can be present or future SFN + diff_frames = (epoch_frame - frame + 1024) % 1024; // According to 38.331 Epochtime is defined for serving cell like this + } + LOG_I(NR_RRC, "Epoch frame %d ahead by %d frames\n", epoch_frame, diff_frames); return diff_frames; } @@ -257,11 +265,11 @@ static int get_ntn_timervalues(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t * return sib19_timer_ms; } -static void nr_rrc_process_ntnconfig(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int frame) +static void nr_rrc_process_ntnconfig(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int frame, bool is_targetcell) { SI_info->SInfo_r17.sib19_validity = true; // Check if Epochtime is sent or not - int diff_frames = eval_epoch_time(SI_info, ntncfg, frame); + int diff_frames = eval_epoch_time(SI_info, ntncfg, frame, is_targetcell); if (ntncfg->ntn_UlSyncValidityDuration_r17) { // ulsyncvalidity duration configured int val430_ms = 0, sib19_timer_ms = 0; @@ -361,7 +369,7 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, sib19 = typeandinfo->choice.sib19_v1700; if (g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) xer_fprint(stdout, &asn_DEF_NR_SIB19_r17, (const void *)sib19); - nr_rrc_process_ntnconfig(rrc, SI_info, sib19->ntn_Config_r17, frame); + nr_rrc_process_ntnconfig(rrc, SI_info, sib19->ntn_Config_r17, frame, false); break; default: break; @@ -599,6 +607,31 @@ static void nr_rrc_process_dedicatedNAS_MessageList(NR_UE_RRC_INST_t *rrc, NR_RR } } +/** @brief Add bearer in PDCP/SDAP for 5GC association (SA) */ +static void rrc_ue_add_bearer(const int ue_id, const NR_DRB_ToAddMod_t *drb, const nr_pdcp_entity_security_keys_and_algos_t *sp) +{ + DevAssert(drb->cnAssociation); + DevAssert(drb->cnAssociation->present != NR_DRB_ToAddMod__cnAssociation_PR_NOTHING); + // get SDAP config + sdap_config_t sdap = {0}; + if (drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity) { + DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity); + + // EPC association + sdap.pdusession_id = drb->cnAssociation->choice.eps_BearerIdentity; + sdap.drb_id = drb->drb_Identity; + sdap.defaultDRB = true; + } else { + DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config); + DevAssert(drb->cnAssociation->choice.sdap_Config); + sdap = nr_sdap_get_config(GNB_FLAG_NO, drb->cnAssociation->choice.sdap_Config, drb->drb_Identity); + } + // add SDAP entity + nr_sdap_addmod_entity(GNB_FLAG_NO, ue_id, &sdap); + // add PDCP entity + nr_pdcp_add_drb(GNB_FLAG_NO, ue_id, drb->pdcp_Config, &sdap, sp); +} + /** * @brief add, modify and release SRBs and/or DRBs * @ref 3GPP TS 38.331 @@ -706,10 +739,7 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_Rad nr_reconfigure_sdap_entity(sdap_Config, ue_rrc->ue_id, sdap_Config->pdu_Session, DRB_id); } else { set_DRB_status(ue_rrc ,DRB_id, RB_ESTABLISHED); - add_drb(false, - ue_rrc->ue_id, - radioBearerConfig->drb_ToAddModList->list.array[cnt], - &security_up_parameters); + rrc_ue_add_bearer(ue_rrc->ue_id, radioBearerConfig->drb_ToAddModList->list.array[cnt], &security_up_parameters); } } } // drb_ToAddModList // @@ -725,12 +755,15 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, { AssertFatal(!fullConfig, "fullConfig not supported yet\n"); NR_CellGroupConfig_t *cellGroupConfig = NULL; - uper_decode(NULL, - &asn_DEF_NR_CellGroupConfig, //might be added prefix later - (void **)&cellGroupConfig, - (uint8_t *)masterCellGroup->buf, - masterCellGroup->size, 0, 0); - + asn_dec_rval_t dec_rval = uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, //might be added prefix later + (void **)&cellGroupConfig, + (uint8_t *)masterCellGroup->buf, + masterCellGroup->size, 0, 0); + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E(NR_RRC, "CellGroupConfig decode error\n"); + return; + } if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); } @@ -801,28 +834,30 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe NR_RRCReconfiguration_v1540_IEs_t *rec_1540 = rec_1530->nonCriticalExtension; if (rec_1540) { NR_RRCReconfiguration_v1560_IEs_t *rec_1560 = rec_1540->nonCriticalExtension; - if (rec_1560->sk_Counter) { - // TODO perform AS security key update procedure as specified in 5.3.5.7 - LOG_E(NR_RRC, "RRCReconfiguration includes sk-Counter but this is not implemented yet\n"); - } - if (rec_1560->mrdc_SecondaryCellGroupConfig) { - // TODO perform handling of mrdc-SecondaryCellGroupConfig as specified in 5.3.5.3 - LOG_E(NR_RRC, "RRCReconfiguration includes mrdc-SecondaryCellGroupConfig but this is not handled yet\n"); - } - if (rec_1560->radioBearerConfig2) { - NR_RadioBearerConfig_t *RadioBearerConfig = NULL; - asn_dec_rval_t dec_rval = uper_decode(NULL, - &asn_DEF_NR_RadioBearerConfig, - (void **)&RadioBearerConfig, - (uint8_t *)rec_1560->radioBearerConfig2->buf, - rec_1560->radioBearerConfig2->size, - 0, - 0); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E(NR_RRC, "radioBearerConfig2 decode error\n"); - SEQUENCE_free(&asn_DEF_NR_RadioBearerConfig, RadioBearerConfig, 1); - } else - nr_rrc_ue_process_RadioBearerConfig(rrc, RadioBearerConfig); + if (rec_1560) { + if (rec_1560->sk_Counter) { + // TODO perform AS security key update procedure as specified in 5.3.5.7 + LOG_E(NR_RRC, "RRCReconfiguration includes sk-Counter but this is not implemented yet\n"); + } + if (rec_1560->mrdc_SecondaryCellGroupConfig) { + // TODO perform handling of mrdc-SecondaryCellGroupConfig as specified in 5.3.5.3 + LOG_E(NR_RRC, "RRCReconfiguration includes mrdc-SecondaryCellGroupConfig but this is not handled yet\n"); + } + if (rec_1560->radioBearerConfig2) { + NR_RadioBearerConfig_t *RadioBearerConfig = NULL; + asn_dec_rval_t dec_rval = uper_decode(NULL, + &asn_DEF_NR_RadioBearerConfig, + (void **)&RadioBearerConfig, + (uint8_t *)rec_1560->radioBearerConfig2->buf, + rec_1560->radioBearerConfig2->size, + 0, + 0); + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E(NR_RRC, "radioBearerConfig2 decode error\n"); + SEQUENCE_free(&asn_DEF_NR_RadioBearerConfig, RadioBearerConfig, 1); + } else + nr_rrc_ue_process_RadioBearerConfig(rrc, RadioBearerConfig); + } } } } @@ -1136,20 +1171,19 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ LOG_E(NR_RRC, "\n"); // free the memory SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)cellGroupConfig, 1); + } else { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); + + nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); + AssertFatal(!IS_SA_MODE(get_softmodem_params()), "secondaryCellGroup only used in NSA for now\n"); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; + nr_mac_rrc_config_cg_t *config_cg = &rrc_msg.payload.config_cg; + config_cg->cellGroupConfig = cellGroupConfig; + config_cg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } - - if (LOG_DEBUGFLAG(DEBUG_ASN1)) - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); - - nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); - - AssertFatal(!IS_SA_MODE(get_softmodem_params()), "secondaryCellGroup only used in NSA for now\n"); - nr_mac_rrc_message_t rrc_msg = {0}; - rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; - nr_mac_rrc_config_cg_t *config_cg = &rrc_msg.payload.config_cg; - config_cg->cellGroupConfig = cellGroupConfig; - config_cg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; - nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } if (ie->measConfig) { LOG_I(NR_RRC, "RRCReconfiguration includes Measurement Configuration\n"); @@ -1428,6 +1462,11 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, uint8_t *const bufferP, const uint8_t buffer_len) { + // MIB received on the target cell. Now process target ntncfg once new timing is received. + if (phycellid == rrc->phyCellID && rrc->target_ntncfg) { + rrc->process_target_ntncfg = true; + } + NR_BCCH_BCH_Message_t *bcch_message = NULL; rrc->phyCellID = phycellid; rrc->arfcn_ssb = ssb_arfcn; @@ -1629,13 +1668,29 @@ static void nr_rrc_signal_maxrtxindication(int ue_id) itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, msg); } +/** @brief Release all active RLC entities for a UE and set to inactive. + * This is typically used when tearing down all DRBs at UE side, + * such as after a PDU session release or full reconfiguration. + * @param rrc Pointer to NR_UE_RRC_INST_t structure + * @param id Logical Channel ID (must be in range [0, NR_MAX_NUM_LCID-1]) */ +static void nr_rrc_release_rlc_entity(NR_UE_RRC_INST_t *rrc, int id) +{ + DevAssert(rrc); + DevAssert(id >= 0 && id < NR_MAX_NUM_LCID); + if (rrc->active_RLC_entity[id]) { + rrc->active_RLC_entity[id] = false; + nr_rlc_release_entity(rrc->ue_id, id); + LOG_I(RLC, "Released RLC entity: ue_id=%ld, lc_id=%d\n", rrc->ue_id, id); + } +} + static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, const NR_CellGroupConfig_t *cellGroupConfig) { if (cellGroupConfig->rlc_BearerToReleaseList != NULL) { for (int i = 0; i < cellGroupConfig->rlc_BearerToReleaseList->list.count; i++) { NR_LogicalChannelIdentity_t *lcid = cellGroupConfig->rlc_BearerToReleaseList->list.array[i]; AssertFatal(lcid, "LogicalChannelIdentity shouldn't be null here\n"); - nr_rlc_release_entity(rrc->ue_id, *lcid); + nr_rrc_release_rlc_entity(rrc, *lcid); } } @@ -1659,8 +1714,13 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, const NR_CellGroupC nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); } else { // DRB NR_DRB_Identity_t drb_id = rlc_bearer->servedRadioBearer->choice.drb_Identity; - nr_rlc_add_drb(rrc->ue_id, drb_id, rlc_bearer); - nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); + if (!rlc_bearer->rlc_Config) { + LOG_E(RLC, "RLC-Config not present but is mandatory for setup\n"); + rrc->active_RLC_entity[lcid] = false; + } else { + nr_rlc_add_drb(rrc->ue_id, drb_id, rlc_bearer); + nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); + } } } } @@ -1688,7 +1748,10 @@ static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, rrc->arfcn_ssb = *dcc->frequencyInfoDL->absoluteFrequencySSB; // consider the target SpCell to be one with a physical cell identity indicated by the physCellId - rrc->phyCellID = *reconfigurationWithSync->spCellConfigCommon->physCellId; + if (!reconfigurationWithSync->spCellConfigCommon->physCellId) + LOG_E(NR_RRC, "physCellId absent but should be mandatory present upon cell change and cell addition\n"); + else + rrc->phyCellID = *reconfigurationWithSync->spCellConfigCommon->physCellId; } NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; @@ -1704,13 +1767,20 @@ static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, // 3GPP TS38.331 section 5.3.5.5.2 nr_timer_stop(&tac->T430); + + if (rrc->target_ntncfg) { + ASN_STRUCT_FREE(asn_DEF_NR_NTN_Config_r17, rrc->target_ntncfg); + rrc->target_ntncfg = NULL; + rrc->process_target_ntncfg = false; + } if (reconfigurationWithSync->spCellConfigCommon && reconfigurationWithSync->spCellConfigCommon->ext2 && reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17) { NR_NTN_Config_r17_t *ntncfg = reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17; // EPOCH time is always sent if NTN config is sent through DCCH AssertFatal(ntncfg->epochTime_r17, "NTN-CONFIG sent in dedicated mode should have EPOCHTIME\n"); - nr_rrc_process_ntnconfig(rrc, &rrc->perNB[gNB_index].SInfo, ntncfg, rrc->current_frame); + const int copy_result = asn_copy(&asn_DEF_NR_NTN_Config_r17, (void **)&rrc->target_ntncfg, ntncfg); + AssertFatal(copy_result == 0, "unable to copy NR_NTN_Config_r17_t\n"); } } @@ -1808,10 +1878,7 @@ static void nr_rrc_rrcsetup_fallback(NR_UE_RRC_INST_t *rrc) } } for (int i = 1; i < NR_MAX_NUM_LCID; i++) { - if (rrc->active_RLC_entity[i]) { - rrc->active_RLC_entity[i] = false; - nr_rlc_release_entity(rrc->ue_id, i); - } + nr_rrc_release_rlc_entity(rrc, i); } nr_sdap_delete_ue_entities(rrc->ue_id); @@ -2213,13 +2280,7 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); rrc->UECap.sdu_size = (enc_rval.encoded + 7) / 8; LOG_I(PHY, "[RRC]UE NR Capability encoded, %d bytes (%zd bits)\n", rrc->UECap.sdu_size, enc_rval.encoded + 7); - /* RAT Container */ - NR_UE_CapabilityRAT_Container_t *ue_CapabilityRAT_Container = CALLOC(1, sizeof(NR_UE_CapabilityRAT_Container_t)); - ue_CapabilityRAT_Container->rat_Type = NR_RAT_Type_nr; - OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container->ue_CapabilityRAT_Container, (const char *)rrc->UECap.sdu, rrc->UECap.sdu_size); NR_UECapabilityEnquiry_IEs_t *ueCapabilityEnquiry_ie = UECapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry; - // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.buf = UE_rrc_inst[ue_mod_idP].UECapability; - // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.size = UE_rrc_inst[ue_mod_idP].UECapability_size; AssertFatal(UECapabilityEnquiry->criticalExtensions.present == NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry, "UECapabilityEnquiry->criticalExtensions.present (%d) != UECapabilityEnquiry__criticalExtensions_PR_c1 (%d)\n", UECapabilityEnquiry->criticalExtensions.present,NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry); @@ -2232,6 +2293,10 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa for (int i = 0; i < ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.count; i++) { if (ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.array[i]->rat_Type == NR_RAT_Type_nr) { + /* RAT Container */ + NR_UE_CapabilityRAT_Container_t *ue_CapabilityRAT_Container = CALLOC(1, sizeof(NR_UE_CapabilityRAT_Container_t)); + ue_CapabilityRAT_Container->rat_Type = NR_RAT_Type_nr; + OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container->ue_CapabilityRAT_Container, (const char *)rrc->UECap.sdu, rrc->UECap.sdu_size); asn1cSeqAdd(&UEcapList->list, ue_CapabilityRAT_Container); uint8_t buffer[500]; asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, 500); @@ -2245,8 +2310,7 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); } } - /* Free struct members after it's done - including locally allocated ue_CapabilityRAT_Container */ + /* Free struct members after it's done including locally allocated ue_CapabilityRAT_Container */ ASN_STRUCT_RESET(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg); } @@ -2582,6 +2646,13 @@ void *rrc_nrue(void *notUsed) nr_rrc_handle_timers(rrc); NR_UE_RRC_SI_INFO *SInfo = &rrc->perNB[NRRRC_FRAME_PROCESS(msg_p).gnb_id].SInfo; nr_rrc_SI_timers(SInfo); + if (rrc->process_target_ntncfg) { + // Process target NTNCFG as the target cells timing is acquired + nr_rrc_process_ntnconfig(rrc, &rrc->perNB[NRRRC_FRAME_PROCESS(msg_p).gnb_id].SInfo, rrc->target_ntncfg, rrc->current_frame, true); + ASN_STRUCT_FREE(asn_DEF_NR_NTN_Config_r17, rrc->target_ntncfg); + rrc->target_ntncfg = NULL; + rrc->process_target_ntncfg = false; + } break; case NR_RRC_MAC_INAC_IND: @@ -2762,6 +2833,14 @@ static void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc, NR_Reestab set_DRB_status(rrc, i, RB_SUSPENDED); } } + + // Free Target NTNcfg is stored + if (rrc->target_ntncfg) { + ASN_STRUCT_FREE(asn_DEF_NR_NTN_Config_r17, rrc->target_ntncfg); + rrc->target_ntncfg = NULL; + rrc->process_target_ntncfg = false; + } + // release the MCG SCell(s), if configured // no SCell configured in our implementation @@ -2916,10 +2995,7 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, } } for (int i = 0; i < NR_MAX_NUM_LCID; i++) { - if (rrc->active_RLC_entity[i]) { - rrc->active_RLC_entity[i] = false; - nr_rlc_release_entity(rrc->ue_id, i); - } + nr_rrc_release_rlc_entity(rrc, i); } for (int i = 0; i < NB_CNX_UE; i++) { @@ -2955,6 +3031,13 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, asn1cFreeStruc(asn_DEF_NR_UE_TimersAndConstants, tac->sib1_TimersAndConstants); } + // Free Target NTNcfg is stored + if (rrc->target_ntncfg) { + ASN_STRUCT_FREE(asn_DEF_NR_NTN_Config_r17, rrc->target_ntncfg); + rrc->target_ntncfg = NULL; + rrc->process_target_ntncfg = false; + } + // reset MAC NR_UE_MAC_reset_cause_t cause = (rrc->nrRrcState == RRC_STATE_DETACH_NR) ? DETACH : GO_TO_IDLE; nr_mac_rrc_message_t rrc_msg = {0}; diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index ae8837bff2..0672af7741 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -268,6 +268,8 @@ typedef struct NR_UE_RRC_INST_s { NR_SL_PreconfigurationNR_r16_t *sl_preconfig; // NTN params bool is_NTN_UE; + NR_NTN_Config_r17_t *target_ntncfg; + bool process_target_ntncfg; notifiedFIFO_t *mac_input_nf; } NR_UE_RRC_INST_t; diff --git a/openair2/SDAP/nr_sdap/nr_sdap.c b/openair2/SDAP/nr_sdap/nr_sdap.c index f6602c7597..1aec02814e 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap.c +++ b/openair2/SDAP/nr_sdap/nr_sdap.c @@ -47,7 +47,6 @@ static void reblock_tun_socket(int fd) bool sdap_data_req(protocol_ctxt_t *ctxt_p, const ue_id_t ue_id, const srb_flag_t srb_flag, - const rb_id_t rb_id, const mui_t mui, const confirm_t confirm, const sdu_size_t sdu_buffer_size, @@ -69,7 +68,6 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p, bool ret = sdap_entity->tx_entity(sdap_entity, ctxt_p, srb_flag, - rb_id, mui, confirm, sdu_buffer_size, @@ -82,7 +80,7 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p, return ret; } -void sdap_data_ind(rb_id_t pdcp_entity, +void sdap_data_ind(int pdcp_entity, int is_gnb, bool has_sdap_rx, int pdusession_id, @@ -100,7 +98,6 @@ void sdap_data_ind(rb_id_t pdcp_entity, sdap_entity->rx_entity(sdap_entity, pdcp_entity, is_gnb, - has_sdap_rx, pdusession_id, ue_id, buf, @@ -116,8 +113,6 @@ static void *sdap_tun_read_thread(void *arg) int len; reblock_tun_socket(entity->pdusession_sock); - int rb_id = 1; - while (!entity->stop_thread) { len = read(entity->pdusession_sock, &rx_buf, NL_MAX_PAYLOAD); if (len == -1) { @@ -148,7 +143,6 @@ static void *sdap_tun_read_thread(void *arg) entity->tx_entity(entity, &ctxt, SRB_FLAG_NO, - rb_id, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO, len, diff --git a/openair2/SDAP/nr_sdap/nr_sdap.h b/openair2/SDAP/nr_sdap/nr_sdap.h index 3877e58603..1164641970 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap.h +++ b/openair2/SDAP/nr_sdap/nr_sdap.h @@ -35,7 +35,6 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p, const ue_id_t ue_id, const srb_flag_t srb_flag, - const rb_id_t rb_id, const mui_t mui, const confirm_t confirm, const sdu_size_t sdu_buffer_size, @@ -53,7 +52,7 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p, * Uplink - gNB * Downlink - nrUE */ -void sdap_data_ind(rb_id_t pdcp_entity, +void sdap_data_ind(int pdcp_entity, int is_gnb, bool has_sdap_rx, int pdusession_id, diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index 6860fba6e6..dc747e5a60 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -34,6 +34,8 @@ #include "tun_if.h" #include "nr_sdap.h" +#define NO_SDAP_HEADER 0 + typedef struct { nr_sdap_entity_t *sdap_entity_llist; } nr_sdap_entity_info; @@ -42,35 +44,22 @@ static nr_sdap_entity_info sdap_info; instance_t *N3GTPUInst = NULL; -/** - * @brief indicates whether it is a receiving SDAP entity - * i.e. for UE, header for DL data is present - * for gNB, header for UL data is present - */ -bool is_sdap_rx(bool is_gnb, NR_SDAP_Config_t *sdap_config) +/** @brief Returns a bitmap indicating the SDAP entity role, + * i.e. for UL transmission, header for UL data is present in RX/TX + * for DL transmission, header for DL data is present in RX/TX */ +static int get_sdap_role(bool is_gnb, const NR_SDAP_Config_t *sdap_config) { - if (is_gnb) { - return sdap_config->sdap_HeaderUL == NR_SDAP_Config__sdap_HeaderUL_present; - } else { - return sdap_config->sdap_HeaderDL == NR_SDAP_Config__sdap_HeaderDL_present; - } + sdap_role_t role_ul = is_gnb ? SDAP_UL_RX : SDAP_UL_TX; + sdap_role_t role_dl = is_gnb ? SDAP_DL_TX : SDAP_DL_RX; + int role = NO_SDAP_HEADER; + if (sdap_config->sdap_HeaderUL == NR_SDAP_Config__sdap_HeaderUL_present) + role |= role_ul; + if (sdap_config->sdap_HeaderDL == NR_SDAP_Config__sdap_HeaderDL_present) + role |= role_dl; + return role; } -/** - * @brief indicates whether it is a transmitting SDAP entity - * i.e. for UE, header for UL data is present - * for gNB, header for DL data is present - */ -bool is_sdap_tx(bool is_gnb, NR_SDAP_Config_t *sdap_config) -{ - if (is_gnb) { - return sdap_config->sdap_HeaderDL == NR_SDAP_Config__sdap_HeaderDL_present; - } else { - return sdap_config->sdap_HeaderUL == NR_SDAP_Config__sdap_HeaderUL_present; - } -} - -void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu) +void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, int sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu) { protocol_ctxt_t ctxt = { .rntiMaybeUEid = ue_id }; @@ -84,7 +73,7 @@ void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_s PDCP_TRANSMISSION_MODE_UNKNOWN, NULL, NULL); - LOG_D(SDAP, "Control PDU - Submitting Control PDU to DRB ID: %ld\n", sdap_ctrl_pdu_drb); + LOG_D(SDAP, "Control PDU - Submitting Control PDU to DRB ID: %d\n", sdap_ctrl_pdu_drb); LOG_D(SDAP, "QFI: %u\n R: %u\n D/C: %u\n", ctrl_pdu.QFI, ctrl_pdu.R, ctrl_pdu.DC); return; } @@ -92,7 +81,6 @@ void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_s static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, protocol_ctxt_t *ctxt_p, const srb_flag_t srb_flag, - const rb_id_t rb_id, const mui_t mui, const confirm_t confirm, const sdu_size_t sdu_buffer_size, @@ -105,9 +93,8 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, /* The offset of the SDAP header, it might be 0 if has_sdap_tx is not true in the pdcp entity. */ int offset=0; bool ret = false; - /*Hardcode DRB ID given from upper layer (ue/gnb_tun_read_thread rb_id), it will change if we have SDAP*/ - rb_id_t sdap_drb_id = rb_id; - int pdcp_ent_has_sdap = 0; + bool sdap_ul_tx = false; + bool sdap_dl_tx = false; if(sdu_buffer == NULL) { LOG_E(SDAP, "%s:%d:%s: NULL sdu_buffer \n", __FILE__, __LINE__, __FUNCTION__); @@ -115,19 +102,22 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, } uint8_t sdap_buf[SDAP_MAX_PDU]; - rb_id_t pdcp_entity = entity->qfi2drb_map(entity, qfi); + int drb_id = entity->qfi2drb_map(entity, qfi); - if(pdcp_entity){ - sdap_drb_id = pdcp_entity; - pdcp_ent_has_sdap = entity->qfi2drb_table[qfi].has_sdap_tx; - LOG_D(SDAP, "TX - QFI: %u is mapped to DRB ID: %ld\n", qfi, entity->qfi2drb_table[qfi].drb_id); + if (drb_id != SDAP_MAP_RULE_EMPTY) { + sdap_ul_tx = entity->qfi2drb_table[qfi].entity_role & SDAP_UL_TX; // UE TX entity + sdap_dl_tx = entity->qfi2drb_table[qfi].entity_role & SDAP_DL_TX; // gNB TX entity + LOG_D(SDAP, "TX - QFI: %u is mapped to DRB ID: %d\n", qfi, entity->qfi2drb_table[qfi].drb_id); + } else { + LOG_E(SDAP, "QFI %u not mapped to any DRB - dropping SDU of size %d\n", qfi, sdu_buffer_size); + return false; } - if(!pdcp_ent_has_sdap){ - LOG_D(SDAP, "TX - DRB ID: %ld does not have SDAP\n", entity->qfi2drb_table[qfi].drb_id); + if (!sdap_ul_tx && !sdap_dl_tx) { + LOG_D(SDAP, "TX - DRB ID: %d does not have SDAP header\n", entity->qfi2drb_table[qfi].drb_id); ret = nr_pdcp_data_req_drb(ctxt_p, srb_flag, - sdap_drb_id, + drb_id, mui, confirm, sdu_buffer_size, @@ -147,7 +137,7 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, return 0; } - if(ctxt_p->enb_flag) { // gNB + if (sdap_dl_tx) { // create DL Data PDU with SDAP header offset = SDAP_HDR_LENGTH; /* * TS 37.324 4.4 Functions @@ -165,7 +155,7 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, LOG_D(SDAP, "TX Entity QFI: %u \n", sdap_hdr.QFI); LOG_D(SDAP, "TX Entity RQI: %u \n", sdap_hdr.RQI); LOG_D(SDAP, "TX Entity RDI: %u \n", sdap_hdr.RDI); - } else { // nrUE + } else if (sdap_ul_tx) { // create UL Data PDU with SDAP header offset = SDAP_HDR_LENGTH; /* * TS 37.324 4.4 Functions @@ -195,7 +185,7 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, */ ret = nr_pdcp_data_req_drb(ctxt_p, srb_flag, - sdap_drb_id, + drb_id, mui, confirm, sdu_buffer_size + offset, @@ -211,9 +201,8 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, } static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, - rb_id_t pdcp_entity, + int pdcp_entity, int is_gnb, - bool has_sdap_rx, int pdusession_id, ue_id_t ue_id, char *buf, @@ -221,9 +210,23 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, { /* The offset of the SDAP header, it might be 0 if has_sdap_rx is not true in the pdcp entity. */ int offset=0; + bool sdap_ul_rx = false; + bool sdap_dl_rx = false; + /* If SDAP header is disabled for this entity, bypass header parsing */ + if (entity->enable_sdap) { + uint8_t qfi = buf[0] & 0x3F; // QFI is always the first 6 bits in the first octet + if (qfi >= SDAP_MAX_QFI) { + LOG_E(SDAP, "Invalid QFI %d received in SDAP header\n", qfi); + return; + } + // Fetch entity role from the qfi2drb_table + sdap_ul_rx = entity->qfi2drb_table[qfi].entity_role & SDAP_UL_RX; // gNB RX entity + sdap_dl_rx = entity->qfi2drb_table[qfi].entity_role & SDAP_DL_RX; // UE RX entity + } + if (is_gnb) { // gNB - if (has_sdap_rx) { // Handling the SDAP Header + if (sdap_ul_rx) { // UL Data/Control PDU with SDAP header offset = SDAP_HDR_LENGTH; nr_sdap_ul_hdr_t *sdap_hdr = (nr_sdap_ul_hdr_t *)buf; LOG_D(SDAP, "RX Entity Received QFI: %u\n", sdap_hdr->QFI); @@ -255,7 +258,7 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, * 5.2.2 Downlink * if the DRB from which this SDAP data PDU is received is configured by RRC with the presence of SDAP header. */ - if (has_sdap_rx) { // Handling the SDAP Header + if (sdap_dl_rx) { // DL Data/Control PDU with SDAP header offset = SDAP_HDR_LENGTH; /* * TS 37.324 5.2 Data transfer @@ -281,7 +284,7 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, */ if(!entity->qfi2drb_table[sdap_hdr->QFI].drb_id && entity->default_drb){ nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(sdap_hdr->QFI); - rb_id_t sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, pdcp_entity, SDAP_CTRL_PDU_MAP_DEF_DRB, sdap_hdr->QFI); + int sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, SDAP_CTRL_PDU_MAP_DEF_DRB, sdap_hdr->QFI); entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu); } @@ -296,7 +299,7 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, */ if (pdcp_entity != entity->qfi2drb_table[sdap_hdr->QFI].drb_id) { nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(sdap_hdr->QFI); - rb_id_t sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, pdcp_entity, SDAP_CTRL_PDU_MAP_RULE_DRB, sdap_hdr->QFI); + int sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, SDAP_CTRL_PDU_MAP_RULE_DRB, sdap_hdr->QFI); entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu); } @@ -333,51 +336,52 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, } } -/** - * @brief update QFI to DRB mapping rules -*/ -void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, uint8_t qfi, rb_id_t drb, bool has_sdap_rx, bool has_sdap_tx) +static void nr_sdap_qfi2drb_map_add(nr_sdap_entity_t *entity, + const uint8_t qfi, + const uint8_t drb_id, + const uint8_t role) { - if(qfi < SDAP_MAX_QFI && - qfi > SDAP_MAP_RULE_EMPTY && - drb > 0 && - drb <= AVLBL_DRB){ - entity->qfi2drb_table[qfi].drb_id = drb; - entity->qfi2drb_table[qfi].has_sdap_rx = has_sdap_rx; - entity->qfi2drb_table[qfi].has_sdap_tx = has_sdap_tx; - LOG_D(SDAP, "Updated mapping: QFI %u -> DRB %ld \n", qfi, entity->qfi2drb_table[qfi].drb_id); - } else { - LOG_D(SDAP, "Map updated failed, QFI: %u, DRB: %ld\n", qfi, drb); - } + qfi2drb_t *qfi2drb = &entity->qfi2drb_table[qfi]; + LOG_D(SDAP, "%s mapping: QFI %u -> DRB %d \n", qfi2drb->drb_id == SDAP_NO_MAPPING_RULE ? "Add" : "Update", qfi, drb_id); + qfi2drb->drb_id = drb_id; + qfi2drb->entity_role = role; } -void nr_sdap_qfi2drb_map_del(nr_sdap_entity_t *entity, uint8_t qfi){ - entity->qfi2drb_table[qfi].drb_id = SDAP_NO_MAPPING_RULE; - LOG_D(SDAP, "Deleted mapping for QFI: %u \n", qfi); +static void nr_sdap_qfi2drb_map_del(nr_sdap_entity_t *entity, const uint8_t qfi) +{ + qfi2drb_t *qfi2drb = &entity->qfi2drb_table[qfi]; + qfi2drb->drb_id = SDAP_NO_MAPPING_RULE; + LOG_D(SDAP, "Deleted mapping for QFI=%d, DRB=%d\n", qfi, qfi2drb->drb_id); } /** - * @brief maps the QFIs to the default DRB if not mapping rule exists - * @return DRB that is mapped to the QFI, 0 if no mapping and no default DRB exists for that QFI -*/ -rb_id_t nr_sdap_qfi2drb_map(nr_sdap_entity_t *entity, uint8_t qfi){ - rb_id_t pdcp_entity; - - pdcp_entity = entity->qfi2drb_table[qfi].drb_id; - - if(pdcp_entity){ - LOG_D(SDAP, "Mapping rule exists for QFI: %u\n", qfi); - return pdcp_entity; - } else if(entity->default_drb) { - LOG_D(SDAP, "Mapping QFI: %u to Default DRB: %ld\n", qfi, entity->default_drb); - entity->qfi2drb_map_update(entity, qfi, entity->default_drb, entity->qfi2drb_table[qfi].has_sdap_rx, entity->qfi2drb_table[qfi].has_sdap_tx); + * @brief get the DRB ID mapped to the QFI, for both DL and UL + * @return DRB that is mapped to the QFI + * or the default DRB if no mapping rule exists + * or 0 if no mapping and no default DRB exists for that QFI + * @ref TS 37.324, 5.2.1 Uplink + * If there is no stored QoS flow to DRB mapping rule for the + * QoS flow as specified in the subclause 5.3, and a default DRB is configured, + * map the SDAP SDU to the default DRB else, map the SDAP SDU to the DRB according + * to the stored QoS flow to DRB mapping rule. */ +static int nr_sdap_qfi2drb(nr_sdap_entity_t *entity, uint8_t qfi) +{ + /* Fetch DRB ID mapped to QFI */ + int drb_id = entity->qfi2drb_table[qfi].drb_id; + if (drb_id) { + /* QoS flow to DRB mapping rule exists, return corresponding DRB ID */ + LOG_D(SDAP, "Existing QoS flow to DRB mapping rule: QFI %u to DRB %d\n", qfi, drb_id); + return drb_id; + } else if (entity->default_drb) { + /* QoS flow to DRB mapping rule does not exist, map SDAP SDU to default DRB, e.g. return default DRB of the SDAP entity */ + LOG_D(SDAP, "QoS flow to DRB mapping rule does not exists! mapping SDU to Default DRB: %d\n", entity->default_drb); return entity->default_drb; } else { - LOG_D(SDAP, "Mapping rule and default DRB do not exist for QFI:%u\n", qfi); + /* Note: UE undefined behaviour when neither a default DRB + nor a stored QoS flow to DRB mapping rule exists */ + LOG_E(SDAP, "Mapping rule and default DRB do not exist for QFI:%u\n", qfi); return SDAP_MAP_RULE_EMPTY; } - - return pdcp_entity; } nr_sdap_ul_hdr_t nr_sdap_construct_ctrl_pdu(uint8_t qfi){ @@ -391,15 +395,16 @@ nr_sdap_ul_hdr_t nr_sdap_construct_ctrl_pdu(uint8_t qfi){ return sdap_end_marker_hdr; } -rb_id_t nr_sdap_map_ctrl_pdu(nr_sdap_entity_t *entity, rb_id_t pdcp_entity, int map_type, uint8_t dl_qfi){ - rb_id_t drb_of_endmarker = 0; +int nr_sdap_map_ctrl_pdu(nr_sdap_entity_t *entity, int map_type, uint8_t dl_qfi) +{ + int drb_of_endmarker = 0; if(map_type == SDAP_CTRL_PDU_MAP_DEF_DRB){ drb_of_endmarker = entity->default_drb; - LOG_D(SDAP, "Mapping Control PDU QFI: %u to Default DRB: %ld\n", dl_qfi, drb_of_endmarker); + LOG_D(SDAP, "Mapping Control PDU QFI: %u to Default DRB: %d\n", dl_qfi, drb_of_endmarker); } if(map_type == SDAP_CTRL_PDU_MAP_RULE_DRB){ drb_of_endmarker = entity->qfi2drb_map(entity, dl_qfi); - LOG_D(SDAP, "Mapping Control PDU QFI: %u to DRB: %ld\n", dl_qfi, drb_of_endmarker); + LOG_D(SDAP, "Mapping Control PDU QFI: %u to DRB: %d\n", dl_qfi, drb_of_endmarker); } return drb_of_endmarker; } @@ -407,7 +412,7 @@ rb_id_t nr_sdap_map_ctrl_pdu(nr_sdap_entity_t *entity, rb_id_t pdcp_entity, int /** * @brief Submit the end-marker control PDU to PDCP according to TS 37.324, clause 5.3 */ -void nr_sdap_submit_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu) +void nr_sdap_submit_ctrl_pdu(ue_id_t ue_id, int sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu) { if(sdap_ctrl_pdu_drb){ nr_pdcp_submit_sdap_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, ctrl_pdu); @@ -415,116 +420,114 @@ void nr_sdap_submit_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_u } } -/** - * @brief UL QoS flow to DRB mapping configuration for an existing SDAP entity - * according to TS 37.324, 5.3 QoS flow to DRB Mapping, clause 5.3.1 Configuration Procedures - */ -static void nr_sdap_ue_qfi2drb_config(nr_sdap_entity_t *existing_sdap_entity, - rb_id_t pdcp_entity, - ue_id_t ue_id, - NR_QFI_t *mapped_qfi_2_add, - uint8_t mappedQFIs2AddCount, - uint8_t drb_identity, - bool has_sdap_rx, - bool has_sdap_tx) +/** @brief UL QoS flow to DRB mapping configuration for a SDAP entity has already been established + * according to TS 37.324, 5.3 QoS flow to DRB Mapping, 5.3.1 Configuration Procedures. */ +static void nr_sdap_ue_control_pdu_config(nr_sdap_entity_t *entity, const ue_id_t ue_id, const sdap_config_t *sdap) { - LOG_D(SDAP, "RRC Configuring SDAP Entity\n"); - for(int i = 0; i < mappedQFIs2AddCount; i++){ - uint8_t qfi = mapped_qfi_2_add[i]; - /* a default DRB exists and there is no QFI to DRB mapping rule for the QFI */ - if (existing_sdap_entity->default_drb && existing_sdap_entity->qfi2drb_table[qfi].drb_id == SDAP_NO_MAPPING_RULE) { - nr_sdap_ul_hdr_t sdap_ctrl_pdu = existing_sdap_entity->sdap_construct_ctrl_pdu(qfi); - rb_id_t sdap_ctrl_pdu_drb = - existing_sdap_entity->sdap_map_ctrl_pdu(existing_sdap_entity, pdcp_entity, SDAP_CTRL_PDU_MAP_DEF_DRB, qfi); - existing_sdap_entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu); + // handle QFIs to DRB mapping rule to add + for (int i = 0; i < sdap->mappedQFIs2AddCount; i++) { + uint8_t qfi = sdap->mappedQFIs2Add[i]; + /* a default DRB exists and there is no stored QFI to DRB mapping rule for the QFI */ + if (entity->default_drb && entity->qfi2drb_table[qfi].drb_id == SDAP_NO_MAPPING_RULE) { + // construct an end-marker control PDU (6.2.3 TS 37.324) + nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(qfi); + // map the end-marker control PDU to the default DRB + int sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, SDAP_CTRL_PDU_MAP_DEF_DRB, qfi); + // submit the end-marker control PDU to the lower layers + entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu); } - /* the stored UL QFI to DRB mapping rule is different from the configured one and has UL SDAP header*/ - if (existing_sdap_entity->qfi2drb_table[qfi].drb_id != drb_identity && existing_sdap_entity->qfi2drb_table[qfi].has_sdap_tx) { - nr_sdap_ul_hdr_t sdap_ctrl_pdu = existing_sdap_entity->sdap_construct_ctrl_pdu(qfi); - rb_id_t sdap_ctrl_pdu_drb = - existing_sdap_entity->sdap_map_ctrl_pdu(existing_sdap_entity, pdcp_entity, SDAP_CTRL_PDU_MAP_RULE_DRB, qfi); - existing_sdap_entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu); + /* the stored UL QFI to DRB mapping rule is different from the configured one and has UL SDAP header */ + bool ul_sdap_header = (entity->qfi2drb_table[qfi].entity_role & SDAP_UL_TX) != 0; + if (entity->qfi2drb_table[qfi].drb_id != sdap->drb_id && ul_sdap_header) { + // construct an end-marker control PDU (6.2.3 TS 37.324) + nr_sdap_ul_hdr_t sdap_ctrl_pdu = entity->sdap_construct_ctrl_pdu(qfi); + // map the end-marker control PDU to the DRB according to the stored QoS flow to DRB mapping rule + int sdap_ctrl_pdu_drb = entity->sdap_map_ctrl_pdu(entity, SDAP_CTRL_PDU_MAP_RULE_DRB, qfi); + // submit the end-marker control PDU to the lower layers + entity->sdap_submit_ctrl_pdu(ue_id, sdap_ctrl_pdu_drb, sdap_ctrl_pdu); } - /* update QFI to DRB mapping rules */ - LOG_D(SDAP, "Storing the configured QoS flow to DRB mapping rule\n"); - existing_sdap_entity->qfi2drb_map_update(existing_sdap_entity, qfi, drb_identity, has_sdap_rx, has_sdap_tx); } } +/** @brief Add QoS flows to a DRB */ +static void nr_sdap_add_qos_flows_to_drb(nr_sdap_entity_t *entity, const sdap_config_t *sdap) +{ + for (int i = 0; i < sdap->mappedQFIs2AddCount; i++) { + uint8_t qfi = sdap->mappedQFIs2Add[i]; + LOG_D(SDAP, "Adding QFI to DRB mapping rules: %d mapped QFIs for DRB %d\n", sdap->mappedQFIs2AddCount, sdap->drb_id); + if (qfi < SDAP_MAX_QFI && sdap->drb_id > SDAP_MAP_RULE_EMPTY && sdap->drb_id <= MAX_DRBS_PER_UE) { + entity->qfi2drb_map_add(entity, qfi, sdap->drb_id, sdap->role); + } else { + LOG_E(SDAP, "Failed to add qfi2drb mapping: QFI=%d, DRB=%d\n", qfi, sdap->drb_id); + } + } +} + +/** @brief Remove QoS flows from a DRB */ +static void nr_sdap_rm_qos_flows_from_drb(nr_sdap_entity_t *entity, const sdap_config_t *sdap) +{ + for (int i = 0; i < sdap->mappedQFIs2ReleaseCount; i++) { + uint8_t qfi = sdap->mappedQFIs2Release[i]; + LOG_D(SDAP, "Removing QFI from DRB mapping rules: QFI=%d for DRB=%d\n", qfi, sdap->drb_id); + entity->qfi2drb_map_delete(entity, qfi); + } +} + +/** @brief Update QFI to DRB mapping rules + * @param qfi the QoS Flow index, used as unique index of the qfi2drb mapping table + * @param drb the DRB ID to be mapped */ +static void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, const sdap_config_t *sdap) +{ + if (!entity->is_gnb) { // UE control PDU configuration + nr_sdap_ue_control_pdu_config(entity, entity->ue_id, sdap); + } + nr_sdap_add_qos_flows_to_drb(entity, sdap); + nr_sdap_rm_qos_flows_from_drb(entity, sdap); +} + /** * @brief add a new SDAP entity according to 5.1.1. of 3GPP TS 37.324 * @note there is one SDAP entity per PDU session * * @param is_gnb, indicates whether it is for gNB or UE - * @param has_sdap_rx, indicates whether it is a receiving SDAP entity - * @param has_sdap_tx, indicates whether it is a transmitting SDAP entity * @param ue_id, UE ID - * @param pdusession_id, PDU session ID - * @param is_defaultDRB, indicates whether the entity has a default DRB - * @param mapped_qfi_2_add, list of QoS flows to add/update - * @param mappedQFIs2AddCount, number of QoS flows to add/update - */ -nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, - bool has_sdap_rx, - bool has_sdap_tx, - ue_id_t ue_id, - int pdusession_id, - bool is_defaultDRB, - uint8_t drb_identity, - NR_QFI_t *mapped_qfi_2_add, - uint8_t mappedQFIs2AddCount) + * @param sdap, SDAP configuration */ +static void nr_sdap_add_entity(const int is_gnb, const ue_id_t ue_id, const sdap_config_t *sdap) { - /* check whether the SDAP entity already exists and - update QFI to DRB mapping rules in that case */ - if (nr_sdap_get_entity(ue_id, pdusession_id)) { - LOG_E(SDAP, "SDAP Entity for UE already exists with RNTI/UE ID: %lu and PDU SESSION ID: %d\n", ue_id, pdusession_id); - nr_sdap_entity_t *existing_sdap_entity = nr_sdap_get_entity(ue_id, pdusession_id); - rb_id_t pdcp_entity = existing_sdap_entity->default_drb; - if(!is_gnb) - nr_sdap_ue_qfi2drb_config(existing_sdap_entity, - pdcp_entity, - ue_id, - mapped_qfi_2_add, - mappedQFIs2AddCount, - drb_identity, - has_sdap_rx, - has_sdap_tx); - return existing_sdap_entity; - } - - nr_sdap_entity_t *sdap_entity; - sdap_entity = calloc(1, sizeof(nr_sdap_entity_t)); - - if(sdap_entity == NULL) { - LOG_E(SDAP, "SDAP Entity creation failed, out of memory\n"); - exit(1); - } + nr_sdap_entity_t *sdap_entity = calloc_or_fail(1, sizeof(*sdap_entity)); + // SDAP entity ids sdap_entity->ue_id = ue_id; - sdap_entity->pdusession_id = pdusession_id; + sdap_entity->pdusession_id = sdap->pdusession_id; sdap_entity->is_gnb = is_gnb; + sdap_entity->enable_sdap = (sdap->role != NO_SDAP_HEADER); + // rx/tx entities sdap_entity->tx_entity = nr_sdap_tx_entity; sdap_entity->rx_entity = nr_sdap_rx_entity; + // control pdu function pointers sdap_entity->sdap_construct_ctrl_pdu = nr_sdap_construct_ctrl_pdu; sdap_entity->sdap_map_ctrl_pdu = nr_sdap_map_ctrl_pdu; sdap_entity->sdap_submit_ctrl_pdu = nr_sdap_submit_ctrl_pdu; + // QFI to DRB mapping functions pointers sdap_entity->qfi2drb_map_update = nr_sdap_qfi2drb_map_update; + sdap_entity->qfi2drb_map_add = nr_sdap_qfi2drb_map_add; sdap_entity->qfi2drb_map_delete = nr_sdap_qfi2drb_map_del; - sdap_entity->qfi2drb_map = nr_sdap_qfi2drb_map; - + sdap_entity->qfi2drb_map = nr_sdap_qfi2drb; sdap_entity->pdusession_sock = -1; - if(is_defaultDRB) { - sdap_entity->default_drb = drb_identity; - LOG_I(SDAP, "Default DRB for the created SDAP entity: %ld \n", sdap_entity->default_drb); - LOG_D(SDAP, "RRC updating mapping rules: %d\n", mappedQFIs2AddCount); - for (int i = 0; i < mappedQFIs2AddCount; i++) - sdap_entity->qfi2drb_map_update(sdap_entity, mapped_qfi_2_add[i], sdap_entity->default_drb, has_sdap_rx, has_sdap_tx); + // set default DRB + if (sdap->defaultDRB) { + sdap_entity->default_drb = sdap->drb_id; + LOG_I(SDAP, "Default DRB for the created SDAP entity: DRB %d \n", sdap_entity->default_drb); } + // Add QoS flows to the DRB (initial configuration) + nr_sdap_add_qos_flows_to_drb(sdap_entity, sdap); + + // update SDAP entity list pointers sdap_entity->next_entity = sdap_info.sdap_entity_llist; sdap_info.sdap_entity_llist = sdap_entity; @@ -533,7 +536,17 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, // PDCP SDUs to/from the TUN interface. start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id); } - return sdap_entity; +} + +/** @brief Add or modify an SDAP entity if it already exists */ +void nr_sdap_addmod_entity(const int is_gnb, const ue_id_t ue_id, const sdap_config_t *sdap) +{ + nr_sdap_entity_t *sdap_entity = nr_sdap_get_entity(ue_id, sdap->pdusession_id); + if (sdap_entity) { + sdap_entity->qfi2drb_map_update(sdap_entity, sdap); + } else { + nr_sdap_add_entity(is_gnb, ue_id, sdap); + } } /** @@ -583,14 +596,13 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) LOG_E(SDAP, "SDAP entities not established or Invalid range of pdusession_id [0, 256].\n"); return false; } - LOG_D(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; if (entityPtr->pdusession_sock != -1) remove_ip_if(entityPtr); free(entityPtr); - LOG_D(SDAP, "Successfully deleted Entity.\n"); + LOG_D(SDAP, "Successfully deleted SDAP entity for UE %lx and PDU Session id %d\n", ue_id, pdusession_id); return true; } else { while ((entityPtr->ue_id != ue_id || entityPtr->pdusession_id != pdusession_id) && entityPtr->next_entity != NULL @@ -606,7 +618,7 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) remove_ip_if(entityPtr); } free(entityPtr); - LOG_D(SDAP, "Successfully deleted Entity.\n"); + LOG_D(SDAP, "Successfully deleted Entity for UE %lx and PDU Session id %d\n", ue_id, pdusession_id); return true; } } @@ -653,6 +665,40 @@ bool nr_sdap_delete_ue_entities(ue_id_t ue_id) return ret; } +/** @brief This function gets the relevant SDAP config from the received SDAP-Config */ +sdap_config_t nr_sdap_get_config(const int is_gnb, const NR_SDAP_Config_t *sdap_Config, const int drb_id) +{ + DevAssert(sdap_Config); + sdap_config_t sdapConfig = {0}; + sdapConfig.drb_id = drb_id; + sdapConfig.role = get_sdap_role(is_gnb, sdap_Config); + LOG_D(SDAP, "SDAP headers %s\n", sdapConfig.role == NO_SDAP_HEADER ? "absent" : "present"); + sdapConfig.defaultDRB = sdap_Config->defaultDRB; + // 3GPP TS 38.331 The network sets sdap-HeaderUL to present if the field defaultDRB is set to true + if (sdapConfig.defaultDRB && (sdap_Config->sdap_HeaderUL != NR_SDAP_Config__sdap_HeaderUL_present)) + LOG_D(SDAP, "Received SDAP-Config with defaultDRB but sdap-HeaderUL is not present\n"); + if (sdap_Config->mappedQoS_FlowsToAdd) { + sdapConfig.mappedQFIs2AddCount = sdap_Config->mappedQoS_FlowsToAdd->list.count; + DevAssert(sdapConfig.mappedQFIs2AddCount <= SDAP_MAX_QFI); + LOG_D(SDAP, "DRB %d: mapped QFIs = %d \n", sdapConfig.drb_id, sdapConfig.mappedQFIs2AddCount); + for (int i = 0; i < sdapConfig.mappedQFIs2AddCount; i++){ + DevAssert(i < SDAP_MAX_QFI); + sdapConfig.mappedQFIs2Add[i] = *sdap_Config->mappedQoS_FlowsToAdd->list.array[i]; + LOG_D(SDAP, "Captured mappedQoS_FlowsToAdd[%d] from RRC: %ld\n", i, sdapConfig.mappedQFIs2Add[i]); + } + } + sdapConfig.pdusession_id = sdap_Config->pdu_Session; + if (sdap_Config->mappedQoS_FlowsToRelease) { + sdapConfig.mappedQFIs2ReleaseCount = sdap_Config->mappedQoS_FlowsToRelease->list.count; + DevAssert(sdapConfig.mappedQFIs2ReleaseCount <= SDAP_MAX_QFI); + for (int i = 0; i < sdapConfig.mappedQFIs2ReleaseCount; i++) { + DevAssert(i < SDAP_MAX_QFI); + sdapConfig.mappedQFIs2Release[i] = *sdap_Config->mappedQoS_FlowsToRelease->list.array[i]; + } + } + return sdapConfig; +} + /** * @brief SDAP Entity reconfiguration at UE according to TS 37.324 * and triggered by RRC reconfiguration events according to clause 5.3.5.6.5 of TS 38.331. @@ -670,27 +716,8 @@ void nr_reconfigure_sdap_entity(NR_SDAP_Config_t *sdap_config, ue_id_t ue_id, in ue_id, pdusession_id); /* QFI to DRB mapping */ - NR_QFI_t *mappedQFIs2Add = (NR_QFI_t *)sdap_config->mappedQoS_FlowsToAdd->list.array[0]; - uint8_t mappedQFIs2AddCount = sdap_config->mappedQoS_FlowsToAdd->list.count; - bool has_sdap_rx = is_sdap_rx(is_gnb, sdap_config); - bool has_sdap_tx = is_sdap_tx(is_gnb, sdap_config); - nr_sdap_ue_qfi2drb_config(sdap_entity, - sdap_entity->default_drb, - ue_id, - mappedQFIs2Add, - mappedQFIs2AddCount, - drb_id, - has_sdap_rx, - has_sdap_tx); - /* handle QFIs to DRB mapping rule to release */ - if (sdap_config->mappedQoS_FlowsToRelease) { - NR_QFI_t *mappedQFIs2release = (NR_QFI_t *)sdap_config->mappedQoS_FlowsToRelease->list.array[0]; - uint8_t mappedQFIs2RemoveCount = sdap_config->mappedQoS_FlowsToRelease->list.count; - for(int i = 0; i < mappedQFIs2RemoveCount; i++){ - uint8_t qfi = mappedQFIs2release[i]; - sdap_entity->qfi2drb_map_delete(sdap_entity, qfi); - } - } + sdap_config_t sdap = nr_sdap_get_config(is_gnb, sdap_config, drb_id); + sdap_entity->qfi2drb_map_update(sdap_entity, &sdap); } void set_qfi(uint8_t qfi, uint8_t pduid, ue_id_t ue_id) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index 3a42c6c076..9f85ac21cf 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -38,7 +38,6 @@ #define SDAP_HDR_LENGTH (1) #define SDAP_MAX_QFI (64) #define SDAP_MAP_RULE_EMPTY (0) -#define AVLBL_DRB (5) #define SDAP_NO_MAPPING_RULE (0) #define SDAP_REFLECTIVE_MAPPING (1) #define SDAP_RQI_HANDLING (1) @@ -69,20 +68,38 @@ typedef struct nr_sdap_ul_hdr_s { uint8_t DC:1; } __attribute__((packed)) nr_sdap_ul_hdr_t; +typedef enum { + SDAP_UL_TX = (1 << 0), + SDAP_UL_RX = (1 << 1), + SDAP_DL_TX = (1 << 2), + SDAP_DL_RX = (1 << 3) +} sdap_role_t; + typedef struct qfi2drb_s { - rb_id_t drb_id; - bool has_sdap_rx; - bool has_sdap_tx; + int drb_id; + int entity_role; } qfi2drb_t; -void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu); +void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, int sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu); + +typedef struct sdap_configuration_s { + int pdusession_id; + int drb_id; + int role; + bool defaultDRB; + NR_QFI_t mappedQFIs2Add[SDAP_MAX_QFI]; + uint8_t mappedQFIs2AddCount; + NR_QFI_t mappedQFIs2Release[SDAP_MAX_QFI]; + uint8_t mappedQFIs2ReleaseCount; +} sdap_config_t; typedef struct nr_sdap_entity_s { ue_id_t ue_id; - rb_id_t default_drb; + int default_drb; /// sdap_tun_read_thread needs to know if we are gNB/UE, so for noS1 mode, /// store which one we are bool is_gnb; + bool enable_sdap; int pdusession_id; int pdusession_sock; pthread_t pdusession_thread; @@ -91,18 +108,21 @@ typedef struct nr_sdap_entity_s { qfi2drb_t qfi2drb_table[SDAP_MAX_QFI]; - void (*qfi2drb_map_update)(struct nr_sdap_entity_s *entity, uint8_t qfi, rb_id_t drb, bool has_sdap_rx, bool has_sdap_tx); - void (*qfi2drb_map_delete)(struct nr_sdap_entity_s *entity, uint8_t qfi); - rb_id_t (*qfi2drb_map)(struct nr_sdap_entity_s *entity, uint8_t qfi); + void (*qfi2drb_map_update)(struct nr_sdap_entity_s *entity, const sdap_config_t *sdap); + void (*qfi2drb_map_delete)(struct nr_sdap_entity_s *entity, const uint8_t qfi); + void (*qfi2drb_map_add)(struct nr_sdap_entity_s *entity, + const uint8_t qfi, + const uint8_t drb_id, + const uint8_t role); + int (*qfi2drb_map)(struct nr_sdap_entity_s *entity, uint8_t qfi); nr_sdap_ul_hdr_t (*sdap_construct_ctrl_pdu)(uint8_t qfi); - rb_id_t (*sdap_map_ctrl_pdu)(struct nr_sdap_entity_s *entity, rb_id_t pdcp_entity, int map_type, uint8_t dl_qfi); - void (*sdap_submit_ctrl_pdu)(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu); + int (*sdap_map_ctrl_pdu)(struct nr_sdap_entity_s *entity, int map_type, uint8_t dl_qfi); + void (*sdap_submit_ctrl_pdu)(ue_id_t ue_id, int sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu); bool (*tx_entity)(struct nr_sdap_entity_s *entity, protocol_ctxt_t *ctxt_p, const srb_flag_t srb_flag, - const rb_id_t rb_id, const mui_t mui, const confirm_t confirm, const sdu_size_t sdu_buffer_size, @@ -114,9 +134,8 @@ typedef struct nr_sdap_entity_s { const bool rqi); void (*rx_entity)(struct nr_sdap_entity_s *entity, - rb_id_t pdcp_entity, + int pdcp_entity, int is_gnb, - bool has_sdap_rx, int pdusession_id, ue_id_t ue_id, char *buf, @@ -126,23 +145,6 @@ typedef struct nr_sdap_entity_s { struct nr_sdap_entity_s *next_entity; } nr_sdap_entity_t; -/* QFI to DRB Mapping Related Function */ -void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, uint8_t qfi, rb_id_t drb, bool has_sdap_rx, bool has_sdap_tx); - -/* QFI to DRB Mapping Related Function */ -void nr_sdap_qfi2drb_map_del(nr_sdap_entity_t *entity, uint8_t qfi); - -/* - * TS 37.324 - * 4.4 Functions - * Mapping between a QoS flow and a DRB for both DL and UL. - * - * 5.2.1 Uplink - * If there is no stored QoS flow to DRB mapping rule for the QoS flow as specified in the subclause 5.3, map the SDAP SDU to the default DRB - * else, map the SDAP SDU to the DRB according to the stored QoS flow to DRB mapping rule. - */ -rb_id_t nr_sdap_qfi2drb_map(nr_sdap_entity_t *entity, uint8_t qfi); - /* * TS 37.324 5.3 QoS flow to DRB Mapping * construct an end-marker control PDU, as specified in the subclause 6.2.3, for the QoS flow; @@ -155,33 +157,24 @@ nr_sdap_ul_hdr_t nr_sdap_construct_ctrl_pdu(uint8_t qfi); * 1.) default DRB or * 2.) DRB according to the stored QoS flow to DRB mapping rule */ -rb_id_t nr_sdap_map_ctrl_pdu(nr_sdap_entity_t *entity, rb_id_t pdcp_entity, int map_type, uint8_t dl_qfi); +int nr_sdap_map_ctrl_pdu(nr_sdap_entity_t *entity, int map_type, uint8_t dl_qfi); /* * TS 37.324 5.3 QoS flow to DRB Mapping * Submit the end-marker control PDU to the lower layer. */ -void nr_sdap_submit_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu); - -/* - * TS 37.324 4.4 5.1.1 SDAP entity establishment - * Establish an SDAP entity. - */ -nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, - bool has_sdap_rx, - bool has_sdap_tx, - ue_id_t ue_id, - int pdusession_id, - bool is_defaultDRB, - uint8_t default_DRB, - NR_QFI_t *mapped_qfi_2_add, - uint8_t mappedQFIs2AddCount); +void nr_sdap_submit_ctrl_pdu(ue_id_t ue_id, int sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu); /* Entity Handling Related Functions */ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id); +sdap_config_t nr_sdap_get_config(const int is_gnb, const NR_SDAP_Config_t *sdap_Config, const int drb_id); + void nr_sdap_release_drb(ue_id_t ue_id, int drb_id, int pdusession_id); +/** @brief Add or modify an SDAP entity based on whether it already exists */ +void nr_sdap_addmod_entity(const int is_gnb, const ue_id_t ue_id, const sdap_config_t *sdap); + /** * @brief Function to delete a single SDAP Entity based on the ue_id and pdusession_id. * @note 1. SDAP entities may have the same ue_id. @@ -200,20 +193,6 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id); */ bool nr_sdap_delete_ue_entities(ue_id_t ue_id); -/** - * @brief indicates whether it is a receiving SDAP entity - * i.e. for UE, header for DL data is present - * for gNB, header for UL data is present - */ -bool is_sdap_rx(bool is_gnb, NR_SDAP_Config_t *sdap_config); - -/** - * @brief indicates whether it is a transmitting SDAP entity - * i.e. for UE, header for UL data is present - * for gNB, header for DL data is present - */ -bool is_sdap_tx(bool is_gnb, NR_SDAP_Config_t *sdap_config); - /** * @brief Run the SDAP reconfiguration for the DRB * @param[in] ue_id Unique identifier for the User Equipment. ID Range [0, 65536]. diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index d0230e0a03..5a58af6b84 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1772,7 +1772,7 @@ static void send_nas_5gmm_ind(instance_t instance, const Guti5GSMobileIdentity_t itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); } -static void request_pdusession(nr_ue_nas_t *nas, int pdusession_id) +void request_pdusession(nr_ue_nas_t *nas, int pdusession_id) { MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_PDU_SESSION_REQ); NAS_PDU_SESSION_REQ(message_p).pdusession_id = pdusession_id; diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index 2d62c799ea..7a19997444 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -113,5 +113,6 @@ void *nas_nrue_task(void *args_p); void *nas_nrue(void *args_p); void nas_init_nrue(int num_ues); void nr_ue_create_ip_if(const char *ifnameprefix, const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id); +void request_pdusession(nr_ue_nas_t *nas, int pdusession_id); #endif /* __NR_NAS_MSG_SIM_H__*/ diff --git a/openair3/NGAP/ngap_common.c b/openair3/NGAP/ngap_common.c index c3865cff10..8be57349ec 100644 --- a/openair3/NGAP/ngap_common.c +++ b/openair3/NGAP/ngap_common.c @@ -106,7 +106,7 @@ ngap_cause_t decode_ngap_cause(const NGAP_Cause_t *in) nr_guami_t decode_ngap_guami(const NGAP_GUAMI_t *in) { nr_guami_t out = {0}; - TBCD_TO_MCC_MNC(&in->pLMNIdentity, out.mcc, out.mnc, out.mnc_len); + TBCD_TO_MCC_MNC(&in->pLMNIdentity, out.plmn.mcc, out.plmn.mnc, out.plmn.mnc_digit_length); OCTET_STRING_TO_INT8(&in->aMFRegionID, out.amf_region_id); OCTET_STRING_TO_INT16(&in->aMFSetID, out.amf_set_id); OCTET_STRING_TO_INT8(&in->aMFPointer, out.amf_pointer); diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index cff9cd0b72..7dd6359b7a 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -76,9 +76,9 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng const nr_guami_t *guami = &msg->ue_identity.guami; LOG_D(NGAP, "GUAMI is present: MCC=%03d MNC=%0*d RegionID=%d SetID=%d Pointer=%d\n", - guami->mcc, - guami->mnc_len, - guami->mnc, + guami->plmn.mcc, + guami->plmn.mnc_digit_length, + guami->plmn.mnc, guami->amf_region_id, guami->amf_set_id, guami->amf_pointer); @@ -89,9 +89,9 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng msg->gNB_ue_ngap_id, amf->amf_name, amf->assoc_id, - guami->mcc, - guami->mnc_len, - guami->mnc, + guami->plmn.mcc, + guami->plmn.mnc_digit_length, + guami->plmn.mnc, guami->amf_region_id, guami->amf_set_id, guami->amf_pointer); @@ -181,7 +181,6 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf .amf_ref = amf, .gNB_ue_ngap_id = UEfirstReq->gNB_ue_ngap_id, .gNB_instance = instance_p, - .selected_plmn_identity = UEfirstReq->plmn, }; // RAN UE NGAP ID (M) @@ -211,16 +210,14 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR; asn1cCalloc(ie->value.choice.UserLocationInformation.choice.userLocationInformationNR, userinfo_nr_p); - /* Set nRCellIdentity. default userLocationInformationNR */ - MACRO_GNB_ID_TO_CELL_IDENTITY(instance_p->gNB_id, - 0, // Cell ID - &userinfo_nr_p->nR_CGI.nRCellIdentity); + /* NR CGI: use gNB ID and Cell ID passed from RRC */ + MACRO_GNB_ID_TO_CELL_IDENTITY(instance_p->gNB_id, UEfirstReq->nr_cell_id, &userinfo_nr_p->nR_CGI.nRCellIdentity); - plmn_id_t *plmn = &ue_desc_p.selected_plmn_identity; + /* Use UE's selected PLMN for nR-CGI (from Initial UE Message) */ + plmn_id_t *plmn = &UEfirstReq->plmn; MCC_MNC_TO_TBCD(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->nR_CGI.pLMNIdentity); - /* In case of network sharing, - the selected PLMN is indicated by the PLMN Identity IE within the TAI IE */ + /* Set TAI - use UE's selected PLMN */ INT24_TO_OCTET_STRING(instance_p->tac, &userinfo_nr_p->tAI.tAC); MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->tAI.pLMNIdentity); } @@ -444,17 +441,20 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_ ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR; asn1cCalloc(ie->value.choice.UserLocationInformation.choice.userLocationInformationNR, userinfo_nr_p); - /* Set nRCellIdentity. default userLocationInformationNR */ + /* Set nRCellIdentity: use gNB ID and Cell ID */ MACRO_GNB_ID_TO_CELL_IDENTITY(ngap_gNB_instance_p->gNB_id, - 0, // Cell ID + ngap_uplink_nas_p->nr_cell_id, &userinfo_nr_p->nR_CGI.nRCellIdentity); - plmn_id_t *plmn = &ue_context_p->selected_plmn_identity; + + /* NR CGI */ + plmn_id_t *plmn = &ngap_uplink_nas_p->plmn; MCC_MNC_TO_TBCD(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->nR_CGI.pLMNIdentity); - /* Set TAI */ - INT24_TO_OCTET_STRING(ngap_gNB_instance_p->tac, &userinfo_nr_p->tAI.tAC); + /* TAI */ + INT24_TO_OCTET_STRING(ngap_uplink_nas_p->tac, &userinfo_nr_p->tAI.tAC); MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->tAI.pLMNIdentity); } + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode uplink NAS transport\n"); /* Encode procedure has failed... */ diff --git a/openair3/NGAP/ngap_gNB_nnsf.c b/openair3/NGAP/ngap_gNB_nnsf.c index f895737a0d..e16e790d38 100644 --- a/openair3/NGAP/ngap_gNB_nnsf.c +++ b/openair3/NGAP/ngap_gNB_nnsf.c @@ -156,7 +156,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *in ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, const plmn_id_t selected_plmn_identity, - uint8_t amf_setid) + uint16_t amf_setid) { struct ngap_gNB_amf_data_s *amf_data_p = NULL; @@ -286,8 +286,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *inst struct plmn_identity_s *served_plmn_p = NULL; STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) { - if ((served_plmn_p->mcc == guami.mcc) && - (served_plmn_p->mnc == guami.mnc)) { + if ((served_plmn_p->mcc == guami.plmn.mcc) && (served_plmn_p->mnc == guami.plmn.mnc)) { break; } } @@ -322,9 +321,9 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *inst } NGAP_WARN("No matching AMF found for GUAMI (MCC=%03d MNC=%0*d RegionID=%d SetID=%d Pointer=%d)\n", - guami.mcc, - guami.mnc_len, - guami.mnc, + guami.plmn.mcc, + guami.plmn.mnc_digit_length, + guami.plmn.mnc, guami.amf_region_id, guami.amf_set_id, guami.amf_pointer); @@ -373,8 +372,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instanc struct plmn_identity_s *served_plmn_p = NULL; STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) { - if ((served_plmn_p->mcc == guami.mcc) && - (served_plmn_p->mnc == guami.mnc)) { + if ((served_plmn_p->mcc == guami.plmn.mcc) && (served_plmn_p->mnc == guami.plmn.mnc)) { break; } } diff --git a/openair3/NGAP/ngap_gNB_nnsf.h b/openair3/NGAP/ngap_gNB_nnsf.h index 8a87ecfce2..0b7c7059e3 100644 --- a/openair3/NGAP/ngap_gNB_nnsf.h +++ b/openair3/NGAP/ngap_gNB_nnsf.h @@ -43,7 +43,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *in ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, const plmn_id_t selected_plmn_identity, - uint8_t amf_setid); + uint16_t amf_setid); ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, diff --git a/openair3/NGAP/ngap_gNB_ue_context.h b/openair3/NGAP/ngap_gNB_ue_context.h index 1022f2f4c3..8053e8f8c6 100644 --- a/openair3/NGAP/ngap_gNB_ue_context.h +++ b/openair3/NGAP/ngap_gNB_ue_context.h @@ -69,11 +69,6 @@ typedef struct ngap_gNB_ue_context_s { /* Reference to AMF data this UE is attached to */ struct ngap_gNB_amf_data_s *amf_ref; - /* Signaled by the UE in RRC Connection Setup Complete and used in NAS Uplink - * to route NAS messages correctly. 0-based, not 1-based as in TS 36.331 - * 6.2.2 RRC Connection Setup Complete! */ - plmn_id_t selected_plmn_identity; - /* Reference to gNB data this UE is attached to */ ngap_gNB_instance_t *gNB_instance; } ngap_gNB_ue_context_t; diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index 82afa451c0..567a166491 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -477,6 +477,7 @@ static void sctp_handle_new_association_req(const instance_t instance, if (errno != EINPROGRESS) { SCTP_ERROR("Connect failed: %s\n", strerror(errno)); sctp_itti_send_association_resp(requestor, instance, -1, req->ulp_cnx_id, SCTP_STATE_UNREACHABLE, 0, 0); + freeaddrinfo(serv); close(sd); return; } else { diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 9be1873612..ed15d48f80 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -152,6 +152,7 @@ class gtpEndPoint { } }; +static void gtpv1uReceiverCancel(pthread_t t); class gtpEndPoints { public: pthread_mutex_t gtp_lock = PTHREAD_MUTEX_INITIALIZER; @@ -168,8 +169,10 @@ class gtpEndPoints { ~gtpEndPoints() { // automatically close all sockets on quit - for (const auto &p : instances) + for (const auto &p : instances) { + gtpv1uReceiverCancel(p.second.thrData.t); close(p.first); + } } }; @@ -289,7 +292,7 @@ static int gtpv1uCreateAndSendMsg(gtpv1u_bearer_t *bearer, DevAssert(bearer->ip.ss_family == AF_INET); struct sockaddr_in *to = (struct sockaddr_in *)&bearer->ip; LOG_D(GTPU, - "Peer IP:" IPV4_ADDR " port:%u outgoing teid:%x\n", + "Peer IP:" IPV4_ADDR " port:%u outgoing TEID:0x%x\n", IPV4_ADDR_FORMAT(to->sin_addr.s_addr), htons(to->sin_port), bearer->teid_outgoing); @@ -329,7 +332,7 @@ static void _gtpv1uSendDirect(instance_t instance, } LOG_D(GTPU, - "[%ld] sending a packet to UE:RAB:teid %lx/%x/%x, len %lu, oldseq %d, oldnum %d\n", + "[%ld] sending a packet to UE:RAB:TEID %lx/%d/0x%x, len %lu, oldseq %d, oldnum %d\n", instance, ue_id, bearer_id, @@ -489,7 +492,7 @@ static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_end_marker_req_t *re } LOG_D(GTPU, - "[%ld] sending a end packet packet to UE:RAB:teid %lx/%x/%x\n", + "[%ld] sending a end packet packet to UE:RAB:TEID %lx/%d/0x%x\n", instance, ue_id, bearer_id, @@ -638,7 +641,7 @@ void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, struct sockaddr_in *sa4 = (struct sockaddr_in *)sockaddr; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sockaddr; LOG_I(GTPU, - "[%ld] UE ID %ld: Update tunnel TEID incoming %x outgoing %x to remote IPv4 %s, IPv6 %s, port %d\n", + "[%ld] UE ID %ld: Update tunnel TEID incoming 0x%x outgoing 0x%x to remote IPv4 %s, IPv6 %s, port %d\n", instance, ue_id, ptr2->second.teid_incoming, @@ -673,7 +676,7 @@ teid_t newGtpuCreateTunnel(instance_t instance, teid_t incoming_teid = gtpv1uNewTeid(); while (globGtp.te2ue_mapping.find(incoming_teid) != globGtp.te2ue_mapping.end()) { - LOG_W(GTPU, "[%ld] generated a random Teid that exists, re-generating (%x)\n", instance, incoming_teid); + LOG_W(GTPU, "[%ld] generated a random TEID that exists, re-generating (0x%x)\n", instance, incoming_teid); incoming_teid = gtpv1uNewTeid(); }; @@ -718,7 +721,7 @@ teid_t newGtpuCreateTunnel(instance_t instance, char ip4[INET_ADDRSTRLEN]; char ip6[INET6_ADDRSTRLEN]; LOG_I(GTPU, - "[%ld] UE ID %ld: Create tunnel TEID incoming %x outgoing %x to remote IPv4 %s, IPv6 %s, port %d\n", + "[%ld] UE ID %ld: Create tunnel TEID incoming 0x%x outgoing 0x%x to remote IPv4 %s, IPv6 %s, port %d\n", instance, ue_id, bearer.teid_incoming, @@ -822,7 +825,7 @@ int gtpv1u_create_ngu_tunnel(const instance_t instance, gtpCallbackSDAP callBackSDAP) { LOG_D(GTPU, - "[%ld] Start create tunnels for ue id %lu, num_tunnels %d, sgw_S1u_teid %x\n", + "[%ld] Start create tunnels for ue id %lu, num_tunnels %d, TEID 0x%x\n", instance, create_tunnel_req->ue_id, create_tunnel_req->num_tunnels, @@ -902,17 +905,17 @@ int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id) } map::iterator rb_it = ue_it->second.bearers.find(rb_id); if (rb_it == ue_it->second.bearers.end()) { - LOG_E(GTPU, "%s() UE %ld has no bearer %d, available\n", __func__, ue_id, rb_id); + LOG_E(GTPU, "%s() UE %ld has no tunnel for bearer %d\n", __func__, ue_id, rb_id); pthread_mutex_unlock(&globGtp.gtp_lock); return !GTPNOK; } - int teid = rb_it->second.teid_incoming; + teid_t teid = rb_it->second.teid_incoming; globGtp.te2ue_mapping.erase(teid); ue_it->second.bearers.erase(rb_id); pthread_mutex_unlock(&globGtp.gtp_lock); - LOG_I(GTPU, "Deleted tunnel TEID %d (RB %d) for ue id %ld, remaining bearers:\n", teid, rb_id, ue_id); + LOG_I(GTPU, "Deleted tunnel TEID 0x%x for bearer %d of UE %ld, remaining tunnels:\n", teid, rb_id, ue_id); for (auto b : ue_it->second.bearers) - LOG_I(GTPU, "bearer %ld\n", b.first); + LOG_I(GTPU, "Bearer %ld\n", b.first); return !GTPNOK; } @@ -979,45 +982,12 @@ int gtpv1u_delete_all_s1u_tunnel(const instance_t instance, const rnti_t rnti) return newGtpuDeleteAllTunnels(instance, rnti); } -int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id) -{ - LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", instance, ue_id); - pthread_mutex_lock(&globGtp.gtp_lock); - getInstRetInt(compatInst(instance)); - getUeRetInt(inst, ue_id); - int nb = 0; - - for (int i = 0; i < nbTunnels; i++) { - auto ptr2 = ptrUe->second.bearers.find(pdusession_id[i]); - - if (ptr2 == ptrUe->second.bearers.end()) { - LOG_E(GTPU, "[%ld] GTP-U instance: delete of not existing tunnel UE ID:RAB: %ld/%x\n", instance, ue_id, pdusession_id[i]); - } else { - globGtp.te2ue_mapping.erase(ptr2->second.teid_incoming); - nb++; - } - } - - if (ptrUe->second.bearers.size() == 0) - // no tunnels on this ue id, erase the ue entry - inst->ue2te_mapping.erase(ptrUe); - - pthread_mutex_unlock(&globGtp.gtp_lock); - LOG_I(GTPU, "[%ld] Deleted all tunnels for ue id %lu (%d tunnels deleted)\n", instance, ue_id, nb); - return !GTPNOK; -} - int gtpv1u_delete_x2u_tunnel(const instance_t instanceP, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { LOG_E(GTPU, "x2 tunnel not implemented\n"); return 0; } -int gtpv1u_delete_ngu_tunnel(const instance_t instance, gtpv1u_gnb_delete_tunnel_req_t *req) -{ - return newGtpuDeleteTunnels(instance, req->ue_id, req->num_pdusession, req->pdusession_id); -} - static gtpv1u_bearer_t create_bearer(int socket, const struct sockaddr_in *addr, uint32_t teid, uint16_t seq) { gtpv1u_bearer_t bearer = {.sock_fd = socket, .teid_outgoing = teid, .seqNum = seq}; @@ -1040,7 +1010,7 @@ static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, const } uint16_t seq = ntohs(*(uint16_t *)(msgHdr + 1)); - LOG_D(GTPU, "[%d] Received a echo request, TEID: %d, seq: %hu\n", h, msgHdr->teid, seq); + LOG_D(GTPU, "[%d] Received a echo request, TEID: 0x%x, seq: %hu\n", h, msgHdr->teid, seq); uint8_t recovery[2] = {14, 0}; gtpv1u_bearer_t bearer = create_bearer(h, addr, ntohl(msgHdr->teid), seq); return gtpv1uCreateAndSendMsg(&bearer, @@ -1058,10 +1028,11 @@ static int Gtpv1uHandleError(int h, uint8_t *msgBuf, uint32_t msgBufLen, const s if (msgBufLen < sizeof(Gtpv1uError)) LOG_E(GTPU, "Received GTP error indication with truncated size %u (mini size: %lu)\n", msgBufLen,sizeof(Gtpv1uError)+4); Gtpv1uError *msg = ( Gtpv1uError *)msgBuf; - LOG_E(GTPU, "Received GTP error indication: \n" - " TEID %u (must be 0 from TS 29.281)\n" - " TV id for TEID %u (must be 16)\n" - " TEID in error %u (should be a TEID we sent)\n" + LOG_E(GTPU, + "Received GTP error indication: \n" + " TEID 0x%x (must be 0 from TS 29.281)\n" + " TV id for TEID 0x%x (must be 16)\n" + " TEID in error 0x%x (should be a TEID we sent)\n" " TV id for GTP addr %u (should be 133)\n" " len for addr of UPF %u (should be IPv4 or IPv6 len)" " (TS 29.281 Sec 7.3.1 Error Handling not implemented)\n", @@ -1100,7 +1071,7 @@ static int Gtpv1uHandleEndMarker(int h, uint8_t *msgBuf, uint32_t msgBufLen, con auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); if (tunnel == globGtp.te2ue_mapping.end()) { - LOG_E(GTPU, "[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, msgHdr->teid); + LOG_E(GTPU, "[%d] Received a incoming packet on unknown TEID (0x%x) Dropping!\n", h, msgHdr->teid); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; } @@ -1129,7 +1100,7 @@ static int Gtpv1uHandleEndMarker(int h, uint8_t *msgBuf, uint32_t msgBufLen, con if (!tunnel->second.callBack(&ctxt, srb_flag, rb_id, mui, confirm, 0, NULL, mode, &sourceL2Id, &destinationL2Id)) LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); - LOG_D(GTPU, "[%d] Received END marker packet for: teid:%x\n", h, ntohl(msgHdr->teid)); + LOG_D(GTPU, "[%d] Received END marker packet for: TEID:0x%x\n", h, ntohl(msgHdr->teid)); return !GTPNOK; } @@ -1146,7 +1117,7 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const st auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); if (tunnel == globGtp.te2ue_mapping.end()) { - LOG_E(GTPU, "[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, ntohl(msgHdr->teid)); + LOG_E(GTPU, "[%d] Received a incoming packet on unknown TEID (0x%x) Dropping!\n", h, ntohl(msgHdr->teid)); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; } @@ -1244,7 +1215,6 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const st if (!uedata.callBackSDAP(&ctxt, uedata.ue_id, srb_flag, - rb_id, mui, confirm, sdu_buffer_size, @@ -1280,11 +1250,11 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const st 1); } - LOG_D(GTPU, "[%d] Received a %d bytes packet for: teid:%x\n", h, msgBufLen - offset, ntohl(msgHdr->teid)); + LOG_D(GTPU, "[%d] Received a %d bytes packet for: TEID:0x%x\n", h, msgBufLen - offset, ntohl(msgHdr->teid)); return !GTPNOK; } -static void gtpv1uReceiveHandleMessage(int h) +static bool gtpv1uReceiveHandleMessage(int h) { uint8_t udpData[65536]; int udpDataLen; @@ -1294,19 +1264,19 @@ static void gtpv1uReceiveHandleMessage(int h) if ((udpDataLen = recvfrom(h, udpData, sizeof(udpData), 0, (struct sockaddr *)&addr, &from_len)) < 0) { LOG_E(GTPU, "[%d] Recvfrom failed (%s)\n", h, strerror(errno)); - return; + return false; } else if (udpDataLen == 0) { LOG_W(GTPU, "[%d] Recvfrom returned 0\n", h); - return; + return true; } else { if (udpDataLen < (int)sizeof(Gtpv1uMsgHeaderT)) { LOG_W(GTPU, "[%d] received malformed gtp packet \n", h); - return; + return true; } Gtpv1uMsgHeaderT *msg = (Gtpv1uMsgHeaderT *)udpData; if ((int)(ntohs(msg->msgLength) + sizeof(Gtpv1uMsgHeaderT)) != udpDataLen) { LOG_W(GTPU, "[%d] received malformed gtp packet length\n", h); - return; + return true; } LOG_D(GTPU, "[%d] Received GTP data, msg type: %x\n", h, msg->msgType); switch (msg->msgType) { @@ -1338,18 +1308,27 @@ static void gtpv1uReceiveHandleMessage(int h) break; } } + return true; } static void* gtpv1uReceiver(void *thr) { gtpThread_t *gt = (gtpThread_t *)thr; - while (true) { - gtpv1uReceiveHandleMessage(gt->h); + while (gtpv1uReceiveHandleMessage(gt->h)) { } LOG_W(GTPU, "exiting thread\n"); return NULL; } +static void gtpv1uReceiverCancel(pthread_t t) +{ + int rc; + rc = pthread_cancel(t); + DevAssert(rc == 0); + rc = pthread_join(t, NULL); + DevAssert(rc == 0); +} + #include void *gtpv1uTask(void *args) @@ -1371,6 +1350,8 @@ void *gtpv1uTask(void *args) // DATA TO BE SENT TO UDP case TERMINATE_MESSAGE: + LOG_W(GTPU, "Exiting GTP instance %ld\n", myInstance); + itti_exit_task(); break; case TIMER_HAS_EXPIRED: diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index 4fcb8190e4..9274cd52f2 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -49,7 +49,6 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; typedef bool (*gtpCallbackSDAP)(protocol_ctxt_t *ctxt_pP, const ue_id_t ue_id, const srb_flag_t srb_flagP, - const rb_id_t rb_idP, const mui_t muiP, const confirm_t confirmP, const sdu_size_t sdu_buffer_sizeP, @@ -101,9 +100,6 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; gtpCallback callBack, gtpCallbackSDAP callBackSDAP); - int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req); - int gtpv1u_update_ue_id(const instance_t instanceP, ue_id_t old_ue_id, ue_id_t new_ue_id); // New API @@ -125,7 +121,6 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id); int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id); - int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id); void gtpv1uSendDirect(instance_t instance, ue_id_t ue_id, int bearer_id, uint8_t *buf, size_t len, bool seqNumFlag, bool npduNumFlag); void gtpv1uSendDirectWithNRUSeqNum(instance_t instance, diff --git a/radio/ETHERNET/CMakeLists.txt b/radio/ETHERNET/CMakeLists.txt index 3a9b9dc5cb..dd0f603eda 100644 --- a/radio/ETHERNET/CMakeLists.txt +++ b/radio/ETHERNET/CMakeLists.txt @@ -9,5 +9,3 @@ set_target_properties(oai_eth_transpro PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMA add_custom_command(TARGET oai_eth_transpro POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_eth_transpro.so liboai_transpro.so WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) - -add_subdirectory(benetel) diff --git a/radio/ETHERNET/benetel/4g/CMakeLists.txt b/radio/ETHERNET/benetel/4g/CMakeLists.txt deleted file mode 100644 index 164e33eb28..0000000000 --- a/radio/ETHERNET/benetel/4g/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -pkg_check_modules(libdpdk REQUIRED libdpdk=20.05.0) - -add_library(benetel_4g MODULE - benetel.c - shared_buffers.c - low.c - low_dpdk.c - dpdk_driver.c -) - -target_compile_definitions(benetel_4g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") - -SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") -target_include_directories(benetel_4g PRIVATE ${libdpdk_INCLUDE_DIRS}) -target_link_libraries(benetel_4g PRIVATE ${libdpdk_LIBRARIES}) -target_link_libraries(benetel_4g PRIVATE pthread dl rt m numa) -set_target_properties(benetel_4g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -add_custom_command(TARGET benetel_4g POST_BUILD - COMMAND ${CMAKE_COMMAND} -E create_symlink libbenetel_4g.so liboai_transpro.so - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/benetel/4g/benetel.c b/radio/ETHERNET/benetel/4g/benetel.c deleted file mode 100644 index 8e221fe929..0000000000 --- a/radio/ETHERNET/benetel/4g/benetel.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include - -#include "common_lib.h" -#include "ethernet_lib.h" -#include "shared_buffers.h" -#include "low.h" -#include "common/utils/LOG/log.h" -#include "common/utils/LOG/vcd_signal_dumper.h" - -typedef struct { - eth_state_t e; - shared_buffers buffers; - rru_config_msg_type_t last_msg; - int capabilities_sent; - void *benetel_priv; - char *dpdk_main_command_line; -} benetel_eth_state_t; - -int trx_benetel_start(openair0_device *device) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return 0; -} - - -void trx_benetel_end(openair0_device *device) -{ - printf("BENETEL: %s\n", __FUNCTION__); -} - - -int trx_benetel_stop(openair0_device *device) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int trx_benetel_set_freq(openair0_device* device, openair0_config_t *openair0_cfg) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int trx_benetel_set_gains(openair0_device* device, - openair0_config_t *openair0_cfg) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int trx_benetel_get_stats(openair0_device* device) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int trx_benetel_reset_stats(openair0_device* device) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int ethernet_tune(openair0_device *device, - unsigned int option, - int value) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return 0; -} - -int trx_benetel_write_raw(openair0_device *device, - openair0_timestamp timestamp, - void **buff, int nsamps, int cc, int flags) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return nsamps*4; -} - -int trx_benetel_read_raw(openair0_device *device, - openair0_timestamp *timestamp, - void **buff, int nsamps, int cc) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return nsamps*4; -} - -char *msg_type(int t) -{ - static char *s[12] = { - "RAU_tick", - "RRU_capabilities", - "RRU_config", - "RRU_config_ok", - "RRU_start", - "RRU_stop", - "RRU_sync_ok", - "RRU_frame_resynch", - "RRU_MSG_max_num", - "RRU_check_sync", - "RRU_config_update", - "RRU_config_update_ok", - }; - - if (t < 0 || t > 11) return "UNKNOWN"; - return s[t]; -} - -int trx_benetel_ctlsend(openair0_device *device, void *msg, ssize_t msg_len) -{ - RRU_CONFIG_msg_t *rru_config_msg = msg; - benetel_eth_state_t *s = device->priv; - - printf("BENETEL: %s\n", __FUNCTION__); - - printf(" rru_config_msg->type %d [%s]\n", rru_config_msg->type, - msg_type(rru_config_msg->type)); - - s->last_msg = rru_config_msg->type; - - return msg_len; -} - -int trx_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len) -{ - RRU_CONFIG_msg_t *rru_config_msg = msg; - benetel_eth_state_t *s = device->priv; - - printf("BENETEL: %s\n", __FUNCTION__); - - if (s->last_msg == RAU_tick && s->capabilities_sent == 0) { - RRU_capabilities_t *cap; - rru_config_msg->type = RRU_capabilities; - rru_config_msg->len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); - cap = (RRU_capabilities_t*)&rru_config_msg->msg[0]; - cap->FH_fmt = OAI_IF4p5_only; - cap->num_bands = 1; - cap->band_list[0] = 7; - cap->nb_rx[0] = device->openair0_cfg->rx_num_channels; - cap->nb_tx[0] = device->openair0_cfg->tx_num_channels; - cap->max_pdschReferenceSignalPower[0] = -27; - cap->max_rxgain[0] = 90; - - s->capabilities_sent = 1; - - return rru_config_msg->len; - } - if (s->last_msg == RRU_config) { - rru_config_msg->type = RRU_config_ok; - return 0; - } - if (s->last_msg == RRU_start) { - s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line); - } - /* correct? */ - while (1) pause(); - - return 0; -} - -void benetel_fh_if4p5_south_in(RU_t *ru, - int *frame, - int *subframe) -{ - benetel_eth_state_t *s = ru->ifdevice.priv; - PHY_VARS_eNB **eNB_list = ru->eNB_list, *eNB; - LTE_DL_FRAME_PARMS *fp; - int symbol; - int32_t *rxdata; - int antenna; - - lock_ul_buffer(&s->buffers, *subframe); -next: - while (!((s->buffers.ul_busy[0][*subframe] == 0x3fff && - s->buffers.ul_busy[1][*subframe] == 0x3fff) || - s->buffers.prach_busy[*subframe] == 1)) - wait_ul_buffer(&s->buffers, *subframe); - if (s->buffers.prach_busy[*subframe] == 1) { - int i; - int antenna = 0; - uint16_t *in; - uint16_t *out; - in = (uint16_t *)s->buffers.prach[*subframe]; - out = (uint16_t *)ru->prach_rxsigF[0][antenna]; - for (i = 0; i < 840*2; i++) - out[i] = ntohs(in[i]); - s->buffers.prach_busy[*subframe] = 0; - ru->wakeup_prach_eNB(ru->eNB_list[0], ru, *frame, *subframe); - goto next; - } - - eNB = eNB_list[0]; - fp = &eNB->frame_parms; - for (antenna = 0; antenna < ru->nb_rx; antenna++) { - for (symbol = 0; symbol < 14; symbol++) { - int i; - uint16_t *p = (uint16_t *)(&s->buffers.ul[antenna][*subframe][symbol*1200*4]); - for (i = 0; i < 1200*2; i++) { - p[i] = htons(p[i]); - } - rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size]; -#if 1 - memcpy(rxdata + 2048 - 600, - &s->buffers.ul[antenna][*subframe][symbol*1200*4], - 600 * 4); - memcpy(rxdata, - &s->buffers.ul[antenna][*subframe][symbol*1200*4] + 600*4, - 600 * 4); -#endif - } - } - - s->buffers.ul_busy[0][*subframe] = 0; - s->buffers.ul_busy[1][*subframe] = 0; - signal_ul_buffer(&s->buffers, *subframe); - unlock_ul_buffer(&s->buffers, *subframe); - - //printf("BENETEL: %s (f.sf %d.%d)\n", __FUNCTION__, *frame, *subframe); - - RU_proc_t *proc = &ru->proc; - extern int sf_ahead; - int f = *frame; - int sf = *subframe; - - //calculate timestamp_rx, timestamp_tx based on frame and subframe - proc->tti_rx = sf; - proc->frame_rx = f; - proc->timestamp_rx = ((proc->frame_rx * 10) + proc->tti_rx ) * fp->samples_per_tti ; - - if (get_nprocs()<=4) { - proc->tti_tx = (sf+sf_ahead)%10; - proc->frame_tx = (sf>(9-sf_ahead)) ? (f+1)&1023 : f; - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,f); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,sf); - proc->symbol_mask[sf] = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff); - -} - -void benetel_fh_if4p5_south_out(RU_t *ru, - int frame, - int subframe, - uint64_t timestamp) -{ - benetel_eth_state_t *s = ru->ifdevice.priv; - PHY_VARS_eNB **eNB_list = ru->eNB_list, *eNB; - LTE_DL_FRAME_PARMS *fp; - int symbol; - int32_t *txdata; - int aa; - - //printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, subframe, timestamp); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); - - lock_dl_buffer(&s->buffers, subframe); - if (s->buffers.dl_busy[0][subframe] || - s->buffers.dl_busy[1][subframe]) { - printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, subframe); - unlock_dl_buffer(&s->buffers, subframe); - return; - } - eNB = eNB_list[0]; - fp = &eNB->frame_parms; - if (ru->num_eNB != 1 || fp->ofdm_symbol_size != 2048 || - fp->Ncp != NORMAL || fp->symbols_per_tti != 14) { - printf("%s:%d:%s: unsupported configuration\n", - __FILE__, __LINE__, __FUNCTION__); - exit(1); - } - - for (aa = 0; aa < ru->nb_tx; aa++) { - for (symbol = 0; symbol < 14; symbol++) { - txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size]; -#if 1 - memcpy(&s->buffers.dl[aa][subframe][symbol*1200*4], - txdata + 2048 - 600, - 600 * 4); - memcpy(&s->buffers.dl[aa][subframe][symbol*1200*4] + 600*4, - txdata + 1, - 600 * 4); -#endif - int i; - uint16_t *p = (uint16_t *)(&s->buffers.dl[aa][subframe][symbol*1200*4]); - for (i = 0; i < 1200*2; i++) { - p[i] = htons(p[i]); - } - } - } - - s->buffers.dl_busy[0][subframe] = 0x3fff; - s->buffers.dl_busy[1][subframe] = 0x3fff; - unlock_dl_buffer(&s->buffers, subframe); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx, ru->proc.frame_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx, ru->proc.tti_tx); - -} - -void *get_internal_parameter(char *name) -{ - printf("BENETEL: %s\n", __FUNCTION__); - - if (!strcmp(name, "fh_if4p5_south_in")) - return benetel_fh_if4p5_south_in; - if (!strcmp(name, "fh_if4p5_south_out")) - return benetel_fh_if4p5_south_out; - - return NULL; -} - -__attribute__((__visibility__("default"))) -int transport_init(openair0_device *device, - openair0_config_t *openair0_cfg, - eth_params_t * eth_params ) -{ - benetel_eth_state_t *eth; - - printf("BENETEL: %s\n", __FUNCTION__); - - device->Mod_id = 0; - device->transp_type = ETHERNET_TP; - device->trx_start_func = trx_benetel_start; - device->trx_get_stats_func = trx_benetel_get_stats; - device->trx_reset_stats_func = trx_benetel_reset_stats; - device->trx_end_func = trx_benetel_end; - device->trx_stop_func = trx_benetel_stop; - device->trx_set_freq_func = trx_benetel_set_freq; - device->trx_set_gains_func = trx_benetel_set_gains; - - device->trx_write_func = trx_benetel_write_raw; - device->trx_read_func = trx_benetel_read_raw; - - device->trx_ctlsend_func = trx_benetel_ctlsend; - device->trx_ctlrecv_func = trx_benetel_ctlrecv; - - device->get_internal_parameter = get_internal_parameter; - - eth = calloc(1, sizeof(benetel_eth_state_t)); - if (eth == NULL) { - AssertFatal(0==1, "out of memory\n"); - } - - eth->e.flags = ETH_RAW_IF4p5_MODE; - eth->e.compression = NO_COMPRESS; - eth->e.if_name = eth_params->local_if_name; - device->priv = eth; - device->openair0_cfg=&openair0_cfg[0]; - - if (openair0_cfg->sdr_addrs == NULL) { - printf("benetel: fatal: sdr_addrs not set in configuration file\n"); - exit(1); - } - - eth->dpdk_main_command_line = strdup(openair0_cfg->sdr_addrs); - if (eth->dpdk_main_command_line == NULL) { - AssertFatal(0==1, "out of memory\n"); - } - - eth->last_msg = -1; - - init_buffers(ð->buffers); - - return 0; -} diff --git a/radio/ETHERNET/benetel/4g/dpdk_driver.c b/radio/ETHERNET/benetel/4g/dpdk_driver.c deleted file mode 100644 index 2b6ef37e6f..0000000000 --- a/radio/ETHERNET/benetel/4g/dpdk_driver.c +++ /dev/null @@ -1,774 +0,0 @@ -/* license: to be defined */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "low.h" - -// HEADER DEFINITION -#define ANT_NUM buf[23] -#define PAYLOAD_1 buf[20] -#define PAYLOAD_2 buf[21] -#define ETH_TYPE buf[17] -#define SYMBOL buf[29] -#define SUBFRAME buf[28] -#define FRAME buf[27] - -static volatile bool force_quit; - -unsigned short iq[33600]; -unsigned char iq_swap[67200]; - -unsigned short *iq_ptr[14]; -unsigned int dl_start = 0; - -/* MAC updating enabled by default */ -static int mac_updating = 1; -#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 -#define MAX_PKT_BURST 32 -#define BURST_TX_DRAIN_US 5 /* TX drain every ~100us */ -#define MEMPOOL_CACHE_SIZE 256 -/* - * Configurable number of RX/TX ring descriptors - */ -#define RTE_TEST_RX_DESC_DEFAULT 1024 -#define RTE_TEST_TX_DESC_DEFAULT 1024 -static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; -static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; -/* ethernet addresses of ports */ -static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; -/* mask of enabled ports */ -static uint32_t l2fwd_enabled_port_mask = 0; -/* list of enabled ports */ -static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; -static unsigned int l2fwd_rx_queue_per_lcore = 1; -#define MAX_RX_QUEUE_PER_LCORE 16 -#define MAX_TX_QUEUE_PER_PORT 16 -struct lcore_queue_conf { - unsigned n_rx_port; - unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; -} __rte_cache_aligned; -struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; -static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; -static struct rte_eth_conf port_conf = { - .rxmode = { - .split_hdr_size = 0, - .offloads = DEV_RX_OFFLOAD_JUMBO_FRAME, - .split_hdr_size = 0, - .max_rx_pkt_len = 9500, - }, - .txmode = { - .mq_mode = ETH_MQ_TX_NONE, - }, -}; -struct rte_mempool * l2fwd_pktmbuf_pool = NULL; -/* Per-port statistics struct */ -struct l2fwd_port_statistics { - uint64_t tx; - uint64_t rx; - uint64_t dropped; -} __rte_cache_aligned; -struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; -#define MAX_TIMER_PERIOD 86400 /* 1 day max */ -/* A tsc-based timer responsible for triggering statistics printout */ -static uint64_t timer_period = 10; /* default period is 10 seconds */ -/* Print out statistics on packets dropped */ -static void -print_stats(void) -{ - uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; - unsigned portid; - total_packets_dropped = 0; - total_packets_tx = 0; - total_packets_rx = 0; - const char clr[] = { 27, '[', '2', 'J', '\0' }; - const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; - /* Clear screen and move to top left */ - printf("%s%s", clr, topLeft); - printf("\nPort statistics ===================================="); - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { - /* skip disabled ports */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - printf("\nStatistics for port %u ------------------------------" - "\nPackets sent: %24"PRIu64 - "\nPackets received: %20"PRIu64 - "\nPackets dropped: %21"PRIu64, - portid, - port_statistics[portid].tx, - port_statistics[portid].rx, - port_statistics[portid].dropped); - total_packets_dropped += port_statistics[portid].dropped; - total_packets_tx += port_statistics[portid].tx; - total_packets_rx += port_statistics[portid].rx; - } - printf("\nAggregate statistics ===============================" - "\nTotal packets sent: %18"PRIu64 - "\nTotal packets received: %14"PRIu64 - "\nTotal packets dropped: %15"PRIu64, - total_packets_tx, - total_packets_rx, - total_packets_dropped); - printf("\n====================================================\n"); -} -static void -l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs) -{ - unsigned char *buf, *buf_tx; - unsigned int len; - struct ether_hdr *eth; - - unsigned dst_port; - int sent, prach_ctrl = 0; - struct rte_eth_dev_tx_buffer *buffer; - - unsigned char * IQ_ptr; - - ul_packet_t p; - - buf = rte_pktmbuf_mtod(m, unsigned char *); - //rte_memdump(stdout, "Rx Packet",buf ,34); - eth = rte_pktmbuf_mtod(m, struct ether_hdr *); - len = rte_pktmbuf_data_len(m); - - IQ_ptr = &buf[34]; - - //destination mac address (RRU MAC) - eth->d_addr.addr_bytes[0] = 0x02; - eth->d_addr.addr_bytes[1] = 0x00; - eth->d_addr.addr_bytes[2] = 0x5e; - eth->d_addr.addr_bytes[3] = 0x01; - eth->d_addr.addr_bytes[4] = 0x01; - eth->d_addr.addr_bytes[5] = 0x01; - - //source mac address (DU MAC) - eth->s_addr.addr_bytes[0] = 0xdd; - eth->s_addr.addr_bytes[1] = 0xdd; - eth->s_addr.addr_bytes[2] = 0xdd; - eth->s_addr.addr_bytes[3] = 0xdd; - eth->s_addr.addr_bytes[4] = 0xdd; - eth->s_addr.addr_bytes[5] = 0xdd; - - dst_port = l2fwd_dst_ports[portid]; - #if 1 - - if (buf[18] == 0xAA) //msg1 check - { - printf("\nHandshake MSG 1 Received\n"); - printf("\n====================================================\n"); - - buf[18] = 0xBB;//change to msg2 after receive msg1 - - printf("Handshake MSG 2 Sent\n"); - printf("\n====================================================\n"); - } - - #else - // Handshake Condition - if (buf[18] == 0x01 || buf[18] == 0x03) // ORAN handshake msgs. - { - if (buf[18] == 0x01) //msg1 check - { - printf("\nHandshake MSG 1 Received\n"); - printf("\n====================================================\n"); - - buf[18] = 0x02;//change to msg2 after receive msg1 - - printf("Handshake MSG 2 Sent\n"); - printf("\n====================================================\n"); - } - - else if(buf[18] == 0x03) //msg3 check - { - printf("Handshake MSG 3 Sent\n"); - printf("\n====================================================\n"); - - buf[18] = 0x04; - - printf("Handshake MSG 4 Sent\n"); - printf("\n====================================================\n"); - } - } - #endif - // Trigger start send DL packets - if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && SYMBOL == 0x09 && ANT_NUM == 0x00 && dl_start == 0){ - - printf("\nU-Plane Started\n"); - printf("\n====================================================\n"); - - dl_start = 1; - } - - - if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce) { - p.frame = FRAME; - p.subframe = SUBFRAME >> 4; - p.slot = 0; /* unused */ - p.symbol = SYMBOL; - p.antenna = ANT_NUM; - memcpy(p.iq, IQ_ptr, 4800); - store_ul(bs, &p); - } - - // U-PLANE UL PROCESSING - if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && dl_start == 1) - { - int a = ANT_NUM; - int tx_frame = FRAME; - int tx_subframe = SUBFRAME >> 4; - int tx_symbol = SYMBOL + 5; - if (tx_symbol > 13) { - tx_symbol -= 14; - tx_subframe++; - if (tx_subframe == 10) { - tx_subframe = 0; - tx_frame = (tx_frame + 1) & 255; - } - } - -// ANT_NUM = 0x00; -// SYMBOL = (SYMBOL + 5) % 14; - PAYLOAD_2 = 0xc8; - - FRAME = tx_frame; - SUBFRAME = tx_subframe << 4; - SYMBOL = tx_symbol; - - /* send actual DL data (if available) */ - lock_dl_buffer(bs->buffers, tx_subframe); - if (!(bs->buffers->dl_busy[a][tx_subframe] & (1 << tx_symbol))) { - printf("%s: warning, DL underflow (antenna %d sf.symbol %d.%d)\n", - __FUNCTION__, - a, - tx_subframe, tx_symbol); - memset(IQ_ptr, 0, 1200 * 4); - } else { - memcpy(IQ_ptr, bs->buffers->dl[a][tx_subframe] + tx_symbol * 1200*4, - 1200*4); - } - bs->buffers->dl_busy[a][tx_subframe] &= ~(1 << tx_symbol); - unlock_dl_buffer(bs->buffers, tx_subframe); - } - - // U-PLANE PRACH PROCESSING - else if(PAYLOAD_1 == 0x0d && PAYLOAD_2 == 0x28){ - if (ANT_NUM == 0) { - store_prach(bs, FRAME, SUBFRAME>>4, IQ_ptr); - } - - rte_pktmbuf_free(m); - return; - } - - // Send Packets - buffer = tx_buffer[dst_port]; - - sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); - - if (sent) - port_statistics[dst_port].tx += sent; - -} -/* main processing loop */ -static void -l2fwd_main_loop(benetel_t *bs) -{ - struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; - struct rte_mbuf *m; - int sent; - unsigned lcore_id; - uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; - unsigned i, j, portid, nb_rx; - struct lcore_queue_conf *qconf; - const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * - BURST_TX_DRAIN_US; - struct rte_eth_dev_tx_buffer *buffer; - prev_tsc = 0; - timer_tsc = 0; - lcore_id = rte_lcore_id(); - qconf = &lcore_queue_conf[lcore_id]; - if (qconf->n_rx_port == 0) { - RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); - return; - } - RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); - for (i = 0; i < qconf->n_rx_port; i++) { - portid = qconf->rx_port_list[i]; - RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, - portid); - } - while (!force_quit) { - cur_tsc = rte_rdtsc(); - /* - * TX burst queue drain - */ - diff_tsc = cur_tsc - prev_tsc; - if (unlikely(diff_tsc > drain_tsc)) { - for (i = 0; i < qconf->n_rx_port; i++) { - portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; - buffer = tx_buffer[portid]; - sent = rte_eth_tx_buffer_flush(portid, 0, buffer); - if (sent) - port_statistics[portid].tx += sent; - } - /* if timer is enabled */ - if (timer_period > 0) { - /* advance the timer */ - timer_tsc += diff_tsc; - /* if timer has reached its timeout */ - if (unlikely(timer_tsc >= timer_period)) { - /* do this only on master core */ - if (lcore_id == rte_get_master_lcore()) { - //print_stats(); - /* reset the timer */ - timer_tsc = 0; - } - } - } - prev_tsc = cur_tsc; - } - /* - * Read packet from RX queues - */ - for (i = 0; i < qconf->n_rx_port; i++) { - portid = qconf->rx_port_list[i]; - nb_rx = rte_eth_rx_burst(portid, 0, - pkts_burst, MAX_PKT_BURST); - port_statistics[portid].rx += nb_rx; - for (j = 0; j < nb_rx; j++) { - m = pkts_burst[j]; - rte_prefetch0(rte_pktmbuf_mtod(m, void *)); - l2fwd_simple_forward(m, portid, bs); - } - } - } -} -static int -l2fwd_launch_one_lcore(void *bs) -{ - l2fwd_main_loop(bs); - return 0; -} -/* display usage */ -static void -l2fwd_usage(const char *prgname) -{ - printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" - " -p PORTMASK: hexadecimal bitmask of ports to configure\n" - " -q NQ: number of queue (=ports) per lcore (default is 1)\n" - " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n" - " --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n" - " When enabled:\n" - " - The source MAC address is replaced by the TX port MAC address\n" - " - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n", - prgname); -} -static int -l2fwd_parse_portmask(const char *portmask) -{ - char *end = NULL; - unsigned long pm; - /* parse hexadecimal string */ - pm = strtoul(portmask, &end, 16); - if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) - return -1; - if (pm == 0) - return -1; - return pm; -} -static unsigned int -l2fwd_parse_nqueue(const char *q_arg) -{ - char *end = NULL; - unsigned long n; - /* parse hexadecimal string */ - n = strtoul(q_arg, &end, 10); - if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) - return 0; - if (n == 0) - return 0; - if (n >= MAX_RX_QUEUE_PER_LCORE) - return 0; - return n; -} -static int -l2fwd_parse_timer_period(const char *q_arg) -{ - char *end = NULL; - int n; - /* parse number string */ - n = strtol(q_arg, &end, 10); - if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) - return -1; - if (n >= MAX_TIMER_PERIOD) - return -1; - return n; -} -static const char short_options[] = - "p:" /* portmask */ - "q:" /* number of queues */ - "T:" /* timer period */ - ; -#define CMD_LINE_OPT_MAC_UPDATING "mac-updating" -#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating" -enum { - /* long options mapped to a short option */ - /* first long only option value must be >= 256, so that we won't - * conflict with short options */ - CMD_LINE_OPT_MIN_NUM = 256, -}; -static const struct option lgopts[] = { - { CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1}, - { CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0}, - {NULL, 0, 0, 0} -}; -/* Parse the argument given in the command line of the application */ -static int -l2fwd_parse_args(int argc, char **argv) -{ - int opt, ret, timer_secs; - char **argvopt; - int option_index; - char *prgname = argv[0]; - argvopt = argv; - while ((opt = getopt_long(argc, argvopt, short_options, - lgopts, &option_index)) != EOF) { - switch (opt) { - /* portmask */ - case 'p': - l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); - if (l2fwd_enabled_port_mask == 0) { - printf("invalid portmask\n"); - l2fwd_usage(prgname); - return -1; - } - break; - /* nqueue */ - case 'q': - l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); - if (l2fwd_rx_queue_per_lcore == 0) { - printf("invalid queue number\n"); - l2fwd_usage(prgname); - return -1; - } - break; - /* timer period */ - case 'T': - timer_secs = l2fwd_parse_timer_period(optarg); - if (timer_secs < 0) { - printf("invalid timer period\n"); - l2fwd_usage(prgname); - return -1; - } - timer_period = timer_secs; - break; - /* long options */ - case 0: - break; - default: - l2fwd_usage(prgname); - return -1; - } - } - if (optind >= 0) - argv[optind-1] = prgname; - ret = optind-1; - optind = 1; /* reset getopt lib */ - return ret; -} -/* Check the link status of all ports in up to 9s, and print them finally */ -static void -check_all_ports_link_status(uint32_t port_mask) -{ -#define CHECK_INTERVAL 100 /* 100ms */ -#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ - uint16_t portid; - uint8_t count, all_ports_up, print_flag = 0; - struct rte_eth_link link; - printf("\nChecking link status"); - fflush(stdout); - for (count = 0; count <= MAX_CHECK_TIME; count++) { - if (force_quit) - return; - all_ports_up = 1; - RTE_ETH_FOREACH_DEV(portid) { - if (force_quit) - return; - if ((port_mask & (1 << portid)) == 0) - continue; - memset(&link, 0, sizeof(link)); - rte_eth_link_get_nowait(portid, &link); - /* print link status if flag set */ - if (print_flag == 1) { - if (link.link_status) - printf( - "Port%d Link Up. Speed %u Mbps - %s\n", - portid, link.link_speed, - (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? - ("full-duplex") : ("half-duplex\n")); - else - printf("Port %d Link Down\n", portid); - continue; - } - /* clear all_ports_up flag if any link down */ - if (link.link_status == ETH_LINK_DOWN) { - all_ports_up = 0; - break; - } - } - /* after finally printing all link status, get out */ - if (print_flag == 1) - break; - if (all_ports_up == 0) { - printf("."); - fflush(stdout); - rte_delay_ms(CHECK_INTERVAL); - } - /* set the print_flag if all ports up or timeout */ - if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { - print_flag = 1; - printf("done\n"); - } - } -} -static void -signal_handler(int signum) -{ - if (signum == SIGINT || signum == SIGTERM) { - printf("\n\nSignal %d received, preparing to exit...\n", - signum); - force_quit = true; - } -} -int -dpdk_main(int argc, char **argv, benetel_t *bs) -{ - struct lcore_queue_conf *qconf; - int ret; - uint16_t nb_ports; - uint16_t nb_ports_available = 0; - uint16_t portid, last_port; - unsigned lcore_id, rx_lcore_id; - unsigned nb_ports_in_mask = 0; - unsigned int nb_lcores = 0; - unsigned int nb_mbufs; - /* init EAL */ - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); - argc -= ret; - argv += ret; - force_quit = false; - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - /* parse application arguments (after the EAL ones) */ - ret = l2fwd_parse_args(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); - printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled"); - /* convert to number of cycles */ - timer_period *= rte_get_timer_hz(); - nb_ports = rte_eth_dev_count_avail(); - if (nb_ports == 0) - rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); - /* check port mask to possible port mask */ - if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1)) - rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n", - (1 << nb_ports) - 1); - /* reset l2fwd_dst_ports */ - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) - l2fwd_dst_ports[portid] = 0; - last_port = 0; - /* - * Each logical core is assigned a dedicated TX queue on each port. - */ - RTE_ETH_FOREACH_DEV(portid) { - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - if (nb_ports_in_mask % 2) { - l2fwd_dst_ports[portid] = last_port; - l2fwd_dst_ports[last_port] = portid; - } - else - last_port = portid; - nb_ports_in_mask++; - } - if (nb_ports_in_mask % 2) { - printf("Notice: odd number of ports in portmask.\n"); - l2fwd_dst_ports[last_port] = last_port; - } - rx_lcore_id = 0; - qconf = NULL; - /* Initialize the port/queue configuration of each logical core */ - RTE_ETH_FOREACH_DEV(portid) { - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - /* get the lcore_id for this port */ - while (rte_lcore_is_enabled(rx_lcore_id) == 0 || - lcore_queue_conf[rx_lcore_id].n_rx_port == - l2fwd_rx_queue_per_lcore) { - rx_lcore_id++; - if (rx_lcore_id >= RTE_MAX_LCORE) - rte_exit(EXIT_FAILURE, "Not enough cores\n"); - } - if (qconf != &lcore_queue_conf[rx_lcore_id]) { - /* Assigned a new logical core in the loop above. */ - qconf = &lcore_queue_conf[rx_lcore_id]; - nb_lcores++; - } - qconf->rx_port_list[qconf->n_rx_port] = portid; - qconf->n_rx_port++; - printf("Lcore %u: RX port %u\n", rx_lcore_id, portid); - } - nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST + - nb_lcores * MEMPOOL_CACHE_SIZE), 8192U); - /* create the mbuf pool */ - l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs, - MEMPOOL_CACHE_SIZE, 0, 9680, - rte_socket_id()); - if (l2fwd_pktmbuf_pool == NULL) - rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); - /* Initialise each port */ - RTE_ETH_FOREACH_DEV(portid) { - struct rte_eth_rxconf rxq_conf; - struct rte_eth_txconf txq_conf; - struct rte_eth_conf local_port_conf = port_conf; - struct rte_eth_dev_info dev_info; - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { - printf("Skipping disabled port %u\n", portid); - continue; - } - nb_ports_available++; - /* init port */ - printf("Initializing port %u... ", portid); - fflush(stdout); - rte_eth_dev_info_get(portid, &dev_info); - if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) - local_port_conf.txmode.offloads |= - DEV_TX_OFFLOAD_MBUF_FAST_FREE; - ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", - ret, portid); - ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, - &nb_txd); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Cannot adjust number of descriptors: err=%d, port=%u\n", - ret, portid); - rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); - /* init one RX queue */ - fflush(stdout); - rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = local_port_conf.rxmode.offloads; - ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, - rte_eth_dev_socket_id(portid), - &rxq_conf, - l2fwd_pktmbuf_pool); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", - ret, portid); - /* init one TX queue on each port */ - fflush(stdout); - txq_conf = dev_info.default_txconf; - txq_conf.offloads = local_port_conf.txmode.offloads; - ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, - rte_eth_dev_socket_id(portid), - &txq_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", - ret, portid); - /* Initialize TX buffers */ - tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", - RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, - rte_eth_dev_socket_id(portid)); - if (tx_buffer[portid] == NULL) - rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", - portid); - rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); - ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], - rte_eth_tx_buffer_count_callback, - &port_statistics[portid].dropped); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Cannot set error callback for tx buffer on port %u\n", - portid); - /* Start device */ - ret = rte_eth_dev_start(portid); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", - ret, portid); - printf("done: \n"); - rte_eth_promiscuous_enable(portid); - printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", - portid, - l2fwd_ports_eth_addr[portid].addr_bytes[0], - l2fwd_ports_eth_addr[portid].addr_bytes[1], - l2fwd_ports_eth_addr[portid].addr_bytes[2], - l2fwd_ports_eth_addr[portid].addr_bytes[3], - l2fwd_ports_eth_addr[portid].addr_bytes[4], - l2fwd_ports_eth_addr[portid].addr_bytes[5]); - /* initialize port stats */ - memset(&port_statistics, 0, sizeof(port_statistics)); - } - if (!nb_ports_available) { - rte_exit(EXIT_FAILURE, - "All available ports are disabled. Please set portmask.\n"); - } - check_all_ports_link_status(l2fwd_enabled_port_mask); - ret = 0; - /* launch per-lcore init on every lcore */ - rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, bs, CALL_MASTER); - RTE_LCORE_FOREACH_SLAVE(lcore_id) { - if (rte_eal_wait_lcore(lcore_id) < 0) { - ret = -1; - break; - } - } - RTE_ETH_FOREACH_DEV(portid) { - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - printf("Closing port %d...", portid); - rte_eth_dev_stop(portid); - rte_eth_dev_close(portid); - printf(" Done\n"); - } - printf("Bye...\n"); - return ret; -} diff --git a/radio/ETHERNET/benetel/4g/low.c b/radio/ETHERNET/benetel/4g/low.c deleted file mode 100644 index 14783a700b..0000000000 --- a/radio/ETHERNET/benetel/4g/low.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "low.h" - -#include -#include -#include - -void store_ul(benetel_t *bs, ul_packet_t *ul) -{ - int a = ul->antenna; - - if (ul->subframe != bs->next_subframe[a] || - ul->symbol != bs->next_symbol[a]) { - printf("%s: fatal, antenna %d expected frame.sf.symbol %d.%d.%d, got %d.%d.%d\n", - __FUNCTION__, - a, - bs->expected_benetel_frame[a], bs->next_subframe[a], bs->next_symbol[a], - ul->frame, ul->subframe, ul->symbol); - exit(1); - } - - lock_ul_buffer(bs->buffers, bs->next_subframe[a]); - if (bs->buffers->ul_busy[a][bs->next_subframe[a]] & (1 << bs->next_symbol[a])) { - printf("%s: warning, UL overflow (sf.symbol %d.%d)\n", __FUNCTION__, - bs->next_subframe[a], bs->next_symbol[a]); - } - memcpy(bs->buffers->ul[a][bs->next_subframe[a]] + bs->next_symbol[a] * 1200*4, - ul->iq, 1200*4); - bs->buffers->ul_busy[a][bs->next_subframe[a]] |= (1 << bs->next_symbol[a]); - signal_ul_buffer(bs->buffers, bs->next_subframe[a]); - unlock_ul_buffer(bs->buffers, bs->next_subframe[a]); - - bs->next_symbol[a]++; - if (bs->next_symbol[a] == 14) { - bs->next_symbol[a] = 0; - bs->next_subframe[a] = (bs->next_subframe[a] + 1) % 10; - if (bs->next_subframe[a] == 0) { - bs->expected_benetel_frame[a]++; - bs->expected_benetel_frame[a] &= 255; - } - } -} - -void store_prach(benetel_t *bs, int frame, int subframe, void *data) -{ - static int last_frame = -1; - static int last_subframe = -1; - /* hack: antenna number is always 0, discard second packet with same f/sf */ - if (frame == last_frame && subframe == last_subframe) return; - last_frame = frame; - last_subframe = subframe; - - lock_ul_buffer(bs->buffers, subframe); - if (bs->buffers->prach_busy[subframe]) { - printf("store_prach: fatal: previous prach buffer not processed\n"); - unlock_ul_buffer(bs->buffers, subframe); - return; - } - bs->buffers->prach_busy[subframe] = 1; - memcpy(bs->buffers->prach[subframe], data, 849*4); - signal_ul_buffer(bs->buffers, subframe); - unlock_ul_buffer(bs->buffers, subframe); - -} - -void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); - -void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) -{ - if (!strcmp(ifname, "dpdk")) - return benetel_start_dpdk(ifname, buffers, dpdk_main_command_line); - printf("benetel: fatal: interface %s not supported, only dpdpk is supported\n", ifname); - exit(1); -} diff --git a/radio/ETHERNET/benetel/4g/low.h b/radio/ETHERNET/benetel/4g/low.h deleted file mode 100644 index e74bf89163..0000000000 --- a/radio/ETHERNET/benetel/4g/low.h +++ /dev/null @@ -1,50 +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 - */ - -#ifndef _BENETEL_4G_LOW_H_ -#define _BENETEL_4G_LOW_H_ - -#include "shared_buffers.h" - -typedef struct { - shared_buffers *buffers; - /* [2] is for two antennas */ - int next_subframe[2]; - int next_symbol[2]; - int expected_benetel_frame[2]; - char *dpdk_main_command_line; -} benetel_t; - -typedef struct { - int frame; - int subframe; - int slot; - int symbol; - int antenna; - unsigned char iq[4800]; -} ul_packet_t; - -void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); - -void store_ul(benetel_t *bs, ul_packet_t *ul); -void store_prach(benetel_t *bs, int frame, int subframe, void *data); - -#endif /* _BENETEL_4G_LOW_H_ */ diff --git a/radio/ETHERNET/benetel/4g/low_dpdk.c b/radio/ETHERNET/benetel/4g/low_dpdk.c deleted file mode 100644 index edf62a67e0..0000000000 --- a/radio/ETHERNET/benetel/4g/low_dpdk.c +++ /dev/null @@ -1,119 +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 - */ - -/* those 2 lines for CPU_SET */ -#define _GNU_SOURCE -#include - -#include -#include -#include -#include - -#include "low.h" - -int dpdk_main(int argc, char **argv, benetel_t *); - -void *dpdk_thread(void *_bs) -{ - benetel_t *bs = _bs; - int n = 0; - char **v = NULL; // { "softmodem", "-n", "2", "-l", "8", "--", "-p", "0x2" }; - char *s = bs->dpdk_main_command_line; - char *tok; - - while ((tok = strtok(s, " ")) != NULL) { - n++; - v = realloc(v, n * sizeof(char *)); - if (v == NULL) { - printf("%s: out of memory\n", __FUNCTION__); - exit(1); - } - v[n-1] = tok; - s = NULL; - } - - dpdk_main(n, v, bs); - exit(1); - return 0; -} - -void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) -{ - benetel_t *bs; - - bs = calloc(1, sizeof(benetel_t)); - if (bs == NULL) { - printf("%s: out of memory\n", __FUNCTION__); - exit(1); - } - - bs->buffers = buffers; - - bs->expected_benetel_frame[0] = 255; - bs->expected_benetel_frame[1] = 255; - - bs->dpdk_main_command_line = dpdk_main_command_line; - - pthread_attr_t attr; - - if (pthread_attr_init(&attr) != 0) { - printf("pthread_attr_init failed\n"); - exit(1); - } - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(12,&cpuset); - if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset) != 0) { - printf("pthread_attr_setaffinity_np failed\n"); - exit(1); - } - - if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) { - printf("pthread_attr_setschedpolicy failed\n"); - exit(1); - } - - struct sched_param params; - params.sched_priority = sched_get_priority_max(SCHED_FIFO); - if (sched_get_priority_max(SCHED_FIFO) == -1) { - printf("sched_get_priority_max failed\n"); - exit(1); - } - if (pthread_attr_setschedparam(&attr, ¶ms) != 0) { - printf("pthread_setschedparam failed\n"); - exit(1); - } - - pthread_t t; - if (pthread_create(&t, &attr, dpdk_thread, bs) != 0) { - printf("%s: thread creation failed\n", __FUNCTION__); - exit(1); - } - - if (pthread_attr_destroy(&attr) != 0) { - printf("pthread_attr_init failed\n"); - exit(1); - } - - return bs; -} diff --git a/radio/ETHERNET/benetel/4g/shared_buffers.c b/radio/ETHERNET/benetel/4g/shared_buffers.c deleted file mode 100644 index 380cbabc73..0000000000 --- a/radio/ETHERNET/benetel/4g/shared_buffers.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "shared_buffers.h" - -#include -#include -#include - -void init_buffers(shared_buffers *s) -{ - int subframe; - - memset(s, 0, sizeof(*s)); - - for (subframe = 0; subframe < 10; subframe++) { - if (pthread_mutex_init(&s->m_dl[subframe], NULL) != 0 || - pthread_cond_init(&s->c_dl[subframe], NULL) != 0 || - pthread_mutex_init(&s->m_ul[subframe], NULL) != 0 || - pthread_cond_init(&s->c_ul[subframe], NULL) != 0) { - printf("%s: error initializing mutex/cond\n", __FUNCTION__); - exit(1); - } - } - - /* in FDD the eNB's first transmitted DL subframe is 4 but the device - * needs to have subframes 1, 2 and 3 ready. Let's pretend there are ready. - */ - s->dl_busy[0][1] = 0x3fff; - s->dl_busy[0][2] = 0x3fff; - s->dl_busy[0][3] = 0x3fff; - s->dl_busy[1][1] = 0x3fff; - s->dl_busy[1][2] = 0x3fff; - s->dl_busy[1][3] = 0x3fff; -} - -void lock_dl_buffer(shared_buffers *s, int subframe) -{ - if (pthread_mutex_lock(&s->m_dl[subframe]) != 0) { - printf("%s: fatal: lock fails\n", __FUNCTION__); - exit(1); - } -} - -void unlock_dl_buffer(shared_buffers *s, int subframe) -{ - if (pthread_mutex_unlock(&s->m_dl[subframe]) != 0) { - printf("%s: fatal: unlock fails\n", __FUNCTION__); - exit(1); - } -} - -void wait_dl_buffer(shared_buffers *s, int subframe) -{ - if (pthread_cond_wait(&s->c_dl[subframe], &s->m_dl[subframe]) != 0) { - printf("%s: fatal: cond_wait fails\n", __FUNCTION__); - exit(1); - } -} - -void signal_dl_buffer(shared_buffers *s, int subframe) -{ - if (pthread_cond_broadcast(&s->c_dl[subframe]) != 0) { - printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); - exit(1); - } -} - -void lock_ul_buffer(shared_buffers *s, int subframe) -{ - if (pthread_mutex_lock(&s->m_ul[subframe]) != 0) { - printf("%s: fatal: lock fails\n", __FUNCTION__); - exit(1); - } -} - -void unlock_ul_buffer(shared_buffers *s, int subframe) -{ - if (pthread_mutex_unlock(&s->m_ul[subframe]) != 0) { - printf("%s: fatal: unlock fails\n", __FUNCTION__); - exit(1); - } -} - -void wait_ul_buffer(shared_buffers *s, int subframe) -{ - if (pthread_cond_wait(&s->c_ul[subframe], &s->m_ul[subframe]) != 0) { - printf("%s: fatal: cond_wait fails\n", __FUNCTION__); - exit(1); - } -} - -void signal_ul_buffer(shared_buffers *s, int subframe) -{ - if (pthread_cond_broadcast(&s->c_ul[subframe]) != 0) { - printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); - exit(1); - } -} diff --git a/radio/ETHERNET/benetel/4g/shared_buffers.h b/radio/ETHERNET/benetel/4g/shared_buffers.h deleted file mode 100644 index ed174265c5..0000000000 --- a/radio/ETHERNET/benetel/4g/shared_buffers.h +++ /dev/null @@ -1,61 +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 - */ - -#ifndef _BENETEL_4G_SHARED_BUFFERS_H_ -#define _BENETEL_4G_SHARED_BUFFERS_H_ - -#include -#include - -typedef struct { - /* [2] is for two antennas */ - unsigned char dl[2][10][14*1200*4]; - unsigned char ul[2][10][14*1200*4]; - uint16_t dl_busy[2][10]; - uint16_t ul_busy[2][10]; - - pthread_mutex_t m_ul[10]; - pthread_cond_t c_ul[10]; - - pthread_mutex_t m_dl[10]; - pthread_cond_t c_dl[10]; - - unsigned char prach[10][849*4]; - unsigned char prach_busy[10]; - - /* statistics/error counting */ - int ul_overflow; - int dl_underflow; -} shared_buffers; - -void init_buffers(shared_buffers *s); - -void lock_dl_buffer(shared_buffers *s, int subframe); -void unlock_dl_buffer(shared_buffers *s, int subframe); -void wait_dl_buffer(shared_buffers *s, int subframe); -void signal_dl_buffer(shared_buffers *s, int subframe); - -void lock_ul_buffer(shared_buffers *s, int subframe); -void unlock_ul_buffer(shared_buffers *s, int subframe); -void wait_ul_buffer(shared_buffers *s, int subframe); -void signal_ul_buffer(shared_buffers *s, int subframe); - -#endif /* _BENETEL_4G_SHARED_BUFFERS_H_ */ diff --git a/radio/ETHERNET/benetel/5g/CMakeLists.txt b/radio/ETHERNET/benetel/5g/CMakeLists.txt deleted file mode 100644 index cdad594ce3..0000000000 --- a/radio/ETHERNET/benetel/5g/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -pkg_check_modules(libdpdk REQUIRED libdpdk=20.05.0) - -add_library(benetel_5g MODULE - benetel.c - shared_buffers.c - low.c - low_dpdk.c - dpdk_driver.c -) - -SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") -target_include_directories(benetel_5g PRIVATE ${libdpdk_INCLUDE_DIRS}) -target_link_libraries(benetel_5g PRIVATE ${libdpdk_LIBRARIES}) -target_link_libraries(benetel_5g PRIVATE pthread dl rt m numa) -set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") -set_target_properties(benetel_5g PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -add_custom_command(TARGET benetel_5g POST_BUILD - COMMAND ${CMAKE_COMMAND} -E create_symlink libbenetel_5g.so liboai_transpro.so - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/radio/ETHERNET/benetel/5g/benetel.c b/radio/ETHERNET/benetel/5g/benetel.c deleted file mode 100644 index 996d568767..0000000000 --- a/radio/ETHERNET/benetel/5g/benetel.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include - -#include "common_lib.h" -#include "ethernet_lib.h" -#include "shared_buffers.h" -#include "low.h" -#include "openair1/PHY/defs_gNB.h" - -typedef struct { - eth_state_t e; - shared_buffers buffers; - rru_config_msg_type_t last_msg; - int capabilities_sent; - void *benetel_priv; - char *dpdk_main_command_line; -} benetel_eth_state_t; - -int trx_benetel_start(openair0_device *device) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return 0; -} - - -void trx_benetel_end(openair0_device *device) -{ - printf("BENETEL: %s\n", __FUNCTION__); -} - - -int trx_benetel_stop(openair0_device *device) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int trx_benetel_set_freq(openair0_device* device, openair0_config_t *openair0_cfg) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int trx_benetel_set_gains(openair0_device* device, - openair0_config_t *openair0_cfg) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int trx_benetel_get_stats(openair0_device* device) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int trx_benetel_reset_stats(openair0_device* device) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return(0); -} - - -int ethernet_tune(openair0_device *device, - unsigned int option, - int value) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return 0; -} - -int trx_benetel_write_raw(openair0_device *device, - openair0_timestamp timestamp, - void **buff, int nsamps, int cc, int flags) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return nsamps*4; -} - -int trx_benetel_read_raw(openair0_device *device, - openair0_timestamp *timestamp, - void **buff, int nsamps, int cc) -{ - printf("BENETEL: %s\n", __FUNCTION__); - return nsamps*4; -} - -char *msg_type(int t) -{ - static char *s[12] = { - "RAU_tick", - "RRU_capabilities", - "RRU_config", - "RRU_config_ok", - "RRU_start", - "RRU_stop", - "RRU_sync_ok", - "RRU_frame_resynch", - "RRU_MSG_max_num", - "RRU_check_sync", - "RRU_config_update", - "RRU_config_update_ok", - }; - - if (t < 0 || t > 11) return "UNKNOWN"; - return s[t]; -} - -int trx_benetel_ctlsend(openair0_device *device, void *msg, ssize_t msg_len) -{ - RRU_CONFIG_msg_t *rru_config_msg = msg; - benetel_eth_state_t *s = device->priv; - - printf("BENETEL: %s\n", __FUNCTION__); - - printf(" rru_config_msg->type %d [%s]\n", rru_config_msg->type, - msg_type(rru_config_msg->type)); - - s->last_msg = rru_config_msg->type; - - return msg_len; -} - -int trx_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len) -{ - RRU_CONFIG_msg_t *rru_config_msg = msg; - benetel_eth_state_t *s = device->priv; - - printf("BENETEL: %s\n", __FUNCTION__); - - if (s->last_msg == RAU_tick && s->capabilities_sent == 0) { - RRU_capabilities_t *cap; - rru_config_msg->type = RRU_capabilities; - rru_config_msg->len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); - cap = (RRU_capabilities_t*)&rru_config_msg->msg[0]; - cap->FH_fmt = OAI_IF4p5_only; - cap->num_bands = 1; - cap->band_list[0] = 78; - /* TODO: hardcoded to 1 for the moment, get the real value somehow... */ - cap->nb_rx[0] = 1; //device->openair0_cfg->rx_num_channels; - cap->nb_tx[0] = 1; //device->openair0_cfg->tx_num_channels; - cap->max_pdschReferenceSignalPower[0] = -27; - cap->max_rxgain[0] = 90; - - s->capabilities_sent = 1; - - return rru_config_msg->len; - } -#if 0 - if (s->last_msg == RRU_config) { - rru_config_msg->type = RRU_config_ok; - return 0; - } - if (s->last_msg == RRU_start) { -printf("***************** benetel start\n"); - s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line); - } -#endif - if (s->last_msg == RRU_config) { - rru_config_msg->type = RRU_config_ok; - s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line); - } - /* correct? */ -//printf("***************** benetel pause\n"); -// while (1) pause(); - - return 0; -} - -void benetel_fh_if4p5_south_in(RU_t *ru, - int *frame, - int *slot) -{ -//printf("XXX benetel_fh_if4p5_south_in %d %d\n", *frame, *slot); - benetel_eth_state_t *s = ru->ifdevice.priv; - NR_DL_FRAME_PARMS *fp; - int symbol; - int32_t *rxdata; - int antenna; - - lock_ul_buffer(&s->buffers, *slot); -#if 1 -next: - while (!((s->buffers.ul_busy[0][*slot] == 0x3fff && - s->buffers.ul_busy[1][*slot] == 0x3fff) || - s->buffers.prach_busy[*slot] == 1)) - wait_ul_buffer(&s->buffers, *slot); - if (s->buffers.prach_busy[*slot] == 1) { - int i; - int antenna = 0; - uint16_t *in; - uint16_t *out; - in = (uint16_t *)s->buffers.prach[*slot]; - out = (uint16_t *)ru->prach_rxsigF[0][antenna]; - for (i = 0; i < 839*2; i++) - out[i] = ntohs(in[i]); - s->buffers.prach_busy[*slot] = 0; - //printf("prach for f.sl %d.%d\n", *frame, *slot); - //ru->wakeup_prach_gNB(ru->gNB_list[0], ru, *frame, *slot); - goto next; - } -#endif - - fp = ru->nr_frame_parms; - for (antenna = 0; antenna < ru->nb_rx; antenna++) { - for (symbol = 0; symbol < 14; symbol++) { - int i; - int16_t *p = (int16_t *)(&s->buffers.ul[antenna][*slot][symbol*1272*4]); - for (i = 0; i < 1272*2; i++) { - p[i] = (int16_t)(ntohs(p[i])) / 16; - } - rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size]; -#if 0 -if (*slot == 0 && symbol == 0) -printf("rxdata in benetel_fh_if4p5_south_in %p\n", &ru->common.rxdataF[antenna][0]); -#endif -#if 1 - memcpy(rxdata + 2048 - 1272/2, - &s->buffers.ul[antenna][*slot][symbol*1272*4], - (1272/2) * 4); - memcpy(rxdata, - &s->buffers.ul[antenna][*slot][symbol*1272*4] + (1272/2)*4, - (1272/2) * 4); -#endif - } - } - - s->buffers.ul_busy[0][*slot] = 0; - s->buffers.ul_busy[1][*slot] = 0; - signal_ul_buffer(&s->buffers, *slot); - unlock_ul_buffer(&s->buffers, *slot); - - //printf("BENETEL: %s (f.sf %d.%d)\n", __FUNCTION__, *frame, *slot); - - RU_proc_t *proc = &ru->proc; - int f = *frame; - int sl = *slot; - - //calculate timestamp_rx, timestamp_tx based on frame and slot - proc->tti_rx = sl; - proc->frame_rx = f; - /* TODO: be sure of samples_per_slot0 - FK: should use get_samples_per_slot(slot) - but for mu=1 its ok - */ - proc->timestamp_rx = ((proc->frame_rx * 20) + proc->tti_rx ) * fp->samples_per_slot0; - - if (get_nprocs()<=4) { - // why? what if there are more? - proc->tti_tx = (sl+ru->sl_ahead)%20; - proc->frame_tx = (sl>(19-ru->sl_ahead)) ? (f+1)&1023 : f; - } -} - -void benetel_fh_if4p5_south_out(RU_t *ru, - int frame, - int slot, - uint64_t timestamp) -{ - -//printf("XXX benetel_fh_if4p5_south_out %d %d %ld\n", frame, slot, timestamp); - benetel_eth_state_t *s = ru->ifdevice.priv; - NR_DL_FRAME_PARMS *fp; - int symbol; - int32_t *txdata; - int aa; - - //printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, slot, timestamp); - - lock_dl_buffer(&s->buffers, slot); - if (s->buffers.dl_busy[0][slot] || - s->buffers.dl_busy[1][slot]) { - printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, slot); - unlock_dl_buffer(&s->buffers, slot); - return; - } - - fp = ru->nr_frame_parms; - if (ru->num_gNB != 1 || fp->ofdm_symbol_size != 2048 || - fp->Ncp != NORMAL || fp->symbols_per_slot != 14) { - printf("%s:%d:%s: unsupported configuration\n", - __FILE__, __LINE__, __FUNCTION__); - exit(1); - } - - for (aa = 0; aa < ru->nb_tx; aa++) { - for (symbol = 0; symbol < 14; symbol++) { - txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size]; -#if 1 - memcpy(&s->buffers.dl[aa][slot][symbol*1272*4], - txdata + 2048 - (1272/2), - (1272/2) * 4); - memcpy(&s->buffers.dl[aa][slot][symbol*1272*4] + (1272/2)*4, - txdata, - (1272/2) * 4); -#endif - int i; - uint16_t *p = (uint16_t *)(&s->buffers.dl[aa][slot][symbol*1272*4]); - for (i = 0; i < 1272*2; i++) { - p[i] = htons(p[i]); - } - } - } - - s->buffers.dl_busy[0][slot] = 0x3fff; - s->buffers.dl_busy[1][slot] = 0x3fff; - unlock_dl_buffer(&s->buffers, slot); -} - -void *get_internal_parameter(char *name) -{ - printf("BENETEL: %s\n", __FUNCTION__); - - if (!strcmp(name, "fh_if4p5_south_in")) - return benetel_fh_if4p5_south_in; - if (!strcmp(name, "fh_if4p5_south_out")) - return benetel_fh_if4p5_south_out; - - return NULL; -} - -__attribute__((__visibility__("default"))) -int transport_init(openair0_device *device, - openair0_config_t *openair0_cfg, - eth_params_t * eth_params ) -{ - benetel_eth_state_t *eth; - - printf("BENETEL: %s\n", __FUNCTION__); - - device->Mod_id = 0; - device->transp_type = ETHERNET_TP; - device->trx_start_func = trx_benetel_start; - device->trx_get_stats_func = trx_benetel_get_stats; - device->trx_reset_stats_func = trx_benetel_reset_stats; - device->trx_end_func = trx_benetel_end; - device->trx_stop_func = trx_benetel_stop; - device->trx_set_freq_func = trx_benetel_set_freq; - device->trx_set_gains_func = trx_benetel_set_gains; - - device->trx_write_func = trx_benetel_write_raw; - device->trx_read_func = trx_benetel_read_raw; - - device->trx_ctlsend_func = trx_benetel_ctlsend; - device->trx_ctlrecv_func = trx_benetel_ctlrecv; - - device->get_internal_parameter = get_internal_parameter; - - eth = calloc(1, sizeof(benetel_eth_state_t)); - if (eth == NULL) { - AssertFatal(0==1, "out of memory\n"); - } - - eth->e.flags = ETH_RAW_IF4p5_MODE; - eth->e.compression = NO_COMPRESS; - eth->e.if_name = eth_params->local_if_name; - device->priv = eth; - device->openair0_cfg=&openair0_cfg[0]; - - if (openair0_cfg->sdr_addrs == NULL) { - printf("benetel: fatal: sdr_addrs not set in configuration file\n"); - exit(1); - } - - eth->dpdk_main_command_line = strdup(openair0_cfg->sdr_addrs); - if (eth->dpdk_main_command_line == NULL) { - AssertFatal(0==1, "out of memory\n"); - } - - eth->last_msg = -1; - - init_buffers(ð->buffers); - - return 0; -} diff --git a/radio/ETHERNET/benetel/5g/dpdk_driver.c b/radio/ETHERNET/benetel/5g/dpdk_driver.c deleted file mode 100644 index 9b398e9bd9..0000000000 --- a/radio/ETHERNET/benetel/5g/dpdk_driver.c +++ /dev/null @@ -1,835 +0,0 @@ -/* license: to be defined */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "low.h" - -// HEADER DEFINITION -#define ANT_NUM buf[23] -#define PAYLOAD_1 buf[20] -#define PAYLOAD_2 buf[21] -#define ETH_TYPE buf[17] -#define SYMBOL buf[29] -#define SUBFRAME buf[28] -#define FRAME buf[27] - -static volatile bool force_quit; - -unsigned short iq[712320]; -unsigned char iq_swap[1424640]; - -unsigned short *iq_ptr[14]; -unsigned int dl_start = 0, slot_id_ctrl = 0, count_symbol = 0, sf = 0x10; - -/* MAC updating enabled by default */ -static int mac_updating = 1; -#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 -#define MAX_PKT_BURST 32 -#define BURST_TX_DRAIN_US 5 /* TX drain every ~100us */ -#define MEMPOOL_CACHE_SIZE 256 -/* - * Configurable number of RX/TX ring descriptors - */ -#define RTE_TEST_RX_DESC_DEFAULT 1024 -#define RTE_TEST_TX_DESC_DEFAULT 1024 -static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; -static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; -/* ethernet addresses of ports */ -static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; -/* mask of enabled ports */ -static uint32_t l2fwd_enabled_port_mask = 0; -/* list of enabled ports */ -static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; -static unsigned int l2fwd_rx_queue_per_lcore = 1; -#define MAX_RX_QUEUE_PER_LCORE 16 -#define MAX_TX_QUEUE_PER_PORT 16 -struct lcore_queue_conf { - unsigned n_rx_port; - unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; -} __rte_cache_aligned; -struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; -static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; -static struct rte_eth_conf port_conf = { - .rxmode = { - .split_hdr_size = 0, - .offloads = DEV_RX_OFFLOAD_JUMBO_FRAME, - .split_hdr_size = 0, - .max_rx_pkt_len = 9500, - }, - .txmode = { - .mq_mode = ETH_MQ_TX_NONE, - }, -}; -struct rte_mempool * l2fwd_pktmbuf_pool = NULL; -/* Per-port statistics struct */ -struct l2fwd_port_statistics { - uint64_t tx; - uint64_t rx; - uint64_t dropped; -} __rte_cache_aligned; -struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; -#define MAX_TIMER_PERIOD 86400 /* 1 day max */ -/* A tsc-based timer responsible for triggering statistics printout */ -static uint64_t timer_period = 10; /* default period is 10 seconds */ -/* Print out statistics on packets dropped */ -static void -print_stats(void) -{ - uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; - unsigned portid; - total_packets_dropped = 0; - total_packets_tx = 0; - total_packets_rx = 0; - const char clr[] = { 27, '[', '2', 'J', '\0' }; - const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; - /* Clear screen and move to top left */ - printf("%s%s", clr, topLeft); - printf("\nPort statistics ===================================="); - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { - /* skip disabled ports */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - printf("\nStatistics for port %u ------------------------------" - "\nPackets sent: %24"PRIu64 - "\nPackets received: %20"PRIu64 - "\nPackets dropped: %21"PRIu64, - portid, - port_statistics[portid].tx, - port_statistics[portid].rx, - port_statistics[portid].dropped); - total_packets_dropped += port_statistics[portid].dropped; - total_packets_tx += port_statistics[portid].tx; - total_packets_rx += port_statistics[portid].rx; - } - printf("\nAggregate statistics ===============================" - "\nTotal packets sent: %18"PRIu64 - "\nTotal packets received: %14"PRIu64 - "\nTotal packets dropped: %15"PRIu64, - total_packets_tx, - total_packets_rx, - total_packets_dropped); - printf("\n====================================================\n"); -} -static void -l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs) -{ - unsigned char *buf, *buf_tx; - unsigned int len; - struct ether_hdr *eth; - - unsigned dst_port; - int sent, prach_ctrl = 0; - struct rte_eth_dev_tx_buffer *buffer; - - unsigned char * IQ_ptr; - - ul_packet_t p; - - buf = rte_pktmbuf_mtod(m, unsigned char *); - //DD Debug - //rte_memdump(stdout, "Rx Packet",buf ,34); - eth = rte_pktmbuf_mtod(m, struct ether_hdr *); - len = rte_pktmbuf_data_len(m); - - IQ_ptr = &buf[34]; - if (portid == 0) - { - //destination mac address (RRU MAC) - /*eth->d_addr.addr_bytes[0] = 0x02; - eth->d_addr.addr_bytes[1] = 0x00; - eth->d_addr.addr_bytes[2] = 0x5e; - eth->d_addr.addr_bytes[3] = 0x01; - eth->d_addr.addr_bytes[4] = 0x01; - eth->d_addr.addr_bytes[5] = 0x01;*/ - - eth->d_addr.addr_bytes[0] = buf[6]; - eth->d_addr.addr_bytes[1] = buf[7]; - eth->d_addr.addr_bytes[2] = buf[8]; - eth->d_addr.addr_bytes[3] = buf[9]; - eth->d_addr.addr_bytes[4] = buf[10]; - eth->d_addr.addr_bytes[5] = buf[11]; - - //source mac address (DU MAC) - eth->s_addr.addr_bytes[0] = 0xdd; - eth->s_addr.addr_bytes[1] = 0xdd; - eth->s_addr.addr_bytes[2] = 0xdd; - eth->s_addr.addr_bytes[3] = 0xdd; - eth->s_addr.addr_bytes[4] = 0xdd; - eth->s_addr.addr_bytes[5] = 0xdd; - } - else - { - //destination mac address (RRU MAC) - /*eth->d_addr.addr_bytes[0] = 0x02; - eth->d_addr.addr_bytes[1] = 0x00; - eth->d_addr.addr_bytes[2] = 0x5e; - eth->d_addr.addr_bytes[3] = 0x01; - eth->d_addr.addr_bytes[4] = 0x01; - eth->d_addr.addr_bytes[5] = 0x01;*/ - - eth->d_addr.addr_bytes[0] = buf[6]; - eth->d_addr.addr_bytes[1] = buf[7]; - eth->d_addr.addr_bytes[2] = buf[8]; - eth->d_addr.addr_bytes[3] = buf[9]; - eth->d_addr.addr_bytes[4] = buf[10]; - eth->d_addr.addr_bytes[5] = buf[11]; - //source mac address (DU MAC) - eth->s_addr.addr_bytes[0] = 0xdd; - eth->s_addr.addr_bytes[1] = 0xdd; - eth->s_addr.addr_bytes[2] = 0xdd; - eth->s_addr.addr_bytes[3] = 0xdd; - eth->s_addr.addr_bytes[4] = 0xdd; - eth->s_addr.addr_bytes[5] = 0xde; - - } - dst_port = l2fwd_dst_ports[portid]; - //DD Debug - //printf("dstPort =%d\n", dst_port); - // Handshake Condition - if (buf[18] == 0xAA ) // ORAN handshake msgs. - { - printf("\n Start UP Request Received\n"); - printf("\n====================================================\n"); - - buf[18] = 0xBB;//change to msg2 after receive msg1 - - printf(" Start Up Response Sent\n"); - printf("\n====================================================\n"); - - } - - // Trigger start send DL packets - if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && SYMBOL == 0x44 && ANT_NUM == 0x00 && SUBFRAME == 0x00 && dl_start == 0){ - - printf("\nU-Plane Started\n"); - printf("\n====================================================\n"); - - dl_start = 1; - count_symbol = 28; - } - - - if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4) { - int subframe = SUBFRAME >> 4; - int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03); - p.frame = FRAME; - p.slot = subframe * 2 + slot; - p.symbol = SYMBOL & 0x3f; - p.antenna = ANT_NUM; - memcpy(p.iq, IQ_ptr, 5088); - store_ul(bs, &p); - // if (p.symbol==0) printf("store ul f.sl.sy %d.%d.%d\n", p.frame, p.slot, p.symbol); - } - - // U-PLANE UL PROCESSING - if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && dl_start == 1) - { - int a = ANT_NUM & 0x01; - int frame = FRAME; - int subframe = SUBFRAME >> 4; - int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03); - int symbol = SYMBOL & 0x3f; - int oai_slot; - - int tx_frame = frame; - int tx_subframe = subframe; - int tx_slot = slot; - int tx_symbol = symbol + 10; - - if (tx_symbol > 13) { - tx_symbol -= 14; - tx_slot++; - if (tx_slot == 2) { - tx_slot = 0; - tx_subframe++; - if (tx_subframe == 10) { - tx_subframe = 0; - tx_frame = (tx_frame + 1) & 255; - } - } - } - - // Mask the symbol bits from UL packet received and apply the shift. - SYMBOL = ((SYMBOL & 0b00111111) + 10) % 14; - - ANT_NUM = a; - SUBFRAME = sf; - - if (a == 1) - slot_id_ctrl++; - - // Slot id control for DL - if (slot_id_ctrl > 13) { - SYMBOL = SYMBOL | 0b01000000; - - if (a == 1) { - if (slot_id_ctrl > 27) { - slot_id_ctrl = 0; - sf = sf + 0x10; - - if (sf > 0x90){ - sf = 0; - } - } - } - } - - /* send actual DL data (if available) */ - oai_slot = tx_subframe * 2 + tx_slot; - lock_dl_buffer(bs->buffers, oai_slot); - if (!(bs->buffers->dl_busy[a][oai_slot] & (1 << tx_symbol))) { - //printf("%s: warning, DL underflow (antenna %d sl.symbol %d.%d)\n", __FUNCTION__,a, oai_slot, tx_symbol); - memset(IQ_ptr, 0, 1272 * 4); - } else { - memcpy(IQ_ptr, bs->buffers->dl[a][oai_slot] + tx_symbol * 1272*4, - 1272*4); - } - //printf("DL buffer f sf slot symbol %d %d %d %d (sf %d)\n", tx_frame, tx_subframe, tx_slot, tx_symbol, (int)sf); - bs->buffers->dl_busy[a][oai_slot] &= ~(1 << tx_symbol); - unlock_dl_buffer(bs->buffers, oai_slot); - } - - // U-PLANE PRACH PROCESSING - else if(PAYLOAD_1 == 0x0d && PAYLOAD_2 == 0x28){ - if (ANT_NUM == 0) { - int subframe = SUBFRAME >> 4; - //int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03); - if (subframe==9) { - //printf("store prach f.sf.sl %d.%d.%d %d\n", FRAME, subframe, slot, subframe * 2 + slot); - store_prach(bs, FRAME, subframe * 2 + 1, IQ_ptr); - } - } - rte_pktmbuf_free(m); - return; - } - - // Send Packets - buffer = tx_buffer[dst_port]; - - sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); - - if (sent) - port_statistics[dst_port].tx += sent; - -} -/* main processing loop */ -static void -l2fwd_main_loop(benetel_t *bs) -{ - struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; - struct rte_mbuf *m; - int sent; - unsigned lcore_id; - uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; - unsigned i, j, portid, nb_rx; - struct lcore_queue_conf *qconf; - const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * - BURST_TX_DRAIN_US; - struct rte_eth_dev_tx_buffer *buffer; - prev_tsc = 0; - timer_tsc = 0; - lcore_id = rte_lcore_id(); - qconf = &lcore_queue_conf[lcore_id]; - if (qconf->n_rx_port == 0) { - RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); - return; - } - RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); - for (i = 0; i < qconf->n_rx_port; i++) { - portid = qconf->rx_port_list[i]; - RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, - portid); - } - while (!force_quit) { - cur_tsc = rte_rdtsc(); - /* - * TX burst queue drain - */ - diff_tsc = cur_tsc - prev_tsc; - if (unlikely(diff_tsc > drain_tsc)) { - for (i = 0; i < qconf->n_rx_port; i++) { - portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; - buffer = tx_buffer[portid]; - sent = rte_eth_tx_buffer_flush(portid, 0, buffer); - if (sent) - port_statistics[portid].tx += sent; - } - /* if timer is enabled */ - if (timer_period > 0) { - /* advance the timer */ - timer_tsc += diff_tsc; - /* if timer has reached its timeout */ - if (unlikely(timer_tsc >= timer_period)) { - /* do this only on master core */ - if (lcore_id == rte_get_master_lcore()) { - print_stats(); - /* reset the timer */ - timer_tsc = 0; - } - } - } - prev_tsc = cur_tsc; - } - /* - * Read packet from RX queues - */ - for (i = 0; i < qconf->n_rx_port; i++) { - portid = qconf->rx_port_list[i]; - nb_rx = rte_eth_rx_burst(portid, 0, - pkts_burst, MAX_PKT_BURST); - port_statistics[portid].rx += nb_rx; - for (j = 0; j < nb_rx; j++) { - m = pkts_burst[j]; - rte_prefetch0(rte_pktmbuf_mtod(m, void *)); - l2fwd_simple_forward(m, portid, bs); - } - } - } -} -static int -l2fwd_launch_one_lcore(void *bs) -{ - l2fwd_main_loop(bs); - return 0; -} -/* display usage */ -static void -l2fwd_usage(const char *prgname) -{ - printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" - " -p PORTMASK: hexadecimal bitmask of ports to configure\n" - " -q NQ: number of queue (=ports) per lcore (default is 1)\n" - " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n" - " --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n" - " When enabled:\n" - " - The source MAC address is replaced by the TX port MAC address\n" - " - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n", - prgname); -} -static int -l2fwd_parse_portmask(const char *portmask) -{ - char *end = NULL; - unsigned long pm; - /* parse hexadecimal string */ - pm = strtoul(portmask, &end, 16); - if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) - return -1; - if (pm == 0) - return -1; - return pm; -} -static unsigned int -l2fwd_parse_nqueue(const char *q_arg) -{ - char *end = NULL; - unsigned long n; - /* parse hexadecimal string */ - n = strtoul(q_arg, &end, 10); - if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) - return 0; - if (n == 0) - return 0; - if (n >= MAX_RX_QUEUE_PER_LCORE) - return 0; - return n; -} -static int -l2fwd_parse_timer_period(const char *q_arg) -{ - char *end = NULL; - int n; - /* parse number string */ - n = strtol(q_arg, &end, 10); - if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) - return -1; - if (n >= MAX_TIMER_PERIOD) - return -1; - return n; -} -static const char short_options[] = - "p:" /* portmask */ - "q:" /* number of queues */ - "T:" /* timer period */ - ; -#define CMD_LINE_OPT_MAC_UPDATING "mac-updating" -#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating" -enum { - /* long options mapped to a short option */ - /* first long only option value must be >= 256, so that we won't - * conflict with short options */ - CMD_LINE_OPT_MIN_NUM = 256, -}; -static const struct option lgopts[] = { - { CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1}, - { CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0}, - {NULL, 0, 0, 0} -}; -/* Parse the argument given in the command line of the application */ -static int -l2fwd_parse_args(int argc, char **argv) -{ - int opt, ret, timer_secs; - char **argvopt; - int option_index; - char *prgname = argv[0]; - argvopt = argv; - while ((opt = getopt_long(argc, argvopt, short_options, - lgopts, &option_index)) != EOF) { - switch (opt) { - /* portmask */ - case 'p': - l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); - if (l2fwd_enabled_port_mask == 0) { - printf("invalid portmask\n"); - l2fwd_usage(prgname); - return -1; - } - break; - /* nqueue */ - case 'q': - l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); - if (l2fwd_rx_queue_per_lcore == 0) { - printf("invalid queue number\n"); - l2fwd_usage(prgname); - return -1; - } - break; - /* timer period */ - case 'T': - timer_secs = l2fwd_parse_timer_period(optarg); - if (timer_secs < 0) { - printf("invalid timer period\n"); - l2fwd_usage(prgname); - return -1; - } - timer_period = timer_secs; - break; - /* long options */ - case 0: - break; - case 'proc-type': - break; - case 'socket-mem': - break; - case 'file-prefix': - l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); - if (l2fwd_rx_queue_per_lcore == 0) { - printf("invalid queue number\n"); - l2fwd_usage(prgname); - return -1; - } - break; - /* timer period */ - /* timer period */ - /* timer period */ - default: - l2fwd_usage(prgname); - return -1; - } - } - if (optind >= 0) - argv[optind-1] = prgname; - ret = optind-1; - optind = 1; /* reset getopt lib */ - return ret; -} -/* Check the link status of all ports in up to 9s, and print them finally */ -static void -check_all_ports_link_status(uint32_t port_mask) -{ -#define CHECK_INTERVAL 100 /* 100ms */ -#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ - uint16_t portid; - uint8_t count, all_ports_up, print_flag = 0; - struct rte_eth_link link; - printf("\nChecking link status"); - fflush(stdout); - for (count = 0; count <= MAX_CHECK_TIME; count++) { - if (force_quit) - return; - all_ports_up = 1; - RTE_ETH_FOREACH_DEV(portid) { - if (force_quit) - return; - if ((port_mask & (1 << portid)) == 0) - continue; - memset(&link, 0, sizeof(link)); - rte_eth_link_get_nowait(portid, &link); - /* print link status if flag set */ - if (print_flag == 1) { - if (link.link_status) - printf( - "Port%d Link Up. Speed %u Mbps - %s\n", - portid, link.link_speed, - (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? - ("full-duplex") : ("half-duplex\n")); - else - printf("Port %d Link Down\n", portid); - continue; - } - /* clear all_ports_up flag if any link down */ - if (link.link_status == ETH_LINK_DOWN) { - all_ports_up = 0; - break; - } - } - /* after finally printing all link status, get out */ - if (print_flag == 1) - break; - if (all_ports_up == 0) { - printf("."); - fflush(stdout); - rte_delay_ms(CHECK_INTERVAL); - } - /* set the print_flag if all ports up or timeout */ - if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { - print_flag = 1; - printf("done\n"); - } - } -} -static void -signal_handler(int signum) -{ - if (signum == SIGINT || signum == SIGTERM) { - printf("\n\nSignal %d received, preparing to exit...\n", - signum); - force_quit = true; - } -} -int -dpdk_main(int argc, char **argv, benetel_t *bs) -{ - struct lcore_queue_conf *qconf; - int ret; - uint16_t nb_ports; - uint16_t nb_ports_available = 0; - uint16_t portid, last_port; - unsigned lcore_id, rx_lcore_id; - unsigned nb_ports_in_mask = 0; - unsigned int nb_lcores = 0; - unsigned int nb_mbufs; - /* init EAL */ - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); - argc -= ret; - argv += ret; - force_quit = false; - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - /* parse application arguments (after the EAL ones) */ - ret = l2fwd_parse_args(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); - printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled"); - /* convert to number of cycles */ - timer_period *= rte_get_timer_hz(); - nb_ports = rte_eth_dev_count_avail(); - if (nb_ports == 0) - rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); - /* check port mask to possible port mask */ - if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1)) - rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n", - (1 << nb_ports) - 1); - /* reset l2fwd_dst_ports */ - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) - l2fwd_dst_ports[portid] = 0; - last_port = 0; - /* - * Each logical core is assigned a dedicated TX queue on each port. - */ - RTE_ETH_FOREACH_DEV(portid) { - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - if (nb_ports_in_mask % 2) { - l2fwd_dst_ports[portid] = last_port; - l2fwd_dst_ports[last_port] = portid; - } - else - last_port = portid; - nb_ports_in_mask++; - } - if (nb_ports_in_mask % 2) { - printf("Notice: odd number of ports in portmask.\n"); - l2fwd_dst_ports[last_port] = last_port; - } - rx_lcore_id = 0; - qconf = NULL; - /* Initialize the port/queue configuration of each logical core */ - RTE_ETH_FOREACH_DEV(portid) { - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - /* get the lcore_id for this port */ - while (rte_lcore_is_enabled(rx_lcore_id) == 0 || - lcore_queue_conf[rx_lcore_id].n_rx_port == - l2fwd_rx_queue_per_lcore) { - rx_lcore_id++; - if (rx_lcore_id >= RTE_MAX_LCORE) - rte_exit(EXIT_FAILURE, "Not enough cores\n"); - } - if (qconf != &lcore_queue_conf[rx_lcore_id]) { - /* Assigned a new logical core in the loop above. */ - qconf = &lcore_queue_conf[rx_lcore_id]; - nb_lcores++; - } - qconf->rx_port_list[qconf->n_rx_port] = portid; - qconf->n_rx_port++; - printf("Lcore %u: RX port %u\n", rx_lcore_id, portid); - } - nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST + - nb_lcores * MEMPOOL_CACHE_SIZE), 8192U); - /* create the mbuf pool */ - //DD Debug - //printf ("Proc Type %d \n", rte_eal_process_type()); - l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs, - MEMPOOL_CACHE_SIZE, 0, 9680, - rte_socket_id()); - if (l2fwd_pktmbuf_pool == NULL) - rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); - /* Initialise each port */ - RTE_ETH_FOREACH_DEV(portid) { - struct rte_eth_rxconf rxq_conf; - struct rte_eth_txconf txq_conf; - struct rte_eth_conf local_port_conf = port_conf; - struct rte_eth_dev_info dev_info; - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { - printf("Skipping disabled port %u\n", portid); - continue; - } - nb_ports_available++; - /* init port */ - printf("Initializing port %u... ", portid); - fflush(stdout); - rte_eth_dev_info_get(portid, &dev_info); - if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) - local_port_conf.txmode.offloads |= - DEV_TX_OFFLOAD_MBUF_FAST_FREE; - ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", - ret, portid); - ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, - &nb_txd); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Cannot adjust number of descriptors: err=%d, port=%u\n", - ret, portid); - rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); - /* init one RX queue */ - fflush(stdout); - rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = local_port_conf.rxmode.offloads; - ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, - rte_eth_dev_socket_id(portid), - &rxq_conf, - l2fwd_pktmbuf_pool); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", - ret, portid); - /* init one TX queue on each port */ - fflush(stdout); - txq_conf = dev_info.default_txconf; - txq_conf.offloads = local_port_conf.txmode.offloads; - ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, - rte_eth_dev_socket_id(portid), - &txq_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", - ret, portid); - /* Initialize TX buffers */ - tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", - RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, - rte_eth_dev_socket_id(portid)); - if (tx_buffer[portid] == NULL) - rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", - portid); - rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); - ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], - rte_eth_tx_buffer_count_callback, - &port_statistics[portid].dropped); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Cannot set error callback for tx buffer on port %u\n", - portid); - /* Start device */ - ret = rte_eth_dev_start(portid); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", - ret, portid); - printf("done: \n"); - rte_eth_promiscuous_enable(portid); - printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", - portid, - l2fwd_ports_eth_addr[portid].addr_bytes[0], - l2fwd_ports_eth_addr[portid].addr_bytes[1], - l2fwd_ports_eth_addr[portid].addr_bytes[2], - l2fwd_ports_eth_addr[portid].addr_bytes[3], - l2fwd_ports_eth_addr[portid].addr_bytes[4], - l2fwd_ports_eth_addr[portid].addr_bytes[5]); - /* initialize port stats */ - memset(&port_statistics, 0, sizeof(port_statistics)); - } - if (!nb_ports_available) { - rte_exit(EXIT_FAILURE, - "All available ports are disabled. Please set portmask.\n"); - } - check_all_ports_link_status(l2fwd_enabled_port_mask); - ret = 0; - /* launch per-lcore init on every lcore */ - rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, bs, CALL_MASTER); - RTE_LCORE_FOREACH_SLAVE(lcore_id) { - if (rte_eal_wait_lcore(lcore_id) < 0) { - ret = -1; - break; - } - } - RTE_ETH_FOREACH_DEV(portid) { - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - printf("Closing port %d...", portid); - rte_eth_dev_stop(portid); - rte_eth_dev_close(portid); - printf(" Done\n"); - } - printf("Bye...\n"); - return ret; -} diff --git a/radio/ETHERNET/benetel/5g/low.c b/radio/ETHERNET/benetel/5g/low.c deleted file mode 100644 index b34d69784f..0000000000 --- a/radio/ETHERNET/benetel/5g/low.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "low.h" - -#include -#include -#include - -void store_ul(benetel_t *bs, ul_packet_t *ul) -{ -#if 0 -struct timespec t; -static struct timespec old; -clock_gettime(CLOCK_REALTIME, &t); -printf("store_ul %d.%ld (%ld)\n", (int)(t.tv_sec % 60), t.tv_nsec, t.tv_nsec - old.tv_nsec); -old = t; -#endif - - int a = ul->antenna; - - if (ul->slot != bs->next_slot[a] || - ul->symbol != bs->next_symbol[a]) { - printf("%s: error, antenna %d expected frame.sl.symbol %d.%d.%d, got %d.%d.%d\n", - __FUNCTION__, - a, bs->expected_benetel_frame[a], bs->next_slot[a], bs->next_symbol[a], - ul->frame, ul->slot, ul->symbol); - } - - /* fill missing data with 0s */ - while (ul->slot != bs->next_slot[a] || - ul->symbol != bs->next_symbol[a]) { - lock_ul_buffer(bs->buffers, bs->next_slot[a]); - if (bs->buffers->ul_busy[a][bs->next_slot[a]] & (1 << bs->next_symbol[a])) { - printf("%s: warning, antenna %d UL overflow (sl.symbol %d.%d)\n", __FUNCTION__, - a, bs->next_slot[a], bs->next_symbol[a]); - } - - memset(bs->buffers->ul[a][bs->next_slot[a]] + bs->next_symbol[a] * 1272*4, - 0, 1272*4); - bs->buffers->ul_busy[a][bs->next_slot[a]] |= (1 << bs->next_symbol[a]); - signal_ul_buffer(bs->buffers, bs->next_slot[a]); - unlock_ul_buffer(bs->buffers, bs->next_slot[a]); - - bs->next_symbol[a]++; - if (bs->next_symbol[a] == 14) { - bs->next_symbol[a] = 0; - bs->next_slot[a] = (bs->next_slot[a] + 1) % 20; - if (bs->next_slot[a] == 0) { - bs->expected_benetel_frame[a]++; - bs->expected_benetel_frame[a] &= 255; - } - } - } - - lock_ul_buffer(bs->buffers, bs->next_slot[a]); - if (bs->buffers->ul_busy[a][bs->next_slot[a]] & (1 << bs->next_symbol[a])) { - printf("%s: warning, antenna %d UL overflow (sl.symbol %d.%d)\n", __FUNCTION__, - a, bs->next_slot[a], bs->next_symbol[a]); - } - - memcpy(bs->buffers->ul[a][bs->next_slot[a]] + bs->next_symbol[a] * 1272*4, - ul->iq, 1272*4); - bs->buffers->ul_busy[a][bs->next_slot[a]] |= (1 << bs->next_symbol[a]); - signal_ul_buffer(bs->buffers, bs->next_slot[a]); - unlock_ul_buffer(bs->buffers, bs->next_slot[a]); - - bs->next_symbol[a]++; - if (bs->next_symbol[a] == 14) { - bs->next_symbol[a] = 0; - bs->next_slot[a] = (bs->next_slot[a] + 1) % 20; - if (bs->next_slot[a] == 0) { - bs->expected_benetel_frame[a]++; - bs->expected_benetel_frame[a] &= 255; - } - } -} - -void store_prach(benetel_t *bs, int frame, int slot, void *data) -{ - static int last_frame = -1; - static int last_slot = -1; - /* hack: antenna number is always 0, discard second packet with same f/sf */ - //if (frame == last_frame && slot == last_slot) return; - if (frame == last_frame && slot == last_slot) { printf("got f.sl %d.%d twice\n", frame, slot); return; } - last_frame = frame; - last_slot = slot; - - lock_ul_buffer(bs->buffers, slot); - if (bs->buffers->prach_busy[slot]) { - printf("store_prach: fatal: previous prach buffer not processed\n"); - unlock_ul_buffer(bs->buffers, slot); - return; - } - bs->buffers->prach_busy[slot] = 1; - memcpy(bs->buffers->prach[slot], data, 839*4); - signal_ul_buffer(bs->buffers, slot); - unlock_ul_buffer(bs->buffers, slot); - -} - -void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); - -void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) -{ - if (!strcmp(ifname, "dpdk")) - return benetel_start_dpdk(ifname, buffers, dpdk_main_command_line); - printf("benetel: fatal: interface %s not supported, only dpdpk is supported\n", ifname); - exit(1); -} diff --git a/radio/ETHERNET/benetel/5g/low.h b/radio/ETHERNET/benetel/5g/low.h deleted file mode 100644 index 659819296a..0000000000 --- a/radio/ETHERNET/benetel/5g/low.h +++ /dev/null @@ -1,49 +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 - */ - -#ifndef _BENETEL_5G_LOW_H_ -#define _BENETEL_5G_LOW_H_ - -#include "shared_buffers.h" - -typedef struct { - shared_buffers *buffers; - /* [2] is for two antennas */ - int next_slot[2]; - int next_symbol[2]; - int expected_benetel_frame[2]; - char *dpdk_main_command_line; -} benetel_t; - -typedef struct { - int frame; - int slot; - int symbol; - int antenna; - unsigned char iq[5088]; -} ul_packet_t; - -void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); - -void store_ul(benetel_t *bs, ul_packet_t *ul); -void store_prach(benetel_t *bs, int frame, int slot, void *data); - -#endif /* _BENETEL_5G_LOW_H_ */ diff --git a/radio/ETHERNET/benetel/5g/low_dpdk.c b/radio/ETHERNET/benetel/5g/low_dpdk.c deleted file mode 100644 index b26df07723..0000000000 --- a/radio/ETHERNET/benetel/5g/low_dpdk.c +++ /dev/null @@ -1,119 +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 - */ - -/* those 2 lines for CPU_SET */ -#define _GNU_SOURCE -#include - -#include -#include -#include -#include - -#include "low.h" - -int dpdk_main(int argc, char **argv, benetel_t *); - -void *dpdk_thread(void *_bs) -{ - benetel_t *bs = _bs; - int n = 0; - char **v = NULL; // = { "softmodem", "-n", "2", "--file-prefix", "pg2", "-l", "6", "--", "-p", "0x1" }; - char *s = bs->dpdk_main_command_line; - char *tok; - - while ((tok = strtok(s, " ")) != NULL) { - n++; - v = realloc(v, n * sizeof(char *)); - if (v == NULL) { - printf("%s: out of memory\n", __FUNCTION__); - exit(1); - } - v[n-1] = tok; - s = NULL; - } - - dpdk_main(n, v, bs); - exit(1); - return 0; -} - -void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) -{ - benetel_t *bs; - - bs = calloc(1, sizeof(benetel_t)); - if (bs == NULL) { - printf("%s: out of memory\n", __FUNCTION__); - exit(1); - } - - bs->buffers = buffers; - - bs->expected_benetel_frame[0] = 255; - bs->expected_benetel_frame[1] = 255; - - bs->dpdk_main_command_line = dpdk_main_command_line; - - pthread_attr_t attr; - - if (pthread_attr_init(&attr) != 0) { - printf("pthread_attr_init failed\n"); - exit(1); - } - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(10,&cpuset); - if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset) != 0) { - printf("pthread_attr_setaffinity_np failed\n"); - exit(1); - } - - if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) { - printf("pthread_attr_setschedpolicy failed\n"); - exit(1); - } - - struct sched_param params; - params.sched_priority = sched_get_priority_max(SCHED_FIFO); - if (sched_get_priority_max(SCHED_FIFO) == -1) { - printf("sched_get_priority_max failed\n"); - exit(1); - } - if (pthread_attr_setschedparam(&attr, ¶ms) != 0) { - printf("pthread_setschedparam failed\n"); - exit(1); - } - - pthread_t t; - if (pthread_create(&t, &attr, dpdk_thread, bs) != 0) { - printf("%s: thread creation failed\n", __FUNCTION__); - exit(1); - } - - if (pthread_attr_destroy(&attr) != 0) { - printf("pthread_attr_init failed\n"); - exit(1); - } - - return bs; -} diff --git a/radio/ETHERNET/benetel/5g/shared_buffers.c b/radio/ETHERNET/benetel/5g/shared_buffers.c deleted file mode 100644 index a302400eb4..0000000000 --- a/radio/ETHERNET/benetel/5g/shared_buffers.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include "shared_buffers.h" - -#include -#include -#include - -void init_buffers(shared_buffers *s) -{ - int slot; - - memset(s, 0, sizeof(*s)); - - for (slot = 0; slot < 20; slot++) { - if (pthread_mutex_init(&s->m_dl[slot], NULL) != 0 || - pthread_cond_init(&s->c_dl[slot], NULL) != 0 || - pthread_mutex_init(&s->m_ul[slot], NULL) != 0 || - pthread_cond_init(&s->c_ul[slot], NULL) != 0) { - printf("%s: error initializing mutex/cond\n", __FUNCTION__); - exit(1); - } - } - - /* the gNB's first transmitted DL slot is 6 but the device - * needs to have slots 1, 2 and 3, 4 and 5 ready. Let's pretend - * they are ready. - */ - s->dl_busy[0][1] = 0x3fff; - s->dl_busy[0][2] = 0x3fff; - s->dl_busy[0][3] = 0x3fff; - s->dl_busy[0][4] = 0x3fff; - s->dl_busy[0][5] = 0x3fff; - s->dl_busy[1][1] = 0x3fff; - s->dl_busy[1][2] = 0x3fff; - s->dl_busy[1][3] = 0x3fff; - s->dl_busy[1][4] = 0x3fff; - s->dl_busy[1][5] = 0x3fff; -} - -void lock_dl_buffer(shared_buffers *s, int slot) -{ - if (pthread_mutex_lock(&s->m_dl[slot]) != 0) { - printf("%s: fatal: lock fails\n", __FUNCTION__); - exit(1); - } -} - -void unlock_dl_buffer(shared_buffers *s, int slot) -{ - if (pthread_mutex_unlock(&s->m_dl[slot]) != 0) { - printf("%s: fatal: unlock fails\n", __FUNCTION__); - exit(1); - } -} - -void wait_dl_buffer(shared_buffers *s, int slot) -{ - if (pthread_cond_wait(&s->c_dl[slot], &s->m_dl[slot]) != 0) { - printf("%s: fatal: cond_wait fails\n", __FUNCTION__); - exit(1); - } -} - -void signal_dl_buffer(shared_buffers *s, int slot) -{ - if (pthread_cond_broadcast(&s->c_dl[slot]) != 0) { - printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); - exit(1); - } -} - -void lock_ul_buffer(shared_buffers *s, int slot) -{ - if (pthread_mutex_lock(&s->m_ul[slot]) != 0) { - printf("%s: fatal: lock fails\n", __FUNCTION__); - printf("%s: fatal: lock fails slot %d\n", __FUNCTION__, slot); - exit(1); - } -} - -void unlock_ul_buffer(shared_buffers *s, int slot) -{ - if (pthread_mutex_unlock(&s->m_ul[slot]) != 0) { - printf("%s: fatal: unlock fails\n", __FUNCTION__); - exit(1); - } -} - -void wait_ul_buffer(shared_buffers *s, int slot) -{ - if (pthread_cond_wait(&s->c_ul[slot], &s->m_ul[slot]) != 0) { - printf("%s: fatal: cond_wait fails\n", __FUNCTION__); - exit(1); - } -} - -void signal_ul_buffer(shared_buffers *s, int slot) -{ - if (pthread_cond_broadcast(&s->c_ul[slot]) != 0) { - printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); - exit(1); - } -} diff --git a/radio/ETHERNET/benetel/5g/shared_buffers.h b/radio/ETHERNET/benetel/5g/shared_buffers.h deleted file mode 100644 index 9d51b8138d..0000000000 --- a/radio/ETHERNET/benetel/5g/shared_buffers.h +++ /dev/null @@ -1,61 +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 - */ - -#ifndef _BENETEL_5G_SHARED_BUFFERS_H_ -#define _BENETEL_5G_SHARED_BUFFERS_H_ - -#include -#include - -typedef struct { - /* [2] is for two antennas */ - unsigned char dl[2][20][14*1272*4]; - unsigned char ul[2][20][14*1272*4]; - uint16_t dl_busy[2][20]; - uint16_t ul_busy[2][20]; - - pthread_mutex_t m_ul[20]; - pthread_cond_t c_ul[20]; - - pthread_mutex_t m_dl[20]; - pthread_cond_t c_dl[20]; - - unsigned char prach[20][849*4]; - unsigned char prach_busy[20]; - - /* statistics/error counting */ - int ul_overflow; - int dl_underflow; -} shared_buffers; - -void init_buffers(shared_buffers *s); - -void lock_dl_buffer(shared_buffers *s, int slot); -void unlock_dl_buffer(shared_buffers *s, int slot); -void wait_dl_buffer(shared_buffers *s, int slot); -void signal_dl_buffer(shared_buffers *s, int slot); - -void lock_ul_buffer(shared_buffers *s, int slot); -void unlock_ul_buffer(shared_buffers *s, int slot); -void wait_ul_buffer(shared_buffers *s, int slot); -void signal_ul_buffer(shared_buffers *s, int slot); - -#endif /* _BENETEL_5G_SHARED_BUFFERS_H_ */ diff --git a/radio/ETHERNET/benetel/CMakeLists.txt b/radio/ETHERNET/benetel/CMakeLists.txt deleted file mode 100644 index 1a95d1ec2c..0000000000 --- a/radio/ETHERNET/benetel/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_boolean_option(OAI_BENETEL4G OFF "Activate OAI's Benetel 4G radio driver" OFF) -if(OAI_BENETEL4G) - add_subdirectory(4g) -endif() - -add_boolean_option(OAI_BENETEL5G OFF "Activate OAI's Benetel 5G radio driver" OFF) -if(OAI_BENETEL5G) - add_subdirectory(5g) -endif() diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp index 79c58b59f4..923e938869 100644 --- a/radio/USRP/usrp_lib.cpp +++ b/radio/USRP/usrp_lib.cpp @@ -488,38 +488,39 @@ static int trx_usrp_write(openair0_device *device, buff_tx[i][j] = simde_mm256_slli_epi16(tmp, 4); } } - } + } - s->tx_md.has_time_spec = true; - s->tx_md.start_of_burst = (s->tx_count==0) ? true : first_packet_state; - s->tx_md.end_of_burst = last_packet_state; - s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); - s->tx_count++; + s->tx_md.has_time_spec = true; + s->tx_md.start_of_burst = (s->tx_count == 0) ? true : first_packet_state; + s->tx_md.end_of_burst = last_packet_state; + s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); + s->tx_count++; -VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,1); - // bit 13 enables gpio - if ((flags_gpio & TX_GPIO_CHANGE) != 0) { - // push GPIO bits - s->usrp->set_command_time(s->tx_md.time_spec); - s->usrp->set_gpio_attr(s->gpio_bank, "OUT", flags_gpio, MAN_MASK); - s->usrp->clear_command_time(); - } -VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO, 1); + // bit 13 enables gpio + if ((flags_gpio & TX_GPIO_CHANGE) != 0) { + // push GPIO bits + s->usrp->set_command_time(s->tx_md.time_spec); + s->usrp->set_gpio_attr(s->gpio_bank, "OUT", flags_gpio, MAN_MASK); + s->usrp->clear_command_time(); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO, 0); - if (cc>1) { - std::vector buff_ptrs; + if (cc > 1) { + std::vector buff_ptrs; - for (int i=0; itx_stream->send(buff_ptrs, nsamps, s->tx_md); - } - else { - ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md); - } + ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md); + } else { + ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md); + } - if (ret != nsamps) LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps); - return ret; + if (ret != nsamps) { + LOG_E(HW, "[xmit] tx samples %d != %d\n", ret, nsamps); + } + return ret; } else { pthread_mutex_lock(&write_thread->mutex_write); diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index f2161d06a8..fb40852ebb 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -17,7 +17,7 @@ add_library(oran_fhlib_5g MODULE ) set(E_VERSION 5.1.6) -set(F_VERSION 6.1.4) +set(F_VERSION 6.1.5) find_package(xran REQUIRED) if(xran_VERSION VERSION_EQUAL E_VERSION) diff --git a/radio/fhi_72/mplane/connect-mplane.c b/radio/fhi_72/mplane/connect-mplane.c index 9744ce01e8..9d00d26bdf 100644 --- a/radio/fhi_72/mplane/connect-mplane.c +++ b/radio/fhi_72/mplane/connect-mplane.c @@ -59,24 +59,7 @@ bool connect_mplane(ru_session_t *ru_session) void disconnect_mplane(void *rus_disconnect) { ru_session_list_t *ru_session_list = (ru_session_list_t *)rus_disconnect; - - for (size_t i = 0; i num_rus; i++) { - ru_session_t *ru_session = &ru_session_list->ru_session[i]; - if (ru_session->session == NULL) - continue; - MP_LOG_I("Sending PM de-activation request for RU \"%s\".\n", ru_session->ru_ip_add); - bool success = pm_conf(ru_session, "false"); - if (success) - MP_LOG_I("Successfully de-activated PM for RU \"%s\".\n", ru_session->ru_ip_add); - MP_LOG_I("Disconnecting from RU \"%s\".\n", ru_session->ru_ip_add); - nc_session_free(ru_session->session, NULL); - ru_session->session = NULL; -#ifdef MPLANE_V1 - ly_ctx_destroy((struct ly_ctx *)ru_session->ctx, NULL); -#elif defined MPLANE_V2 - ly_ctx_destroy((struct ly_ctx *)ru_session->ctx); -#endif - } + free_ru_session_list(ru_session_list); nc_client_destroy(); } diff --git a/radio/fhi_72/mplane/init-mplane.c b/radio/fhi_72/mplane/init-mplane.c index fc20ba5af4..fcd908562a 100644 --- a/radio/fhi_72/mplane/init-mplane.c +++ b/radio/fhi_72/mplane/init-mplane.c @@ -141,6 +141,43 @@ bool init_mplane(ru_session_list_t *ru_session_list) return true; } +static void init_ru_notif(ru_session_t *ru_session, const char* buffer) +{ + char* usage_state = get_ru_xml_node(buffer, "usage-state"); + if (usage_state != NULL && strcmp(usage_state, "busy") == 0) { + ru_session->ru_notif.rx_carrier_state = BUSY_CARRIER; + ru_session->ru_notif.tx_carrier_state = BUSY_CARRIER; + ru_session->ru_notif.config_change = true; + } else if (usage_state != NULL && strcmp(usage_state, "active") == 0) { + ru_session->ru_notif.rx_carrier_state = READY_CARRIER; + ru_session->ru_notif.tx_carrier_state = READY_CARRIER; + ru_session->ru_notif.config_change = true; + } else { // "idle" or NULL + ru_session->ru_notif.rx_carrier_state = DISABLED_CARRIER; + ru_session->ru_notif.tx_carrier_state = DISABLED_CARRIER; + ru_session->ru_notif.config_change = false; + } + + char *oper_state = get_ru_xml_node(buffer, "oper-state"); + ru_session->ru_notif.hardware.oper_state = (str_to_enum_oper(oper_state) != OPER_COUNT) ? str_to_enum_oper(oper_state) : ENABLED_OPER; + + char *admin_state = get_ru_xml_node(buffer, "admin-state"); + ru_session->ru_notif.hardware.admin_state = (str_to_enum_admin(admin_state) != ADMIN_COUNT) ? str_to_enum_admin(admin_state) : UNLOCKED_ADMIN; + + char *avail_state = get_ru_xml_node(buffer, "availability-state"); + ru_session->ru_notif.hardware.avail_state = (str_to_enum_avail(avail_state) != AVAIL_COUNT) ? str_to_enum_avail(avail_state) : NORMAL_AVAIL; + + char *ptp_state = get_ru_xml_node(buffer, "sync-state"); + ru_session->ru_notif.ptp_state = str_to_enum_ptp(ptp_state); + MP_LOG_I("RU is in \"%s\" sync state.\n", ptp_state); + + free(usage_state); + free(oper_state); + free(admin_state); + free(avail_state); + free(ptp_state); +} + bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const size_t num_rus) { bool success = false; @@ -149,12 +186,8 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz success = get_mplane(ru_session, &operational_ds); AssertError(success, return false, "[MPLANE] Unable to continue: could not get RU answer via get_mplane().\n"); - bool ptp_state = false; - const char *sync_state = get_ru_xml_node(operational_ds, "sync-state"); - if (strcmp(sync_state, "LOCKED") == 0) { - MP_LOG_I("RU is already PTP synchronized.\n"); - ptp_state = true; - } + // init RU notifications + init_ru_notif(ru_session, operational_ds); /* 1) as per M-plane spec, RU must be in supervised mode, where stream = NULL && filter = "/o-ran-supervision:supervision-notification"; @@ -163,7 +196,6 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz => since more than one subscription at the time within one session is not possible, we will subscribe to all notifications */ const char *stream = "NETCONF"; const char *filter = NULL; - ru_session->ru_notif.ptp_state = ptp_state; success = subscribe_mplane(ru_session, stream, filter, (void *)&ru_session->ru_notif); AssertError(success, return false, "[MPLANE] Unable to continue: could not get RU answer via subscribe_mplane().\n"); @@ -189,26 +221,18 @@ bool manage_ru(ru_session_t *ru_session, const openair0_config_t *oai, const siz success = load_yang_models(ru_session, operational_ds); AssertError(success, return false, "[MPLANE] Unable to load yang models.\n"); - if (ru_session->ru_notif.ptp_state) { - char *content = NULL; - success = configure_ru_from_yang(ru_session, oai, num_rus, &content); - AssertError(success, return false, "[MPLANE] Unable to create content for RPC for start-up procedure.\n"); + while (1) { + sleep(5); + if (!ru_session->ru_notif.ptp_state && !ru_session->ru_notif.hardware.oper_state && !ru_session->ru_notif.hardware.admin_state && !ru_session->ru_notif.hardware.avail_state) { + char *content = NULL; + success = configure_ru_from_yang(ru_session, oai, num_rus, &content); + AssertError(success, return false, "[MPLANE] Unable to create content for RPC for start-up procedure.\n"); - success = edit_val_commmit_rpc(ru_session, content); - AssertError(success, return false, "[MPLANE] Unable to continue.\n"); - free(content); - } - - const char *usage_state = get_ru_xml_node(operational_ds, "usage-state"); - MP_LOG_I("Usage state = \"%s\" for RU \"%s\".\n", usage_state, ru_session->ru_ip_add); - if (strcmp(usage_state, "busy") == 0) { // carriers are already activated - ru_session->ru_notif.rx_carrier_state = true; - ru_session->ru_notif.tx_carrier_state = true; - ru_session->ru_notif.config_change = true; - } else { - ru_session->ru_notif.rx_carrier_state = false; - ru_session->ru_notif.tx_carrier_state = false; - ru_session->ru_notif.config_change = false; + success = edit_val_commmit_rpc(ru_session, content); + AssertError(success, return false, "[MPLANE] Unable to continue.\n"); + free(content); + break; + } } free(operational_ds); diff --git a/radio/fhi_72/mplane/ru-mplane-api.c b/radio/fhi_72/mplane/ru-mplane-api.c index df4bf3b8ba..f04e294dfc 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.c +++ b/radio/fhi_72/mplane/ru-mplane-api.c @@ -20,11 +20,145 @@ */ #include "ru-mplane-api.h" +#include "init-mplane.h" #include "xml/get-xml.h" #include "common/utils/assertions.h" #include +#include +#include + +static void free_pm_stats(pm_stats_t *src) +{ + // free Rx window measurements + for (size_t i = 0; i < src->rx_num; i++) { + free(src->rx_window_meas[i]); + } + free(src->rx_window_meas); + + // free Tx measurements + for (size_t i = 0; i < src->tx_num; i++) { + free(src->tx_meas[i]); + } + free(src->tx_meas); +} + +static void free_uplane_info(uplane_info_t *src) +{ + for (size_t i = 0; i < src->num; i++) { + free(src->name[i]); + } + free(src->name); +} + +static void free_ru_mplane_config(ru_mplane_config_t *src) +{ + // free DU MAC address(es) and VLAN tag(s) + for (size_t i = 0; i < src->num_cu_planes; i++) { + free(src->du_mac_addr[i]); + } + free(src->du_mac_addr); + free(src->vlan_tag); + + // free interface name + free(src->interface_name); + + // free endpoints and carriers + free_uplane_info(&src->tx_endpoints); + free_uplane_info(&src->rx_endpoints); + free_uplane_info(&src->tx_carriers); + free_uplane_info(&src->rx_carriers); +} + +static void free_ru_session(ru_session_t *src) +{ + // username + free(src->username); + + // if no RU connected to, free only the initialized RU IP address + if (src->session == NULL) { + free(src->ru_ip_add); + return; + } + + // disconnect from the RU + MP_LOG_I("Sending PM de-activation request for RU \"%s\".\n", src->ru_ip_add); + bool success = pm_conf(src, "false"); + if (success) + MP_LOG_I("Successfully de-activated PM for RU \"%s\".\n", src->ru_ip_add); + MP_LOG_I("Disconnecting from RU \"%s\".\n", src->ru_ip_add); + + // free RU IP address + free(src->ru_ip_add); + // free RU M-plane config + free_ru_mplane_config(&src->ru_mplane_config); + // free NETCONF session + nc_session_free(src->session, NULL); + src->session = NULL; + // free libyang context +#ifdef MPLANE_V1 + ly_ctx_destroy((struct ly_ctx *)src->ctx, NULL); +#elif defined MPLANE_V2 + ly_ctx_destroy((struct ly_ctx *)src->ctx); +#endif + // free only the RU MAC addressin xran M-plane info + free(src->xran_mplane.ru_mac_addr); + // nothing to free in ru_notif + // free PM stats + free_pm_stats(&src->pm_stats); +} + +void free_ru_session_list(ru_session_list_t *src) +{ + // DU key pair + for (size_t i = 0; i < 2; i++) { + free(src->du_key_pair[i]); + } + free(src->du_key_pair); + + // RU session + for (size_t i = 0; i < src->num_rus; i++) { + free_ru_session(&src->ru_session[i]); + } + free(src->ru_session); +} + +oper_state_e str_to_enum_oper(const char* value) { +#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name; + OPER_STATE +#undef X + return OPER_COUNT; +}; + +admin_state_e str_to_enum_admin(const char* value) { +#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name; + ADMIN_STATE +#undef X + return ADMIN_COUNT; +}; + +avail_state_e str_to_enum_avail(const char* value) { +#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name; + AVAIL_STATE +#undef X + return AVAIL_COUNT; +}; + +ptp_state_e str_to_enum_ptp(const char* value) { +#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name; + PTP_STATE +#undef X + return PTP_COUNT; +}; + +carrier_state_e str_to_enum_carrier(const char* value) { +#define X(name, str) if (value != NULL && strcmp(value, str) == 0) return name; + CARRIER_STATE +#undef X + return CARRIER_COUNT; +}; + static void free_match_list(char **match_list, size_t count) { for (size_t i = 0; i < count; i++) { @@ -63,13 +197,15 @@ static void fix_benetel_setting(xran_mplane_t *xran_mplane, const uint32_t inter bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane) { /* some O-RU vendors are not fully compliant as per M-plane specifications */ - const char *ru_vendor = get_ru_xml_node(buffer, "mfg-name"); + char *ru_vendor = get_ru_xml_node(buffer, "mfg-name"); // RU MAC xran_mplane->ru_mac_addr = get_ru_xml_node(buffer, "mac-address"); // TODO: support for VVDN, as it defines multiple MAC addresses // MTU - const uint32_t interface_mtu = (uint32_t)atoi(get_ru_xml_node(buffer, "l2-mtu")); + char *int_mtu_str = get_ru_xml_node(buffer, "l2-mtu"); + const uint32_t interface_mtu = (uint32_t)atoi(int_mtu_str); + free(int_mtu_str); // IQ bitwidth char **match_list = NULL; @@ -107,14 +243,17 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ free_match_list(match_list, count); // Managed delay support - const char *managed_delay = get_ru_xml_node(buffer, "managed-delay-support"); + char *managed_delay = get_ru_xml_node(buffer, "managed-delay-support"); xran_mplane->managed_delay = (strcasecmp(managed_delay, "NON_MANAGED") == 0) ? false : true; + free(managed_delay); // Store the max gain - xran_mplane->max_tx_gain = (double)atof(get_ru_xml_node(buffer, "max-gain")); + char *max_tx_gain_str = get_ru_xml_node(buffer, "max-gain"); + xran_mplane->max_tx_gain = (double)atof(max_tx_gain_str); + free(max_tx_gain_str); // Model name - const char *model_name = get_ru_xml_node(buffer, "model-name"); + char *model_name = get_ru_xml_node(buffer, "model-name"); if (strcasecmp(ru_vendor, "BENETEL") == 0 /* || strcmp(ru_vendor, "VVDN-LPRU") == 0 || strcmp(ru_vendor, "Metanoia") == 0 */) { fix_benetel_setting(xran_mplane, interface_mtu, first_iq_width, max_num_ant, model_name); @@ -150,6 +289,9 @@ bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_ xran_mplane->ru_port, xran_mplane->max_tx_gain); + free(ru_vendor); + free(model_name); + return true; } @@ -185,7 +327,7 @@ bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config) bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats) { - const char *ru_vendor = get_ru_xml_node(buffer, "mfg-name"); + char *ru_vendor = get_ru_xml_node(buffer, "mfg-name"); if (strcasecmp(ru_vendor, "BENETEL") == 0) { pm_stats->start_up_timing = false; } else { @@ -200,5 +342,7 @@ bool get_pm_object_list(const char *buffer, pm_stats_t *pm_stats) MP_LOG_I("Successfully retreived all performance measurement names.\n"); + free(ru_vendor); + return true; } diff --git a/radio/fhi_72/mplane/ru-mplane-api.h b/radio/fhi_72/mplane/ru-mplane-api.h index 85fac5515c..f568bbaf3e 100644 --- a/radio/fhi_72/mplane/ru-mplane-api.h +++ b/radio/fhi_72/mplane/ru-mplane-api.h @@ -31,10 +31,86 @@ #define MP_LOG_I(x, args...) LOG_I(HW, "[MPLANE] " x, ##args) #define MP_LOG_W(x, args...) LOG_W(HW, "[MPLANE] " x, ##args) +#define OPER_STATE \ + X(ENABLED_OPER, "enabled") \ + X(DISABLED_OPER, "disabled") + +typedef enum { +#define X(name, str) name, + OPER_STATE +#undef X + OPER_COUNT +} oper_state_e; + +oper_state_e str_to_enum_oper(const char* value); + +#define ADMIN_STATE \ + X(UNLOCKED_ADMIN, "unlocked") \ + X(SHUTTING_DOWN_ADMIN, "shutting-down") \ + X(LOCKED_ADMIN, "locked") + +typedef enum { +#define X(name, str) name, + ADMIN_STATE +#undef X + ADMIN_COUNT +} admin_state_e; + +admin_state_e str_to_enum_admin(const char* value); + +#define AVAIL_STATE \ + X(NORMAL_AVAIL, "NORMAL") \ + X(DEGRADED_AVAIL, "DEGRADED") \ + X(FAULTY_AVAIL, "FAULTY") + +typedef enum { +#define X(name, str) name, + AVAIL_STATE +#undef X + AVAIL_COUNT +} avail_state_e; + +avail_state_e str_to_enum_avail(const char* value); + typedef struct { - bool ptp_state; - bool rx_carrier_state; - bool tx_carrier_state; + oper_state_e oper_state; // "enabled", "disabled" + admin_state_e admin_state; // "unlocked", "shutting-down", "locked" + avail_state_e avail_state; // "NORMAL", "DEGRADED", "FAULTY" +} hardware_notif_t; + +#define PTP_STATE \ + X(LOCKED_PTP, "LOCKED") \ + X(FREERUN_PTP, "FREERUN") \ + X(HOLDOVER_PTP, "HOLDOVER") + +typedef enum { +#define X(name, str) name, + PTP_STATE +#undef X + PTP_COUNT +} ptp_state_e; + +ptp_state_e str_to_enum_ptp(const char* value); + +#define CARRIER_STATE \ + X(READY_CARRIER, "READY") \ + X(DISABLED_CARRIER, "DISABLED") \ + X(BUSY_CARRIER, "BUSY") + +typedef enum { +#define X(name, str) name, + CARRIER_STATE +#undef X + CARRIER_COUNT +} carrier_state_e; + +carrier_state_e str_to_enum_carrier(const char* value); + +typedef struct { + hardware_notif_t hardware; + ptp_state_e ptp_state; // "LOCKED", "FREERUN", "HOLDOVER" + carrier_state_e rx_carrier_state; // "READY", "DISABLED", "BUSY" + carrier_state_e tx_carrier_state; // "READY", "DISABLED", "BUSY" bool config_change; // to be extended with any notification callback @@ -112,6 +188,8 @@ typedef struct { } ru_session_list_t; +void free_ru_session_list(ru_session_list_t *src); + bool get_config_for_xran(const char *buffer, const int max_num_ant, xran_mplane_t *xran_mplane); bool get_uplane_info(const char *buffer, ru_mplane_config_t *ru_mplane_config); diff --git a/radio/fhi_72/mplane/subscribe-mplane.c b/radio/fhi_72/mplane/subscribe-mplane.c index bec7e28a68..38c770848d 100644 --- a/radio/fhi_72/mplane/subscribe-mplane.c +++ b/radio/fhi_72/mplane/subscribe-mplane.c @@ -30,13 +30,8 @@ static void recv_notif_v1(const struct nc_notif *notif, ru_notif_t *answer) { const char *node_name = notif->tree->child->attr->name; - const char *value = notif->tree->child->attr->value_str; if (strcmp(node_name, "sync-state")) { - if (strcmp(value, "LOCKED") == 0) { - answer->ptp_state = true; - } else { - answer->ptp_state = false; - } + answer->ptp_state = str_to_enum_ptp(notif->tree->child->attr->value_str); } // carriers state - to be filled @@ -52,6 +47,8 @@ static void notif_clb_v1(struct nc_session *session, const struct nc_notif *noti MP_LOG_I("\nReceived notification at (%s)\n%s\n", notif->datetime, subs_reply); recv_notif_v1(notif, answer); + + free(subs_reply); } #elif MPLANE_V2 static void log_v2_pm_info(const char *ru_ip_add, struct lyd_node_inner *stats) @@ -85,33 +82,36 @@ static void log_v2_pm_info(const char *ru_ip_add, struct lyd_node_inner *stats) meas_list[7], count_list[7]); } +static void get_hardware_states(struct lyd_node_inner *op, ru_notif_t *answer) +{ + struct lyd_node *child = NULL; + LY_LIST_FOR(op->child, child) { + if (strcmp(child->schema->name, "admin-state") == 0) { + answer->hardware.admin_state = str_to_enum_admin(lyd_get_value(child)); + } else if (strcmp(child->schema->name, "availability-state") == 0) { + answer->hardware.avail_state = str_to_enum_avail(lyd_get_value(child)); + } + } +} + static void recv_notif_v2(struct lyd_node_inner *op, ru_notif_t *answer) { const char *notif = op->schema->name; if (strcmp(notif, "synchronization-state-change") == 0) { - const char *value = lyd_get_value(op->child); - if (strcmp(value, "LOCKED") == 0) { - answer->ptp_state = true; - } else { // "FREERUN" or "HOLDOVER" - answer->ptp_state = false; - } + answer->ptp_state = str_to_enum_ptp(lyd_get_value(op->child)); } else if (strcmp(notif, "rx-array-carriers-state-change") == 0) { - const char *value = lyd_get_value(lyd_child(op->child)->next); - if (strcmp(value, "READY") == 0) { - answer->rx_carrier_state = true; - } else { // "DISABLED" or "BUSY" - answer->rx_carrier_state = false; - } + answer->rx_carrier_state = str_to_enum_carrier(lyd_get_value(lyd_child(op->child)->next)); } else if (strcmp(notif, "tx-array-carriers-state-change") == 0) { - const char *value = lyd_get_value(lyd_child(op->child)->next); - if (strcmp(value, "READY") == 0) { - answer->tx_carrier_state = true; - } else { // "DISABLED" or "BUSY" - answer->tx_carrier_state = false; - } + answer->tx_carrier_state = str_to_enum_carrier(lyd_get_value(lyd_child(op->child)->next)); } else if (strcmp(notif, "netconf-config-change") == 0) { answer->config_change = true; + } else if (strcmp(notif, "hardware-state-oper-enabled") == 0) { + answer->hardware.oper_state = ENABLED_OPER; + get_hardware_states(op, answer); + } else if (strcmp(notif, "hardware-state-oper-disabled") == 0) { + answer->hardware.oper_state = DISABLED_OPER; + get_hardware_states(op, answer); } } @@ -126,11 +126,14 @@ static void notif_clb_v2(struct nc_session *session, const struct lyd_node *envp struct lyd_node_inner *op_inner = (struct lyd_node_inner *)op; if (strcmp(op_inner->schema->name, "measurement-result-stats") == 0) { log_v2_pm_info(ru_ip_add, op_inner); + free(subs_reply); return; } MP_LOG_I("Received notification from RU \"%s\" at (%s)\n%s\n", ru_ip_add, ((struct lyd_node_opaq *)lyd_child(envp))->value, subs_reply); recv_notif_v2(op_inner, answer); + + free(subs_reply); } #endif diff --git a/radio/fhi_72/mplane/xml/get-xml.c b/radio/fhi_72/mplane/xml/get-xml.c index 6456219293..138896103f 100644 --- a/radio/fhi_72/mplane/xml/get-xml.c +++ b/radio/fhi_72/mplane/xml/get-xml.c @@ -23,8 +23,9 @@ #include #include +#include -static char *find_ru_xml_node(xmlNode *node, const char *filter) +static xmlChar *find_ru_xml_node(xmlNode *node, const char *filter) { for (xmlNode *cur_node = node; cur_node; cur_node = cur_node->next) { if (cur_node->type != XML_ELEMENT_NODE) @@ -39,9 +40,9 @@ static char *find_ru_xml_node(xmlNode *node, const char *filter) break; } } - return (char *)xmlNodeGetContent(target_node); + return xmlNodeGetContent(target_node); } - char *answer = find_ru_xml_node(cur_node->children, filter); + xmlChar *answer = find_ru_xml_node(cur_node->children, filter); if (answer != NULL) { return answer; } @@ -56,7 +57,13 @@ char *get_ru_xml_node(const char *buffer, const char *filter) xmlDoc *doc = xmlReadMemory(buffer, len, NULL, NULL, 0); xmlNode *root_element = xmlDocGetRootElement(doc); - return find_ru_xml_node(root_element->children, filter); + xmlChar *content = find_ru_xml_node(root_element->children, filter); + + char *value = strdup((char *)content); + xmlFree(content); + xmlFreeDoc(doc); + + return value; } static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_list, size_t *count) @@ -74,11 +81,12 @@ static void find_ru_xml_list(xmlNode *node, const char *filter, char ***match_li break; } } - const char *content = (const char *)xmlNodeGetContent(name_node ? name_node : cur_node); + xmlChar *content = xmlNodeGetContent(name_node ? name_node : cur_node); if (content) { *match_list = realloc(*match_list, (*count + 1) * sizeof(char *)); - (*match_list)[*count] = strdup(content); + (*match_list)[*count] = strdup((char *)content); (*count)++; + xmlFree(content); } } find_ru_xml_list(cur_node->children, filter, match_list, count); @@ -93,4 +101,6 @@ void get_ru_xml_list(const char *buffer, const char *filter, char ***match_list, xmlNode *root_element = xmlDocGetRootElement(doc); find_ru_xml_list(root_element->children, filter, match_list, count); + + xmlFreeDoc(doc); } diff --git a/radio/fhi_72/mplane/yang/create-yang-config.c b/radio/fhi_72/mplane/yang/create-yang-config.c index 187fe5b7c1..8f35888797 100644 --- a/radio/fhi_72/mplane/yang/create-yang-config.c +++ b/radio/fhi_72/mplane/yang/create-yang-config.c @@ -233,85 +233,91 @@ static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0 ret = lyd_new_path(NULL, (struct ly_ctx *)ru_session->ctx, "/o-ran-uplane-conf:user-plane-configuration", NULL, 0, root); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create root \"user-plane-configuration\" node.\n"); - if (ru_session->ru_mplane_config.rx_carriers.num != 1 || ru_session->ru_mplane_config.tx_carriers.num !=1) - MP_LOG_I("Only one carrier supported at the moment.\n"); - + const size_t num_rx_ch = oai->rx_num_channels / num_rus; + // RX carriers - struct lyd_node *rx_carrier_node = NULL; - ret = lyd_new_list(*root, NULL, "rx-array-carriers", 0, &rx_carrier_node, ru_session->ru_mplane_config.rx_carriers.name[0]); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-array-carriers\" node.\n"); + const size_t num_rx_carriers = (ru_session->ru_mplane_config.rx_carriers.num == 1) ? 1 : num_rx_ch; + for (size_t i = 0; i < num_rx_carriers; i++) { + struct lyd_node *rx_carrier_node = NULL; + ret = lyd_new_list(*root, NULL, "rx-array-carriers", 0, &rx_carrier_node, ru_session->ru_mplane_config.rx_carriers.name[i]); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-array-carriers\" node.\n"); - char rx_freq[16]; - snprintf(rx_freq, sizeof(rx_freq), "%.0f", oai->rx_freq[0]); - ret = lyd_new_term(rx_carrier_node, NULL, "center-of-channel-bandwidth", rx_freq, 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"center-of-channel-bandwidth\" node.\n"); + char rx_freq[16]; + snprintf(rx_freq, sizeof(rx_freq), "%.0f", oai->rx_freq[0]); + ret = lyd_new_term(rx_carrier_node, NULL, "center-of-channel-bandwidth", rx_freq, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"center-of-channel-bandwidth\" node.\n"); - char rx_arfcn[16]; - snprintf(rx_arfcn, sizeof(rx_arfcn), "%d", to_nrarfcn(oai->nr_band, oai->rx_freq[0], oai->nr_scs_for_raster, oai->rx_bw)); - ret = lyd_new_term(rx_carrier_node, NULL, "absolute-frequency-center", rx_arfcn, 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"absolute-frequency-center\" node.\n"); + char rx_arfcn[16]; + snprintf(rx_arfcn, sizeof(rx_arfcn), "%d", to_nrarfcn(oai->nr_band, oai->rx_freq[0], oai->nr_scs_for_raster, oai->rx_bw)); + ret = lyd_new_term(rx_carrier_node, NULL, "absolute-frequency-center", rx_arfcn, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"absolute-frequency-center\" node.\n"); - char rx_bw[16]; - snprintf(rx_bw, sizeof(rx_bw), "%.0f", oai->rx_bw); - ret = lyd_new_term(rx_carrier_node, NULL, "channel-bandwidth", rx_bw, 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"channel-bandwidth\" node.\n"); + char rx_bw[16]; + snprintf(rx_bw, sizeof(rx_bw), "%.0f", oai->rx_bw); + ret = lyd_new_term(rx_carrier_node, NULL, "channel-bandwidth", rx_bw, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"channel-bandwidth\" node.\n"); - ret = lyd_new_term(rx_carrier_node, NULL, "downlink-radio-frame-offset", "0", 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-radio-frame-offset\" node.\n"); + ret = lyd_new_term(rx_carrier_node, NULL, "downlink-radio-frame-offset", "0", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-radio-frame-offset\" node.\n"); - ret = lyd_new_term(rx_carrier_node, NULL, "downlink-sfn-offset", "0", 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-sfn-offset\" node.\n"); + ret = lyd_new_term(rx_carrier_node, NULL, "downlink-sfn-offset", "0", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-sfn-offset\" node.\n"); - // gain offset applied uniformly across all array elements or layers - // needs to be within - ret = lyd_new_term(rx_carrier_node, NULL, "gain-correction", "0", 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain-correction\" node.\n"); + // gain offset applied uniformly across all array elements or layers + // needs to be within + ret = lyd_new_term(rx_carrier_node, NULL, "gain-correction", "0", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain-correction\" node.\n"); - ret = lyd_new_term(rx_carrier_node, NULL, "n-ta-offset", "0", 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"n-ta-offset\" node.\n"); + ret = lyd_new_term(rx_carrier_node, NULL, "n-ta-offset", "0", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"n-ta-offset\" node.\n"); - ret = lyd_new_term(rx_carrier_node, NULL, "active", "ACTIVE", 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n"); + ret = lyd_new_term(rx_carrier_node, NULL, "active", "ACTIVE", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n"); + } + + const size_t num_tx_ch = oai->tx_num_channels / num_rus; // TX carriers - struct lyd_node *tx_carrier_node = NULL; - ret = lyd_new_list(*root, NULL, "tx-array-carriers", 0, &tx_carrier_node, ru_session->ru_mplane_config.tx_carriers.name[0]); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-array-carriers\" node.\n"); + const size_t num_tx_carriers = (ru_session->ru_mplane_config.tx_carriers.num == 1) ? 1 : num_tx_ch; + for (size_t i = 0; i < num_tx_carriers; i++) { + struct lyd_node *tx_carrier_node = NULL; + ret = lyd_new_list(*root, NULL, "tx-array-carriers", 0, &tx_carrier_node, ru_session->ru_mplane_config.tx_carriers.name[i]); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-array-carriers\" node.\n"); - char tx_freq[16]; - snprintf(tx_freq, sizeof(tx_freq), "%.0f", oai->tx_freq[0]); - ret = lyd_new_term(tx_carrier_node, NULL, "center-of-channel-bandwidth", tx_freq, 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"center-of-channel-bandwidth\" node.\n"); + char tx_freq[16]; + snprintf(tx_freq, sizeof(tx_freq), "%.0f", oai->tx_freq[0]); + ret = lyd_new_term(tx_carrier_node, NULL, "center-of-channel-bandwidth", tx_freq, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"center-of-channel-bandwidth\" node.\n"); - char tx_arfcn[16]; - snprintf(tx_arfcn, sizeof(tx_arfcn), "%d", to_nrarfcn(oai->nr_band, oai->tx_freq[0], oai->nr_scs_for_raster, oai->tx_bw)); - ret = lyd_new_term(tx_carrier_node, NULL, "absolute-frequency-center", tx_arfcn, 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"absolute-frequency-center\" node.\n"); + char tx_arfcn[16]; + snprintf(tx_arfcn, sizeof(tx_arfcn), "%d", to_nrarfcn(oai->nr_band, oai->tx_freq[0], oai->nr_scs_for_raster, oai->tx_bw)); + ret = lyd_new_term(tx_carrier_node, NULL, "absolute-frequency-center", tx_arfcn, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"absolute-frequency-center\" node.\n"); - char tx_bw[16]; - snprintf(tx_bw, sizeof(tx_bw), "%.0f", oai->tx_bw); - ret = lyd_new_term(tx_carrier_node, NULL, "channel-bandwidth", tx_bw, 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"channel-bandwidth\" node.\n"); + char tx_bw[16]; + snprintf(tx_bw, sizeof(tx_bw), "%.0f", oai->tx_bw); + ret = lyd_new_term(tx_carrier_node, NULL, "channel-bandwidth", tx_bw, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"channel-bandwidth\" node.\n"); - // oai->tx_gain takes the value of att_tx from the RU section of gNB config file - // we assume the same gain is applied to all channels; same as above for the frequency - const double tx_gain_value = ((oai->tx_gain[0] * 10000) < ru_session->xran_mplane.max_tx_gain) ? (oai->tx_gain[0] * 10000) : ru_session->xran_mplane.max_tx_gain; - char tx_gain_str[8]; - snprintf(tx_gain_str, sizeof(tx_gain_str), "%.f", tx_gain_value); - ret = lyd_new_term(tx_carrier_node, NULL, "gain", tx_gain_str, 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain\" node.\n"); + // oai->tx_gain takes the value of att_tx from the RU section of gNB config file + // we assume the same gain is applied to all channels; same as above for the frequency + const double tx_gain_value = ((oai->tx_gain[0] * 10000) < ru_session->xran_mplane.max_tx_gain) ? (oai->tx_gain[0] * 10000) : ru_session->xran_mplane.max_tx_gain; + char tx_gain_str[8]; + snprintf(tx_gain_str, sizeof(tx_gain_str), "%.f", tx_gain_value); + ret = lyd_new_term(tx_carrier_node, NULL, "gain", tx_gain_str, 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"gain\" node.\n"); - ret = lyd_new_term(tx_carrier_node, NULL, "downlink-radio-frame-offset", "0", 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-radio-frame-offset\" node.\n"); + ret = lyd_new_term(tx_carrier_node, NULL, "downlink-radio-frame-offset", "0", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-radio-frame-offset\" node.\n"); - ret = lyd_new_term(tx_carrier_node, NULL, "downlink-sfn-offset", "0", 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-sfn-offset\" node.\n"); + ret = lyd_new_term(tx_carrier_node, NULL, "downlink-sfn-offset", "0", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"downlink-sfn-offset\" node.\n"); - ret = lyd_new_term(tx_carrier_node, NULL, "active", "ACTIVE", 0, NULL); - VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n"); + ret = lyd_new_term(tx_carrier_node, NULL, "active", "ACTIVE", 0, NULL); + VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"active\" node.\n"); + } // PUSCH & PRACH endpoints - const size_t num_rx_ch = oai->rx_num_channels / num_rus; for (size_t i = 0; i < num_rx_ch; i++) { struct lyd_node *pusch_node = NULL; ret = lyd_new_list(*root, NULL, "low-level-rx-endpoints", 0, &pusch_node, ru_session->ru_mplane_config.rx_endpoints.name[i]); @@ -330,7 +336,6 @@ static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0 } // PDSCH endpoints - const size_t num_tx_ch = oai->tx_num_channels / num_rus; for (size_t i = 0; i < num_tx_ch; i++) { struct lyd_node *pdsch_node = NULL; ret = lyd_new_list(*root, NULL, "low-level-tx-endpoints", 0, &pdsch_node, ru_session->ru_mplane_config.tx_endpoints.name[i]); @@ -342,6 +347,7 @@ static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0 // PUSCH and PRACH links for (size_t i = 0; i < num_rx_ch; i++) { + const size_t rx_carrier_id = (num_rx_carriers == 1) ? 0 : i; // PUSCH struct lyd_node *pusch_link_node = NULL; char pusch_link[16]; @@ -352,7 +358,7 @@ static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0 ret = lyd_new_term(pusch_link_node, NULL, "processing-element", u_proc_elem, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"processing-element\" node.\n"); - ret = lyd_new_term(pusch_link_node, NULL, "rx-array-carrier", ru_session->ru_mplane_config.rx_carriers.name[0], 0, NULL); + ret = lyd_new_term(pusch_link_node, NULL, "rx-array-carrier", ru_session->ru_mplane_config.rx_carriers.name[rx_carrier_id], 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-array-carrier\" node.\n"); ret = lyd_new_term(pusch_link_node, NULL, "low-level-rx-endpoint", ru_session->ru_mplane_config.rx_endpoints.name[i], 0, NULL); @@ -368,7 +374,7 @@ static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0 ret = lyd_new_term(prach_link_node, NULL, "processing-element", u_proc_elem, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"processing-element\" node.\n"); - ret = lyd_new_term(prach_link_node, NULL, "rx-array-carrier", ru_session->ru_mplane_config.rx_carriers.name[0], 0, NULL); + ret = lyd_new_term(prach_link_node, NULL, "rx-array-carrier", ru_session->ru_mplane_config.rx_carriers.name[rx_carrier_id], 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"rx-array-carrier\" node.\n"); const size_t prach_endpoint_name_offset = i + (ru_session->ru_mplane_config.rx_endpoints.num / 2); @@ -378,6 +384,7 @@ static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0 // PDSCH links for (size_t i = 0; i < num_tx_ch; i++) { + const size_t tx_carrier_id = (num_tx_carriers == 1) ? 0 : i; struct lyd_node *pdsch_link_node = NULL; char pdsch_link[16]; snprintf(pdsch_link, sizeof(pdsch_link), "%s%ld", "PdschLink", i); @@ -387,7 +394,7 @@ static bool create_uplane_conf_v2(const ru_session_t *ru_session, const openair0 ret = lyd_new_term(pdsch_link_node, NULL, "processing-element", u_proc_elem, 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"processing-element\" node.\n"); - ret = lyd_new_term(pdsch_link_node, NULL, "tx-array-carrier", ru_session->ru_mplane_config.tx_carriers.name[0], 0, NULL); + ret = lyd_new_term(pdsch_link_node, NULL, "tx-array-carrier", ru_session->ru_mplane_config.tx_carriers.name[tx_carrier_id], 0, NULL); VERIFY_SUCCESS(ret == LY_SUCCESS, "[MPLANE] Failed to create \"tx-array-carrier\" node.\n"); ret = lyd_new_term(pdsch_link_node, NULL, "low-level-tx-endpoint", ru_session->ru_mplane_config.tx_endpoints.name[i], 0, NULL); diff --git a/radio/fhi_72/mplane/yang/get-yang.c b/radio/fhi_72/mplane/yang/get-yang.c index 60131b34cf..2eb39aa1d6 100644 --- a/radio/fhi_72/mplane/yang/get-yang.c +++ b/radio/fhi_72/mplane/yang/get-yang.c @@ -42,20 +42,30 @@ static bool store_schemas(xmlNode *node, ru_session_t *ru_session, struct ly_ctx if (strcmp((const char *)cur_node->name, "schema") == 0) { xmlNode *name_node = xmlFirstElementChild(cur_node); - char *module_name = (char *)xmlNodeGetContent(name_node); + xmlChar *module_name = xmlNodeGetContent(name_node); xmlNode *revision_node = xmlNextElementSibling(name_node); - char *module_revision = (char *)xmlNodeGetContent(revision_node); + xmlChar *module_revision = xmlNodeGetContent(revision_node); xmlNode *format_node = xmlNextElementSibling(revision_node); - char *module_format = (char *)xmlNodeGetContent(format_node); + xmlChar *module_format = xmlNodeGetContent(format_node); - if (strcmp(module_format, "yang") != 0) + if (strcmp((char*)module_format, "yang") != 0) { + xmlFree(module_name); + xmlFree(module_revision); + xmlFree(module_format); continue; + } MP_LOG_I("RPC request to RU \"%s\" = for module \"%s\".\n", ru_session->ru_ip_add, module_name); - struct nc_rpc *get_schema_rpc = nc_rpc_getschema(module_name, module_revision, "yang", param); + struct nc_rpc *get_schema_rpc = nc_rpc_getschema((char*)module_name, (char*)module_revision, "yang", param); char *schema_data = NULL; bool success = rpc_send_recv((struct nc_session *)ru_session->session, get_schema_rpc, wd, timeout, &schema_data); - AssertError(success, return false, "[MPLANE] Unable to get schema for module \"%s\" from RU \"%s\".\n", module_name, ru_session->ru_ip_add); + if (!success) { + MP_LOG_W("[MPLANE] Unable to get schema for module \"%s\" from RU \"%s\".\n", module_name, ru_session->ru_ip_add); + xmlFree(module_name); + xmlFree(module_revision); + xmlFree(module_format); + return false; + } if (schema_data) { #ifdef MPLANE_V1 @@ -68,11 +78,21 @@ static bool store_schemas(xmlNode *node, ru_session_t *ru_session, struct ly_ctx if (!mod) { MP_LOG_W("Unable to load module \"%s\" from RU \"%s\".\n", module_name, ru_session->ru_ip_add); nc_rpc_free(get_schema_rpc); +#ifdef MPLANE_V1 + ly_ctx_destroy(*ctx, NULL); +#elif defined MPLANE_V2 ly_ctx_destroy(*ctx); - return false; - } +#endif + xmlFree(module_name); + xmlFree(module_revision); + xmlFree(module_format); + return false; + } } nc_rpc_free(get_schema_rpc); + xmlFree(module_name); + xmlFree(module_revision); + xmlFree(module_format); } } @@ -105,6 +125,7 @@ bool load_yang_models(ru_session_t *ru_session, const char *buffer) xmlNode *root_element = xmlDocGetRootElement(doc); bool success = load_from_operational_ds(root_element->children, ru_session, ctx); + xmlFreeDoc(doc); if (success) { MP_LOG_I("Successfully loaded all yang modules from operational datastore for RU \"%s\".\n", ru_session->ru_ip_add); return true; @@ -116,7 +137,7 @@ bool load_yang_models(ru_session_t *ru_session, const char *buffer) 1) the yang models order is not good - the dependancy models have to be loaded first 2) earlier O-RAN yang versions (e.g. v4) is not properly defined (i.e. optional parameters should not be included by default) */ const char *yang_dir = YANG_MODELS; - const char *yang_models[] = {"ietf-interfaces", "iana-if-type", "ietf-ip", "iana-hardware", "ietf-hardware", "o-ran-interfaces", "o-ran-module-cap", "o-ran-compression-factors", "o-ran-processing-element", "o-ran-uplane-conf", "ietf-netconf-acm", "ietf-crypto-types", "o-ran-file-management", "o-ran-performance-management"}; + const char *yang_models[] = {"ietf-interfaces", "iana-if-type", "ietf-ip", "iana-hardware", "ietf-hardware", "o-ran-wg4-features", "o-ran-interfaces", "o-ran-module-cap", "o-ran-compression-factors", "ietf-crypto-types", "o-ran-usermgmt", "o-ran-processing-element", "o-ran-hardware", "o-ran-common-yang-types", "o-ran-delay-management", "o-ran-uplane-conf", "ietf-netconf-acm", "o-ran-file-management", "o-ran-performance-management"}; #ifdef MPLANE_V1 *ctx = ly_ctx_new(yang_dir, 0); diff --git a/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang b/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang index 1b94b03176..342dde899c 100644 --- a/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang +++ b/radio/fhi_72/mplane/yang/models/ietf-crypto-types.yang @@ -19,28 +19,27 @@ module ietf-crypto-types { "IETF NETCONF (Network Configuration) Working Group"; contact - "WG Web: - WG List: - Author: Kent Watsen - Author: Wang Haiguang "; + "WG Web: https://datatracker.ietf.org/wg/netconf + WG List: NETCONF WG list + Author: Kent Watsen "; description "This module defines common YANG types for cryptographic applications. - Copyright (c) 2019 IETF Trust and the persons identified + Copyright (c) 2022 IETF Trust and the persons identified as authors of the code. All rights reserved. Redistribution and use in source and binary forms, with or without modification, is permitted pursuant to, and - subject to the license terms contained in, the Simplified + subject to the license terms contained in, the Revised BSD License set forth in Section 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info). - This version of this YANG module is part of RFC XXXX - (https://www.rfc-editor.org/info/rfcXXXX); see the RFC - itself for full legal notices.; + This version of this YANG module is part of RFC AAAA + (https://www.rfc-editor.org/info/rfcAAAA); see the RFC + itself for full legal notices. The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', @@ -49,1066 +48,361 @@ module ietf-crypto-types { (RFC 8174) when, and only when, they appear in all capitals, as shown here."; - revision 2019-04-29 { + revision 2022-12-12 { description "Initial version"; reference - "RFC XXXX: Common YANG Data Types for Cryptography"; + "RFC AAAA: YANG Data Types and Groupings for Cryptography"; } - /**************************************/ - /* Identities for Hash Algorithms */ - /**************************************/ + /****************/ + /* Features */ + /****************/ - identity hash-algorithm { + feature one-symmetric-key-format { description - "A base identity for hash algorithm verification."; + "Indicates that the server supports the + 'one-symmetric-key-format' identity."; } - identity sha-224 { - base hash-algorithm; + feature one-asymmetric-key-format { description - "The SHA-224 algorithm."; + "Indicates that the server supports the + 'one-asymmetric-key-format' identity."; + } + + feature symmetrically-encrypted-value-format { + description + "Indicates that the server supports the + 'symmetrically-encrypted-value-format' identity."; + } + + feature asymmetrically-encrypted-value-format { + description + "Indicates that the server supports the + 'asymmetrically-encrypted-value-format' identity."; + } + + feature cms-enveloped-data-format { + description + "Indicates that the server supports the + 'cms-enveloped-data-format' identity."; + } + + feature cms-encrypted-data-format { + description + "Indicates that the server supports the + 'cms-encrypted-data-format' identity."; + } + + feature csr-generation { + description + "Indicates that the server implements the + 'generate-csr' action."; + } + + feature p10-based-csrs { + description + "Indicates that the erver implements support + for generating P10-based CSRs, as defined + in RFC 2986."; reference - "RFC 6234: US Secure Hash Algorithms."; - } - identity sha-256 { - base hash-algorithm; - description - "The SHA-256 algorithm."; - reference - "RFC 6234: US Secure Hash Algorithms."; + "RFC 2986: PKCS #10: Certification Request Syntax + Specification Version 1.7"; } - identity sha-384 { - base hash-algorithm; + feature certificate-expiration-notification { description - "The SHA-384 algorithm."; - reference - "RFC 6234: US Secure Hash Algorithms."; + "Indicates that the server implements the + 'certificate-expiration' notification."; } - identity sha-512 { - base hash-algorithm; + feature hidden-keys { description - "The SHA-512 algorithm."; - reference - "RFC 6234: US Secure Hash Algorithms."; + "Indicates that the server supports hidden keys."; } - /***********************************************/ - /* Identities for Asymmetric Key Algorithms */ - /***********************************************/ - - identity asymmetric-key-algorithm { + feature password-encryption { description - "Base identity from which all asymmetric key - encryption Algorithm."; + "Indicates that the server supports password + encryption."; } - identity rsa1024 { - base asymmetric-key-algorithm; + feature symmetric-key-encryption { description - "The RSA algorithm using a 1024-bit key."; - reference - "RFC 8017: - PKCS #1: RSA Cryptography Specifications Version 2.2."; + "Indicates that the server supports encryption + of symmetric keys."; } - identity rsa2048 { - base asymmetric-key-algorithm; + feature private-key-encryption { description - "The RSA algorithm using a 2048-bit key."; - reference - "RFC 8017: - PKCS #1: RSA Cryptography Specifications Version 2.2."; + "Indicates that the server supports encryption + of private keys."; } - identity rsa3072 { - base asymmetric-key-algorithm; + /*************************************************/ + /* Base Identities for Key Format Structures */ + /*************************************************/ + + identity symmetric-key-format { description - "The RSA algorithm using a 3072-bit key."; - reference - "RFC 8017: - PKCS #1: RSA Cryptography Specifications Version 2.2."; + "Base key-format identity for symmetric keys."; } - identity rsa4096 { - base asymmetric-key-algorithm; + identity public-key-format { description - "The RSA algorithm using a 4096-bit key."; - reference - "RFC 8017: - PKCS #1: RSA Cryptography Specifications Version 2.2."; + "Base key-format identity for public keys."; } - identity rsa7680 { - base asymmetric-key-algorithm; + identity private-key-format { description - "The RSA algorithm using a 7680-bit key."; - reference - "RFC 8017: - PKCS #1: RSA Cryptography Specifications Version 2.2."; - } - - identity rsa15360 { - base asymmetric-key-algorithm; - description - "The RSA algorithm using a 15360-bit key."; - reference - "RFC 8017: - PKCS #1: RSA Cryptography Specifications Version 2.2."; - } - - identity secp192r1 { - base asymmetric-key-algorithm; - description - "The ECDSA algorithm using a NIST P256 Curve."; - reference - "RFC 6090: - Fundamental Elliptic Curve Cryptography Algorithms."; - } - identity secp224r1 { - base asymmetric-key-algorithm; - description - "The ECDSA algorithm using a NIST P256 Curve."; - reference - "RFC 6090: - Fundamental Elliptic Curve Cryptography Algorithms."; - } - - identity secp256r1 { - base asymmetric-key-algorithm; - description - "The ECDSA algorithm using a NIST P256 Curve."; - reference - "RFC 6090: - Fundamental Elliptic Curve Cryptography Algorithms."; - } - - identity secp384r1 { - base asymmetric-key-algorithm; - description - "The ECDSA algorithm using a NIST P256 Curve."; - reference - "RFC 6090: - Fundamental Elliptic Curve Cryptography Algorithms."; - } - - identity secp521r1 { - base asymmetric-key-algorithm; - description - "The ECDSA algorithm using a NIST P256 Curve."; - reference - "RFC 6090: - Fundamental Elliptic Curve Cryptography Algorithms."; - } - - /*************************************/ - /* Identities for MAC Algorithms */ - /*************************************/ - - identity mac-algorithm { - description - "A base identity for mac generation."; - } - - identity hmac-sha1 { - base mac-algorithm; - description - "Generating MAC using SHA1 hash function"; - reference - "RFC 3174: US Secure Hash Algorithm 1 (SHA1)"; - } - - identity hmac-sha1-96 { - base mac-algorithm; - description - "Generating MAC using SHA1 hash function"; - reference - "RFC 2404: The Use of HMAC-SHA-1-96 within ESP and AH"; - } - - identity hmac-sha2-224 { - base mac-algorithm; - description - "Generating MAC using SHA2 hash function"; - reference - "RFC 6234: - US Secure Hash Algorithms (SHA and SHA-based HMAC and - HKDF)"; - } - - identity hmac-sha2-256 { - base mac-algorithm; - description - "Generating MAC using SHA2 hash function"; - reference - "RFC 6234: - US Secure Hash Algorithms (SHA and SHA-based HMAC and - HKDF)"; - } - - identity hmac-sha2-256-128 { - base mac-algorithm; - description - "Generating a 256 bits MAC using SHA2 hash function and - truncate it to 128 bits"; - reference - "RFC 4868: - Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 - with IPsec"; - } - - identity hmac-sha2-384 { - base mac-algorithm; - description - "Generating MAC using SHA2 hash function"; - reference - "RFC 6234: - US Secure Hash Algorithms (SHA and SHA-based HMAC and - HKDF)"; - } - - identity hmac-sha2-384-192 { - base mac-algorithm; - description - "Generating a 384 bits MAC using SHA2 hash function and - truncate it to 192 bits"; - reference - "RFC 4868: - Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with - IPsec"; - } - - identity hmac-sha2-512 { - base mac-algorithm; - description - "Generating MAC using SHA2 hash function"; - reference - "RFC 6234: - US Secure Hash Algorithms (SHA and SHA-based HMAC and - HKDF)"; - } - - identity hmac-sha2-512-256 { - base mac-algorithm; - description - "Generating a 512 bits MAC using SHA2 hash function and - truncating it to 256 bits"; - reference - "RFC 4868: - Using HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 with - IPsec"; - } - - identity aes-128-gmac { - base mac-algorithm; - description - "Generating MAC using the Advanced Encryption Standard (AES) - Galois Message Authentication Code (GMAC) as a mechanism to - provide data origin authentication"; - reference - "RFC 4543: - The Use of Galois Message Authentication Code (GMAC) in - IPsec ESP and AH"; - } - - identity aes-192-gmac { - base mac-algorithm; - description - "Generating MAC using the Advanced Encryption Standard (AES) - Galois Message Authentication Code (GMAC) as a mechanism to - provide data origin authentication"; - reference - "RFC 4543: - The Use of Galois Message Authentication Code (GMAC) in - IPsec ESP and AH"; - } - - identity aes-256-gmac { - base mac-algorithm; - description - "Generating MAC using the Advanced Encryption Standard (AES) - Galois Message Authentication Code (GMAC) as a mechanism to - provide data origin authentication"; - reference - "RFC 4543: - The Use of Galois Message Authentication Code (GMAC) in - IPsec ESP and AH"; - } - - identity aes-cmac-96 { - base mac-algorithm; - description - "Generating MAC using Advanced Encryption Standard (AES) - Cipher-based Message Authentication Code (CMAC)"; - reference - "RFC 4494: The AES-CMAC-96 Algorithm and its Use with IPsec"; - } - - identity aes-cmac-128 { - base mac-algorithm; - description - "Generating MAC using Advanced Encryption Standard (AES) - Cipher-based Message Authentication Code (CMAC)"; - reference - "RFC 4493: The AES-CMAC Algorithm"; - } - - /********************************************/ - /* Identities for Encryption Algorithms */ - /********************************************/ - - identity encryption-algorithm { - description - "A base identity for encryption algorithm."; - } - - identity aes-128-cbc { - base encryption-algorithm; - description - "Encrypt message with AES algorithm in CBC mode with a key - length of 128 bits"; - reference - "RFC 3565: - Use of the Advanced Encryption Standard (AES) Encryption - Algorithm in Cryptographic Message Syntax (CMS)"; - } - - identity aes-192-cbc { - base encryption-algorithm; - description - "Encrypt message with AES algorithm in CBC mode with a key - length of 192 bits"; - reference - "RFC 3565: - Use of the Advanced Encryption Standard (AES) Encryption - Algorithm in Cryptographic Message Syntax (CMS)"; - } - - identity aes-256-cbc { - base encryption-algorithm; - description - "Encrypt message with AES algorithm in CBC mode with a key - length of 256 bits"; - reference - "RFC 3565: - Use of the Advanced Encryption Standard (AES) Encryption - Algorithm in Cryptographic Message Syntax (CMS)"; - } - - identity aes-128-ctr { - base encryption-algorithm; - description - "Encrypt message with AES algorithm in CTR mode with a key - length of 128 bits"; - reference - "RFC 3686: - Using Advanced Encryption Standard (AES) Counter Mode with - IPsec Encapsulating Security Payload (ESP)"; - } - identity aes-192-ctr { - base encryption-algorithm; - description - "Encrypt message with AES algorithm in CTR mode with a key - length of 192 bits"; - reference - "RFC 3686: - Using Advanced Encryption Standard (AES) Counter Mode with - IPsec Encapsulating Security Payload (ESP)"; - } - - identity aes-256-ctr { - base encryption-algorithm; - description - "Encrypt message with AES algorithm in CTR mode with a key - length of 256 bits"; - reference - "RFC 3686: - Using Advanced Encryption Standard (AES) Counter Mode with - IPsec Encapsulating Security Payload (ESP)"; + "Base key-format identity for private keys."; } /****************************************************/ - /* Identities for Encryption and MAC Algorithms */ + /* Identities for Private Key Format Structures */ /****************************************************/ - identity encryption-and-mac-algorithm { + identity rsa-private-key-format { + base private-key-format; description - "A base identity for encryption and MAC algorithm."; - } - - identity aes-128-ccm { - base encryption-and-mac-algorithm; - description - "Encrypt message with AES algorithm in CCM mode with a key - length of 128 bits; it can also be used for generating MAC"; + "Indicates that the private key value is encoded + as an RSAPrivateKey (from RFC 3447)."; reference - "RFC 4309: - Using Advanced Encryption Standard (AES) CCM Mode with - IPsec Encapsulating Security Payload (ESP)"; + "RFC 3447: PKCS #1: RSA Cryptography + Specifications Version 2.2"; } - identity aes-192-ccm { - base encryption-and-mac-algorithm; + identity ec-private-key-format { + base private-key-format; description - "Encrypt message with AES algorithm in CCM mode with a key - length of 192 bits; it can also be used for generating MAC"; + "Indicates that the private key value is encoded + as an ECPrivateKey (from RFC 5915)"; reference - "RFC 4309: - Using Advanced Encryption Standard (AES) CCM Mode with - IPsec Encapsulating Security Payload (ESP)"; + "RFC 5915: Elliptic Curve Private Key Structure"; } - identity aes-256-ccm { - base encryption-and-mac-algorithm; + identity one-asymmetric-key-format { + if-feature "one-asymmetric-key-format"; + base private-key-format; description - "Encrypt message with AES algorithm in CCM mode with a key - length of 256 bits; it can also be used for generating MAC"; + "Indicates that the private key value is a CMS + OneAsymmetricKey structure, as defined in RFC 5958, + encoded using ASN.1 distinguished encoding rules + (DER), as specified in ITU-T X.690."; reference - "RFC 4309: - Using Advanced Encryption Standard (AES) CCM Mode with - IPsec Encapsulating Security Payload (ESP)"; + "RFC 5958: Asymmetric Key Packages + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; } - identity aes-128-gcm { - base encryption-and-mac-algorithm; - description - "Encrypt message with AES algorithm in GCM mode with a key - length of 128 bits; it can also be used for generating MAC"; - reference - "RFC 4106: - The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating - Security Payload (ESP)"; - } + /***************************************************/ + /* Identities for Public Key Format Structures */ + /***************************************************/ - identity aes-192-gcm { - base encryption-and-mac-algorithm; + identity ssh-public-key-format { + base public-key-format; description - "Encrypt message with AES algorithm in GCM mode with a key - length of 192 bits; it can also be used for generating MAC"; - reference - "RFC 4106: - The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating - Security Payload (ESP)"; - } + "Indicates that the public key value is an SSH public key, + as specified by RFC 4253, Section 6.6, i.e.: - identity mac-aes-256-gcm { - base encryption-and-mac-algorithm; - description - "Encrypt message with AES algorithm in GCM mode with a key - length of 128 bits; it can also be used for generating MAC"; - reference - "RFC 4106: - The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating - Security Payload (ESP)"; - } - identity chacha20-poly1305 { - base encryption-and-mac-algorithm; - description - "Encrypt message with chacha20 algorithm and generate MAC with - POLY1305; it can also be used for generating MAC"; - reference - "RFC 8439: ChaCha20 and Poly1305 for IETF Protocols"; - } - - /******************************************/ - /* Identities for signature algorithm */ - /******************************************/ - - identity signature-algorithm { - description - "A base identity for asymmetric key encryption algorithm."; - } - - identity dsa-sha1 { - base signature-algorithm; - description - "The signature algorithm using DSA algorithm with SHA1 hash - algorithm"; + string certificate or public key format + identifier + byte[n] key/certificate data."; reference "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; } - identity rsassa-pkcs1-sha1 { - base signature-algorithm; + identity subject-public-key-info-format { + base public-key-format; description - "The signature algorithm using RSASSA-PKCS1-v1_5 with the SHA1 - hash algorithm."; + "Indicates that the public key value is a SubjectPublicKeyInfo + structure, as described in RFC 5280 encoded using ASN.1 + distinguished encoding rules (DER), as specified in + ITU-T X.690."; reference - "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; } - identity rsassa-pkcs1-sha256 { - base signature-algorithm; + /******************************************************/ + /* Identities for Symmetric Key Format Structures */ + /******************************************************/ + + identity octet-string-key-format { + base symmetric-key-format; description - "The signature algorithm using RSASSA-PKCS1-v1_5 with the - SHA256 hash algorithm."; + "Indicates that the key is encoded as a raw octet string. + The length of the octet string MUST be appropriate for + the associated algorithm's block size. + + How the associated algorithm is known is outside the + scope of this module. This statement also applies when + the octet string has been encrypted."; + } + + identity one-symmetric-key-format { + if-feature "one-symmetric-key-format"; + base symmetric-key-format; + description + "Indicates that the private key value is a CMS + OneSymmetricKey structure, as defined in RFC 6031, + encoded using ASN.1 distinguished encoding rules + (DER), as specified in ITU-T X.690."; reference - "RFC 8332: - Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell - (SSH) Protocol - RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; + "RFC 6031: Cryptographic Message Syntax (CMS) + Symmetric Key Package Content Type + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; } - identity rsassa-pkcs1-sha384 { - base signature-algorithm; + + /*************************************************/ + /* Identities for Encrypted Value Structures */ + /*************************************************/ + + identity encrypted-value-format { description - "The signature algorithm using RSASSA-PKCS1-v1_5 with the - SHA384 hash algorithm."; + "Base format identity for encrypted values."; + } + + identity symmetrically-encrypted-value-format { + if-feature "symmetrically-encrypted-value-format"; + base encrypted-value-format; + description + "Base format identity for symmetrically encrypted + values."; + } + + identity asymmetrically-encrypted-value-format { + if-feature "asymmetrically-encrypted-value-format"; + base encrypted-value-format; + description + "Base format identity for asymmetrically encrypted + values."; + } + + identity cms-encrypted-data-format { + if-feature "cms-encrypted-data-format"; + base symmetrically-encrypted-value-format; + description + "Indicates that the encrypted value conforms to + the 'encrypted-data-cms' type with the constraint + that the 'unprotectedAttrs' value is not set."; reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; + "RFC 5652: Cryptographic Message Syntax (CMS) + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; } - identity rsassa-pkcs1-sha512 { - base signature-algorithm; + identity cms-enveloped-data-format { + if-feature "cms-enveloped-data-format"; + base asymmetrically-encrypted-value-format; description - "The signature algorithm using RSASSA-PKCS1-v1_5 with the - SHA512 hash algorithm."; + "Indicates that the encrypted value conforms to the + 'enveloped-data-cms' type with the following constraints: + + The EnvelopedData structure MUST have exactly one + 'RecipientInfo'. + + If the asymmetric key supports public key cryptography + (e.g., RSA), then the 'RecipientInfo' must be a + 'KeyTransRecipientInfo' with the 'RecipientIdentifier' + using a 'subjectKeyIdentifier' with the value set using + 'method 1' in RFC 7093 over the recipient's public key. + + Otherwise, if the asymmetric key supports key agreement + (e.g., ECC), then the 'RecipientInfo' must be a + 'KeyAgreeRecipientInfo'. The 'OriginatorIdentifierOrKey' + value must use the 'OriginatorPublicKey' alternative. + The 'UserKeyingMaterial' value must not be present. + There must be exactly one 'RecipientEncryptedKeys' value + having the 'KeyAgreeRecipientIdentifier' set to 'rKeyId' + with the value set using 'method 1' in RFC 7093 over the + recipient's public key."; reference - "RFC 8332: - Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell - (SSH) Protocol - RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; + "RFC 5652: Cryptographic Message Syntax (CMS) + RFC 7093: + Additional Methods for Generating Key + Identifiers Values + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; } - identity rsassa-pss-rsae-sha256 { - base signature-algorithm; + /*********************************************************/ + /* Identities for Certificate Signing Request Formats */ + /*********************************************************/ + + identity csr-format { description - "The signature algorithm using RSASSA-PSS with mask generation - function 1 and SHA256 hash algorithm. If the public key is - carried in an X.509 certificate, it MUST use the rsaEncryption - OID"; + "A base identity for the certificate signing request + formats. Additional derived identities MAY be defined + by future efforts."; + } + + identity p10-csr { + if-feature "p10-based-csrs"; + base csr-format; + description + "Indicates the 'CertificationRequest' structure + defined in RFC 2986."; reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; + "RFC 2986: PKCS #10: Certification Request Syntax + Specification Version 1.7"; } - identity rsassa-pss-rsae-sha384 { - base signature-algorithm; + /***************************************************/ + /* Typedefs for ASN.1 structures from RFC 2986 */ + /***************************************************/ + + typedef csr-info { + type binary; description - "The signature algorithm using RSASSA-PSS with mask generation - function 1 and SHA384 hash algorithm. If the public key is - carried in an X.509 certificate, it MUST use the rsaEncryption - OID"; + "A CertificationRequestInfo structure, as defined in + RFC 2986, encoded using ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; + "RFC 2986: PKCS #10: Certification Request Syntax + Specification Version 1.7 + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; } - identity rsassa-pss-rsae-sha512 { - base signature-algorithm; + typedef p10-csr { + type binary; description - "The signature algorithm using RSASSA-PSS with mask generation - function 1 and SHA512 hash algorithm. If the public key is - carried in an X.509 certificate, it MUST use the rsaEncryption - OID"; + "A CertificationRequest structure, as specified in + RFC 2986, encoded using ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity rsassa-pss-pss-sha256 { - base signature-algorithm; - description - "The signature algorithm using RSASSA-PSS with mask generation - function 1 and SHA256 hash algorithm. If the public key is - carried in an X.509 certificate, it MUST use the RSASSA-PSS - OID"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity rsassa-pss-pss-sha384 { - base signature-algorithm; - description - "The signature algorithm using RSASSA-PSS with mask generation - function 1 and SHA256 hash algorithm. If the public key is - carried in an X.509 certificate, it MUST use the RSASSA-PSS - OID"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity rsassa-pss-pss-sha512 { - base signature-algorithm; - description - "The signature algorithm using RSASSA-PSS with mask generation - function 1 and SHA256 hash algorithm. If the public key is - carried in an X.509 certificate, it MUST use the RSASSA-PSS - OID"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity ecdsa-secp256r1-sha256 { - base signature-algorithm; - description - "The signature algorithm using ECDSA with curve name secp256r1 - and SHA256 hash algorithm."; - reference - "RFC 5656: Elliptic Curve Algorithm Integration in the - Secure Shell Transport Layer - RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity ecdsa-secp384r1-sha384 { - base signature-algorithm; - description - "The signature algorithm using ECDSA with curve name secp384r1 - and SHA384 hash algorithm."; - reference - "RFC 5656: Elliptic Curve Algorithm Integration in the - Secure Shell Transport Layer - RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity ecdsa-secp521r1-sha512 { - base signature-algorithm; - description - "The signature algorithm using ECDSA with curve name secp521r1 - and SHA512 hash algorithm."; - reference - "RFC 5656: Elliptic Curve Algorithm Integration in the - Secure Shell Transport Layer - RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity ed25519 { - base signature-algorithm; - description - "The signature algorithm using EdDSA as defined in RFC 8032 or - its successors."; - reference - "RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)"; - } - - identity ed448 { - base signature-algorithm; - description - "The signature algorithm using EdDSA as defined in RFC 8032 or - its successors."; - reference - "RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)"; - } - - identity eccsi { - base signature-algorithm; - description - "The signature algorithm using ECCSI signature as defined in - RFC 6507."; - reference - "RFC 6507: - Elliptic Curve-Based Certificateless Signatures for - Identity-based Encryption (ECCSI)"; - } - - /**********************************************/ - /* Identities for key exchange algorithms */ - /**********************************************/ - - identity key-exchange-algorithm { - description - "A base identity for Diffie-Hellman based key exchange - algorithm."; - } - - identity psk-only { - base key-exchange-algorithm; - description - "Using Pre-shared key for authentication and key exchange"; - reference - "RFC 4279: - Pre-Shared Key cipher suites for Transport Layer Security - (TLS)"; - } - - identity dhe-ffdhe2048 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with 2048 bit - finite field"; - reference - "RFC 7919: - Negotiated Finite Field Diffie-Hellman Ephemeral Parameters - for Transport Layer Security (TLS)"; - } - - identity dhe-ffdhe3072 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with 3072 bit finite - field"; - reference - "RFC 7919: - Negotiated Finite Field Diffie-Hellman Ephemeral Parameters - for Transport Layer Security (TLS)"; - } - - identity dhe-ffdhe4096 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with 4096 bit - finite field"; - reference - "RFC 7919: - Negotiated Finite Field Diffie-Hellman Ephemeral Parameters - for Transport Layer Security (TLS)"; - } - - identity dhe-ffdhe6144 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with 6144 bit - finite field"; - reference - "RFC 7919: - Negotiated Finite Field Diffie-Hellman Ephemeral Parameters - for Transport Layer Security (TLS)"; - } - - identity dhe-ffdhe8192 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with 8192 bit - finite field"; - reference - "RFC 7919: - Negotiated Finite Field Diffie-Hellman Ephemeral Parameters - for Transport Layer Security (TLS)"; - } - - identity psk-dhe-ffdhe2048 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with Diffie-Hellman key - generation mechanism, where the DH group is FFDHE2048"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity psk-dhe-ffdhe3072 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with Diffie-Hellman key - generation mechanism, where the DH group is FFDHE3072"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity psk-dhe-ffdhe4096 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with Diffie-Hellman key - generation mechanism, where the DH group is FFDHE4096"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity psk-dhe-ffdhe6144 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with Diffie-Hellman key - generation mechanism, where the DH group is FFDHE6144"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity psk-dhe-ffdhe8192 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with Diffie-Hellman key - generation mechanism, where the DH group is FFDHE8192"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity ecdhe-secp256r1 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with elliptic group - over curve secp256r1"; - reference - "RFC 8422: - Elliptic Curve Cryptography (ECC) Cipher Suites for - Transport Layer Security (TLS) Versions 1.2 and Earlier"; - } - - identity ecdhe-secp384r1 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with elliptic group - over curve secp384r1"; - reference - "RFC 8422: - Elliptic Curve Cryptography (ECC) Cipher Suites for - Transport Layer Security (TLS) Versions 1.2 and Earlier"; - } - - identity ecdhe-secp521r1 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with elliptic group - over curve secp521r1"; - reference - "RFC 8422: - Elliptic Curve Cryptography (ECC) Cipher Suites for - Transport Layer Security (TLS) Versions 1.2 and Earlier"; - } - - identity ecdhe-x25519 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with elliptic group - over curve x25519"; - reference - "RFC 8422: - Elliptic Curve Cryptography (ECC) Cipher Suites for - Transport Layer Security (TLS) Versions 1.2 and Earlier"; - } - - identity ecdhe-x448 { - base key-exchange-algorithm; - description - "Ephemeral Diffie Hellman key exchange with elliptic group - over curve x448"; - reference - "RFC 8422: - Elliptic Curve Cryptography (ECC) Cipher Suites for - Transport Layer Security (TLS) Versions 1.2 and Earlier"; - } - - identity psk-ecdhe-secp256r1 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with elliptic group-based - Ephemeral Diffie Hellman key exchange over curve secp256r1"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity psk-ecdhe-secp384r1 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with elliptic group-based - Ephemeral Diffie Hellman key exchange over curve secp384r1"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity psk-ecdhe-secp521r1 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with elliptic group-based - Ephemeral Diffie Hellman key exchange over curve secp521r1"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity psk-ecdhe-x25519 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with elliptic group-based - Ephemeral Diffie Hellman key exchange over curve x25519"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity psk-ecdhe-x448 { - base key-exchange-algorithm; - description - "Key exchange using pre-shared key with elliptic group-based - Ephemeral Diffie Hellman key exchange over curve x448"; - reference - "RFC 8446: - The Transport Layer Security (TLS) Protocol Version 1.3"; - } - - identity diffie-hellman-group14-sha1 { - base key-exchange-algorithm; - description - "Using DH group14 and SHA1 for key exchange"; - reference - "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; - } - - identity diffie-hellman-group14-sha256 { - base key-exchange-algorithm; - description - "Using DH group14 and SHA256 for key exchange"; - reference - "RFC 8268: - More Modular Exponentiation (MODP) Diffie-Hellman (DH) - Key Exchange (KEX) Groups for Secure Shell (SSH)"; - } - - identity diffie-hellman-group15-sha512 { - base key-exchange-algorithm; - description - "Using DH group15 and SHA512 for key exchange"; - reference - "RFC 8268: - More Modular Exponentiation (MODP) Diffie-Hellman (DH) - Key Exchange (KEX) Groups for Secure Shell (SSH)"; - } - - identity diffie-hellman-group16-sha512 { - base key-exchange-algorithm; - description - "Using DH group16 and SHA512 for key exchange"; - reference - "RFC 8268: - More Modular Exponentiation (MODP) Diffie-Hellman (DH) - Key Exchange (KEX) Groups for Secure Shell (SSH)"; - } - - identity diffie-hellman-group17-sha512 { - base key-exchange-algorithm; - description - "Using DH group17 and SHA512 for key exchange"; - - reference - "RFC 8268: - More Modular Exponentiation (MODP) Diffie-Hellman (DH) - Key Exchange (KEX) Groups for Secure Shell (SSH)"; - } - - identity diffie-hellman-group18-sha512 { - base key-exchange-algorithm; - description - "Using DH group18 and SHA512 for key exchange"; - reference - "RFC 8268: - More Modular Exponentiation (MODP) Diffie-Hellman (DH) - Key Exchange (KEX) Groups for Secure Shell (SSH)"; - } - - identity ecdh-sha2-secp256r1 { - base key-exchange-algorithm; - description - "Elliptic curve-based Diffie Hellman key exchange over curve - secp256r1 and using SHA2 for MAC generation"; - reference - "RFC 6239: Suite B Cryptographic Suites for Secure Shell - (SSH)"; - } - - identity ecdh-sha2-secp384r1 { - base key-exchange-algorithm; - description - "Elliptic curve-based Diffie Hellman key exchange over curve - secp384r1 and using SHA2 for MAC generation"; - reference - "RFC 6239: Suite B Cryptographic Suites for Secure Shell - (SSH)"; - } - - identity rsaes-oaep { - base key-exchange-algorithm; - description - "RSAES-OAEP combines the RSAEP and RSADP primitives with the - EME-OAEP encoding method"; - reference - "RFC 8017: - PKCS #1: RSA Cryptography Specifications Version 2.2."; - } - - identity rsaes-pkcs1-v1_5 { - base key-exchange-algorithm; - description - " RSAES-PKCS1-v1_5 combines the RSAEP and RSADP primitives - with the EME-PKCS1-v1_5 encoding method"; - reference - "RFC 8017: - PKCS #1: RSA Cryptography Specifications Version 2.2."; - } - - /**********************************************************/ - /* Typedefs for identityrefs to above base identities */ - /**********************************************************/ - - typedef hash-algorithm-ref { - type identityref { - base hash-algorithm; - } - description - "This typedef enables importing modules to easily define an - identityref to the 'hash-algorithm' base identity."; - } - - typedef signature-algorithm-ref { - type identityref { - base signature-algorithm; - } - description - "This typedef enables importing modules to easily define an - identityref to the 'signature-algorithm' base identity."; - } - - typedef mac-algorithm-ref { - type identityref { - base mac-algorithm; - } - description - "This typedef enables importing modules to easily define an - identityref to the 'mac-algorithm' base identity."; - } - - typedef encryption-algorithm-ref { - type identityref { - base encryption-algorithm; - } - description - "This typedef enables importing modules to easily define an - identityref to the 'encryption-algorithm' - base identity."; - } - - typedef encryption-and-mac-algorithm-ref { - type identityref { - base encryption-and-mac-algorithm; - } - description - "This typedef enables importing modules to easily define an - identityref to the 'encryption-and-mac-algorithm' - base identity."; - } - - typedef asymmetric-key-algorithm-ref { - type identityref { - base asymmetric-key-algorithm; - } - description - "This typedef enables importing modules to easily define an - identityref to the 'asymmetric-key-algorithm' - base identity."; - } - - typedef key-exchange-algorithm-ref { - type identityref { - base key-exchange-algorithm; - } - description - "This typedef enables importing modules to easily define an - identityref to the 'key-exchange-algorithm' base identity."; + "RFC 2986: + PKCS #10: Certification Request Syntax Specification + Version 1.7 + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; } /***************************************************/ @@ -1149,6 +443,43 @@ module ietf-crypto-types { Encoding Rules (DER)."; } + /***************************************************/ + /* Typedefs for ASN.1 structures from RFC 6960 */ + /***************************************************/ + typedef oscp-request { + type binary; + description + "A OCSPRequest structure, as specified in RFC 6960, + encoded using ASN.1 distinguished encoding rules + (DER), as specified in ITU-T X.690."; + reference + "RFC 6960: + X.509 Internet Public Key Infrastructure Online + Certificate Status Protocol - OCSP + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + + typedef oscp-response { + type binary; + description + "A OCSPResponse structure, as specified in RFC 6960, + encoded using ASN.1 distinguished encoding rules + (DER), as specified in ITU-T X.690."; + reference + "RFC 6960: + X.509 Internet Public Key Infrastructure Online + Certificate Status Protocol - OCSP + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER)."; + } + /***********************************************/ /* Typedefs for ASN.1 structures from 5652 */ /***********************************************/ @@ -1228,24 +559,6 @@ module ietf-crypto-types { "RFC 5652: Cryptographic Message Syntax (CMS)"; } - /***************************************************/ - /* Typedefs for structures related to RFC 4253 */ - /***************************************************/ - - typedef ssh-host-key { - type binary; - description - "The binary public key data for this SSH key, as - specified by RFC 4253, Section 6.6, i.e.: - - string certificate or public key format - identifier - byte[n] key/certificate data."; - reference - "RFC 4253: The Secure Shell (SSH) Transport Layer - Protocol"; - } - /*********************************************************/ /* Typedefs for ASN.1 structures related to RFC 5280 */ /*********************************************************/ @@ -1325,376 +638,368 @@ module ietf-crypto-types { and Certificate Revocation List (CRL) Profile."; } - /**********************************************/ - /* Groupings for keys and/or certificates */ - /**********************************************/ + /*****************/ + /* Groupings */ + /*****************/ + + grouping encrypted-value-grouping { + description + "A reusable grouping for a value that has been encrypted by + a referenced symmetric or asymmetric key."; + container encrypted-by { + nacm:default-deny-write; + description + "An empty container enabling a reference to the key that + encrypted the value to be augmented in. The referenced + key MUST be a symmetric key or an asymmetric key. + + A symmetric key MUST be referenced via a leaf node called + 'symmetric-key-ref'. An asymmetric key MUST be referenced + via a leaf node called 'asymmetric-key-ref'. + + The leaf nodes MUST be direct descendants in the data tree, + and MAY be direct descendants in the schema tree."; + } + leaf encrypted-value-format { + type identityref { + base encrypted-value-format; + } + mandatory true; + description + "Identifies the format of the 'encrypted-value' leaf. + + If 'encrypted-by' points to a symmetric key, then a + 'symmetrically-encrypted-value-format' based identity + MUST by set (e.g., cms-encrypted-data-format). + + If 'encrypted-by' points to an asymmetric key, then an + 'asymmetrically-encrypted-value-format' based identity + MUST by set (e.g., cms-enveloped-data-format)."; + } + leaf encrypted-value { + nacm:default-deny-write; + type binary; + must '../encrypted-by'; + mandatory true; + description + "The value, encrypted using the referenced symmetric + or asymmetric key. The value MUST be encoded using + the format associated with the 'encrypted-value-format' + leaf."; + } + } + + grouping password-grouping { + description + "A password that MAY be encrypted."; + choice password-type { + nacm:default-deny-write; + mandatory true; + description + "Choice between password types."; + case cleartext-password { + leaf cleartext-password { + nacm:default-deny-all; + type string; + description + "The cleartext value of the password."; + } + } + case encrypted-password { + if-feature "password-encryption"; + container encrypted-password { + description + "A container for the encrypted password value."; + uses encrypted-value-grouping; + } + } + } + } + + grouping symmetric-key-grouping { + description + "A symmetric key."; + leaf key-format { + nacm:default-deny-write; + type identityref { + base symmetric-key-format; + } + description + "Identifies the symmetric key's format. Implementations + SHOULD ensure that the incoming symmetric key value is + encoded in the specified format. + + For encrypted keys, the value is the same as it would + have been if the key were not encrypted."; + } + choice key-type { + nacm:default-deny-write; + mandatory true; + description + "Choice between key types."; + case cleartext-key { + leaf cleartext-key { + nacm:default-deny-all; + type binary; + must '../key-format'; + description + "The binary value of the key. The interpretation of + the value is defined by the 'key-format' field."; + } + } + case hidden-key { + if-feature "hidden-keys"; + leaf hidden-key { + type empty; + must 'not(../key-format)'; + description + "A hidden key. How such keys are created is outside + the scope of this module."; + } + } + case encrypted-key { + if-feature "symmetric-key-encryption"; + container encrypted-key { + must '../key-format'; + description + "A container for the encrypted symmetric key value. + The interpretation of the 'encrypted-value' node + is via the 'key-format' node"; + uses encrypted-value-grouping; + } + } + } + } grouping public-key-grouping { description - "A public key. - - The 'algorithm' and 'public-key' nodes are not - mandatory because they MAY be defined in . - Implementations SHOULD assert that these values are - either configured or that they exist in ."; - leaf algorithm { + "A public key."; + leaf public-key-format { nacm:default-deny-write; - type asymmetric-key-algorithm-ref; - must '../public-key'; + type identityref { + base public-key-format; + } + mandatory true; description - "Identifies the key's algorithm. More specifically, - this leaf specifies how the 'public-key' binary leaf - is encoded."; - reference - "RFC CCCC: Common YANG Data Types for Cryptography"; + "Identifies the public key's format. Implementations SHOULD + ensure that the incoming public key value is encoded in the + specified format."; } leaf public-key { nacm:default-deny-write; type binary; - must '../algorithm'; + mandatory true; description - "A binary that contains the value of the public key. The - interpretation of the content is defined by the key - algorithm. For example, a DSA key is an integer, an RSA - key is represented as RSAPublicKey as defined in - RFC 8017, and an Elliptic Curve Cryptography (ECC) key - is represented using the 'publicKey' described in - RFC 5915."; - reference - "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: - RSA Cryptography Specifications Version 2.2. - RFC 5915: Elliptic Curve Private Key Structure."; + "The binary value of the public key. The interpretation + of the value is defined by 'public-key-format' field."; } } grouping asymmetric-key-pair-grouping { description - "A private/public key pair. - The 'algorithm', 'public-key', and 'private-key' nodes are - not mandatory because they MAY be defined in . - Implementations SHOULD assert that these values are either - configured or that they exist in ."; + "A private key and its associated public key. Implementations + SHOULD ensure that the two keys are a matching pair."; uses public-key-grouping; - leaf private-key { - nacm:default-deny-all; - type union { - type binary; - type enumeration { - enum permanently-hidden { - description - "The private key is inaccessible due to being - protected by the system (e.g., a cryptographic - hardware module). - - How such keys are backed-up and restored, if - at all, is implementation specific. - - Servers MUST fail any attempt by a client to - configure this value directly. This value is - not set by clients, but rather is set by the - 'generate-hidden-key' and 'install-hidden-key' - actions."; - } - } + leaf private-key-format { + nacm:default-deny-write; + type identityref { + base private-key-format; } - must '../public-key'; description - "A binary that contains the value of the private key. The - interpretation of the content is defined by the key - algorithm. For example, a DSA key is an integer, an RSA - key is represented as RSAPrivateKey as defined in - RFC 8017, and an Elliptic Curve Cryptography (ECC) key - is represented as ECPrivateKey as defined in RFC 5915."; - reference - "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: - RSA Cryptography Specifications Version 2.2. - RFC 5915: Elliptic Curve Private Key Structure."; - } // private-key + "Identifies the private key's format. Implementations SHOULD + ensure that the incoming private key value is encoded in the + specified format. - action generate-hidden-key { - nacm:default-deny-all; + For encrypted keys, the value is the same as it would have + been if the key were not encrypted."; + } + choice private-key-type { + nacm:default-deny-write; + mandatory true; description - "Requests the device to generate a hidden key using the - specified asymmetric key algorithm. This action is - used to request the system to generate a key that is - 'permanently-hidden', perhaps protected by a cryptographic - hardware module. The resulting asymmetric key values are - considered operational state and hence present only in - and bound to the lifetime of the parent - 'config true' node. Subsequent invocations of this or - the 'install-hidden-key' action are denied with error-tag - 'data-exists'."; - input { - leaf algorithm { - type asymmetric-key-algorithm-ref; - mandatory true; - description - "The algorithm to be used when generating the - asymmetric key."; - reference - "RFC CCCC: Common YANG Data Types for Cryptography"; - } - } - } // generate-hidden-key - - action install-hidden-key { - nacm:default-deny-all; - description - "Requests the device to load the specified values into - a hidden key. The resulting asymmetric key values are - considered operational state and hence present only in - and bound to the lifetime of the parent - 'config true' node. Subsequent invocations of this - or the 'generate-hidden-key' action are denied with - error-tag 'data-exists'."; - input { - leaf algorithm { - type asymmetric-key-algorithm-ref; - mandatory true; - description - "The algorithm to be used when generating the - asymmetric key."; - reference - "RFC CCCC: Common YANG Data Types for Cryptography"; - } - leaf public-key { + "Choice between key types."; + case cleartext-private-key { + leaf cleartext-private-key { + nacm:default-deny-all; type binary; + must '../private-key-format'; description - "A binary that contains the value of the public key. - The interpretation of the content is defined by the key - algorithm. For example, a DSA key is an integer, an - RSA key is represented as RSAPublicKey as defined in - RFC 8017, and an Elliptic Curve Cryptography (ECC) key - is represented using the 'publicKey' described in - RFC 5915."; - reference - "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: - RSA Cryptography Specifications Version 2.2. - RFC 5915: Elliptic Curve Private Key Structure."; - } - leaf private-key { - type binary; - description - "A binary that contains the value of the private key. - The interpretation of the content is defined by the key - algorithm. For example, a DSA key is an integer, an RSA - key is represented as RSAPrivateKey as defined in - RFC 8017, and an Elliptic Curve Cryptography (ECC) key - is represented as ECPrivateKey as defined in RFC 5915."; - reference - "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: - RSA Cryptography Specifications Version 2.2. - RFC 5915: Elliptic Curve Private Key Structure."; + "The value of the binary key The key's value is + interpreted by the 'private-key-format' field."; } } - } // install-hidden-key - } // asymmetric-key-pair-grouping + case hidden-private-key { + if-feature "hidden-keys"; + leaf hidden-private-key { + type empty; + must 'not(../private-key-format)'; + description + "A hidden key. How such keys are created is + outside the scope of this module."; + } + } + case encrypted-private-key { + if-feature "private-key-encryption"; + container encrypted-private-key { + must '../private-key-format'; + description + "A container for the encrypted asymmetric private key + value. The interpretation of the 'encrypted-value' + node is via the 'private-key-format' node"; + uses encrypted-value-grouping; + } + } + } + } + grouping certificate-expiration-grouping { + description + "A notification for when a certificate is about to, or + already has, expired."; + notification certificate-expiration { + if-feature "certificate-expiration-notification"; + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } grouping trust-anchor-cert-grouping { description "A trust anchor certificate, and a notification for when it is about to (or already has) expire."; - leaf cert { + leaf cert-data { nacm:default-deny-write; type trust-anchor-cert-cms; description "The binary certificate data for this certificate."; - reference - "RFC YYYY: Common YANG Data Types for Cryptography"; - } - notification certificate-expiration { - description - "A notification indicating that the configured certificate - is either about to expire or has already expired. When to - send notifications is an implementation specific decision, - but it is RECOMMENDED that a notification be sent once a - month for 3 months, then once a week for four weeks, and - then once a day thereafter until the issue is resolved."; - leaf expiration-date { - type yang:date-and-time; - mandatory true; - description - "Identifies the expiration date on the certificate."; - } - } - } - - grouping trust-anchor-certs-grouping { - description - "A list of trust anchor certificates, and a notification - for when one is about to (or already has) expire."; - leaf-list cert { - nacm:default-deny-write; - type trust-anchor-cert-cms; - description - "The binary certificate data for this certificate."; - reference - "RFC YYYY: Common YANG Data Types for Cryptography"; - } - notification certificate-expiration { - description - "A notification indicating that the configured certificate - is either about to expire or has already expired. When to - send notifications is an implementation specific decision, - but it is RECOMMENDED that a notification be sent once a - month for 3 months, then once a week for four weeks, and - then once a day thereafter until the issue is resolved."; - leaf expiration-date { - type yang:date-and-time; - mandatory true; - description - "Identifies the expiration date on the certificate."; - } } + uses certificate-expiration-grouping; } grouping end-entity-cert-grouping { description "An end entity certificate, and a notification for when - it is about to (or already has) expire."; - leaf cert { + it is about to (or already has) expire. Implementations + SHOULD assert that, where used, the end entity certificate + contains the expected public key."; + leaf cert-data { nacm:default-deny-write; type end-entity-cert-cms; description "The binary certificate data for this certificate."; - reference - "RFC YYYY: Common YANG Data Types for Cryptography"; - } - notification certificate-expiration { - description - "A notification indicating that the configured certificate - is either about to expire or has already expired. When to - send notifications is an implementation specific decision, - but it is RECOMMENDED that a notification be sent once a - month for 3 months, then once a week for four weeks, and - then once a day thereafter until the issue is resolved."; - leaf expiration-date { - type yang:date-and-time; - mandatory true; - description - "Identifies the expiration date on the certificate."; - } } + uses certificate-expiration-grouping; } - grouping end-entity-certs-grouping { + grouping generate-csr-grouping { description - "A list of end entity certificates, and a notification for - when one is about to (or already has) expire."; - leaf-list cert { - nacm:default-deny-write; - type end-entity-cert-cms; - description - "The binary certificate data for this certificate."; - reference - "RFC YYYY: Common YANG Data Types for Cryptography"; - } - notification certificate-expiration { - description - "A notification indicating that the configured certificate - is either about to expire or has already expired. When to - send notifications is an implementation specific decision, - but it is RECOMMENDED that a notification be sent once a - month for 3 months, then once a week for four weeks, and - then once a day thereafter until the issue is resolved."; - leaf expiration-date { - type yang:date-and-time; - mandatory true; - description - "Identifies the expiration date on the certificate."; - } - } - } - - grouping asymmetric-key-pair-with-cert-grouping { - description - "A private/public key pair and an associated certificate."; - uses asymmetric-key-pair-grouping; - uses end-entity-cert-grouping; - - action generate-certificate-signing-request { + "Defines the 'generate-csr' action."; + action generate-csr { + if-feature "csr-generation"; nacm:default-deny-all; description "Generates a certificate signing request structure for the associated asymmetric key using the passed subject - and attribute values. The specified assertions need - to be appropriate for the certificate's use. For - example, an entity certificate for a TLS server - SHOULD have values that enable clients to satisfy - RFC 6125 processing."; + and attribute values. + + This action statement is only available when the + associated 'public-key-format' node's value is + 'subject-public-key-info-format'."; + reference + "RFC 6125: + Representation and Verification of Domain-Based + Application Service Identity within Internet Public Key + Infrastructure Using X.509 (PKIX) Certificates in the + Context of Transport Layer Security (TLS)"; input { - leaf subject { - type binary; + leaf csr-format { + type identityref { + base csr-format; + } mandatory true; description - "The 'subject' field per the CertificationRequestInfo - structure as specified by RFC 2986, Section 4.1 - encoded using the ASN.1 distinguished encoding - rules (DER), as specified in ITU-T X.690."; - reference - "RFC 2986: - PKCS #10: Certification Request Syntax - Specification Version 1.7. - ITU-T X.690: - Information technology - ASN.1 encoding rules: - Specification of Basic Encoding Rules (BER), - Canonical Encoding Rules (CER) and Distinguished - Encoding Rules (DER)."; + "Specifies the format for the returned certifiacte."; } - leaf attributes { - type binary; + leaf csr-info { + type csr-info; + mandatory true; description - "The 'attributes' field from the structure - CertificationRequestInfo as specified by RFC 2986, - Section 4.1 encoded using the ASN.1 distinguished - encoding rules (DER), as specified in ITU-T X.690."; + "A CertificationRequestInfo structure, as defined in + RFC 2986. + + Enables the client to provide a fully-populated + CertificationRequestInfo structure that the server + only needs to sign in order to generate the complete + 'CertificationRequest' structure to return in the + 'output'. + + The 'AlgorithmIdentifier' field contained inside + the 'SubjectPublicKeyInfo' field MUST be one known + to be supported by the device."; reference "RFC 2986: - PKCS #10: Certification Request Syntax - Specification Version 1.7. - ITU-T X.690: - Information technology - ASN.1 encoding rules: - Specification of Basic Encoding Rules (BER), - Canonical Encoding Rules (CER) and Distinguished - Encoding Rules (DER)."; + PKCS #10: Certification Request Syntax Specification + RFC AAAA: + YANG Data Types and Groupings for Cryptography"; } } output { - leaf certificate-signing-request { - type binary; + choice csr-type { mandatory true; description - "A CertificationRequest structure as specified by - RFC 2986, Section 4.2 encoded using the ASN.1 - distinguished encoding rules (DER), as specified - in ITU-T X.690."; - reference - "RFC 2986: - PKCS #10: Certification Request Syntax - Specification Version 1.7. - ITU-T X.690: - Information technology - ASN.1 encoding rules: - Specification of Basic Encoding Rules (BER), - Canonical Encoding Rules (CER) and Distinguished - Encoding Rules (DER)."; + "A choice amongst certificate signing request formats. + Additional formats MAY be augmented into this 'choice' + statement by future efforts."; + case p10-csr { + leaf p10-csr { + type p10-csr; + description + "A CertificationRequest, as defined in RFC 2986."; + } + description + "A CertificationRequest, as defined in RFC 2986."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax Specification + RFC AAAA: + YANG Data Types and Groupings for Cryptography"; + } } } - } // generate-certificate-signing-request - } // asymmetric-key-pair-with-cert-grouping + } + } // generate-csr-grouping + grouping asymmetric-key-pair-with-cert-grouping { + description + "A private/public key pair and an associated certificate. + Implementations SHOULD assert that certificates contain + the matching public key."; + uses asymmetric-key-pair-grouping; + uses end-entity-cert-grouping; + uses generate-csr-grouping; + } // asymmetric-key-pair-with-cert-grouping grouping asymmetric-key-pair-with-certs-grouping { description - "A private/public key pair and associated certificates."; + "A private/public key pair and associated certificates. + Implementations SHOULD assert that certificates contain + the matching public key."; uses asymmetric-key-pair-grouping; container certificates { nacm:default-deny-write; description - "Certificates associated with this asymmetric key. - More than one certificate supports, for instance, - a TPM-protected asymmetric key that has both IDevID - and LDevID certificates associated."; + "Certificates associated with this asymmetric key."; list certificate { key "name"; description @@ -1702,82 +1007,16 @@ module ietf-crypto-types { leaf name { type string; description - "An arbitrary name for the certificate. If the name - matches the name of a certificate that exists - independently in (i.e., an IDevID), - then the 'cert' node MUST NOT be configured."; + "An arbitrary name for the certificate."; } - uses end-entity-cert-grouping; - } - } // certificates - - action generate-certificate-signing-request { - nacm:default-deny-all; - description - "Generates a certificate signing request structure for - the associated asymmetric key using the passed subject - and attribute values. The specified assertions need - to be appropriate for the certificate's use. For - example, an entity certificate for a TLS server - SHOULD have values that enable clients to satisfy - RFC 6125 processing."; - input { - leaf subject { - type binary; - mandatory true; - description - "The 'subject' field per the CertificationRequestInfo - structure as specified by RFC 2986, Section 4.1 - encoded using the ASN.1 distinguished encoding - rules (DER), as specified in ITU-T X.690."; - reference - "RFC 2986: - PKCS #10: Certification Request Syntax - Specification Version 1.7. - ITU-T X.690: - Information technology - ASN.1 encoding rules: - Specification of Basic Encoding Rules (BER), - Canonical Encoding Rules (CER) and Distinguished - Encoding Rules (DER)."; - } - leaf attributes { - type binary; - description - "The 'attributes' field from the structure - CertificationRequestInfo as specified by RFC 2986, - Section 4.1 encoded using the ASN.1 distinguished - encoding rules (DER), as specified in ITU-T X.690."; - reference - "RFC 2986: - PKCS #10: Certification Request Syntax - Specification Version 1.7. - ITU-T X.690: - Information technology - ASN.1 encoding rules: - Specification of Basic Encoding Rules (BER), - Canonical Encoding Rules (CER) and Distinguished - Encoding Rules (DER)."; + uses end-entity-cert-grouping { + refine "cert-data" { + mandatory true; + } } } - output { - leaf certificate-signing-request { - type binary; - mandatory true; - description - "A CertificationRequest structure as specified by - RFC 2986, Section 4.2 encoded using the ASN.1 - distinguished encoding rules (DER), as specified - in ITU-T X.690."; - reference - "RFC 2986: - PKCS #10: Certification Request Syntax - Specification Version 1.7. - ITU-T X.690: - Information technology - ASN.1 encoding rules: - Specification of Basic Encoding Rules (BER), - Canonical Encoding Rules (CER) and Distinguished - Encoding Rules (DER)."; - } - } - } // generate-certificate-signing-request + } + uses generate-csr-grouping; } // asymmetric-key-pair-with-certs-grouping + } diff --git a/radio/fhi_72/mplane/yang/models/o-ran-common-yang-types.yang b/radio/fhi_72/mplane/yang/models/o-ran-common-yang-types.yang new file mode 100644 index 0000000000..4fa9d7f542 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/o-ran-common-yang-types.yang @@ -0,0 +1,449 @@ +module o-ran-common-yang-types { + yang-version 1.1; + namespace "urn:o-ran:common-yang-types:1.0"; + prefix "o-ran-types"; + + import ietf-inet-types { + prefix inet; + } + + organization "O-RAN Alliance"; + + + + contact + "www.o-ran.org"; + + description + "This module defines ORAN common YANG types. + + Copyright 2023 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2023-08-14" { + description + "version 2.0.0 + + 1) New availability status typedef"; + + reference "ORAN-WG1.IM.0-v01.00"; + } + + revision "2022-08-15" { + description + "version 1.1.0 + + 1) style guide corrections"; + + reference "ORAN-WG1.IM.0-v01.00"; + } + + revision "2020-10-10" { + description + "version 1.0.0 + + 1) Initial creation"; + + reference "ORAN-WG1.IM.0-v01.00"; + } + + typedef version { + type string { + pattern '[0-9]+(\.[0-9]+){1,2}'; + } + description + "Definition used to represent a version of an interface."; + } + + typedef timezone-name { + type string; + description + "A time zone name as used by the Time Zone Database, + sometimes referred to as the 'Olson Database'. + + The complete set of valid values is defined in + https://www.iana.org/time-zones. + + The exact set of supported values is an + implementation-specific matter."; + + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database + IANA Time Zone Database https://www.iana.org/time-zones "; + } + + typedef protocol { + type enumeration { + enum ECPRI { + description + "Indicates that an O-RU supports the ecpri header format + for the C/U plane"; + } + enum IEEE-1914-3 { + description + "Indicates that an O-RU supports the 1914.3 header format + for the C/U plane"; + } + } + description "the type of C/U plane protocol"; + } + + typedef duplex-scheme { + type enumeration { + enum TDD { + description + "TDD scheme"; + } + enum FDD { + description + "FDD scheme"; + } + } + description + "Type of duplex scheme O-RU supports."; + } + + typedef active { + type enumeration { + enum INACTIVE { + description + "Carrier does not provide signal - transmission is disabled"; + } + enum SLEEP{ + description + "Carrier is fully configured and was active but is energy saving mode"; + } + enum ACTIVE{ + description + "Carrier is fully configured and properly providing the signal"; + } + } + description "the active status of a carrier"; + } + + typedef state { + type enumeration { + enum DISABLED { + description + "Array carrier is not active - transmission of signal is disabled."; + } + enum BUSY { + description + "Array carrier is processing an operation requested by change of active parameter. + When array carriers is BUSY the transmission of signal is not guaranteed."; + } + enum READY { + description + "Array carrier had completed activation operation - is active and transmission of signal is ongoing."; + } + } + description "the state on an array carrier"; + } + + typedef transport-session { + type enumeration { + enum ETHERNET { + description "VLAN based CUS Transport "; + } + enum UDP_IP { +// if-feature o-ran-int:UDPIP-BASED-CU-PLANE; How to handle enum value constrained by feature defined in o-ran-interface.yang? + description "UDP/IP based CUS Transport "; + } + enum ALIAS_MAC{ +// if-feature o-ran-int:ALIASMAC-BASED-CU-PLANE; How to handle enum value constrained by feature defined in o-ran-interface.yang? + description "Alias MAC address based CUS Transport "; + } + enum SHARED_CELL { +// if-feature o-ran-elements:SHARED_CELL; How to handle enum value constrained by feature defined in o-ran-processing-element.yang? + description "VLAN based CUS Transport used for Shared Cell scenario"; + } + } + description "the transport session type"; + } + + typedef netconf-client-id { + type union { + type inet:ip-address; + type inet:uri; + } + description "A NETCONF client identifier"; + } + + typedef ca-ra-server-id { + type union { + type inet:ip-address; + type inet:uri; + } + description "A CA/RA Server identifier"; + } + + typedef segw-id { + type union { + type inet:ip-address; + type inet:uri; + } + description "A SeGW identifier"; + } + + typedef pcp { + type uint8 { + range "0..7"; + } + description + "Priority Code Point. PCP is a 3-bit field that refers to the + class of service applied to a VLAN tagged frame. The + field specifies a priority value between 0 and 7, these values + can be used by quality of service (QoS) to prioritize + different classes of traffic."; + reference + "IEEE 802.1Q-2014: Virtual Bridged Local Area Networks"; + } + + typedef vlan-id { + type uint16 { + range "1..4094"; + } + description + "The VLAN-ID that uniquely identifies a VLAN. This is the 12-bit VLAN-ID + used in the VLAN Tag header."; + reference "[802.1q] 9.6"; + } + + typedef geographic-coordinate-degree { + type decimal64 { + fraction-digits 8; + } + description + "Decimal degree (DD) used to express latitude and longitude + geographic coordinates."; + } + + typedef prach-preamble-format { + type enumeration { + enum LTE-0 { + description + "LTE PRACH Preamble format 0"; + } + enum LTE-1 { + description + "LTE PRACH Preamble format 1"; + } + enum LTE-2 { + description + "LTE PRACH Preamble format 2"; + } + enum LTE-3 { + description + "LTE PRACH Preamble format 3"; + } + enum LTE-4 { + description + "LTE PRACH Preamble format 4"; + } + enum LTE-NB0 { + description + "LTE Narrowband PRACH format 0"; + } + enum LTE-NB1 { + description + "LTE Narrowband PRACH format 1"; + } + enum NR-0 { + description + "5GNR PRACH Preamble format 0"; + } + enum NR-1 { + description + "5GNR PRACH Preamble format 1"; + } + enum NR-2 { + description + "5GNR PRACH Preamble format 2"; + } + enum NR-3 { + description + "5GNR PRACH Preamble format 3"; + } + enum NR-A1 { + description + "5GNR PRACH Preamble format A1"; + } + enum NR-A2 { + description + "5GNR PRACH Preamble format A2"; + } + enum NR-A3 { + description + "5GNR PRACH Preamble format A3"; + } + enum NR-B1 { + description + "5GNR PRACH Preamble format B1"; + } + enum NR-B2 { + description + "5GNR PRACH Preamble format B2"; + } + enum NR-B3 { + description + "5GNR PRACH Preamble format B3"; + } + enum NR-B4 { + description + "5GNR PRACH Preamble format B4"; + } + enum NR-C0 { + description + "5GNR PRACH Preamble format C0"; + } + enum NR-C2 { + description + "5GNR PRACH Preamble format C2"; + } + enum LTE-NB0-a { + description + "LTE Narrowband PRACH format 0-a"; + } + enum LTE-NB1-a { + description + "LTE Narrowband PRACH format 1-a"; + } + enum LTE-NB2 { + description + "LTE Narrowband PRACH format 2"; + } + } + + description + "PRACH preamble format definition"; + } + + typedef polarisation_type { + type enumeration { + enum MINUS_45 { + description "MINUS_45"; + } + enum ZERO { + description "ZERO"; + } + enum PLUS_45 { + description "PLUS_45"; + } + enum PLUS_90 { + description "PLUS_90"; + } + } + description "Type definition for polarisations"; + } + + typedef bandwidth { + type uint32 { + range "200 | 1400 | 3000 | 5000 | 10000 | 15000 | 20000 | 25000 | + 30000 | 40000 | 50000 | 60000 | 70000 | 80000 | 90000 | 100000 + | 200000 | 400000" ; + } + units kilohertz; + description + "transmission bandwidth configuration in units of kHz - + covering NBIoT through to New Radio - see 38.104"; + } + + typedef scs-config-type { + type enumeration { + enum KHZ_15 { + value 0; + description + "15kHz sub carrier spacing"; + } + enum KHZ_30 { + value 1; + description + "30kHz sub carrier spacing"; + } + enum KHZ_60 { + value 2; + description + "60kHz sub carrier spacing"; + } + enum KHZ_120 { + value 3; + description + "120kHz sub carrier spacing"; + } + enum KHZ_240 { + value 4; + description + "240kHz sub carrier spacing"; + } + enum KHZ_1_25 { + value 12; + description + "1,25kHz sub carrier spacing"; + } + enum KHZ_3_75 { + value 13; + description + "3.75kHz sub carrier spacing"; + } + enum KHZ_5 { + value 14; + description + "5kHz sub carrier spacing"; + } + enum KHZ_7_5 { + value 15; + description + "7.5kHz sub carrier spacing"; + } + } + + description + "Scs configuration type definition"; + } + + typedef availability-status { + type union { + type empty; + type enumeration { + enum FAILED { + description + "The resource has an internal fault that prevents it from operating. + The operational state is disabled."; + } + enum DEPENDENCY { + description + "The resource cannot operate because some other resource on which it + depends is unavailable. The operational state is disabled."; + } + } + } + description + "When the value of this attribute is empty set, this implies that none of + the status conditions described in the enumerations are present. Only current relevant status for M-plane defined are listed here"; + reference "CCITT Rec. X.731 (1992 E) 8.1.2.3"; + } + +} diff --git a/radio/fhi_72/mplane/yang/models/o-ran-compression-factors.yang b/radio/fhi_72/mplane/yang/models/o-ran-compression-factors.yang index 5816b5ed63..ffccbcd126 100644 --- a/radio/fhi_72/mplane/yang/models/o-ran-compression-factors.yang +++ b/radio/fhi_72/mplane/yang/models/o-ran-compression-factors.yang @@ -13,7 +13,7 @@ module o-ran-compression-factors { "This module defines the module capabilities for the O-RAN Radio Unit U-Plane configuration. - Copyright 2020 the O-RAN Alliance. + Copyright 2024 the O-RAN Alliance. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -39,6 +39,46 @@ module o-ran-compression-factors { contributors may be used to endorse or promote products derived from this software without specific prior written permission."; + revision "2024-08-12" { + description + "version 16.0.0 + + 1) Clarify handling of deprecated leaf compression-format. + 2) Add in SINR compression details"; + + reference "ORAN-WG4.M.0-v16.00"; + } + + revision "2023-08-14" { + description + "version 13.0.0 + + 1) New compression methods BFP-SRES-MASK-IN-SEC-HEADER and MOD-SRES-MASK-IN-SEC-HEADER."; + + reference "ORAN-WG4.M.0-v13.00"; + } + + revision "2021-12-01" { + description + "version 8.0.0 + + 1) typographical corrections in descriptions. + 2) Configuration for Beamforming weights were added together with changes + and updates to compressions. + 3) add new beamspace compression enumeration for BEAMSPACE_TYPEII."; + + reference "ORAN-WG4.M.0-v08.00"; + } + + revision "2021-03-22" { + description + "version 4.1.0 + + 1) typographical corrections in descriptions."; + + reference "ORAN-WG4.M.0-v04.00"; + } + revision "2020-08-10" { description "version 4.0.0 @@ -62,7 +102,7 @@ module o-ran-compression-factors { description "version 1.1.0 - 1) changes related to compression bitwidth presentation"; + 1) changes related to compression bit-width presentation"; reference "ORAN-WG4.M.0-v01.00"; } @@ -82,6 +122,171 @@ module o-ran-compression-factors { "Presence of this feature means that O-RU supports configurable fs-offset for compression."; } + typedef ci-compression-method-def { + type enumeration { + enum NO_COMPRESSION { + description + "No compression will be used"; + } + + enum BLOCK_FLOATING_POINT { + description + "Block floating point compression and decompression will be used"; + } + + enum BLOCK_SCALING { + description + "Block scaling compression and decompresion will be used"; + } + + enum U_LAW { + description + "u-Law compression and decompresion method will be used"; + } + } + description + "Available compression methods for channel information (e.g., ST6)."; + } + + typedef compression-type-def { + type enumeration { + enum STATIC { + description + "Indicates that static compression method will be used (both compression and IQ bitwidth)"; + } + enum DYNAMIC { + description + "Indicates that dynamic compression method will be used"; + } + } + description + "Compression type that O-DU wants to be supported"; + } + + typedef bf-compression-method-def { + type enumeration { + enum NO_COMPRESSION { + description + "No compression will be used"; + } + enum BLOCK_FLOATING_POINT { + description + "Block floating point compression and decompression will be used"; + } + + enum BLOCK_SCALING { + description + "Block scaling compression and decompresion will be used"; + } + + enum U_LAW { + description + "u-Law compression and decompresion method will be used"; + } + + enum BEAMSPACE { + description + "Beamspace compression and decompression will be used"; + } + + enum VOID_1 { + description + "Leftover of modulation, not to be used for beamforming weights"; + } + + enum VOID_2 { + description + "Leftover of block-floating-point-selective-re-sending, not to be used for beamforming weights"; + } + + enum VOID_3 { + description + "Leftover of modulation-compression-selective-re-sending, not to be used for beamforming weights"; + } + + enum BEAMSPACE_TYPEII { + description + "Beamspace compression typeII and decompression will be used "; + } + } + description + "Available compression methods for beamforming weights."; + } + + typedef compression-method-def { + type enumeration { + enum NO_COMPRESSION { + description + "No compression"; + } + enum BLOCK_FLOATING_POINT { + description + "Block floating point compression and decompression method"; + } + + enum BLOCK_SCALING { + description + "Block scaling compression and decompresion method"; + } + + enum U_LAW { + description + "u-Law compression and decompresion method"; + } + + enum VOID_1 { + description + "Leftover of beamspace, not to be used for IQ data."; + } + + enum MODULATION { + description + "Modulation compression and decompression method"; + } + + enum BLOCK-FLOATING-POINT-SELECTIVE-RE-SENDING { + description + "block floating point with selective re sending + compression and decompression method"; + } + + enum MODULATION-COMPRESSION-SELECTIVE-RE-SENDING { + description + "modulation compression with selective re sending + compression and decompression method"; + } + enum BFP-SRES-MASK-IN-SEC-HEADER { + description + "block floating point with selective re sending + compression and decompression method with selective re sending mask in the section header "; + } + + enum MOD-SRES-MASK-IN-SEC-HEADER { + description + "modulation compression with selective re sending + compression and decompression method with selective re sending mask in the section header"; + } + } + description + "Available compression methods for the data."; + } + + typedef sinr-compression-method-def { + type enumeration { + enum BLOCK_FLOATING_POINT { + description + "Block floating point compression and decompression will be used"; + } + + enum NO_COMPRESSION { + description + "No compression will be used"; + } + } + description + "Available compression methods for the SINR."; + } + grouping compression-method-grouping { description "Grouping for compression method."; @@ -89,68 +294,148 @@ module o-ran-compression-factors { leaf iq-bitwidth { type uint8; description - "Bitwidth to be used in compression"; + "Bit-width to be used in compression"; } leaf compression-method { - type enumeration { - enum NO_COMPRESSION { - description - "No compression will be used"; - } - enum BLOCK_FLOATING_POINT { - description - "Block floating point compression and decompression will be used"; - } - - enum BLOCK_SCALING { - description - "Block scaling compression and decompresion will be used"; - } - - enum U_LAW { - description - "u-Law compression and decompresion method will be used"; - } - - enum BEAMSPACE { - description - "Beamspace compression and decompression will be used"; - } - - enum MODULATION { - description - "Modulation compression and decompression will be used"; - } - enum BLOCK-FLOATING-POINT-SELECTIVE-RE-SENDING { - description - "block floating point with selective re sending - compression and decompression will be used"; - } - enum MODULATION-COMPRESSION-SELECTIVE-RE-SENDING { - description - "modulation compression with selective re sending - compression and decompression will be used"; - } - } + type compression-method-def; description - "Compresion method which can be supported by the O-RU"; + "Compression method which can be supported by the O-RU"; } } + grouping compression-details { + description ""; + + leaf iq-bitwidth { + type uint8; + description + "Bitwidth to be used in compression"; + } + + leaf compression-type { + type compression-type-def; + mandatory true; + description + "Compression type that O-DU wants to be supported"; + } + + leaf bitwidth { + when "../compression-type = 'STATIC'"; + type uint8; + status deprecated; + description + "Bitwidth to be used in compression. + This has since been replaced in M-Plane version + 2.0.0 with the iq-bitwidth schema node"; + } + + leaf compression-method { + type compression-method-def; + description + "Compression method which can be supported by the O-RU"; + } + + uses compresion-format-grp { + status deprecated; + } + } + + grouping bf-compression-details { + description "Compression formats defined for beamforming"; + + leaf iq-bitwidth { + type uint8; + description + "Bitwidth to be used in compression"; + } + + leaf compression-type { + type compression-type-def; + mandatory true; + description + "Compression type that O-DU wants to be supported"; + } + + leaf bitwidth { + when "../compression-type = 'STATIC'"; + type uint8; + status deprecated; + description + "Bitwidth to be used in compression. + This has since been replaced in M-Plane version + 2.0.0 with the iq-bitwidth schema node"; + } + + leaf compression-method { + type bf-compression-method-def; + description + "Compression method which can be supported by the beamforming"; + } + + uses compresion-format-grp { + status deprecated; + } + } + + grouping sinr-compression-details { + description "Compression formats defined for SINR"; + + leaf sinr-bitwidth { + type uint8; + description + "Bitwidth to be used in compression"; + } + + leaf sinr-compression-method { + type sinr-compression-method-def; + description + "Compression method which can be supported by the SINR."; + } + + leaf sinr-block-size { + type uint8; + description + "Block size used for reporting SINR. + If the parameter is absent, then the SINR values are sent without zero-padding + i.e., the block size is equal to the number of SINR values + + Please refer to CUS specification clause 7.2.10 for more details."; + } + } + +// *********** Deprecated *********** + grouping compression-formats { + status deprecated; description - "Grouping deicated to list compression formats as choice"; + "Grouping deicated to list compression formats as choice."; + + uses compresion-format-grp { + status deprecated; + } + } + + grouping compresion-format-grp { + status deprecated; + description + "Grouping to for compression format choice"; choice compression-format { + status deprecated; description - "Choice of compression format for particular element"; + "Choice of compression format for particular element. + Note: This method is deprecated. All should be done as emumeration as details are configured + by udCompHdr in CU-Plane messaging. + NOTE: Changing the configuration from any compression format to no compression would require + a delete-config followed by an edit-config"; case no-compresison { description "Compression for beam weights is not supported."; } + case block-floating-point { - description "Block floating point compression and decompression is supported."; + description "Block floating-point compression and decompression is supported."; leaf exponent { type uint8 { @@ -162,7 +447,7 @@ module o-ran-compression-factors { case block-floating-point-selective-re-sending { description - "Block floating point with selective re sending compression and decompression is supported."; + "Block floating-point with selective re sending compression and decompression is supported."; leaf sres-exponent { type uint8 { @@ -173,7 +458,7 @@ module o-ran-compression-factors { } case block-scaling { - description "Block scaling compression and decompresion is supported."; + description "Block scaling compression and decompression is supported."; leaf block-scalar { type uint8; description @@ -182,7 +467,7 @@ module o-ran-compression-factors { } case u-law { - description "u-Law compression and decompresion method is supported."; + description "u-Law compression and decompression method is supported."; leaf comp-bit-width { type uint8 { range "0..15"; @@ -218,7 +503,7 @@ module o-ran-compression-factors { type uint8 { range "0..1"; } - description "Constallation shift flag"; + description "Constellation shift flag"; } leaf mod-comp-scaler { @@ -235,7 +520,7 @@ module o-ran-compression-factors { type uint8 { range "0..1"; } - description "Constallation shift flag"; + description "Constellation shift flag"; } leaf sres-mod-comp-scaler { @@ -250,54 +535,50 @@ module o-ran-compression-factors { } grouping compression-params { + status deprecated; description "Parameters to define compression"; leaf compression-type { - type enumeration { - enum STATIC { - description - "Indicates that static compression method will be used (both compression and IQ bitwidth)"; - } - enum DYNAMIC { - description - "Indicates that dynamic compression method will be used"; - } - } + type compression-type-def; mandatory true; description "Compression type that O-DU wants to be supported"; } -// *********** TO BE REMOVED *********** leaf bitwidth { when "../compression-type = 'STATIC'"; type uint8; status deprecated; description - "Bitwidth to be used in compression. + "Bit-width to be used in compression. This has since been replaced in M-Plane version 2.0.0 with the iq-bitwidth schema node"; } -// ************************************* - uses compression-formats; + uses compression-formats { + status deprecated; + } } grouping compression-parameters { + status deprecated; description "Parameters used to define description type"; leaf iq-bitwidth { type uint8; description - "Bitwidth to be used in compression"; + "Bit-width to be used in compression"; } - uses compression-formats; + uses compression-formats { + status deprecated; + } } grouping format-of-iq-sample { + status deprecated; description "Indicates module capabilities about IQ samples"; @@ -312,17 +593,20 @@ module o-ran-compression-factors { type boolean; description - "Informs if O-RU supports realtime variable bit with"; + "Informs if O-RU supports real-time variable bit with"; } list compression-method-supported { - uses compression-parameters; + status deprecated; + uses compression-parameters { + status deprecated; + } description "List of supported compression methods by O-RU Note: if O-RU supports different compression methods per endpoint then please refer do endpoints to have information what - exactly is supported on a paticular endpoint"; + exactly is supported on a particular endpoint"; } leaf syminc-supported { @@ -353,16 +637,6 @@ module o-ran-compression-factors { } } +// *********** Deprecated End *********** - grouping compression-details { - description ""; - - leaf iq-bitwidth { - type uint8; - description - "Bitwidth to be used in compression"; - } - - uses compression-params; - } } diff --git a/radio/fhi_72/mplane/yang/models/o-ran-delay-management.yang b/radio/fhi_72/mplane/yang/models/o-ran-delay-management.yang new file mode 100644 index 0000000000..339398c2e1 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/o-ran-delay-management.yang @@ -0,0 +1,591 @@ +module o-ran-delay-management { + yang-version 1.1; + namespace "urn:o-ran:delay:1.0"; + prefix "o-ran-delay"; + + import o-ran-wg4-features { + prefix "feat"; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module covers off aspects of O-DU to O-RU delay management, + including configuration data related to O-RU transmission and reception + windows. + + Copyright 2024 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2024-08-12" { + description + "version 16.0.0 + + 1) Removing the range to align bandwidth type to same bandwidth type as + in uplane-config module and module-cap modules. + 2) Add in Ta3-2g data processing delay"; + + reference "ORAN-WG4.M.0-v16.00"; + } + + revision "2024-04-15" { + description + "version 15.0.0 + + 1) add support for for beamforming list and delay profiles(s) per endpoint."; + + reference "ORAN-WG4.M.0-v15.00"; + } + + revision "2022-08-15" { + description + "version 10.0.0 + + 1) introducing new feature for ACK NACK feedback."; + + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2021-12-01" { + description + "version 8.0.0 + + 1) typographical corrections in descriptions. + 2) add new schema node beam-context-gap-period."; + + reference "ORAN-WG4.M.0-v08.00"; + } + + revision "2020-08-10" { + description + "version 4.0.0 + + 1) introduction of new t1a-max-cp-dl leaf to enable decoupled timing between C- and U-Plane"; + + reference "ORAN-WG4.M.0-v04.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) fixing descriptions of ta3-min and ta3-max. + 2) introducing grouping/uses to enable model re-use by WG5"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + + feature ADAPTIVE-RU-PROFILE { + description + "This feature indicates that the O-RU supports adaptive O-RU delay profile + based on information provided by the NETCONF client."; + } + + typedef bandwidth { + type uint32; + units kilohertz; + description + "transmission bandwidth configuration in units of kHz - + covering NB-IoT through to New Radio. + Value shall correspond to a value defined in 38.104."; + } + + grouping bandwidth-configuration { + description + "Grouping for bandwidth and SCS configuration"; + + leaf bandwidth { + type bandwidth; + description + "transmission bandwidth configuration in units of kHz - + covering NBIoT through to New Radio - see 38.104"; + } + leaf subcarrier-spacing { + type uint32 { + range "0 .. 240000 "; + } + units Hertz; + description "sub-carrier spacing in Hz"; + } + } + + grouping t2a-up { + description + "configuration of t2a for uplink"; + + leaf t2a-min-up { + type uint32; + units nanoseconds; + mandatory true; + description + "the minimum O-RU data processing delay between receiving IQ data + message over the fronthaul interface and transmitting + the corresponding first IQ sample at the antenna"; + } + leaf t2a-max-up { + type uint32; + units nanoseconds; + mandatory true; + description + "the earliest allowable time when a data packet is received before + the corresponding first IQ sample is transmitted at the antenna"; + } + } + + grouping t2a-cp-dl { + description + "Grouping for t2a CP for downlink"; + + leaf t2a-min-cp-dl { + type uint32; + units nanoseconds; + mandatory true; + description + "the minimum O-RU data processing delay between receiving downlink + real time control plane message over the fronthaul interface and + transmitting the corresponding first IQ sample at the antenna"; + } + leaf t2a-max-cp-dl { + type uint32; + units nanoseconds; + mandatory true; + description + "the earliest allowable time when a downlink real time control message + is received before the corresponding first IQ sample is transmitted at + the antenna"; + } + } + + grouping ta3 { + description + "Grouping for ta3 configuration"; + + leaf ta3-min { + type uint32; + units nanoseconds; + mandatory true; + description + "the minimum O-RU data processing delay between receiving an IQ sample + at the antenna and transmitting the first data sample over the + fronthaul interface"; + } + leaf ta3-max { + type uint32; + units nanoseconds; + mandatory true; + description + "the maximum O-RU data processing delay between receiving an IQ sample + at the antenna and transmitting the last data sample over the + fronthaul interface"; + } + } + + grouping t2a-cp-ul { + description + "Grouping for t2a CP uplink"; + + leaf t2a-min-cp-ul { + type uint32; + units nanoseconds; + mandatory true; + description + "the minimum O-RU data processing delay between receiving real time + up-link control plane message over the fronthaul interface and + receiving the first IQ sample at the antenna"; + } + leaf t2a-max-cp-ul { + type uint32; + units nanoseconds; + mandatory true; + description + "the earliest allowable time when a real time up-link control message + is received before the corresponding first IQ sample is received at + the antenna"; + } + } + + grouping ta3-ack { + description + "Grouping for ta3-ack configuration"; + leaf ta3-min-ack { + type int32; + units nanoseconds; + description + "the minimum delay between the DL/UL air reference point (tDL=0 or tUL=0) of symbol M + and the time O-RU sends section type 8 (ACK/NACK feedback) to O-DU. + This value can be negative, which indicates it is in advance of the air reference point. + This leaf only exists if section extension 22 (ACK/NACK request) and section type 8 (ACK/NACK feedback) + are supported by at least one endpoint."; + } + + leaf ta3-max-ack { + type int32; + units nanoseconds; + description + "the maximum delay between the DL/UL air reference point (tDL=0 or tUL=0) of symbol M + and the time O-RU sends section type 8 (ACK/NACK feedback) to O-DU. + This value can be negative, which indicates it is in advance of the air reference point. + This leaf only exists if section extension 22 (ACK/NACK request) and section type 8 (ACK/NACK feedback) + are supported by at least one endpoint."; + } + } + + grouping ta3-2g { + description + "Grouping for ta3-2g configuration"; + + leaf ta3-min-2g { + if-feature feat:RRM-MEAS-REPORTING; + type uint32; + units nanoseconds; + description + "The minimum O-RU data processing delay between receiving an IQ sample + at the antenna and transmitting a C-Plane message carrying RRM measurements + over the fronthaul interface. + + Please refer to CUS specification clause 4.4.3 for more details."; + } + leaf ta3-max-2g { + if-feature feat:RRM-MEAS-REPORTING; + type uint32; + units nanoseconds; + description + "The maximum O-RU data processing delay between receiving an IQ sample + at the antenna and transmitting a C-Plane message carrying RRM measurements + over the fronthaul interface. + + Please refer to CUS specification clause 4.4.3 for more details."; + } + } + + grouping ru-delay-profile { + description + "Grouping for RU delay profile"; + + uses t2a-up; + uses t2a-cp-dl; + + leaf tcp-adv-dl { + type uint32; + units nanoseconds; + mandatory true; + description + "the time difference (advance) between the reception window for + downlink real time Control messages and reception window for the + corresponding IQ data messages."; + } + + uses ta3; + uses t2a-cp-ul; + uses ta3-ack; + uses ta3-2g; + } + + grouping o-du-delay-profile { + description + "Grouping for O-DU delay profile"; + + leaf t1a-max-up { + type uint32; + units nanoseconds; + description + "the earliest possible time which the O-DU can support transmitting + an IQ data message prior to transmission of the corresponding IQ + samples at the antenna"; + } + leaf tx-max { + type uint32; + units nanoseconds; + description + "The maximum amount of time which the O-DU requires to transmit + all downlink user plane IQ data message for a symbol"; + } + leaf ta4-max { + type uint32; + units nanoseconds; + description + "the latest possible time which the O-DU can support receiving the + last uplink user plane IQ data message for a symbol."; + } + leaf rx-max { + type uint32; + units nanoseconds; + description + "The maximum time difference the O-DU can support between + receiving the first user plane IQ data message for a symbol and + receiving the last user plane IQ data message for the same symbol"; + } + leaf t1a-max-cp-dl { + type uint32; + units nanoseconds; + description + "The earliest possible time which the O-DU can support transmitting the + downlink real time control message prior to transmission of the + corresponding IQ samples at the antenna."; + } + } + + grouping t12 { + description + "Grouping for t12"; + + leaf t12-min { + type uint32; + units nanoseconds; + description + "the minimum measured delay between DU port-ID and O-RU port-ID"; + } +// additional leaf added by Samsung + leaf t12-max { + type uint32; + units nanoseconds; + description + "the maximum measured delay between CU port-ID and O-RU port-ID"; + } + } + + grouping t34 { + description + "Grouping for t34"; + + leaf t34-min { + type uint32; + units nanoseconds; + description + "the minimum measured delay between O-RU port-ID and CU port-ID"; + } +// additional leaf added by Samsung + leaf t34-max { + type uint32; + units nanoseconds; + description + "the maximum measured delay between O-RU port-ID and CU port-ID"; + } + } + + grouping non-default-ru-delay-profile { + description + "Grouping for O-RU delay profile different from the default value in ru-delay-profile."; + leaf t2a-min-up { + type uint32; + units nanoseconds; + description + "the minimum O-RU data processing delay between receiving IQ data + message over the fronthaul interface and transmitting + the corresponding first IQ sample at the antenna"; + } + leaf t2a-max-up { + type uint32; + units nanoseconds; + description + "the earliest allowable time when a data packet is received before + the corresponding first IQ sample is transmitted at the antenna"; + } + leaf t2a-min-cp-dl { + type uint32; + units nanoseconds; + description + "the minimum O-RU data processing delay between receiving downlink + real time control plane message over the fronthaul interface and + transmitting the corresponding first IQ sample at the antenna"; + } + leaf t2a-max-cp-dl { + type uint32; + units nanoseconds; + description + "the earliest allowable time when a downlink real time control message + is received before the corresponding first IQ sample is transmitted at + the antenna"; + } + leaf tcp-adv-dl { + type uint32; + units nanoseconds; + description + "the time difference (advance) between the reception window for + downlink real time Control messages and reception window for the + corresponding IQ data messages."; + } + leaf ta3-min { + type uint32; + units nanoseconds; + description + "the minimum O-RU data processing delay between receiving an IQ sample + at the antenna and transmitting the first data sample over the + fronthaul interface"; + } + leaf ta3-max { + type uint32; + units nanoseconds; + description + "the maximum O-RU data processing delay between receiving an IQ sample + at the antenna and transmitting the last data sample over the + fronthaul interface"; + } + leaf t2a-min-cp-ul { + type uint32; + units nanoseconds; + description + "the minimum O-RU data processing delay between receiving real time + up-link control plane message over the fronthaul interface and + receiving the first IQ sample at the antenna"; + } + leaf t2a-max-cp-ul { + type uint32; + units nanoseconds; + description + "the earliest allowable time when a real time up-link control message + is received before the corresponding first IQ sample is received at + the antenna"; + } + leaf ta3-min-ack { + type int32; + units nanoseconds; + description + "the minimum delay between the DL/UL air reference point (tDL=0 or tUL=0) of symbol M + and the time O-RU sends section type 8 (ACK/NACK feedback) to O-DU. + This value can be negative, which indicates it is in advance of the air reference point. + This leaf only exists if section extension 22 (ACK/NACK request) and section type 8 (ACK/NACK feedback) + are supported by at least one endpoint."; + } + leaf ta3-max-ack { + type int32; + units nanoseconds; + description + "the maximum delay between the DL/UL air reference point (tDL=0 or tUL=0) of symbol M + and the time O-RU sends section type 8 (ACK/NACK feedback) to O-DU. + This value can be negative, which indicates it is in advance of the air reference point. + This leaf only exists if section extension 22 (ACK/NACK request) and section type 8 (ACK/NACK feedback) + are supported by at least one endpoint."; + } + + uses ta3-2g; + } + + grouping delay-management-group { + description "a delay management grouping"; + list bandwidth-scs-delay-state { + key "bandwidth subcarrier-spacing"; + description + "Array of structures containing sets of parameters for delay management."; + + uses bandwidth-configuration; + + container ru-delay-profile { + config false; + description "container for O-RU delay parameters"; + + uses ru-delay-profile; + } + } + + list non-default-ru-delay-profile { + if-feature feat:BF-DELAY-PROFILE; + key "delay-profile-id"; + description + "Sets of parameters defined when o-ru supported multiple delay profiles, + only the parameters that are different from the default delay profile are defined."; + leaf delay-profile-id { + type uint16 { + range "1..max"; + } + description + "Used to identify the set of delay profile that are different from the default delay profile. + Value '0' is reserved to refer to default value"; + } + list non-default-bandwidth-scs-delay-state { + key "bandwidth subcarrier-spacing"; + description + "Array of structures containing sets of parameters for delay management."; + uses bandwidth-configuration; + container non-default-ru-delay-profile { + config false; + description + "O-RU delay parameters that are different from the default delay profile. + If a parameter doesn't exist, this parameter will use the defalt value determined in ru-delay-profile."; + uses non-default-ru-delay-profile; + } + } + } + + container adaptive-delay-configuration { + if-feature ADAPTIVE-RU-PROFILE; + description "container for adaptive delay parameters"; + list bandwidth-scs-delay-state { + key "bandwidth subcarrier-spacing"; + description + "Array of structures containing sets of parameters for delay management."; + + uses bandwidth-configuration; + + container o-du-delay-profile { + description + "O-DU provided delay profile for adaptive delay configuration"; + + uses o-du-delay-profile; + } + } + + container transport-delay { + description + "O-DU provided transport-delay parameters"; + uses t12; + uses t34; + } + } + + leaf beam-context-gap-period { + type uint16; + units microseconds; + description + "Time gap between the end of reception window of the C-Plane message(Msg-A) with new beam weights for a given beamId and end of the reception window + of the C-Plane message(Msg-B) that cites the same beamId without weights in the new context. + Note: Value of '0' indicates that the end of the Msg-A and Msg-B reception windows are perfectly aligned, which should allow Msg-B to use the new + beamforming weights with a '0' microsecond beam-context-gap-period. Value of '65535' implies infinite gap, which means a beamId may not be reused + at all in a different context (applicable only to weight-based dynamic beamforming). If O-DU chooses not to interpret/honor this value, behaviour + of O-RU is unpredictable if a beamId has new weights loaded in one context and is reused in a different context. Please refer the CUS-Plane spec + Section 'Weight-based dynamic beamforming' for detailed description"; + } + } + container delay-management { + description "top-level tree covering off O-DU to O-RU delay management"; + + uses delay-management-group; + } +} diff --git a/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang b/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang index ee07645a44..ee0a553ff0 100644 --- a/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang +++ b/radio/fhi_72/mplane/yang/models/o-ran-file-management.yang @@ -3,10 +3,12 @@ module o-ran-file-management { namespace "urn:o-ran:file-management:1.0"; prefix "o-ran-file-mgmt"; - import ietf-crypto-types { - prefix "ct"; - } + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } organization "O-RAN Alliance"; @@ -16,7 +18,7 @@ module o-ran-file-management { description "This module defines the configuration and operations for handling upload. - Copyright 2019 the O-RAN Alliance. + Copyright 2024 the O-RAN Alliance. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -42,6 +44,52 @@ module o-ran-file-management { contributors may be used to endorse or promote products derived from this software without specific prior written permission."; + revision "2024-08-12" { + description + "version 10.2.0 + + 1) Improve YANG description enforce typing of IPv6 addresses"; + + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2023-04-10" { + description + "version 10.1.0 + + 1) Remove crypto-types dependency"; + + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2022-08-15" { + description + "version 10.0.0 + + 1) added password for FTPES + 2) clarified path/folder description "; + + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2021-12-01" { + description + "version 7.1.0 + + 1) typographical corrections"; + + reference "ORAN-WG4.M.0-v07.00"; + } + + revision "2021-07-26" { + description + "version 7.0.0 + + 1) added FTPES support"; + + reference "ORAN-WG4.M.0-v07.00"; + } + revision "2019-07-03" { description "version 1.1.0 @@ -63,21 +111,157 @@ module o-ran-file-management { reference "ORAN-WG4.M.0-v01.00"; } + /***********************************************/ + /* Identities for Asymmetric Key Algorithms */ + /***********************************************/ + + identity asymmetric-key-algorithm { + description + "Base identity from which all asymmetric key + encryption Algorithm."; + } + + identity rsa1024 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 1024-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa2048 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 2048-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa3072 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 3072-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa4096 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 4096-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa7680 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 7680-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity rsa15360 { + base asymmetric-key-algorithm; + description + "The RSA algorithm using a 15360-bit key."; + reference + "RFC 8017: + PKCS #1: RSA Cryptography Specifications Version 2.2."; + } + + identity secp192r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + identity secp224r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp256r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp384r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + identity secp521r1 { + base asymmetric-key-algorithm; + description + "The ECDSA algorithm using a NIST P256 Curve."; + reference + "RFC 6090: + Fundamental Elliptic Curve Cryptography Algorithms."; + } + + /**********************************************************/ + /* Typedefs for identityrefs to above base identities */ + /**********************************************************/ + + typedef asymmetric-key-algorithm-ref { + type identityref { + base asymmetric-key-algorithm; + } + description + "This typedef enables importing modules to easily define an + identityref to the 'asymmetric-key-algorithm' + base identity."; + } + grouping file-path-grouping { - description "Complete logical path of the file to upload/download - (no wildcard is allowed) ex : /o-RAN/log/syslog.1"; + description "Grouping, that provides local path and remote path for the + purpose of File Management scenarios."; + leaf local-logical-file-path { type string; mandatory true; - description "Local logical file path"; + description "URI specifying the complete logical path relative to the root of the logical file system + structure (the common root for o-ran/log, o-ran/pm, o-ran/transceiver or o-ran/beamforming) of the file + to upload/download (no wildcard is allowed), including a file name and its extension. + Example: 'o-ran/log/file_1.abc', where 'o-ran/log/' represents relative path to folder containing log files + as specified by O-RAN, 'file_1' represents desired filename and 'abc' represents desired filename's extension. + The content shall conform to RFC3986 'Uniform Resource Identifier (URI): Generic Syntax'"; } leaf remote-file-path { type string; mandatory true; - description "URI specifying the remote-file-path on O-DU/NMS. - Format:sftp://@[:port]/path"; + description "URI specifying the remote-file-path on O-DU/SMO or on stand-alone file server. + The content shall conform to RFC3986 'Uniform Resource Identifier (URI): Generic Syntax'. + When upload/download is via sftp, the format shall be of the form + sftp://@[:port]/path + When upload/download is via ftpes, the format shall be of the form + ftpes://@[:port]/path + IPv6 addresses are distinguished by enclosing the IP literal within square brackets ('[' and ']') as defined by RFC3986 e.g., sftp://user@[2001:0:130F::9C0:876A:130B]:22/path. + + Note, ftpes is not an IANA registered URI scheme, but used here to signal + that a file transfer should be performed over FTPES"; } } @@ -102,7 +286,7 @@ module o-ran-file-management { } grouping credential-information { - description "Type of authentication to use for SFTP upload or download."; + description "Type of authentication to use for file upload or download."; choice credentials { case password { container password { @@ -111,21 +295,22 @@ module o-ran-file-management { type string; mandatory true; description - "password needed for O-RU authentication."; + "password used for O-RU authentication to sFTP server for the associated username defined in the remote-file-path."; } description - "password for O-RU authentication method in use"; + "password for O-RU authentication method in use. This information + shall be ignored by an O-RU that is using FTPES based file transfer"; } container server { list keys { key algorithm; ordered-by user; - uses ct:public-key-grouping; + uses public-key-grouping; description "List of allowed algorithms with its keys"; } description - "Key for sFTP server authentication"; + "SSH Key for file server authentication"; } } case certificate { @@ -134,9 +319,22 @@ module o-ran-file-management { description "certificate authentication method in use"; } + } description ""; } + container application-layer-credential{ + + leaf appl-password { + type string; + description + "The parameter represents the password which may be needed for O-RU application level authentication. + For example, to perform authenticatation towards an FTPes server which does not allow anonymous account, + in addition to X.509v3 certificate for TLS authentication, password configured here need to be used together with username defined in the remote-file-path "; + } + description + "Application layer credential information"; + } } grouping retrieve-input { @@ -144,12 +342,13 @@ module o-ran-file-management { leaf logical-path { type string; mandatory true; - description "O-RAN unit of which the files are to be listed. - ex : O-RAN/log, o-RAN/PM, O-RAN/transceiver"; + description "URL specifying the logical path relative to the root of the logical file system + structure (the common root for o-ran/log, o-ran/pm, o-ran/transceiver or o-ran/beamforming) + of the files to be listed."; } leaf file-name-filter { type string; - description "Filter which are to be applied on the result list of file names (* is allowed as wild-card)."; + description "Filter which needs to be applied on the result list of file names (* is allowed as wild-card)."; } } @@ -163,10 +362,48 @@ module o-ran-file-management { } } + grouping public-key-grouping { + description + "A public key. + + The 'algorithm' and 'public-key' nodes are not + mandatory because they MAY be defined in . + Implementations SHOULD assert that these values are + either configured or that they exist in ."; + leaf algorithm { + nacm:default-deny-write; + type asymmetric-key-algorithm-ref; + must '../public-key'; + description + "Identifies the key's algorithm. More specifically, + this leaf specifies how the 'public-key' binary leaf + is encoded."; + reference + "RFC CCCC: Common YANG Data Types for Cryptography"; + } + leaf public-key { + nacm:default-deny-write; + type binary; + must '../algorithm'; + description + "A binary that contains the value of the public key. The + interpretation of the content is defined by the key + algorithm. For example, a DSA key is an integer, an RSA + key is represented as RSAPublicKey as defined in + RFC 8017, and an Elliptic Curve Cryptography (ECC) key + is represented using the 'publicKey' described in + RFC 5915."; + reference + "RFC 8017: Public-Key Cryptography Standards (PKCS) #1: + RSA Cryptography Specifications Version 2.2. + RFC 5915: Elliptic Curve Private Key Structure."; + } + } + // RPCs rpc file-upload { - description "File upload over SFTP from equipment to NETCONF client"; + description "Management plane trigger to upload file from O-RU to file-server"; input { uses file-path-grouping; uses credential-information; @@ -187,15 +424,9 @@ module o-ran-file-management { } } - notification file-upload-notification { - uses file-path-grouping; - uses output-status-grouping; - description ""; - } - rpc file-download { description - "Management plane triggered to generate the download file of O-RU."; + "Management plane trigger to download file from file-server to O-RU."; input { uses file-path-grouping; uses credential-information; @@ -205,6 +436,12 @@ module o-ran-file-management { } } + notification file-upload-notification { + uses file-path-grouping; + uses output-status-grouping; + description ""; + } + notification file-download-event { uses file-path-grouping; uses output-status-grouping; diff --git a/radio/fhi_72/mplane/yang/models/o-ran-hardware.yang b/radio/fhi_72/mplane/yang/models/o-ran-hardware.yang new file mode 100644 index 0000000000..4e00d034d5 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/o-ran-hardware.yang @@ -0,0 +1,461 @@ +module o-ran-hardware { + yang-version 1.1; + namespace "urn:o-ran:hardware:1.0"; + prefix "o-ran-hw"; + + import ietf-hardware { + prefix hw; + } + import iana-hardware { + prefix ianahw; + } + import ietf-yang-types { + prefix yang; + } + import o-ran-wg4-features { + prefix or-feat; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the YANG definitions for managing the O-RAN hardware. + + Copyright 2024 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2024-04-15" { + description + "version 15.0.0 + + 1) Added support for new fan tray component."; + + reference "ORAN-WG4.M.0-v15.00"; + } + + revision "2023-08-14" { + description + "version 13.0.0 + + 1) New connector types for RS485 and external IO"; + + reference "ORAN-WG4.M.0-v13.00"; + } + + revision "2022-12-05" { + description + "version 10.1.0 + + 1) Clarifications for Network Energy Saving"; + + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2022-08-15" { + description + "version 10.0.0 + + 1) introduction of O-RU connector functionality. + 2) fixing constraints"; + + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2021-12-01" { + description + "version 5.2.0 + + 1) typographical corrections in descriptions."; + + reference "ORAN-WG4.M.0-v05.00"; + } + + revision "2021-03-22" { + description + "version 5.1.0 + + 1) typographical corrections in descriptions."; + + reference "ORAN-WG4.M.0-v05.00"; + } + + revision "2020-12-10" { + description + "version 5.0.0 + + 1) added date-last-service leaf used in pnfRegistration"; + + reference "ORAN-WG4.M.0-v05.00"; + } + + revision "2020-04-17" { + description + "version 3.0.0 + + 1) added new leaf to indicate whether O-RU supports dying gasp + 2) added new identities for PA and FPGA"; + + reference "ORAN-WG4.M.0-v03.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) added new identities to accommodate cross working group use of + o-ran-hardware and associated set of augmentations that are backwards + compatible to version 1.0.0"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + feature ENERGYSAVING { + description + "Indicates that the Radio Unit supports energy saving state."; + } + + // identity statements + identity O-RAN-RADIO { + base ianahw:module; + description + "Module used as it represents a self-contained sub-system + used in /hw:/hardware/hw:component/hw:class to represent + an O-RAN RU"; + } + + identity O-RAN-HW-COMPONENT { + base ianahw:module; + description + "Module used as it represents a self-contained sub-system + used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN hardware component"; + } + + identity O-DU-COMPONENT { + base O-RAN-HW-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN defined O-DU hardware component"; + } + + identity O-RAN-FAN-TRAY { + base O-RAN-HW-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN defined fan tray hardware component."; + } + + identity O-RU-COMPONENT { + base O-RAN-HW-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + any O-RAN defined O-RU hardware component, including a stand-alone + O-RU or an O-RU component integrated into a multi-module system."; + } + + identity O-RU-POWER-AMPLIFIER { + base O-RU-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + an O-RU's power amplifier, and may be used for reporting + measurements on a per class basis"; + } + + identity O-RU-FPGA { + base O-RU-COMPONENT; + description + "Used in /hw:/hardware/hw:component/hw:class to represent + an FPGA in an O-RU, and may be used for reporting + measurements on a per class basis"; + } + + identity O-RU-CONNECTOR { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of O-RU connector."; + } + + identity O-RU-ANTENNA-CONNECTOR { + base O-RU-CONNECTOR; + description + "This identity is applicable if the hardware class is some sort + of connector capable of interfacing between an O-RU and some + antenna function."; + } + + identity O-RU-FEEDER { + base O-RU-ANTENNA-CONNECTOR; + description + "This identity is applicable if the hardware class is an + antenna feeder."; + } + + identity O-RU-BF-CAL { + base O-RU-ANTENNA-CONNECTOR; + description + "This identity is applicable if the hardware class is for + beamforming calibration."; + } + + identity O-RU-RS485 { + base O-RU-CONNECTOR; + description + "This identity is applicable if the hardware class is some sort + of connector capable of interfacing between an O-RU and Antenna + Line Devices using RS-485 electrical standard."; + } + + identity O-RU-EXTIO { + base O-RU-CONNECTOR; + description + "This identity is applicable if the hardware class is some sort + of connector capable of interfacing between an O-RU external I/O lines."; + } + + // typedef statements + typedef energysaving-state { + type enumeration { + enum UNKNOWN { + description + "The O-RU is unable to report its energy saving state."; + } + enum SLEEPING { + description + "The O-RU is in energy saving state. In this mode M-Plane connection is active. Depending + on the O-RU's design - other planes, functions and hardware components which are not needed + by the O-RU in energy saving state can be disabled or switched off by the O-RU autonomously."; + } + enum AWAKE { + description + "The O-RU is not in an energy saving state."; + } + } + description + "New typedef since ietf-hardware only covers power-state + for redundancy purposes, not to indicate energy saving operations. + For details please see O-RAN WG4 M-Plane specification, clause 9.1.3 'Modify state'"; + } + + typedef availability-type { + type enumeration { + enum UNKNOWN { + description "The Radio Unit is unable to report its availability state."; + } + enum NORMAL { + description + "The equipment is functioning correctly."; + } + enum DEGRADED { + description + "The equipment may be reporting a major alarm or may be reporting a critical + alarm that is only impacting one or more subcomponent, but where the + equipment's implementation permit it to continue operation (server traffic) + in a degraded state. + + Used for example, when the equipment has M identical sub-components and + when a critical alarm is impacting only N subcomponents, where N@[:]/path"; } - uses o-ran-fm:credential-information; + uses o-ran-file-mgmt:credential-information; + } + + list remote-file-uploads { + key remote-file-upload-path; + description + "file upload can be done to one or more than one file servers + + An O-RU receiving this list should ignore the deprecated + remote-SFTP-uploads list, if received"; + + leaf remote-file-upload-path { + type inet:uri; + description + "URI specifying the remote location where the files are to be uploaded. + + When upload is via SFTP, the format shall be of the form + sftp://@[:port]/path + When upload is via FTPES, the format shall be of the form + ftpes://@[:port]/path + + Note, ftpes is not an IANA registered URI scheme, but used here to signal + that a file transfer should be performed over FTPES"; + } + + uses o-ran-file-mgmt:credential-information; } // transceiver measurements applicable to all O-RAN HW functions @@ -567,6 +1691,42 @@ module o-ran-performance-management { window measurement objects periodically."; } + leaf shared-cell-measurement-interval { + if-feature feat:SHARED-CELL-STATS; + type uint16; + units seconds; + description + "measurement interval to measure the shared-cell measurement objects periodically."; + } + + leaf symbol-rssi-measurement-interval { + type uint16; + units seconds; + description + "measurement interval to measure the symbol-wise TD-RSSI measurement objects periodically."; + } + + leaf tssi-measurement-interval { + type uint16; + units seconds; + description + "Measurement interval to measure the tx TSSI measurement objects periodically."; + } + + leaf rssi-measurement-interval { + type uint16; + units seconds; + description + "Measurement interval to measure the RSSI measurement objects periodically."; + } + + leaf tx-antenna-measurement-interval { + type uint16; + units seconds; + description + "Measurement interval to measure the tx antenna measurement objects periodically."; + } + leaf notification-interval { type uint16; units seconds; @@ -586,11 +1746,14 @@ module o-ran-performance-management { leaf max-bin-count{ type uint16; config false; - mandatory true; + status deprecated; description "indicates the maximum value of configurable bin-count for frequency table in transceiver-measurement-objects as one of module - capabilities."; + capabilities. + + This leaf is deprecated and replaced with the max-bin-count in the + transceiver-objects list."; } list transceiver-measurement-objects { @@ -673,33 +1836,7 @@ module o-ran-performance-management { } leaf-list report-info { - type enumeration { - enum MAXIMUM { - description - "to report maximum value and its recorded time within the - measurement-interval for the measurement-object."; - } - enum MINIMUM { - description - "to report minimum value and its recorded time within the - measurement-interval for the measurement-object."; - } - enum FIRST { - description - "to report first value and its recorded time within the - measurement-interval for the measurement-object."; - } - enum LATEST { - description - "to report latest value and its recorded time within the - measurement-interval for the measurement-object."; - } - enum FREQUENCY_TABLE { - description - "to report frequency bin table within the - measurement-interval for the measurement-object."; - } - } + type transceiver-report-info; description "The reporting info to the measurement object."; } @@ -715,16 +1852,7 @@ module o-ran-performance-management { } leaf function { - type enumeration { - enum RAW { - description - "the value is expressed by real value."; - } - enum LOG_10 { - description - "the value is expressed by logarithm with base 10."; - } - } + type transceiver-function; description "the value to be recorded for transceiver-measurement @@ -851,7 +1979,7 @@ module o-ran-performance-management { description "the reception window stats are counted per transport flow. When there are multiple transport flows between O-DU and O-RU, - e.g. multiple sets of o-du mac address, ru mac address and + e.g. multiple sets of o-du-mac-address, ru-mac-address and vlan-id, the reception window stats per transport flow are counted in this case. This configuration is allowed only when O-RU supports @@ -862,7 +1990,7 @@ module o-ran-performance-management { description "the reception window stats are counted per eAxC ID, which is - used in the header of receivd data packet. + used in the header of received data packet. This configuration is allowed only when O-RU supports a feature GRANULARITY-EAXC-ID-MEASUREMENT."; } @@ -931,7 +2059,7 @@ module o-ran-performance-management { description "the transmission stats are counted per transport flow. When there are multiple transport flows between O-DU and O-RU, - e.g. multiple sets of o-du mac address, ru mac address and + e.g. multiple sets of o-du-mac-address, ru-mac-address and vlan-id, the transmission stats per transport flow are counted in this case. This configuration is allowed only when O-RU supports @@ -942,7 +2070,7 @@ module o-ran-performance-management { description "the transmission stats are counted per eAxC ID, which is - used in the header of receivd data packet. + used in the header of received data packet. This configuration is allowed only when O-RU supports a feature GRANULARITY-EAXC-ID-MEASUREMENT."; } @@ -968,6 +2096,58 @@ module o-ran-performance-management { } + list shared-cell-measurement-objects { + if-feature feat:SHARED-CELL-STATS; + key "measurement-object"; + description + "optional list used to report shared-cell measurements."; + leaf measurement-object { + type enumeration { + enum RX_UP_UL { + description + "the number of received U-Plane data packets in UL direction, corresponds to shared-cell-combine-entity. + Refer to WG4 CUS secification clause 9.1."; + } + enum RX_UP_UL_COMBINED { + description + "the number of U-Plane data packets, which is processed by combine functional block. + Refer to WG4 CUS secification clause 9.1."; + } + } + description + "target metric to measure shared-cell operation."; + } + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per port + measurement object."; + } + leaf object-unit { + type enumeration { + enum TRANSPORT { + description + "unit to measure the performance per object-id, + the shared-cell stats are counted per TRANSPORT."; + } + } + description "unit to measure the performance per object-id."; + } + leaf report-info { + type enumeration { + enum COUNT { + description + "the number of data packet are counted for shared-cell stats."; + } + } + description + "The reporting info to the measurement object."; + } + uses shared-cell-measurement-result-grouping; +// configuration and measurement result for the shared-cell stats + } + list epe-measurement-objects { key "measurement-object"; description @@ -977,12 +2157,20 @@ module o-ran-performance-management { type enumeration { enum TEMPERATURE { description - "Measured temperature in degrees celcius"; + "Measured temperature in degrees Celsius"; } enum POWER { description "Measured power consumed, in watts (W)"; } + enum VOLTAGE { + description + "Measured voltage, in volts (V)"; + } + enum CURRENT { + description + "Measured current consumption, in amperes (A)"; + } } description "Target metric to measure the performance"; } @@ -994,63 +2182,369 @@ module o-ran-performance-management { "Enable/disable the performance measurement per Object"; } - leaf-list report-info { - type enumeration { - enum MAXIMUM { - description - "to report maximum value and its recorded time within the - measurement-interval for the measurement-object."; - } - enum MINIMUM { - description - "to report minimum value and its recorded time within the - measurement-interval for the measurement-object."; - } - enum AVERAGE { - description - "to report average value within the - measurement-interval for the measurement-object."; - } + leaf object-unit { + type leafref { + path "/hw:hardware/hw:component/hw:class"; } + description + "the hardware component type is used for the object-unit for the + EPE measurements. For example, the object-unit will be set to + or-hw:O-RU-POWER-AMPLIFIER if the measurement relates to + O-RU power amplifiers. + + Other hardware-classes include: + ianahw:power-supply, ianahw:fan, ianahw:cpu"; + } + + leaf-list report-info { + type epe-report-info; description "The reporting info to the measurement object."; } - + leaf bin-count { + type uint16; + description + "the number of bin for the frequency table. + This value shall be less than max-bin-count"; + } + leaf lower-bound { + type decimal64 { + fraction-digits 4; + } + description + "the lower value of the first bin of frequency table."; + } + leaf upper-bound { + type decimal64 { + fraction-digits 4; + } + description + "the upper value of the last bin of frequency table."; + } uses epe-measurement-result-grouping; // configuration and measurement result for the epe-measurement } + list symbol-rssi-measurement-objects { + key "measurement-object"; + description + "optional list used to measure and report symbol-wise time domain RSSI for all UL symbols or configured symbols"; + + leaf measurement-object { + type enumeration { + enum ALL-UL-SYMBOLS { + description + "Measure and report symbol-rssi separately for all UL symbols in every configured number of slots (as defined by 'period' in 'symbol-rssi-measurement-objects'. + And the UL symbols are decided by 'configurable-tdd-pattern', 'static-srs-configuration', 'static-prach-configuration', + and 'dataDirection' in the C-plane messages. + This option is recommended for static TDD case. If this option is used in dynamic TDD case, then O-RU measures + only the allocates UL symbols because O-RU may not know 'candidate UL symbols' which are not allocated. "; + } + + enum CONFIGURED-SYMBOLS { + description + "Measure and report symbol-rssi separately for all configured symbols as defined by the leaf-list 'symbol-index', + This can be used for non-dynamic TDD as well as dynamic TDD cases, + the O-RU should measure all configured symbols, irrespective of whether the UL symbol is allocated or not, + If a c-plane message indicates a symbol within this 'symbol-index' list to be a DL symbol, + O-RU shall not measure RSSI on this symbol."; + } + } + description "Target metric to measure the symbol-rssi"; + } + + leaf object-unit { + type enumeration { + enum RX-ARRAY-CARRIER { + description + "unit to measure the performance per object-id, + only the rx-array-carriers which are not configured with mixed numerology will be measured"; + } + } + mandatory true; + description "unit to measure the performance per object-id."; + } + + list per-rx-array-carrier-configuration { + key "rx-array-carrier"; + description + "measurement configuration per rx-array-carrier to accommodate different Subcarrier Spacing + and TDD pattern per rx-array-carrier, and only the symbol-wise TD-RSSI of the rx-array-carriers + included in per-rx-array-carrier-configuration will be measured and reported"; + + leaf rx-array-carrier { + type leafref { + path "/up:user-plane-configuration/up:rx-array-carriers/up:name"; + } + description "reference to the name of rx-array-carriers"; + } + + leaf period { + type uint16; + + description + "the number of slots that correspond to the period of a TDD-Configuration, + and the start point of the 1st period is subframe#0, slot#0 of the 1st even number radio frame after this configuration is received, + here even number radio frame is used because according to 3GPP TS 38.213, A UE expects that P1 + P2 divides 20 msec"; + } + + leaf-list symbol-index { + type uint16; + + description + "the index of the symbols within 'period'. The first symbol within the 'period is symbol-index=0, next symbol is symbol-index =1 etc. + This symbol-index is different from how symbolId is defined in CUS plane spec. + These symbols are configured for O-RU to measure and report symbol-wise rssi, + used only when 'measurement-object' = 'CONFIGURED-SYMBOLS'. + If a c-plane message indicates a symbol within this 'symbol-index' list to be a DL symbol, + O-RU shall not measure rssi on this symbol"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the symbol-rssi measurement per Object"; + } + + leaf-list report-info { + type symbol-rssi-report-info; + description "The reporting info to the measurement object."; + } + + leaf bin-count { + type uint16; + + description + "the number of bin for the frequency table. + This value shall be less than max-bin-count"; + } + + leaf lower-bound { + type int16; + units dBm; + description + "the lower value of the first bin of frequency table."; + } + + leaf upper-bound { + type int16; + units dBm; + description + "the upper value of the last bin of frequency table."; + } + } + + uses symbol-rssi-measurement-result-grouping; + // configuration and measurement result for the symbol-rssi-measurement + } + + list tssi-measurement-objects { + key "measurement-object"; + description + "optional list used to measure and report time domain TSSI for per tx-array-carrier on specific tx-array-element."; + leaf measurement-object { + type enumeration { + enum TSSI-IQ-POWER-LEVEL { + description + "Measured TSSI (Transmit Signal Strength Indicator) digital IQ Power level for each Tx array carrier on the specific array element"; + } + } + description "Target metric to measure the tssi"; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the TSSI measurement per object"; + } + + leaf object-unit { + type enumeration { + enum CARRIER_ARRAY_ELEMENT { + description + "Unit to measure the performance per object-id."; + } + } + mandatory true; + description "unit to measure the performance per object-id."; + } + + leaf-list report-info { + type tssi-report-info; + description "The reporting info to the measurement object."; + } + uses tssi-measurement-result-grouping; + // configuration and measurement result for the tssi-measurement + } + + list rssi-measurement-objects { + key "measurement-object"; + description + "optional list used to measure and report time domain RSSI for per rx-array-carrier on specific rx-array-element."; + leaf measurement-object { + type enumeration { + enum RSSI { + description + "Measured RSSI (Received Signal Strength Indicator) for each Rx array carrier on the specific array element in dbm"; + } + } + description "Target metric to measure the rssi"; + } + leaf active { + type boolean; + default false; + description + "Enable/disable the RSSI measurement per object"; + } + leaf object-unit { + type enumeration { + enum CARRIER_ARRAY_ELEMENT { + description + "Unit to measure the performance per object-id."; + } + } + mandatory true; + description "unit to measure the performance per object-id."; + } + leaf-list report-info { + type rssi-report-info; + description "The reporting info to the measurement object."; + } + uses rssi-measurement-result-grouping; + // configuration and measurement result for the rssi-measurement + } + + list tx-antenna-measurement-objects { + key "measurement-object"; + description + "Optional list used to report tx-antenna measurements."; + leaf measurement-object { + type enumeration { + enum VSWR { + description + "Measure and report values of VSWR."; + } + } + description "Target metric to measure the tx-antenna measurements."; + } + + leaf active { + type boolean; + default false; + description + "Enable/disable the performance measurement per Object"; + } + + leaf-list report-info { + type tx-antenna-report-info; + description "The reporting info to the measurement object."; + } + + leaf object-unit { + type tx-antenna-object-unit; + mandatory true; + description "Unit to measure the performance per object-id."; + } + + leaf bin-count { + type uint16; + + description + "The number of bin for the frequency table. + This value shall be less than max-bin-count"; + } + + leaf lower-bound { + type decimal64 { + fraction-digits 4; + } + + description + "The lower value of the first bin of frequency table."; + } + + leaf upper-bound { + type decimal64 { + fraction-digits 4; + } + + description + "The upper value of the last bin of frequency table."; + } + uses tx-antenna-measurement-result-grouping; +// configuration and measurement result for the tx-antenna-measurement + + } } grouping measurement-capabilities { + description "a measurement capabilities grouping"; container measurement-capabilitites { config false; description "the type of measurement objects supported by the O-RU"; list transceiver-objects { key measurement-object; + description "list of transceiver objects"; leaf measurement-object { type leafref { path "/performance-measurement-objects/transceiver-measurement-objects/measurement-object"; + require-instance false; } + description "a measurement object"; + } + leaf-list report-info { + type transceiver-report-info; + description "The reporting info supported by this measurement object."; + } + leaf-list function { + type transceiver-function; + description "The function supported by this measurement object."; + } + leaf max-bin-count{ + type uint16; + config false; + description + "when O-RU supports FREQUENCY_TABLE, indicates the maximum value of + configurable bin-count for frequency table in transceiver-measurement-objects."; } } list rx-window-objects { key measurement-object; + description "list of rx window objects"; leaf measurement-object { type leafref { path "/performance-measurement-objects/rx-window-measurement-objects/measurement-object"; + require-instance false; } + description "a measurement object"; } } list tx-stats-objects { key measurement-object; + description "list of tx stats objects"; leaf measurement-object { type leafref { path "/performance-measurement-objects/tx-measurement-objects/measurement-object"; + require-instance false; } + description "a measurement object"; + } + } + list shared-cell-stats-objects { + if-feature feat:SHARED-CELL-STATS; + key measurement-object; + description "list of shared-cell stats objects"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/shared-cell-measurement-objects/measurement-object"; + require-instance false; + } + description "a measurement object"; } } list epe-stats-objects { @@ -1061,7 +2555,9 @@ module o-ran-performance-management { leaf measurement-object { type leafref { path "/performance-measurement-objects/epe-measurement-objects/measurement-object"; + require-instance false; } + description "a measurement object"; } leaf-list component-class { type identityref { @@ -1072,13 +2568,114 @@ module o-ran-performance-management { component for which EPE measurements are supported."; } + leaf-list report-info { + type epe-report-info; + description "The reporting info supported of this measurement object."; + } + leaf max-bin-count{ + type uint16; + config false; + description + "when O-RU supports FREQUENCY_TABLE, indicates the maximum value of + configurable bin-count for frequency table in epe-measurement-objects."; + } + } + + list symbol-rssi-stats-objects { + key measurement-object; + description "list of symbol-wise TD-RSSI stats objects"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/symbol-rssi-measurement-objects/measurement-object"; + require-instance false; + } + description "a measurement object"; + } + leaf-list report-info { + type symbol-rssi-report-info; + description "The reporting info supported for thise measurement object."; + } + leaf max-bin-count{ + type uint16; + config false; + description + "when O-RU supports FREQUENCY_TABLE, indicates the maximum value of + configurable bin-count for frequency table in symbol-rssi-stats-objects."; + } + } + + list tssi-stats-objects { + key measurement-object; + description "list of TSSI stats objects"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tssi-measurement-objects/measurement-object"; + } + description "a measurement object"; + } + leaf-list report-info { + type tssi-report-info; + description "The reporting info supported for thise measurement object."; + } + } + + list rssi-stats-objects { + key measurement-object; + description "list of RSSI stats objects"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/rssi-measurement-objects/measurement-object"; + } + description "a measurement object"; + } + leaf-list report-info { + type rssi-report-info; + description "The reporting info supported for thise measurement object."; + } + } + + list tx-antenna-stats-objects { + key measurement-object; + description "list of tx antenna objects"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tx-antenna-measurement-objects/measurement-object"; + require-instance false; + } + description "a measurement object"; + } + + leaf-list object-unit { + type tx-antenna-object-unit; + description "The object units supported for this measurement object."; + } + + leaf-list report-info { + type tx-antenna-report-info; + description "The reporting info supported for this measurement object."; + } + + leaf max-bin-count{ + type uint16; + config false; + description + "when O-RU supports FREQUENCY_TABLE, indicates the maximum value of + configurable bin-count for frequency table in tx-antenna-stats-objects."; + } } } } grouping measurement-notification { + + description + "notification may contain measurement result for transceiver-stats + and/or rx-window-stats and/or tx-stats and/or epe-stats"; list transceiver-stats { key "measurement-object"; + + description + "measurement result of transceiver-measurement per measurement-object"; leaf measurement-object { type leafref { path "/performance-measurement-objects/transceiver-measurement-objects/measurement-object"; @@ -1091,12 +2688,33 @@ module o-ran-performance-management { uses start-and-end-time; uses transceiver-measurement-result-grouping; - description - "measurement result of transceiver-measurement per measurement-object"; + list multiple-transceiver-measurement-result { + config false; + description + "Multiple measurement results of transceiver-measurement. + + The O-RU shall use this list to report one or more measurements per measurement-object in a single notification. + + In addition, the O-RU shall always use the + + measurement-result-stats/transceiver-stats[measurement-object]/transceiver-measurement-result + + schema-node to report a single transceiver measurement-object. The O-RU should report its latest + transceiver measurements available. This ensures O-DUs supporting earlier versions + of this specification can recover the measurement."; + + uses start-and-end-time; + uses transceiver-measurement-result-grouping; + } + } list rx-window-stats { key "measurement-object"; + + description + "measurement result for the reception window measurement per + measurement-object"; leaf measurement-object { type leafref { path "/performance-measurement-objects/rx-window-measurement-objects/measurement-object"; @@ -1108,14 +2726,35 @@ module o-ran-performance-management { uses start-and-end-time; uses rx-window-measurement-result-grouping; - description - "measurement result for the reception window measurement per - measurement-object"; + list multiple-rx-window-measurement-result { + config false; + description + "Multiple measurement results of rx-window-measurement. + + The O-RU shall use this list to report one or more measurements per measurement-object in a single notification. + + In addition, the O-RU shall always use one of the + + measurement-result-stats/rx-window-stats[measurement-object]/count or + measurement-result-stats/rx-window-stats[measurement-object]/tr-measured-result/count or + measurement-result-stats/rx-window-stats[measurement-object]/eaxc-measured-result/count + + schema-nodes to report a single rx-window measurement-object. The O-RU should report its latest + rx-window measurement available. This ensures O-DUs supporting earlier versions + of this specification can recover the measurement."; + + uses start-and-end-time; + uses rx-window-measurement-result-grouping; + } } list tx-stats { key "measurement-object"; + + description + "measurement result for the tx stats measurement per + measurement-object"; leaf measurement-object { type leafref { path "/performance-measurement-objects/tx-measurement-objects/measurement-object"; @@ -1127,15 +2766,59 @@ module o-ran-performance-management { uses start-and-end-time; uses tx-measurement-result-grouping; - description - "measurement result for the tx stats measurement per - measurement-object"; + list multiple-tx-measurement-result { + config false; + description + "Multiple measurement results of tx-measurement. + + The O-RU shall use this list to report one or more measurements per measurement-object in a single notification. + + In addition, the O-RU shall always use one of the + + measurement-result-stats/tx-stats[measurement-object]/count or + measurement-result-stats/tx-stats[measurement-object]/tr-measured-result/count or + measurement-result-stats/tx-stats[measurement-object]/eaxc-measured-result/count + + schema-nodes to report a single tx-measurement. The O-RU should report its latest + tx-measurement available. This ensures O-DUs supporting earlier versions + of this specification can recover the measurement."; + + uses start-and-end-time; + uses tx-measurement-result-grouping; + } } + list shared-cell-stats { + if-feature feat:SHARED-CELL-STATS; + key "measurement-object"; + + description + "measurement result for the shared-cell measurement per measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/shared-cell-measurement-objects/measurement-object"; + } + description + "measurement-object for the shared-cell measurement"; + } + + list multiple-shared-cell-measurement-result { + config false; + description + "Multiple measurement results of shared-cell-measurement."; + + uses start-and-end-time; + uses shared-cell-measurement-result-grouping; + + } + } + container epe-stats { + status deprecated; description - "container for the epe stats measurement"; + "container for the EPE stats measurement - deprecated because measurement object + isn't included"; uses start-and-end-time; uses epe-measurement-result-grouping; @@ -1143,9 +2826,150 @@ module o-ran-performance-management { } - description - "notification may contain measurement result for transceiver-stats - and/or rx-window-stats"; + list epe-statistics { + key "measurement-object"; + + description + "measurement result for the EPE stats measurement per + measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/epe-measurement-objects/measurement-object"; + } + + description + "measurement-object for the EPE stats measurement"; + } + uses start-and-end-time; + uses epe-measurement-result-grouping; + + list multiple-epe-measurement-result { + config false; + description + "Multiple measurement results of epe-measurement. + + The O-RU shall use this list to report one or more measurements per measurement-object in a single notification. + + In addition, the O-RU shall use the + + measurement-result-stats/epe-statistics[measurement-object]/epe-measurement-resultv2/ + + schema-nodes to report a single epe-measurement for a measurement-object. The O-RU + should report its latest epe-measurement available. This ensures O-DUs supporting earlier + versions of this specification can recover the measurement."; + + uses start-and-end-time; + uses epe-measurement-result-grouping; + } + + } + + list symbol-rssi-stats { + key "measurement-object"; + + description + "measurement result of symbol-rssi-measurement per measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/symbol-rssi-measurement-objects/measurement-object"; + } + + description + "measurement-object for the symbol-rssi-measurement"; + } + + uses start-and-end-time; + uses symbol-rssi-measurement-result-grouping; + + list multiple-symbol-rssi-measurement-result { + config false; + description + "Multiple measurement results of symbol-rssi-measurement. + + The O-RU shall use this list to report one or more measurements per measurement-object in a single notification. + + In addition, the O-RU shall always use one of the + + measurement-result-stats/symbol-rssi-stats[measurement-object]/ + + schema-nodes to report a single symbol-rssi measurement for a measurement-object. + The O-RU should report its latest symbol-rssi measurement available."; + + uses start-and-end-time; + uses symbol-rssi-measurement-result-grouping; + } + } + + list tssi-stats { + key "measurement-object"; + description + "Measurement result of tssi per measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tssi-measurement-objects/measurement-object"; + } + description + "measurement-object for the tx-array-carriers"; + } + + list tssi-measurement-result { + config false; + description + "Multiple measurement results of tssi-measurement. + The O-RU shall use this list to report one or more measurements per measurement-object in a single notification."; + uses start-and-end-time; + uses tssi-measurement-result-grouping; + } + } + + list rssi-stats { + key "measurement-object"; + description + "Measurement result of rssi per measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/rssi-measurement-objects/measurement-object"; + } + description + "measurement-object for the rx-array-carrier"; + } + list rssi-measurement-result { + config false; + description + "Multiple measurement results of rssi-measurement. + The O-RU shall use this list to report one or more measurements per measurement-object in a single notification."; + uses start-and-end-time; + uses rssi-measurement-result-grouping; + } + } + + list tx-antenna-stats { + key "measurement-object"; + + description + "Measurement result of tx-antenna-measurement per measurement-object"; + leaf measurement-object { + type leafref { + path "/performance-measurement-objects/tx-antenna-measurement-objects/measurement-object"; + } + + description + "measurement-object for the tx-antenna-measurement"; + } + + list tx-antenna-measurement-result { + config false; + description + "Multiple measurement results of tx-antenna-measurement. + + The O-RU shall use this list to report one or more measurements per measurement-object in a single notification."; + + uses start-and-end-time; + uses tx-antenna-measurement-result-grouping; + } + + } + } // Top level container diff --git a/radio/fhi_72/mplane/yang/models/o-ran-processing-element.yang b/radio/fhi_72/mplane/yang/models/o-ran-processing-element.yang index fc930a0a81..015d14f2e2 100644 --- a/radio/fhi_72/mplane/yang/models/o-ran-processing-element.yang +++ b/radio/fhi_72/mplane/yang/models/o-ran-processing-element.yang @@ -23,6 +23,14 @@ module o-ran-processing-element { prefix "o-ran-int"; } + import o-ran-wg4-features { + prefix "feat"; + } + + import o-ran-usermgmt { + prefix "or-user"; + } + organization "O-RAN Alliance"; contact @@ -32,7 +40,7 @@ module o-ran-processing-element { "This module defines the YANG definitions for mapping of transport flows to processing elements. Three options are supported: i) virtual MAC based mapping - ii) MAC addrress + VLAN-ID based mapping + ii) MAC address + VLAN-ID based mapping iii) UDP/IP based mapping Copyright 2020 the O-RAN Alliance. @@ -61,16 +69,37 @@ module o-ran-processing-element { contributors may be used to endorse or promote products derived from this software without specific prior written permission."; - revision "2020-04-17" { - description - "version 3.0.0 + revision "2022-08-15" { + description + "version 10.0.0 - 1) added new enum SHARED-CELL-ETH-INTERFACE in - transport-session-type and new containers north-eth-flow and - south-eth-flow to enable Shared cell scenario."; + 1) introducing SHARED-ORU-MULTI-OPERATOR feature + 2) fixing constraints"; - reference "ORAN-WG4.M.0-v03.00"; - } + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2021-12-01" { + description + "version 8.0.0 + + 1) typographical corrections in descriptions. + 2) Add support for multiple transport-session-type per O-RU"; + + reference "ORAN-WG4.M.0-v08.00"; + } + + + revision "2020-04-17" { + description + "version 3.0.0 + + 1) added new enum SHARED-CELL-ETH-INTERFACE in + transport-session-type and new containers north-eth-flow and + south-eth-flow to enable Shared cell scenario."; + + reference "ORAN-WG4.M.0-v03.00"; + } revision "2019-07-03" { description @@ -78,7 +107,7 @@ module o-ran-processing-element { 1) added new leaf to enable O-RU to report the maximum number of transport flows it can support, e.g., due to restrictions on number - of VLAN-IDs when ethernet type transport is used."; + of VLAN-IDs when Ethernet type transport is used."; reference "ORAN-WG4.M.0-v01.00"; } @@ -99,16 +128,162 @@ module o-ran-processing-element { } // groupings - grouping pe-group { - leaf maximum-number-of-transport-flows { - type uint16 { - range "1..4094"; + grouping non-shared-cell-flow-group { + description "a grouping for non-shared cell O-RU flows"; + + container aliasmac-flow { + when "../../../transport-session-type = 'ALIASMAC-INTERFACE'"; + if-feature o-ran-int:ALIASMAC-BASED-CU-PLANE; + description "leafs for virtual mac type data flows"; + leaf ru-aliasmac-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:alias-macs"; + } + mandatory true; + description + "O-RU's alias MAC address used for alias MAC based flow"; + } + leaf vlan-id { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; + } + description + "O-RU's VLAN-ID used for alias MAC based flow"; + } + leaf o-du-mac-address { + type yang:mac-address; + mandatory true; + description + "O-DU's MAC address used for alias MAC based flow"; } - config false; - default 4094; - description - "The maximum number of transport flows that can be supported by an O-RU"; } + container eth-flow { + when "../../../transport-session-type = 'ETH-INTERFACE'"; + description "leafs for mac + vlan-id type data flows"; + leaf ru-mac-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address"; + } + mandatory true; + description + "O-RU's MAC address used for Ethernet based flow"; + } + leaf vlan-id { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; + } + mandatory true; + description + "O-RU's VLAN-ID used for Ethernet based flow"; + } + leaf o-du-mac-address { + type yang:mac-address; + mandatory true; + description + "O-DU's MAC address used for Ethernet based flow"; + } + } + container udpip-flow { + when "../../../transport-session-type = 'UDPIP-INTERFACE'"; + description "leafs for UDP/IP type data flows"; + choice address { + leaf ru-ipv4-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv4/ip:address/ip:ip"; + } + description "O-RU's IPv4 address"; + } + leaf ru-ipv6-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv6/ip:address/ip:ip"; + } + description "O-RU's IPv6 address"; + } + mandatory true; + description "choice of O-RU IPv4 or IPv6 address"; + } + leaf o-du-ip-address { + type inet:ip-address; + mandatory true; + description "O-DU's IP address"; + } + leaf ru-ephemeral-udp-port { + type inet:port-number; + mandatory true; + description + "ephemeral port used by O-RU"; + } + leaf o-du-ephemeral-udp-port { + type inet:port-number; + mandatory true; + description + "ephemeral port used by O-DU"; + } + leaf ecpri-destination-udp { + type inet:port-number; + mandatory true; + description "the well-known UDP port number used by eCPRI"; + // fixme - add in a default when allocated by IANA + } + } + } + + grouping shared-cell-flow-group { + description "a grouping for shared cell O-RU flows"; + + container north-eth-flow { + when "../../../transport-session-type = 'SHARED-CELL-ETH-INTERFACE'"; + if-feature "SHARED_CELL"; + description "leafs for mac + vlan-id type data flows"; + leaf ru-mac-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address"; + } + description + "O-RU's MAC address used for Ethernet based flow"; + } + leaf vlan-id { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; + } + description + "O-RU's VLAN-ID used for Ethernet based flow"; + } + leaf north-node-mac-address { + type yang:mac-address; + description + "North-node's MAC address used for Ethernet based flow"; + } + } + container south-eth-flow { + when "../../../transport-session-type = 'SHARED-CELL-ETH-INTERFACE'"; + if-feature "SHARED_CELL"; + description "leafs for mac + vlan-id type data flows"; + leaf ru-mac-address { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address"; + } + description + "O-RU's MAC address used for Ethernet based flow"; + } + leaf vlan-id { + type leafref { + path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; + } + description + "O-RU's VLAN-ID used for Ethernet based flow"; + } + leaf south-node-mac-address { + type yang:mac-address; + description + "south-node's MAC address used for Ethernet based flow"; + } + } + } + + grouping session-and-markings-group { + description "a grouping with transport session type and enhanced uplane markings"; + leaf transport-session-type { type enumeration { enum ETH-INTERFACE { @@ -158,7 +333,7 @@ module o-ran-processing-element { case ipv4 { when "(../../transport-session-type = 'UDPIP-INTERFACE')"; leaf upv4-dscp-name { - if-feature o-ran-int:UDPIP-BASED-CU-PLANE; + if-feature o-ran-int:UDPIP-BASED-CU-PLANE; type leafref { path "/if:interfaces/if:interface/ip:ipv4/o-ran-int:diffserv-markings/o-ran-int:enhanced-uplane-markings/o-ran-int:up-marking-name"; } @@ -168,7 +343,7 @@ module o-ran-processing-element { case ipv6 { when "(../../transport-session-type = 'UDPIP-INTERFACE')"; leaf upv6-dscp-name { - if-feature o-ran-int:UDPIP-BASED-CU-PLANE; + if-feature o-ran-int:UDPIP-BASED-CU-PLANE; type leafref { path "/if:interfaces/if:interface/ip:ipv6/o-ran-int:diffserv-markings/o-ran-int:enhanced-uplane-markings/o-ran-int:up-marking-name"; } @@ -178,6 +353,21 @@ module o-ran-processing-element { } } } + } + + grouping pe-group { + description "a grouping of processing elements"; + leaf maximum-number-of-transport-flows { + type uint16 { + range "1..4094"; + } + default 4094; + config false; + description + "The maximum number of transport flows that can be supported by an O-RU"; + } + uses session-and-markings-group; + list ru-elements { key "name"; description @@ -193,6 +383,17 @@ module o-ran-processing-element { This name may be used in fault management to refer to a fault source or affected object"; } + leaf sro-id { + if-feature feat:SHARED-ORU-MULTI-OPERATOR; + type leafref { + path "/or-user:users/or-user:user/or-user:sro-id"; + } + description + "The identity of a shared resource operator. When present, + indicates that the list entry corresponds to a processing element + associated with a shared resource operator where the sro-id identifies + the specific shared resource operator"; + } container transport-flow { description "container for the transport-flow used for CU plane"; @@ -202,154 +403,66 @@ module o-ran-processing-element { } description "the interface name "; } - container aliasmac-flow { - when "../../../transport-session-type = 'ALIASMAC-INTERFACE'"; - if-feature o-ran-int:ALIASMAC-BASED-CU-PLANE; - description "leafs for virtual mac type data flows"; - leaf ru-aliasmac-address { - type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:alias-macs"; - } - mandatory true; - description - "O-RU's alias MAC address used for alias MAC based flow"; - } - leaf vlan-id { - type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; - } - description - "O-RU's VLAN-ID used for alias MAC based flow"; - } - leaf o-du-mac-address { - type yang:mac-address; - mandatory true; - description - "O-DU's MAC address used for alias MAC based flow"; + uses non-shared-cell-flow-group; + uses shared-cell-flow-group; + + } + } + list additional-transport-session-type-elements { + if-feature "feat:MULTIPLE-TRANSPORT-SESSION-TYPE"; + key transport-session-type; + + description + "Added to support multiple transport-session-type per O-RU, + it is always assumed that /processing-elements/ru-elements/ is configured with the first type of transport, + and /processing-element/additional-transport-session-elements/ru-elements/ is configured with the other types of transport. + If the O-RU is configured for shared-cell, this list will not be used. An O-RU shall reject any configuration + with a list entry with transport-session-type set to SHARED-CELL-ETH-INTERFACE"; + + uses session-and-markings-group; + + list ru-elements { + key "name"; + description + "the list of transport definitions for each processing element"; + leaf name { + type string { + length "1..255"; } + description + "A name that is unique across the O-RU that identifies a processing + element instance. + + This name may be used in fault management to refer to a fault source + or affected object"; } - container eth-flow { - when "../../../transport-session-type = 'ETH-INTERFACE'"; - description "leafs for mac + vlan-id type data flows"; - leaf ru-mac-address { - type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address"; - } - mandatory true; - description - "O-RU's MAC address used for Ethernet based flow"; - } - leaf vlan-id { - type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; - } - mandatory true; - description - "O-RU's VLAN-ID used for Ethernet based flow"; - } - leaf o-du-mac-address { - type yang:mac-address; - mandatory true; - description - "O-DU's MAC address used for Ethernet based flow"; + leaf sro-id { + if-feature feat:SHARED-ORU-MULTI-OPERATOR; + type leafref { + path "/or-user:users/or-user:user/or-user:sro-id"; } + description + "The identity of a shared resource operator. When present, + indicates that the list entry corresponds to a processing element + associated with a shared resource operator where the sro-id identifies + the specific shared resource operator"; } - container udpip-flow { - when "../../../transport-session-type = 'UDPIP-INTERFACE'"; - description "leafs for UDP/IP type data flows"; - choice address { - leaf ru-ipv4-address { - type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv4/ip:address/ip:ip"; - } - description "O-RU's IPv4 address"; - } - leaf ru-ipv6-address { - type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/ip:ipv6/ip:address/ip:ip"; - } - description "O-RU's IPv6 address"; - } - mandatory true; - description "choice of O-RU IPv4 or IPv6 address"; - } - leaf o-du-ip-address { - type inet:ip-address; - mandatory true; - description "O-DU's IPv address"; - } - leaf ru-ephemeral-udp-port { - type inet:port-number; - mandatory true; - description - "ephemeral port used by O-RU"; - } - leaf o-du-ephemeral-udp-port { - type inet:port-number; - mandatory true; - description - "ephemeral port used by O-DU"; - } - leaf ecpri-destination-udp { - type inet:port-number; - mandatory true; - description "the well known UDP port number used by eCPRI"; - // fixme - add in a default when allocated by IANA - } - } - container north-eth-flow { - when "../../../transport-session-type = 'SHARED-CELL-ETH-INTERFACE'"; - if-feature "SHARED_CELL"; - description "leafs for mac + vlan-id type data flows"; - leaf ru-mac-address { + container transport-flow { + description + "container for the transport-flow used for CU plane"; + leaf interface-name { type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address"; + path "/if:interfaces/if:interface/if:name"; } - description - "O-RU's MAC address used for Ethernet based flow"; - } - leaf vlan-id { - type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; - } - description - "O-RU's VLAN-ID used for Ethernet based flow"; - } - leaf north-node-mac-address { - type yang:mac-address; - description - "North-node's MAC address used for Ethernet based flow"; - } - } - container south-eth-flow { - when "../../../transport-session-type = 'SHARED-CELL-ETH-INTERFACE'"; - if-feature "SHARED_CELL"; - description "leafs for mac + vlan-id type data flows"; - leaf ru-mac-address { - type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:mac-address"; - } - description - "O-RU's MAC address used for Ethernet based flow"; - } - leaf vlan-id { - type leafref { - path "/if:interfaces/if:interface[if:name = current()/../../interface-name]/o-ran-int:vlan-id"; - } - description - "O-RU's VLAN-ID used for Ethernet based flow"; - } - leaf south-node-mac-address { - type yang:mac-address; - description - "south-node's MAC address used for Ethernet based flow"; + description "the interface name "; } + uses non-shared-cell-flow-group; } } } } -// top level container +// top-level container container processing-elements { description diff --git a/radio/fhi_72/mplane/yang/models/o-ran-uplane-conf.yang b/radio/fhi_72/mplane/yang/models/o-ran-uplane-conf.yang index 16fbaf3335..c473e0e14c 100644 --- a/radio/fhi_72/mplane/yang/models/o-ran-uplane-conf.yang +++ b/radio/fhi_72/mplane/yang/models/o-ran-uplane-conf.yang @@ -13,12 +13,34 @@ module o-ran-uplane-conf { import o-ran-module-cap { prefix "mcap"; - revision-date 2020-08-10; } import o-ran-compression-factors { prefix "cf"; - revision-date 2020-08-10; + } + + import o-ran-wg4-features { + prefix "feat"; + } + + import ietf-hardware { + prefix "hw"; + } + + import o-ran-hardware { + prefix "or-hw"; + } + + import o-ran-usermgmt { + prefix "or-user"; + } + + import o-ran-common-yang-types { + prefix "o-ran-cmn"; + } + + import o-ran-delay-management { + prefix "or-dm"; } organization "O-RAN Alliance"; @@ -30,7 +52,7 @@ module o-ran-uplane-conf { "This module defines the module capabilities for the O-RAN Radio Unit U-Plane configuration. - Copyright 2020 the O-RAN Alliance. + Copyright 2024 the O-RAN Alliance. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -56,6 +78,198 @@ module o-ran-uplane-conf { contributors may be used to endorse or promote products derived from this software without specific prior written permission."; + revision "2024-08-12" { + description + "version 16.0.0 + + 1) add up-link performance improvement functionality, including DMRX-BF-EQ and DMS-BF-NEQ features + 2) Introduction of capabilities and configuration for SE27 O-DU controlled dimensionality reduction + 3) add support for se-20-multi-sd-punc-pattern + 4) add support for VSWR thresholds"; + + reference "ORAN-WG4.M.0-v16.00"; + } + + revision "2024-04-15" { + description + "version 15.0.0 + + 1) add support for sending prgSize in SE-21 with ST 5 and ST6. + 2) add support for for beamforming list and delay profiles(s) per endpoint. + 3) add support for user-group optimization. + 4) add support for multiple beamid tables. + 5) support pass band for filterindex09 per scs. + 6) support for M-plane based TRX control for Network Energy Saving. + 7) clarified cp-type is not applicable for ST3 or ST0 + 8) Changed description of max-beams-per-symbol/slot, so they refer to + 'different beamId values' instead of 'beams' + 9) added new leafs called max-beams-per-symbol-multiple-beamid-tables + and max-beams-per-slot-multiple-beamid-tables"; + + reference "ORAN-WG4.M.0-v15.00"; + } + + revision "2023-12-11" { + description + "version 14.0.0 + + 1) Corrected the configurable-tdd-pattern-supported leafref to point + to static-low-level-tx-endpoints + 2) Clarify reference for supported-frame-structures + 3) introduce max-prb-blks-per-sec-ext-23 and se-23-prb-block-mode-supported + 4) Introduction of new energy saving sub-use case - Data Layer control"; + + reference "ORAN-WG4.M.0-v14.00"; + } + + revision "2023-08-14" { + description + "version 13.0.0 + + 1) clarification for I/Q bitwidth parameter + 2) clarification of ul-fft-sampling-offset parameter + 3) adding availability status to carrier operational data and notifications + 4) ability to disable sequence number checking + 5) Introduction of TRX-Control and Advanced Sleep Mode for network energy savings"; + + reference "ORAN-WG4.M.0-v13.00"; + } + + revision "2023-04-10" { + description + "version 12.0.0 + + 1) Typographical corrections + 2) NB-IoT introduction + 3) clarify PRACH repetitions + 4) support for non-scheduled-ueid + 5) continuity bit information in Section Extension 11 + 6) U-Plane Processing Limits"; + + reference "ORAN-WG4.M.0-v12.00"; + } + + revision "2022-12-05" { + description + "version 11.0.0 + + 1) PRB range limit for SE 12 and HP section + 2) Introduction of PRB ranges + 3) uplane-only-dl-mode-enable + 4) Deprecation of power-related capabilities and addition of min-gain + 5) se 23 max mplane limits + 6) support Section Type 4 and associated commands"; + + reference "ORAN-WG4.M.0-v11.00"; + } + + revision "2022-08-15" { + description + "version 10.0.0 + + 1) clarified description statements for representative-t/rx-eaxc-id + 2) clarified description statements for max-num-t/rx-eaxc-ids-per-group + 4) clarified description statements for component carrier + 5) style guide corrections + 6) introduction of O-RU connector functionality + 7) fixing constraints + 8) introducing new feature for ACK NACK feedback + 9) added SHARED-ORU-MULTI-OPERATOR anf SHARED-ORU-MULTI-ODU features"; + + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2022-04-18" { + description + "version 9.0.0 + + 1) Descriptions fixed for max-beam-updates-per-slot / max-beam-updates-per-slot + 2) Added references to CUS-Plane spec for parameters 'frame-structure' and + 'supported-frame-structures' + 3) clarified max-beams-per-symbol, max-beams-per-slot, max-beam-updates-per-slot, + max-beam-updates-per-symbol parameters + 4) Clarification of cp-length and cp-length-other + 5) deprecation of rw-type and rw-duplex-scheme"; + + reference "ORAN-WG4.M.0-v09.00"; + } + + revision "2021-12-01" { + description + "version 8.0.0 + + 1) Various descriptions corrected and/or clarified + 2) Configuration for Beamforming weights were added together with changes and updates to compressions + 3) Added new leaf node 'beam-update-contention-control-limits-required' to 'endpoint-types' + to indicate endpoint capability to support beam update contention control processing limits. + 4) Added instance of 'beam-update-contention-control-limits' to 'endpoint-types'. + 5) Added new leaf node boolean flag 'beam-update-contention-control-enabled' for O-DU to indicate + support of feature BEAM-UPDATE-CONTENTION-CONTROL feature. + 6) deprecate 'channel-information-iq-bitwidth' , and define a new parameter + 'channel-information-bitwidth' under the container 'compression' + 7) add capability and configuration for channel information PRB granularity. + 8) Add support for multiple transport-session-type per O-RU. + 9) add capability and configuration for channel information compression. + 10) deprecate 'channel-information-iq-bitwidth' , and define a new parameter + 'channel-information-bitwidth' under the container 'compression'"; + + reference "ORAN-WG4.M.0-v08.00"; + } + + revision "2021-07-26" { + description + "version 7.0.0 + + 1) Added new grouping 'per-cplane-message-limits' containing params to limit + per C-Plane packet processing when CPLANE-MESSAGE-PROCESSING-LIMITS feature is + supported by O-RU and used by O-DU. + 2) Added new leaf node 'cplane-message-processing-limits-required' to 'endpoint-types' + to indicate endpoint capability to support C-Plane message processing limits. + 3) Added instances of 'per-cplane-message-limits' to 'endpoint-types' and + 'endpoint-capacity-sharing-groups'. + 4) Added new leaf node to low-level-tx/rx-endpoint 'cplane-message-processing-limits-enabled' + for O-DU to configure support for C-Plane limits + 5) Added t-da-offset and t-au-offset for external antenna support + 6) Added Channel IQ bitwidth for ST6 + 7) Added ordered-by user to leaf-list member-tx-eaxc-id and leaf-list member-rx-eaxc-id + 8) Added new PRACH formats + 9) Ensuring beam-ids can only be 15 bits + 10) Clarify mixed numerology restrictions"; + + reference "ORAN-WG4.M.0-v07.00"; + } + + + revision "2021-03-22" { + description + "version 6.0.0 + + 1) typographical corrections in descriptions. + 2) Updates to transmission window control. + 3) Introduces to existing grouping 'endpoint-section-capacity' two new leaf nodes 'max-uplane-section-header-per-symbol' and + 'max-uplane-section-header-per-slot' to limit U-Plane data section header addition/parsing. + 4) deprecated parameter 'max-remasks-per-section-id' since it is duplicate of leaf node 'max-control-sections-per-data-section'. + 5) introduces new leaf nodes 'max-beams-updates-per-slot' and ''max-beams-updates-per-symbol' + to grouping 'endpoint-beam-capacity' + 6) added new SRS features: + STATIC-TRANSMISSION-WINDOW-CONTROL + DYNAMIC-TRANSMISSION-WINDOW-CONTROL + UNIFORMLY-DISTRIBUTED-TRANSMISSION + ORDERED-TRANSMISSION + INDEPENDENT-TRANSMISSION-WINDOW-CONTROL"; + + reference "ORAN-WG4.M.0-v06.00"; + } + + revision "2020-12-10" { + description + "version 5.0.0 + + 1) introduces new coupling method coupling-via-frequency-and-time-with-priorities-optimized + 2) introduces new max-highest-priority-sections-per-slot parameter"; + + reference "ORAN-WG4.M.0-v05.00"; + } revision "2020-08-10" { description @@ -209,6 +423,18 @@ module o-ran-uplane-conf { description "5GNR PRACH Preamble format C2"; } + enum LTE-NB0-a { + description + "LTE Narrowband PRACH format 0-a"; + } + enum LTE-NB1-a { + description + "LTE Narrowband PRACH format 1-a"; + } + enum LTE-NB2 { + description + "LTE Narrowband PRACH format 2"; + } } description @@ -233,6 +459,270 @@ module o-ran-uplane-conf { description "Type definition for polarisations"; } + typedef beamforming-method-type { + type enumeration { + enum NOBF { + description + "No beamforming."; + } + enum PDBF { + description + "Predefined-beam beamforming."; + } + enum WDBF { + description + "Weight-based dynamic beamforming (based on real-time-updated weights)."; + } + enum ABBF { + description + "Attribute-based dynamic beamforming (based on real-time-updated beam attributes)."; + } + enum CIBF { + description + "Channel-information-based beamforming."; + } + enum DMRS_BF_EQ { + description + "DMRS-based beamforming with equalization."; + } + enum DMRS_BF_NEQ { + description + "DMRS-based beamforming without equalization."; + } + } + description + "Type definition for beamforming method."; + } + + typedef symb-reorder-capability { + type enumeration { + enum PER-TX-WIN-SYMB-REORDER-WITH-DMRS-SENDING { + description + "per-window symbol reordering when sending of port-reduced DMRS data is enabled, + please refer to clause 7.7.25.2 of the CUS-Plane Specification."; + } + enum PER-TX-WIN-SYMB-REORDER-WITHOUT-DMRS-SENDING { + description + "per-window symbol reordering when sending of port-reduced DMRS data is not enabled, + please refer to clause 7.7.25.2 of the CUS-Plane Specification."; + } + enum PER-SECTION-TX-WINDOW-REASSIGNMENT { + description + "per-section tx-window reassignment, please refer to clause 7.7.25.3 of the CUS-Plane + Specification."; + } + } + description + "Type definition for symbol reordering method supported."; + } + typedef symb-reorder-method { + type enumeration { + enum PER-TX-WIN-SYMB-REORDERG { + description + "per-window symbol reordering, + please refer to clause 7.7.25.2 of the CUS-Plane Specification."; + } + enum PER-SECTION-TX-WINDOW-REASSIGNMENT { + description + "per-section tx-window reassignment, please refer to clause 7.7.25.3 of the CUS-Plane + Specification."; + } + } + description + "Type definition for symbol reordering method configured."; + } + typedef up-SymbolId-type { + type enumeration { + enum OVER-AIR-SYMBOL-NUMBER { + description + "U-plane symbol Id interpretation as on-air symbol number for symbol reordering."; + } + enum TRANSMISSION-WINDOW-NUMBER { + description + "U-plane symbol Id interpretation as transmission window number for symbol reordering."; + } + } + description + "Type definition for symbol reordering symbol Id interpretation capability."; + } + + typedef user-group-self-assembly-mode { + type enumeration { + enum SELF-ASSEMBLY-WITH-GROUP-ID { + description + "The mode in which the O-RU is capable of assembling user groups using 'usrGroupId' and + 'usrGroupSize' fields in SE-24."; + } + enum SELF-ASSEMBLY-WITHOUT-GROUP-ID { + description + "The mode in which O-RU is capable of assembling user groups without using 'usrGroupId' and 'usrGroupSize' + fields in SE-24, but instead relying on PRB ranges of all UE layers overall all section for assembling + user groups."; + } + } + description + "Possible values for user group self assembly modes that the O-RU can support."; + } + + typedef rrm-meas-types { + type enumeration { + enum MEAS-UE-TAE { + value 0; + description + "UE timing advance error per UE, per slot"; + } + enum MEAS-UE-LAYER-POWER { + value 1; + description + "UE layer signal power per layer,per slot"; + } + enum MEAS-UE-FREQ-OFFSET { + value 2; + description + "UE frequency offset per UE, per slot"; + } + enum MEAS-IPN-ALLOC { + value 3; + description + "Interference plus Noise for allocated PRBs,per slot or per DMRS symbol group"; + } + enum MEAS-IPN-UNALLOC { + value 4; + description + "Interference plus Noise for unallocated PRBs, per slot or per set of symbols in a slot"; + } + enum MEAS-ANT-DMRS-SNR { + value 5; + description + "DMRS Signal to Noise Ratio per antenna, per layer. "; + } + } + description + "RRM measurement types, refer to CUS spec table 9.2.1-1 for details"; + } + + grouping transmission-buffering-capacity { + description + "UL U-plane buffering capacity available for scheduled transmission of UL U-plane messages"; + + list transmission-buffering-capacity { + description + "Buffering capacity for specific IQ format. + If the list does not contain an entry for particular IQ format than endpoint + or group of endpoints then buffering capacity for this IQ format is + max-buffered-prbs = 0 and max-buffered-symbols = 0."; + + uses cf:compression-details; + + leaf max-buffered-prbs { + type uint32; + description + "Max number of PRBs (for IQ format given in compression-details) that can be buffered by an endpoint + or buffered collectively by group of endpoints sharing capacity. This is divided between symbols buffered"; + } + + leaf max-buffered-symbols { + type uint32; + description + "Max number of symbols (for IQ format given in compression-details) that can be buffered by an endpoint + or buffered collectively by group of endpoints sharing capacity"; + } + } + } + + grouping mplane-trx-control-supp-antenna-masks { + description + "A grouping containing list of antenna masks supported by the O-RU"; + + list mplane-supported-trx-control-masks { + key "index"; + description + "List of supported M-Plane controlled TRX control masks."; + + leaf index { + type uint8; + description + "Index to the list of antenna masks"; + } + + leaf antenna-mask { + type binary; + description + "M-Plane controlled O-RU supported antenna mask value."; + } + } + } + grouping array-config-group { + description + "This group represents configuration for supported arrays, + e.g. mplane trx control mask for supported arrayes"; + + list tx-array-antenna-mask-config { + if-feature feat:MPLANE-TRX-CONTROL; + key array-name; + description + "List of mplane configured trx antenna mask for supported arrays"; + + leaf array-name { + type leafref { + path "/user-plane-configuration/tx-arrays/name"; + require-instance false; + } + description + "Unique name of tx-array. "; + } + leaf antenna-bitmask { + type binary; + description + "If mplane-supported-trx-control-masks list is not advertised as part of capability for the referred [tr]x-array,parameter antenna-bitmask may be used for configuration. + The parameter antenna-bitmask-index shall not be used for configuration. + The antenna mask contains as many binary values as number of array elements associated + with respective tx or rx-array. Value of '1' indicates antenna element shall be + kept active and value of '0' indicates antenna element should be turned inactive. + Refer clause 20.3.2 of M-Plane specification."; + } + leaf antenna-bitmask-index { + type uint8; + description + "If mplane-supported-trx-control-masks list is advertised as part of capability for the referred [tr]x-array, + the parameter antenna-bitmask-index may be used for configuration to refer to the index of advertised mplane-supported-trx-control-masks. + The parameter antenna-bitmask shall not be used for configuration."; + } + } + list rx-array-antenna-mask-config { + if-feature feat:MPLANE-TRX-CONTROL; + key array-name; + description + "List of mplane configured trx antenna mask for supported arrays"; + leaf array-name { + type leafref { + path "/user-plane-configuration/rx-arrays/name"; + require-instance false; + } + description + "Unique name of rx-array. "; + } + + leaf antenna-bitmask { + type binary; + description + "If mplane-supported-trx-control-masks list is not advertised as part of capability for the referred [tr]x-array,parameter antenna-bitmask may be used for configuration. + The parameter antenna-bitmask-index shall not be used for configuration. + The antenna mask contains as many binary values as number of array elements associated + with respective tx or rx-array. Value of '1' indicates antenna element shall be + kept active and value of '0' indicates antenna element should be turned inactive. + Refer clause 20.3.2 of M-Plane specification."; + } + leaf antenna-bitmask-index { + type uint8; + description + "If mplane-supported-trx-control-masks list is advertised as part of capability for the referred [tr]x-array, + the parameter antenna-bitmask-index may be used for configuration to refer to the index of advertised mplane-supported-trx-control-masks. + The parameter antenna-bitmask shall not be used for configuration."; + } + } + } + grouping general-config { description "a group for general configuration"; @@ -243,8 +733,8 @@ module o-ran-uplane-conf { type boolean; default false; description - "Informs if regularizationfactor in section extension is configured(true) or not(false), this - leaf indicates whether the O-DU will send the regularizationfactor in section extension. + "Informs if regularization factor in section extension is configured(true) or not(false), this + leaf indicates whether the O-DU will send the regularization factor in section extension. If the O-RU does not support regularization-factor-se-supported in o-ran-module-cap.yang, this leaf is ignored."; @@ -260,7 +750,204 @@ module o-ran-uplane-conf { for all UL and DL C/U plane data flows. If little endian byte order is NOT supported, this node is ignored - (and the default bigendian byte order used)"; + (and the default big endian byte order used)"; + } + + leaf uplane-only-dl-mode-enable { + if-feature feat:UPLANE-ONLY-DL-MODE; + type boolean; + default false; + description + "If set to true, enable IQ data transfer without C-Plane in DL for all + endpoints as specified in the CUS specification clause 8.2.2."; + } + + leaf st4-for-time-domain-beamforming-weights-enabled { + if-feature feat:ST4-SLOT-CONFIG-MSG-SUPPORT; + type boolean; + default false; + description + "If O-RU indicates support for Section Type 4 command 'TIME_DOMAIN_BEAM_CONFIG' , O-DU may + configure the O-RU to use Section Type 4 TIME_DOMAIN_BEAM_CONFIG command by setting this + flag to 'true'. In which case, O-DU shall use only Section Type 4 TIME_DOMAIN_BEAM_CONFIG + for specifying time-domain beam information. refer to clause 12.4.3.4.4 of CUS-Plane spec."; + } + + leaf seq-id-checking-disabled { + if-feature feat:SEQ-ID-CHECKING-CONFIGURABLE; + type boolean; + default false; + description + "When the parameter has value true, sequence number checking is disabled."; + } + + leaf multiple-beamId-tables-support-enabled { + if-feature feat:MULTIPLE-BEAMID-TABLES-SUPPORTED; + type boolean; + default false; + description + "When the parameter has value true, O-DU will be able to use multiple beamId table capability of O-RU. + O-DU shall be able to associate specific [tr]x-array-carrier with specific beamId table indexes advertised + which are advertised in 'tx-array-beamId-table-indexes/rx-array-beamId-table-indexes' as part of tx-array + and rx-array capabilities."; + } + + leaf-list energy-sharing-groups-disabled { + if-feature feat:MPLANE-DATA-LAYER-CONTROL; + type uint8; + description + "A list that indicates which energy sharing groups are currently switched off due to data layer control energy saving. + By default this list is empty and means that no data layer control energy saving is currently ongoing. + This value shall be specific values from the list of 'energy-sharing-group-id' advertised by O-RU + inside respective static-low-level-[tr]x-endpoints."; + } + + leaf config-symb-reorder-method { + if-feature "feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ"; + type symb-reorder-method; + description + "Indicated which symbol reordering method is used. If it's not configured, O-RU shall + operate with natural order."; + } + leaf config-symb-reorder-upSymbId-type { + when "../config-symb-reorder-method = 'PER-TX-WIN-SYMB-REORDERG'"; + if-feature "feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ"; + type leafref { + path "../../endpoint-types/supported-symb-reorder-capabilities/up-symbolId-type-supported"; + require-instance false; + } + description + "Indicated which config-symb-reorder-upSymbId-type intended to be used for symbol reordering, + i.e. either 'on-air symbol number' or 'transmission window number' to the O-RU. + When 'per-section tx-window reassignment' method is used, + the U-Plane symbolId interpretation shall be configured as 'on-air symbol number' + Please refer to clause 7.7.25 in CUS plane for details."; + } + + leaf ueid-persistence-enabled { + if-feature feat:UEID-PERSISTENCE; + type boolean; + description + "Indicates if ueId persistance over multiple slots is enabled. + See CUS-Plane clause 7.7.24.10."; + } + + leaf ueid-layer-bits-configured { + if-feature "feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ"; + type uint8; + description + "This parameter specified the number of bits configured by the O-DU for specifying ueid layers."; + } + + container vswr-thresholds{ + if-feature feat:CONFIGURABLE-VSWR-THRESHOLDS; + description "VSWR thresholds parameters."; + container default-vswr-thresholds { + config false; + leaf default-vswr-minor-threshold { + type decimal64 { + fraction-digits 1; + } + description + "Default VSWR minor threshold."; + } + leaf default-vswr-major-threshold { + type decimal64 { + fraction-digits 1; + } + description + "Default VSWR major threshold."; + } + description + "Default VSWR thresholds used by this O-RU"; + } + container vswr-thresholds-range { + config false; + leaf min { + type decimal64 { + fraction-digits 1; + } + description + "The lowest allowed VSWR threshold"; + } + leaf max { + type decimal64 { + fraction-digits 1; + } + description + "The highest allowed VSWR threshold"; + } + description + "VSWR thresholds shall be configured within this range"; + } + container configurable-vswr-thresholds{ + description "vswr monitoring parameters to be configured by O-RU Controller"; + leaf global-vswr-monitoring-trigger-power { + type decimal64 { + fraction-digits 1; + } + units dBm; + description + "Power threshold for enabling VSWR monitoring."; + } + leaf global-vswr-minor-threshold { + type decimal64 { + fraction-digits 1; + } + description + "configured VSWR minor threshold which will be used to trigger an alarm."; + } + leaf global-vswr-major-threshold { + type decimal64 { + fraction-digits 1; + } + description + "configured VSWR major threshold which will be used to trigger an alarm."; + } + list vswr-threshold-per-tx-array-element { + key "tx-array-name array-element"; + description + "individual vswr-thresholds configuration which will be applied to each tx array element"; + leaf tx-array-name { + type leafref { + path "/o-ran-uplane-conf:user-plane-configuration/o-ran-uplane-conf:tx-arrays/o-ran-uplane-conf:name"; + require-instance false; + } + description + "tx-array where the configured vswr thresholds will be applied"; + } + leaf array-element { + type uint16; + description + "the array-element number of the tx-array if there are multiple array-elements of the tx-array."; + } + leaf vswr-minor-threshold { + type decimal64 { + fraction-digits 1; + } + description + "configured VSWR minor threshold of the tx-array-element which will be used to trigger an alarm. + It shall override the configured global-vswr-minor-tresholds."; + } + leaf vswr-major-threshold { + type decimal64 { + fraction-digits 1; + } + description + "configured VSWR major threshold of the tx-array-element which will be used to trigger an alarm. + It shall override the configured global-vswr-major-tresholds."; + } + leaf vswr-monitoring-trigger-power { + type decimal64 { + fraction-digits 1; + } + units dBm; + description + "Power threshold for enabling VSWR monitoring. + it shall override the configured global-vswr-monitoring-trigger-power."; + } + } + } } } } @@ -389,15 +1076,21 @@ module o-ran-uplane-conf { description "Coupling via frequency and time with priorities. Can be used when coupling-via-frequency-and-time-with-priorities = true in o-ran-module-cap.yang"; } + enum FREQUENCY_AND_TIME_WITH_PRIORITIES_OPTIMIZED { + description "Coupling via frequency and time with priorities optimized. Can be used when + coupling-via-frequency-and-time-with-priorities-optimized = true in o-ran-module-cap.yang"; + } } default NORMAL; description "Method of coupling between C-Plane and U-Plane messages; see methods of coupling - of C-Plane and U-Plane in CUS-Plane specification"; + of C-Plane and U-Plane in CUS-Plane specification. If an O-RU doesn't support the + necessary capability as defined in o-ran-module-cap.yang, the O-RU shall respond + with rpc-error including an error-message describing the error condition"; } } - grouping eaxc { + grouping eaxc { description "One eAxC identifier (eAxC ID) comprises a band and sector identifier (BandSector_ID), a component-carrier identifier (CC_ID) and a @@ -409,11 +1102,11 @@ module o-ran-uplane-conf { Bit allocation is subdivided as follows: * O_DU_Port_ID: Used to differentiate processing units at O-DU * BandSector_ID: Aggregated cell identifier - * CC_ID: distinguishes Carrier Components + * CC_ID: distinguishes Component Carriers * RU_Port_ID: Used to differentiate spatial streams or beams on the O-RU The bitwidth of each of the above fields is variable this model is supposed to check - if we are occpying bits continuously but we do not have to occupy all 16 bits"; + if we are occupying bits continuously, but we do not have to occupy all 16 bits"; leaf o-du-port-bitmask { @@ -486,7 +1179,7 @@ module o-ran-uplane-conf { } units Meter; - description "Average distance between centers of nearby AE in horizontal direction (in array coordinates system)"; + description "Average distance between centres of nearby AE in horizontal direction (in array coordinates system)"; } leaf vertical-spacing{ @@ -495,7 +1188,7 @@ module o-ran-uplane-conf { } units Meter; - description "Average distance between centers of nearby AE in vertical direction (in array coordinates system)"; + description "Average distance between centres of nearby AE in vertical direction (in array coordinates system)"; } container normal-vector-direction { @@ -580,6 +1273,26 @@ module o-ran-uplane-conf { array is serving for. Intended use is to deal with multiband solutions."; } + + list related-o-ru-connectors { + key name; + + leaf name { + type leafref { + path '/hw:hardware/hw:component/hw:name'; + } + must "derived-from-or-self(deref(current())/../hw:class, 'or-hw:O-RU-ANTENNA-CONNECTOR')"; + description + "Referenced name of O-RU connector used by the antenna array."; + } + leaf-list array-element-id { + type uint16; + description + "Identifiers of array element(s) related to specific O-RU connector. Allowed values and semantic - as per CUS-Plane spec, clause 'Identification and Ordering of Array Elements'"; + } + description + "List of unique names that identify instances of O-RU's connectors the external [tr]x-array is reachable through."; + } } grouping array-choice { @@ -591,7 +1304,7 @@ module o-ran-uplane-conf { } description - "Leafref to tx array if such is choosen"; + "Leafref to tx array if such is chosen"; } } case rx { @@ -601,7 +1314,7 @@ module o-ran-uplane-conf { } description - "Leafref to rx array if such is choosen"; + "Leafref to rx array if such is chosen"; } } description @@ -619,10 +1332,7 @@ module o-ran-uplane-conf { type uint8; description - "This parameter defines the frame structure. The first 4 bits define the FFT/iFFT size - being used for all IQ data processing related to this message. - The second 4 bits define the sub carrier spacing as well as the number of slots per 1ms sub-frame - according to 3GPP TS 38.211, taking for completeness also 3GPP TS 36.211 into account"; + "This parameter provides value of frame structure. For semantics and allowed values see CUS-Plane Specification, clause 'frameStructure (frame structure)'"; } leaf cp-type { @@ -639,7 +1349,10 @@ module o-ran-uplane-conf { } description - "Provides type of CP (cyclic prefix) if section type 3 is not used or type of CP cannot be determined from cpLength."; + "Provides type of CP (cyclic prefix). + + For section type 3 or section type 0, element and the value of this leaf shall be ignored by the O-RU. In such circumstances, + please refer to clause 7.5.2.14 cpLength (cyclic prefix length) of the CUS-Plane Specification."; } leaf cp-length { @@ -647,8 +1360,15 @@ module o-ran-uplane-conf { units Ts; mandatory true; description - "Used for symbol 0 for NR & LTE, and symbol 7*2u for NR. - See CUS-plane"; + "Provides length of CP used for the first symbol after subframe boundary or half-subframe boundary. + See CUS-plane + + If a section type 3 is used in C-plane messages addressed to the endpoint, then O-RU takes length of CP from + C-Plane cpLength Information Element and the value of this leaf shall be ignored by the O-RU. See cpLength (cyclic prefix length) + in CUS-Plane for details. + + If a static configuration (see static-prach-configurations) is applicable to the endpoint, then O-RU takes + length of CP from M-Plane cp-length leaf in static-prach-configurations and the value of this leaf shall be ignored by the O-RU."; } leaf cp-length-other { @@ -656,14 +1376,26 @@ module o-ran-uplane-conf { units Ts; mandatory true; description - "Used for other symbols than by cp-length above"; + "Provides length of CP used for symbols other than provided by cp-length. + + If a section type 3 is used in C-plane messages addressed to the endpoint, then O-RU takes length of CP from + C-Plane cpLength Information Element and the value of this leaf shall be ignored by the O-RU. See cpLength (cyclic prefix length) + in CUS-Plane for details. + + If a static configuration (see static-prach-configurations) is applicable to the endpoint, then O-RU takes + length of CP from M-Plane cp-length leaf in static-prach-configurations and the value of this leaf shall be ignored by the O-RU."; } leaf offset-to-absolute-frequency-center { type int32; mandatory true; description - "This provides value of freqOffset to be used if section type 3 is not used. See freqOffset in CUS-plane."; + "This provides value of freqOffset to be used if section type 3 is not used. See freqOffset in CUS-plane. + offset-to-absolute-frequency-center defines the relative spacing between the centre of RE#0 of RB#0 to the center-of-channel-bandwidth. + If offset-to-absolute-frequency-center for NR with SCS=15kHz is odd, + it implies that 7.5kHz shift as indicated by the 3GPP parameter frequencyShift7p5khz for UL is applied, + which means enable the NR UL transmission with a 7.5 kHz shift to the LTE raster, as defined in 3GPP TS 38.331. + When type (in tx/rx-array-carrier) is DSS, 'offset-to-absolute-frequency-center' indicates the 1st RE of 1st RB of NR."; } list number-of-prb-per-scs { @@ -684,23 +1416,53 @@ module o-ran-uplane-conf { description "Determines max number of PRBs that will be used in all sections per one symbol. This is affecting allocation of resources to endpoint. Value shall not exceed constrains - defined by max-prb-per-symbol of endpoint type. In addition sum (over all used epoints - within a group of endpoints sharing resources) of number-of-prb rounded up to + defined by max-prb-per-symbol of endpoint type. In addition, sum (over all used endpoints + within a group of endpoints sharing resources) of number-of-prb rounded up to the nearest value from prb-capacity-allocation-granularity shall not exceed max-prb-per-symbol of the group."; } } } + grouping occupied-bandwidth { + description + "Grouping describing occupied bandwidth of a carrier."; + + container occupied-bandwidth { + description + "Container describing occupied bandwidth of a carrier. + + Information conveyed in this container can be used to determine minimum filter bandwidth in case + it cannot be fully determined basing on the carrier bandwidth itself e.g., when NB-IoT carriers + are allocated in the carrier's guard band."; + + leaf lower-bound { + type uint64; + units Hz; + + description + "Lower bound of the filter pass bandwidth of a carrier."; + } + + leaf upper-bound { + type uint64; + units Hz; + + description + "Upper bound of the filter pass bandwidth of a carrier."; + } + } + } + grouping tx-common-array-carrier-elements { description - "This grouping containes all common parameters for tx-array-carriers and rx-array-carriers"; + "This grouping contains all common parameters for tx-array-carriers and rx-array-carriers"; leaf absolute-frequency-center { type uint32; - mandatory true; + status deprecated; description - "Absolute Radio Frequency Channel Number - indirectly indicates RF center carrier frequency of signal. - Reflected in arfcn."; + "deprecated in version 5.0.0 and replaced with offset-to-absolute-frequency-center + and common FREF translated from absolute-frequency-center (NREF) as defined in 38.104"; } leaf center-of-channel-bandwidth { @@ -708,7 +1470,10 @@ module o-ran-uplane-conf { units Hz; mandatory true; description - "Center frequency of channel bandwidth in Hz. Common for all numerologies."; + "Centre frequency of channel bandwidth in Hz. Common for all numerologies. + center-of-channel-bandwidth is the FREF translated from absolute-frequency-center (NREF) as per 3GPP TS 38.104. + Refer to Table 5: Centre Bandwidth Calculation in M-plane spec for calculation of this parameter + for even and odd number of PRBs in LTE, NR and DSS carrier configuration."; } leaf channel-bandwidth { @@ -738,9 +1503,9 @@ module o-ran-uplane-conf { default INACTIVE; description - "Indicates if transmission is enabled for this array carriers. Note that Netconf server uses state parameter + "Indicates if transmission is enabled for this array carriers. Note that NETCONF server uses state parameter to indicate actual state of array carriers operation. When array carriers is in sleep status, - Netconf server rejects all other operation request to tx-array-carriers object except either request to change from sleep + NETCONF server rejects all other operation request to tx-array-carriers object except either request to change from sleep to active status or delete MO operation (see 4.8) to the object."; } @@ -766,6 +1531,13 @@ module o-ran-uplane-conf { "Indicates state of array carriers activation operation"; } + leaf-list availability-status { + type o-ran-cmn:availability-status; + config false; + description + "indicates availability-status of array carrier"; + } + leaf type { type enumeration { enum NR { @@ -807,29 +1579,43 @@ module o-ran-uplane-conf { path "/user-plane-configuration/tx-array-carriers[name=current()/../name]" + "/duplex-scheme"; require-instance false; } + status deprecated; description - "Config true type of duplex scheme."; + "Config true type of duplex scheme. + Status is deprecated because 'lte-tdd-frame' container, where it was used, is also deprecated. + Additionally duplex-scheme is derived from the band-number."; } leaf rw-type { type leafref { path "/user-plane-configuration/tx-array-carriers[name=current()/../name]" + "/type"; require-instance false; } + status deprecated; description - "Config true type of carrier."; + "Config true type of carrier. + Status is deprecated because leafref is to a 'config true' schema-node"; + } + uses occupied-bandwidth; + + leaf configured-tx-beamId-table-index { + if-feature feat:MULTIPLE-BEAMID-TABLES-SUPPORTED; + type uint8; + description + "The value of beamId table index configured to be used by the O-DU for a given tx-array-carrier. + The value shall be chosen from the list 'tx-array-beamId-table-indexes' advertised by the O-RU."; } } grouping rx-common-array-carrier-elements { description - "This grouping containes all common parameters for tx-array-carriers and rx-array-carriers"; + "This grouping contains all common parameters for tx-array-carriers and rx-array-carriers"; leaf absolute-frequency-center { type uint32; - mandatory true; + status deprecated; description - "Absolute Radio Frequency Channel Number - indirectly indicates RF center carrier frequency of signal. - Reflected in arfcn."; + "deprecated in version 5.0.0 and replaced with offset-to-absolute-frequency-center + and common FREF translated from absolute-frequency-center (NREF) as defined in 38.104"; } leaf center-of-channel-bandwidth { @@ -837,7 +1623,10 @@ module o-ran-uplane-conf { units Hz; mandatory true; description - "Center frequency of channel bandwidth in Hz. Common for all numerologies."; + "Centre frequency of channel bandwidth in Hz. Common for all numerologies. + center-of-channel-bandwidth is the FREF translated from absolute-frequency-center (NREF) as per 3GPP TS 38.104. + Refer to Table 15.2.4-1: Centre Bandwidth Calculation in M-plane spec for calculation of this parameter + for even and odd number of PRBs in LTE, NR and DSS carrier configuration."; } leaf channel-bandwidth { @@ -867,9 +1656,9 @@ module o-ran-uplane-conf { default INACTIVE; description - "Indicates if transmission is enabled for this array carriers. Note that Netconf server uses state parameter + "Indicates if transmission is enabled for this array carriers. Note that NETCONF server uses state parameter to indicate actual state of array carriers operation. When array carriers is in sleep status, - Netconf server rejects all other operation request to tx-array-carriers object except either request to change from sleep + NETCONF server rejects all other operation request to tx-array-carriers object except either request to change from sleep to active status or delete MO operation (see 4.8) to the object."; } @@ -895,6 +1684,13 @@ module o-ran-uplane-conf { "Indicates state of array carriers activation operation"; } + leaf-list availability-status { + type o-ran-cmn:availability-status; + config false; + description + "indicates availability-status of array carrier"; + } + leaf type { type enumeration { enum NR { @@ -931,6 +1727,15 @@ module o-ran-uplane-conf { description "Type of duplex scheme O-RU supports."; } + uses occupied-bandwidth; + + leaf configured-rx-beamId-table-index { + if-feature feat:MULTIPLE-BEAMID-TABLES-SUPPORTED; + type uint8; + description + "The value of beamId table index configured to be used by the O-DU for a given rx-array-carrier. + The value shall be chosen from list 'rx-array-beamId-table-indexes' advertised by the O-RU."; + } } grouping endpoint-section-capacity { @@ -956,38 +1761,196 @@ module o-ran-uplane-conf { "Max number of sections within one slot that can be processed by endpoint or processed collectively by group of endpoints sharing capacity."; } + leaf max-highest-priority-sections-per-slot { + type uint16; + must "current() < ../max-sections-per-slot" { + error-message "the sectionID for the highest priority needs to be less than the max sectionIds per slot"; + } + description + "Max number of highest priority sections within one slot that can be processed by endpoint or processed collectively by + group of endpoints sharing capacity. This leaf applies only when coupling-via-frequency-and-time-with-priorities-optimized + is true, in other instances this leaf is ignored by the O-RU. The sectionId for highest priority section descriptions shall + start from 0 to specified max value and is a subset of max-sections-per-slot and must be less than max-sections-per-slot."; + } leaf max-remasks-per-section-id { type uint8 { range "1..12"; } default 12; + status deprecated; description "maximum number of different reMask values that is applied to a PRB within one section id. This value can be processed by endpoint - or processed collectively by group of endpoints sharing capacity"; + or processed collectively by group of endpoints sharing capacity. + This parameter is duplicated max-control-sections-per-data-section, hence being deprecated."; + } + leaf max-uplane-section-header-per-symbol { + type uint16; + description + "Maximum number of U-Plane data section header within one symbol that can be processed by an endpoint or processed collectively by group of + endpoints sharing capacity. Clarification for multiple U-Plane data section headers per C-Plane section description is specified in sectionId IE + description in CUS-Plane specification. For the cases where this optional parameter is not populated by O-RU or an older version O-DU does not + interpret this parameter, O-DU may optionally use max-sections-per-symbol as the default value to limit of U-Plane data section messages which + can be processed by the O-RU. If none of the above limitations are supported, O-RU and O-DU may rely on offline negotiation. + As an example, this parameter can be used to limit O-RU processing while using Section extension type#6 and #12, which are used for non-contiguous + PRB allocation, and hence results in multiple U-Plane data section headers for a given C-Plane section description."; + } + leaf max-uplane-section-header-per-slot { + type uint16; + description + "Maximum number of U-Plane data section headers within one slot that can be processed by an endpoint or processed collectively by group of + endpoints sharing capacity. Clarification for multiple U-Plane data section headers per C-Plane section description is specified in sectionId IE + description in CUS-Plane specification. For the cases where this optional parameter is not populated by O-RU or an older version O-DU does not + interpret this parameter, O-DU may optionally use max-sections-per-slot as the default value to limit of U-Plane data section messages which can + be processed by the O-RU. If none of the above limitations are supported, O-RU and O-DU may rely on offline negotiation. + As an example, this parameter can be used to limit O-RU processing while using Section extension type#6 and #12, which are used for non-contiguous + PRB allocation, and hence results in multiple U-Plane data section headers for a given C-Plane section description."; } description - "Parameters describing section capacity where section is undestood as number of different sectionId values"; + "Parameters describing section capacity where section is understood as number of different sectionId values. Additionally, max limits for U-Plane data sections + refer to U-Plane data section headers"; + } + + grouping endpoint-section-extension-limits { + leaf max-mcscaleremask-per-prb { + type uint16; + description + "This parameter limits the number of sets of {mcScaleReMask, csf, mcScaleOffset} values per symPrbPattern the O-RU can support when SE 23 is used in a + data section description. Refer to clause 7.7.23.1 of the CUS-Plane specification."; + } + leaf max-prb-ranges-per-sec-ext-12 { + type uint16; + description + "Optional parameter reported by O-RU which applies to Section Extension 12 and specifies + the maximum number of frequency ranges R per section description supported by O-RU. + If this limit is exceeded by the O-DU, the O-RU may send alarm notification with + 'fault-id = 31' to subscribers following the procedures defined in Clause 11 and + Table A.1-1 of O-RAN.WG4.MP.0. + As an example, the O-RU can include the following in the corresponding active-alarm list + entry and alarm-notification message: + Error C-Plane message + Maximum number of frequency ranges in SE-12 per section description exceeded + Reduce frequency ranges per section description used in SE-12"; + } + leaf max-freq-hops-per-sec-ext-13 { + type uint16; + description + "Optional parameter reported by O-RU which applies to Section Extension 13 and specifies + the maximum number of frequency hops R per section description supported by O-RU. + If this limit is exceeded by the O-DU, the O-RU may send alarm notification with + 'fault-id = 31' to subscribers following the procedures defined in Clause 11 and + Table A.1-1 of O-RAN.WG4.MP.0. + As an example, the O-RU can include the following in the corresponding active-alarm list + entry and alarm-notification message: + Error C-Plane message + Maximum number of frequency hops in SE 13 per section description exceeded + Reduce frequency hops per section description used in SE-13"; + } + + leaf max-prb-blks-per-sec-ext-23 { + if-feature feat:SE23-PRB-BLOCK-MODE-SUPPORT; + type uint16; + description + "Optional parameter reported by O-RU which applies to Section Extension 23 and specifies + the maximum number of prb blocks (Refer Clause 7.7.23.1 of CUS-Plane spec prb block) per + section description supported by O-RU. + If this limit is exceeded by the O-DU, the O-RU may send alarm notification with 'fault-id = 31' + to subscribers following the procedures defined in Clause 11 and + Table A.1-1 of O-RAN.WG4.MP.0. + As an example, the O-RU can include the following in the corresponding active-alarm list + entry and alarm-notification message: + Error C-Plane message + Maximum number of prb blocks in SE-23 per section description exceeded + Reduce prb blocks per section description used in SE-23"; + } + + description + "Parameters describing C-Plane section extension limits/capacities."; } grouping endpoint-beam-capacity { leaf max-beams-per-symbol { - type uint16; + type uint16 { + range "min .. 32767"; + } description - "Max number of beams within one symbol that can be processed by endpoint - or processed collectively by group of endpoints sharing capacity"; + "Max number of different beamId values within one symbol that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity + + If the parameter is absent or if value 0 is reported for the parameter, + then the endpoint does not support beamforming operation. + + The parameter doesn't apply if multiple-beamId-tables-support-enabled is set to true. + In such a case, max-beams-per-symbol-multiple-beamid-tables applies."; } leaf max-beams-per-slot { - type uint16; + type uint16 { + range "min .. 32767"; + } description - "Max number of beams within one slot that can be processed by endpoint - or processed collectively by group of endpoints sharing capacity"; + "Max number of different beamId values within one slot that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity + + If the parameter is absent or if value 0 is reported for the parameter, + then the endpoint does not support beamforming operation. + + The parameter doesn't apply if multiple-beamId-tables-support-enabled is set to true. + In such a case, max-beams-per-slot-multiple-beamid-tables applies."; + } + leaf max-beams-per-symbol-multiple-beamid-tables { + if-feature feat:MULTIPLE-BEAMID-TABLES-SUPPORTED; + type uint32; + description + "Max number of different beamId values within one symbol that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity. + beamId values associated with different beamId tables are always considered different. + + This parameter only applies if multiple-beamId-tables-support-enabled is set to true. + If multiple-beamId-tables-support-enabled is set to false, then max-beams-per-symbol applies."; + } + leaf max-beams-per-slot-multiple-beamid-tables { + if-feature feat:MULTIPLE-BEAMID-TABLES-SUPPORTED; + type uint32; + description + "Max number of different beamId values within one slot that can be processed by endpoint + or processed collectively by group of endpoints sharing capacity. + beamId values associated with different beamId tables are always considered different. + + This parameter only applies if multiple-beamId-tables-support-enabled is set to true. + If multiple-beamId-tables-support-enabled is set to false, then max-beams-per-slot applies."; + } + leaf max-beam-updates-per-slot { + type uint16 { + range "min .. 32767"; + } + description + "Max number of beams within one slot that can be updated by endpoint + or processed collectively by group of endpoints sharing capacity + + If the parameter is absent or if value 0 is reported for the parameter, + then the endpoint does not support beamforming operation."; + } + leaf max-beam-updates-per-symbol { + type uint16 { + range "min .. 32767"; + } + description + "Max number of beams within one symbol that can be updated by endpoint + or processed collectively by group of endpoints sharing capacity + + If the parameter is absent or if value 0 is reported for the parameter, + then the endpoint does not support beamforming operation."; } description - "Parameters describing beam capacity where number of beams is understood as number of different beamId values"; + "Parameters describing beam capacity where number of beams is understood as number of different beamId values. + Parameters defined for beam updates shall be used to put a maximum limit on number of beam/beamIds which can be updated + every slot/symbol. Note: This parameter does not put any restriction on which beams/beamIds can be updated. + + If the parameters defining beam capacity and beam updates are absent or if value 0 is reported for the parameters + defining beam capacity and beam updates, then the endpoint does not support beamforming operation."; } grouping endpoint-prb-capacity { @@ -998,6 +1961,25 @@ module o-ran-uplane-conf { or processed collectively by group of endpoints sharing capacity"; } + leaf max-prb-ranges-per-symbol { + type uint32; + description + "Optional parameter reported by O-RU which indicates the maximum number of PRB ranges + that can be processed by single endpoint or processed collectively by group of endpoints + sharing capacity within one symbol. For details please see O-RAN WG4 CUS-Plane specification, + Clause 7.8.2.1.2 'Limits of number of PRB ranges'. + + In case CU-Plane traffic generated by the O-DU exceeds the limit, an O-RU is responsible + for sending alarm notification with 'fault-id = 31' to subscribers following the procedures + defined in Clause 11 and Table A.1-1 of O-RAN.WG4.MP.0. + + As an example, the O-RU can include the following in the corresponding active-alarm list + entry and alarm-notif message: + Error C-Plane message + max-prb-ranges-per-symbol exceeded + Reduce value of number of PRB ranges used per symbol"; + } + description "Attributes presenting processing capacity related to PRB."; } @@ -1017,6 +1999,111 @@ module o-ran-uplane-conf { is set to true."; } + grouping per-cplane-message-limits { + leaf max-beams-per-cplane-message { + type uint16; + description + "Maximum number of beams which can be received in one single C-Plane message. Number of beams, + may include only beamIds, only beam weights or mix of beamIds and beamweights being received by + an O-RU in a single C-Plane message. + To avoid application layer fragmentation of C-Plane message across the fronthaul, O-RU should + avoid setting this to a very low value. + As a usage scenario, an O-RU may choose to define only a few quantized values e.g. (128, 256). + If the value is set to 0 by O-RU, the O-DU need not restrict the number of beams it can send + in single C-Plane message (except limited by MTU size)."; + } + + leaf max-highest-priority-sec-per-cplane-message { + type uint16; + description + "Maximum number of highest priority sections which can be received in one single C-Plane message. + This leaf applies only when 'coupling-via-frequency-and-time-with-priorities' is true"; + } + + leaf max-beams-per-slot-with-cplane-limits { + type uint16; + description + "Maximum number of beams that are required to be processed by endpoint or processed collectively + by group of endpoints sharing capacity when O-DU enables C-Plane limits. This value should replace + 'max-beams-per-slot' defined in 'endpoint-beam-capacity'"; + } + + leaf max-highest-priority-sections-per-slot-with-cplane-limits { + type uint16; + description + "Maximum number of highest priority sections that are required to be processed by endpoint or processed + collectively by group of endpoints sharing capacity when O-DU supports C-Plane limits. This value should + replace 'max-highest-priority-sections-per-slot' defined in 'endpoint-section-capacity'"; + } + + leaf max-num-se22-per-cplane-message { + type uint16; + description + "This value limits the max number of section extension 22 (ACK/NACK request) included in a C-Plane message as supported + by the endpoint or collectively by group of endpoints sharing capacity when O-DU enables C-Plane limits + and when section extension 22 (ACK/NACK request) and section type 8 (ACK/NACK feedback) are supported by the endpoint or endpoint sharing group."; + } + + leaf max-prb-ranges-per-hp-section-sec-ext-12 { + type uint16; + description + "Optional parameter reported by O-RU which applies to Section Extension 12 and specifies the + maximum number of frequency ranges R per highest priority section description supported by O-RU. + If this limit is exceeded by the O-DU, the O-RU is responsible for sending alarm notification + with 'fault-id = 31' to subscribers following the procedures defined in Clause 11 and + Table A.1-1 of O-RAN.WG4.MP.0. + As an example, the O-RU can include the following in the corresponding active-alarm list + entry and alarm-notification message: + Error C-Plane message + Maximum number of frequency hops per highest priority section description exceeded + Reduce frequency range per highest section description"; + } + + description + "Attributes limit maximum instances of certain parameters contained in a C-Plane message e.g. beams, + highest priority sections. This limitation is useful for O-RUs which are packet processing based and are + dimensioned to handle fixed number of parameters contained in a C-Plane message. In addition, if O-DU supports + cplane limits, O-RU can operate more efficiently and endpoint capacity for applicable parameters are enhanced. + as specified by 'max-beams-per-slot-with-cplane-limits' and 'max-highest-priority-sections-per-slot-with-cplane-limits'"; + } + + + grouping per-uplane-message-limits { + leaf max-section-headers-per-uplane-message { + if-feature feat:UPLANE-MESSAGE-PROCESSING-LIMITS; + type uint16; + description + "Maximum number of section headers which can be received in one single U-Plane message."; + } + + description + "Attributes describe maximum instances of certian parameters contained in a U-Plane mesaage e.g. + number of section headers. Those limitations are required for O-RUs which are packet processing based and are + dimensioned to handle limited number of parameters contained in a U-Plane message. "; + } + + grouping beam-update-contention-control-limits { + leaf max-beams-per-symbol-with-beam-contention-control { + type uint16; + description + "Maximum number of beams within one symbol that can be processed by an endpoint or processed collectively + by group of endpoints sharing capacity when O-DU enables the O-RU feature BEAM-UPDATE-CONTENTION-CONTROL. + This value should replace 'max-beams-per-symbol' defined in 'endpoint-beam-capacity'"; + } + + leaf max-beams-updates-per-symbol-with-beam-contention-control { + type uint16; + description + "Maximum number of beams within one symbol that can be updated by an endpoint or processed collectively + by group of endpoints sharing capacity when O-DU enables the O-RU feature BEAM-UPDATE-CONTENTION-CONTROL. + This value should replace 'max-beam-updates-per-symbol' defined in 'endpoint-beam-capacity'"; + } + + description + "If O-DU supports BEAM-UPDATE-CONTENTION-CONTROL, O-RU can operate more efficiently and endpoint capacity for applicable + parameters are enhanced."; + } + grouping endpoint-static-config-support { leaf static-config-supported { type enumeration { @@ -1047,7 +2134,16 @@ module o-ran-uplane-conf { when "(/user-plane-configuration/static-low-level-rx-endpoints[name=current()/../name]/static-config-supported = 'PRACH')"; type uint8; description - "Maximum number of PRACH patterns the endpoint can handle in PRACH configuration"; + "Maximum number of PRACH patterns the endpoint can handle in PRACH configuration. + Due to limited range of the parameter, an O-DU should use extended-max-prach-patterns parameter."; + } + + leaf extended-max-prach-patterns { + when "(/user-plane-configuration/static-low-level-rx-endpoints[name=current()/../name]/static-config-supported = 'PRACH')"; + if-feature feat:EXTENDED-PRACH-CONFIGURATION; + type uint32; + description + "Maximum number of PRACH patterns the endpoint can handle in PRACH configuration if EXTENDED-STATIC-PRACH is supported."; } leaf max-srs-patterns { @@ -1063,6 +2159,7 @@ module o-ran-uplane-conf { grouping endpoint-tdd-pattern-support { leaf configurable-tdd-pattern-supported { + if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; type boolean; default false; @@ -1085,6 +2182,482 @@ module o-ran-uplane-conf { TDD patterns and limitations regarding common TDD switching per groups of endpoints."; } + grouping u-plane-transmission-control { + description + "Configuration for UL U-plane transmission control"; + + leaf transmission-window-control { + if-feature "feat:STATIC-TRANSMISSION-WINDOW-CONTROL or feat:DYNAMIC-TRANSMISSION-WINDOW-CONTROL"; + type enumeration { + enum NONE { + description + "O-RU will use normal transmission type with normal transmission window"; + } + enum STATIC { + if-feature feat:STATIC-TRANSMISSION-WINDOW-CONTROL; + description + "O-RU will use transmission window offset and size and transmission type as configured over M-plane"; + } + enum DYNAMIC { + if-feature feat:DYNAMIC-TRANSMISSION-WINDOW-CONTROL; + description + "O-RU will use transmission window offset and size and transmission type as requested over C-plane"; + } + } + default NONE; + + description + "Selects type of UL U-plane transmission window control for the endpoint"; + } + + leaf transmission-window-schedule { + when "(../transmission-window-control = 'STATIC')"; + if-feature feat:STATIC-TRANSMISSION-WINDOW-CONTROL; + type union { + type empty; + type leafref { + path "/user-plane-configuration/transmission-window-schedules/id"; + } + } + description + "Identifies U-plane transmission window schedule (which provides a list of symbol-specific offsets) + to be used by the endpoint. + Symbol-specific offset values from the schedule are added to endpoint specific offset value + from transmission-window-offset. + If this element is not present, the O-RU assumes as all symbol specific offsets are zero. + For restrictions on values of symbol-specific offsets see description of transmission-window-offset. + This parameter shall not be set to value other than empty if transmission control is not enabled + by transmission-window-control."; + } + + leaf transmission-window-offset { + when "(../transmission-window-control = 'STATIC')"; + if-feature feat:STATIC-TRANSMISSION-WINDOW-CONTROL; + type uint16; + units "number of symbols"; + default 0; + description + "Transmission window offset. + The effective symbol-specific offset is sum of endpoint-specific offset value from transmission-window-offset + and symbol-specific offset from transmission-window-schedules referenced by transmission-window-schedule. + + If this element is not present then O-RU assumes transmission-window-offset is zero. + This parameter shall not be set to value other than 0 if transmission control is not enabled + by transmission-window-control. + + There is no direct upper bound for this parameter (except value range defined by leaf type) but there are + restrictions on combination of values of transmission-window-offset, transmission-window-offset, + symbol-specific offset from transmission-window-schedules and transmission-window-size. + + Specifically, if endpoint is set for delay managed operation (non-time-managed-delay-enabled = FALSE) + then O-RU handles U-Plane transmission as delay managed traffic and combination of values of + transmission-window-offset, symbol-specific offset from transmission-window-schedules and + transmission-window-size must not exceed O-RU buffering capacity (transmission-buffering-capacity) + for the requested reception schedule. + + If endpoint is set for non-delay managed operation (non-time-managed-delay-enabled = TRUE) + then O-RU handles U-Plane transmission on best effort basis. In this case any combination of values + of transmission-window-offset, symbol-specific offset from transmission-window-schedules and + transmission-window-size is permitted. This does not remove restrictions on parameters due to restrictions + defined for value type or restrictions that depend on INDEPENDENT-TRANSMISSION-WINDOW-CONTROL feature + + Additional restrictions on values (and presence) of transmission-window-schedule, transmission-window-offset + and transmission-window-size depend on presence of INDEPENDENT-TRANSMISSION-WINDOW-CONTROL feature. + + If INDEPENDENT-TRANSMISSION-WINDOW-CONTROL feature is not supported then all endpoints with + transmission control enabled that handle the same carrier type and SCS must be configured + (via M-plane or C-plane) with parameter values resulting in transmission windows that coincide + between the endpoints. That is, for every symbol N, the effective transmission window for symbol N + must be shared (start at the same time and end at the same time) by all the endpoints handling + same carrier type and SCS. This restriction applies only to endpoints that have transmission + control enabled. + + If INDEPENDENT-TRANSMISSION-WINDOW-CONTROL feature is supported then restriction described + above does not apply and a different transmission window (window offset and window size) + can be used for every endpoint capable of transmission window control."; + } + + leaf transmission-window-size { + when "(../transmission-window-control = 'STATIC')"; + if-feature feat:STATIC-TRANSMISSION-WINDOW-CONTROL; + type uint16 { + range "0..10000"; + } + units "microsecond"; + default 0; + description + "Transmission window size to be used; only values that are compatible with SCS used + for the endpoint are allowed. + Minimum supported value is determined by SCS specific transmission window size + reported by O-RU in ru-delay-profile. + + Client can use special value 0 (zero) instead of the SCS specific transmission window + size reported by O-RU in ru-delay-profile with the same effect. + This parameter shall not be set to value other than 0 if transmission control is not enabled + (transmission-window-control = NONE) or the endpoint is set for non-delay managed operation + (non-time-managed-delay-enabled = TRUE). + + There is no direct upper bound for this parameter (except value range defined by leaf type) but there are + restrictions on combination of values of transmission-window-offset, transmission-window-offset, + symbol-specific offset from transmission-window-schedules and transmission-window-size. + See description of transmission-window-offset for more details."; + } + + leaf transmission-type { + when "(../transmission-window-control = 'STATIC')"; + if-feature "feat:STATIC-TRANSMISSION-WINDOW-CONTROL and feat:UNIFORMLY-DISTRIBUTED-TRANSMISSION"; + type enumeration { + enum NORMAL { + description + "Normal transmission (unspecified within transmission window)"; + } + enum UNIFORMLY-DISTRIBUTED { + if-feature feat:UNIFORMLY-DISTRIBUTED-TRANSMISSION; + description + "Uniformly distributed over transmission window: each of N messages in the window + transmitted at random time in a separate subwindow; subwindow size is window size / N "; + } + } + + description "Type of delay supported by the endpoint"; + } + } + + grouping tx-endpoint-compression-grouping { + description + "Grouping for endpoint compression"; + + container compression { + presence + "This container shall exists to avoid misaligned compression + methods between devices"; + + description + "Container which consists of global configurable parameters for compression"; + + uses cf:compression-details; + + leaf fs-offset { + if-feature cf:CONFIGURABLE-FS-OFFSET; + type uint8; + default 0; + description + "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. + Please refer to CU-Plane specification for details"; + } + + list dynamic-compression-configuration { + when "../compression-type = 'DYNAMIC'"; + key "id"; + unique "compression-method iq-bitwidth fs-offset"; + description + "List of possible configuration in case dynamic configuration is used + Note: In case of empty list all available compressions can be chosen dynamically + and default fs-offset is taken (0). + If the feature CONFIGURABLE-FS-OFFSET is not supported, + fs-offset will not be considered as one of the criteria for unique statement. + Refer to RFC7950 clause 7.8.3 for details of unique statement"; + + leaf id { + type uint16; + description + "Identification number for particular compression"; + } + + uses cf:compression-method-grouping; + + leaf fs-offset { + if-feature cf:CONFIGURABLE-FS-OFFSET; + type uint8; + default 0; + description + "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. + Please refer to CU-Plane specification for details"; + } + + leaf channel-information-iq-bitwidth { + type uint8{ + range "1..16"; + } + status deprecated; + description + "I/Q bitwidth for channel information in Section Type6. + Leaf is deprecated as it should be independent of dynamic compression, + NETCONF client instead uses channel-information-bitwidth schema node"; + } + } + + leaf channel-information-bitwidth { + type uint8{ + range "1..16"; + } + description + "I/Q bitwidth for channel information in Section Type6. + Maximum value is limited to 16. + Value 1,2,..16 indicates I and Q are each 1,2..16 bits wide respectively. + Note: This parameter shall be used when the NETCONF client does not make use of + the CHANNEL-INFORMATION-COMPRESSION feature."; + } + + list channel-information-compressions { + if-feature "feat:CHANNEL-INFORMATION-COMPRESSION"; + key id; + + leaf id { + type uint16; + description + "Identification number for particular channel information compression"; + } + + leaf channel-information-compression-method { + type cf:ci-compression-method-def; + description + "Channel information compression method"; + } + + leaf iq-bitwidth { + type uint8{ + range "1..16"; + } + description + "Bitwidth to be used in compression, maximum value is limited to 16. + Value 1,2,..16 indicates I and Q are each 1,2..16 bits wide respectively. + + When this schema node is used in the configuration, the O-RU shall ignore the configuration of the + /low-level-tx-endpoints/compression/channel-information-bitwidth schema node"; + } + + description + "List of available compressions, that can be dynamically chosen, for channel information (e.g. ST6) for this endpoint. + Note1: When only one compression is listed here, it implies that channel information compression + is static and mentioned compression is taken into use. + Note2: O-RU Shall reject configuration with compressions that are not supported"; + } + + list bf-weights-compressions { + key id; + + leaf id { + type uint16; + description + "Identification number for particular beamforming compression"; + } + + leaf bf-weights-compression { + type cf:bf-compression-method-def; + description + "Beamforming weight compression method"; + } + + leaf iq-bitwidth { + type uint8 { + range "1..16"; + } + description + "Bitwidth to be used in compression, maximum value is limited to 16. + Value 1,2,..16 indicates I and Q are each 1,2..16 bits wide respectively"; + } + description + "List of available compressions, that can be dynamically chosen, for beamforming weights for this endpoint. + Note1: When only one compression is listed here, it implies that beamforming weights compression + is static and mentioned compression is taken into use. + Note2: O-RU Shall reject configuration with compressions that are not supported"; + } + } + } + + grouping rx-endpoint-compression-grouping { + description + "Grouping for endpoint compression"; + + container compression { + presence + "This container shall exists to avoid misaligned compression + methods between devices"; + + description + "Container which consists of global configurable parameters for compression"; + + uses cf:compression-details; + + leaf fs-offset { + if-feature cf:CONFIGURABLE-FS-OFFSET; + type uint8; + default 0; + description + "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. + Please refer to CU-Plane specification for details"; + } + + list dynamic-compression-configuration { + when "../compression-type = 'DYNAMIC'"; + key "id"; + unique "compression-method iq-bitwidth fs-offset"; + description + "List of possible configuration in case dynamic configuration is used + Note: In case of empty list all available compressions can be chosen dynamically + and default fs-offset is taken (0). + If the feature CONFIGURABLE-FS-OFFSET is not supported, + fs-offset will not be considered as one of the criteria for unique statement. + Refer to RFC7950 clause 7.8.3 for details of unique statement"; + + leaf id { + type uint16; + description + "Identification number for particular compression"; + } + + uses cf:compression-method-grouping; + + leaf fs-offset { + if-feature cf:CONFIGURABLE-FS-OFFSET; + type uint8; + default 0; + description + "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. + Please refer to CU-Plane specification for details"; + } + } + + list bf-weights-compressions { + key id; + + leaf id { + type uint16; + description + "Identification number for particular beamforming compression"; + } + + leaf bf-weights-compression { + type cf:bf-compression-method-def; + description + "Beamforming weight compression method"; + } + + leaf iq-bitwidth { + type uint8; + description + "Bitwidth to be used in compression"; + } + + description + "List of available compressions, that can be dynamically chosen, for beamforming weights for this endpoint. + Note1: When only one compression is listed here, it implies that beamforming weights compression + is static and mentioned compression is taken into use. + Note2: O-RU Shall reject configuration with compressions that are not supported"; + } + } + } + + grouping supported-section-type4-config { + description + "Set of parameters required for section type 4 slot configuration message."; + list st4-supported-commands { + key "st4-command-type"; + + description + "This parameter specifies the list of Section Type 4 command types supported by O-RU."; + leaf st4-command-type { + type enumeration { + enum TIME_DOMAIN_BEAM_CONFIG { + description "O-RU support for receiving time domain beamforming command."; + } + enum TDD_CONFIG_PATTERN { + description "O-RU support for receiving TDD symbol pattern for a given slot."; + } + enum TRX_CONTROL { + if-feature feat:TRX-CONTROL; + description "O-RU support for receiving TRX CONTROL command in a given slot."; + } + enum ASM { + if-feature feat:ADVANCED-SLEEP-MODE; + description "O-RU support for receiving ASM command in a given slot."; + } + } + description + "Section Type 4 command types supported by O-RU."; + } + + list st4-command-scope-params { + key "cmd-scope"; + + description + "This list contains parameters which are specific to a given command scope associated with a particular section type 4 command type."; + + leaf cmd-scope { + type enumeration { + enum ARRAY-COMMAND { + description + "Command applies to all endpoints assigned to the tx-array(s) and/or rx-array(s).If the O-RU + is operating with multiple O-DUs, the scope of an individual O-DU is limited, to the + endpoints assigned to the O-DU which was the originator of the command."; + } + enum CARRIER-COMMAND { + description + "Command applies to all endpoints assigned to the tx-array-carrier and/or rx-array-carrier."; + } + enum O-RU-COMMAND { + description + "O-RU level command, i.e., one that applies to all arrays and carriers. If the O-RU + is operating with multiple O-DUs, the scope of an individual O-DU is limited, as + specified in CUS-Plane specification, clause 7.5.2.17."; + } + } + description "Command scope for section type 4 commands"; + } + + leaf st4-reception-bitmask { + type uint16; + description + "This parameter specifies the O-RU capability to receive Section Type 4 message with associated commands with a particular command scope + for the symbols for which the corresponding bit is set to '1' in the bitmask. If the O-RU receives a Section Type 4 message with + associated command for a symbol whose bit value is set to '0' in this bitmask, the O-RU shall reject the Section Type 4 message"; + } + } + } + + list st4-reception-mask { + key "cmd-scope"; + status deprecated; + + description + "List of symbol mask per command scope, specifying the O-RU capability to receive Section Type 4 message for a + given command scope only for symbols for which the corresponding bit is set to '1' in the bitmask. If the O-RU + receives a Section Type 4 message with associated command for a symbol whose bit value is set to '0' in this + bitmask, the O-RU shall reject the Section Type 4 message"; + + leaf cmd-scope { + type enumeration { + enum ARRAY-COMMAND { + description + "Command applies to all endpoints assigned to the tx-array(s) and/or rx-array(s).If the O-RU + is operating with multiple O-DUs, the scope of an individual O-DU is limited, to the + endpoints assigned to the O-DU which was the originator of the command."; + } + enum CARRIER-COMMAND { + description + "Command applies to all endpoints assigned to the tx-array-carrier and/or rx-array-carrier."; + } + enum O-RU-COMMAND { + description + "O-RU level command, i.e., one that applies to all arrays and carriers. If the O-RU + is operating with multiple O-DUs, the scope of an individual O-DU is limited, as + specified in CUS-Plane specification, clause 7.5.2.17."; + } + } + description "Command scope for section type 4 commands"; + } + + leaf st4-reception-bitmask { + type uint16; + description + "This parameter specifies the O-RU capability to receive Section Type 4 message with associated commands for the symbols + for which the corresponding bit is set to '1' in the bitmask. If the O-RU receives a Section Type 4 message with + associated command for a symbol whose bit value is set to '0' in this bitmask, the O-RU shall reject the Section Type 4 message"; + } + } + } + grouping uplane-conf-group { description "Grouping for uplane configuration related parameters"; @@ -1100,13 +2673,60 @@ module o-ran-uplane-conf { "Unique name of low-level-tx-link object."; } + leaf sro-id { + if-feature feat:SHARED-ORU-MULTI-OPERATOR; + type leafref { + path "/or-user:users/or-user:user/or-user:sro-id"; + } + description + "An optional shared resource operator associated with this list entry. + When present, indicates that the list entry corresponds to a low-level-tx-link + associated with a shared resource operator where the sro-id identifies + a specific shared resource operator. + This schema-node is used to refine NACM privileges for shared + resource operators"; + } + leaf processing-element { type leafref { path "/o-ran-pe:processing-elements/o-ran-pe:ru-elements/o-ran-pe:name"; } mandatory true; description - "Contains name of processing-element to be used as transport by low-level-tx-link"; + "Contains name of processing-element to be used as transport by low-level-tx-link, + if 'transport-qualified-processing-element' is included in the configuration, + the O-RU shall use 'transport-qualified-processing-element' instead of this schema node, + an O-RU Controller shall still configure this schema node with a leafref to a valid ru-element, + but this shall not be used by the O-RU."; + } + + leaf transport-session-type { + if-feature "feat:MULTIPLE-TRANSPORT-SESSION-TYPE"; + type enumeration { + enum ETH-INTERFACE { + description "VLAN based CUS Transport "; + } + enum UDPIP-INTERFACE { + description "UDP/IP based CUS Transport "; + } + enum ALIASMAC-INTERFACE{ + description "Alias MAC address based CUS Transport "; + } + } + description + "transport session type used when an O-RU is configured with multiple processing elements of different transport session types, + in which case it is used for referencing a processing element in 'transport-qualified-processing-element'"; + } + + leaf transport-qualified-processing-element { + if-feature "feat:MULTIPLE-TRANSPORT-SESSION-TYPE"; + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:additional-transport-session-type-elements[o-ran-pe:transport-session-type = current()/../transport-session-type]/o-ran-pe:ru-elements/o-ran-pe:name"; + } + description + "Contains name of processing-element to be used as transport by low-level-tx-link. + Used when the processing element is configured + by the list 'additional-transport-session-type-elements'"; } leaf tx-array-carrier { @@ -1140,13 +2760,60 @@ module o-ran-uplane-conf { "Unique name of low-level-rx-links object."; } + leaf sro-id { + if-feature feat:SHARED-ORU-MULTI-OPERATOR; + type leafref { + path "/or-user:users/or-user:user/or-user:sro-id"; + } + description + "An optional shared resource operator associated with this list entry. + When present, indicates that the list entry corresponds to a low-level-rx-link + associated with a shared resource operator where the sro-id identifies + a specific shared resource operator. + This schema-node is used to refine NACM privileges for shared + resource operators"; + } + leaf processing-element { type leafref { path "/o-ran-pe:processing-elements/o-ran-pe:ru-elements/o-ran-pe:name"; } mandatory true; description - "Contains name of processing-element to be used as transport by LowLevelTxLink"; + "Contains name of processing-element to be used as transport by low-level-rx-link, + if 'transport-qualified-processing-element' is included in the configuration, + the O-RU shall use 'transport-qualified-processing-element' instead of this schema node, + an O-RU Controller shall still configure this schema node with a leafref to a valid ru-element, + but this shall not be used by the O-RU."; + } + + leaf transport-session-type { + if-feature "feat:MULTIPLE-TRANSPORT-SESSION-TYPE"; + type enumeration { + enum ETH-INTERFACE { + description "VLAN based CUS Transport "; + } + enum UDPIP-INTERFACE { + description "UDP/IP based CUS Transport "; + } + enum ALIASMAC-INTERFACE{ + description "Alias MAC address based CUS Transport "; + } + } + description + "transport session type used when an O-RU is configured with multiple processing elements of different transport session types, + in which case it is used for referencing a processing element in 'transport-qualified-processing-element'"; + } + + leaf transport-qualified-processing-element { + if-feature "feat:MULTIPLE-TRANSPORT-SESSION-TYPE"; + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:additional-transport-session-type-elements[o-ran-pe:transport-session-type = current()/../transport-session-type]/o-ran-pe:ru-elements/o-ran-pe:name"; + } + description + "Contains name of processing-element to be used as transport by low-level-rx-link. + Used when the processing element is configured + by the list 'additional-transport-session-type-elements'"; } leaf rx-array-carrier { @@ -1176,13 +2843,49 @@ module o-ran-uplane-conf { description "Parameter to set the non-default marking for user-plane"; } + + leaf enhanced-user-plane-uplink-marking { + if-feature "feat:MULTIPLE-TRANSPORT-SESSION-TYPE"; + type leafref { + path "/o-ran-pe:processing-elements/o-ran-pe:additional-transport-session-type-elements[o-ran-pe:transport-session-type = current()/../transport-session-type]/o-ran-pe:enhanced-uplane-mapping/o-ran-pe:uplane-mapping/o-ran-pe:up-marking-name"; + } + description + "Parameter to set the non-default marking for user-plane. + Used when the enhanced-uplane-mapping is configured + by the list 'additional-transport-session-type-elements'"; + } + } + + grouping common-se24-dmrs-capabilities-grp { + description + "Grouping of common SE23 DMRS BF capabilities. + Please refer to CUS specification clause 7.7.24 for more details."; + + leaf max-user-groups-per-slot { + type uint32; + description + "Maximum number user groups per slot."; + } + + leaf max-entries-per-slot { + type uint32; + description + "Maximum number of entries in the table of DMRS configurations per slot."; + } } list endpoint-types { key "id"; config false; description - "Properties of endpoint that are common to multiple endpoints if such are identified"; + "Properties of endpoint that are common to multiple endpoints if such are identified + Note: For any endpoint supporting mixed numerology within slot/symbol (multiple-numerology-supported=TRUE) + * Interval specific (per-slot and per-symbol) capacity constraints instantaneous capacity usage + (i.e. capacity is shared/distributed between all numerologies used at an instant of time). + * Instantaneous capacity usage is the sum of capacity usages of all intervals of a specific type (slot/symbol) + that share the instant of time at which instantaneous capacity usage is evaluated regardless of numerology. + * Capacity used in an interval is allocated at the start of the interval and is released at the end of the interval + (e.g. capacity used for symbol #N of numerology #M is unavailable during symbol #N and available for reuse after symbol #N ends)."; leaf id { type uint16; @@ -1211,11 +2914,15 @@ module o-ran-uplane-conf { } } + uses supported-section-type4-config { + if-feature feat:ST4-SLOT-CONFIG-MSG-SUPPORT; + } + leaf-list supported-frame-structures { type uint8; description - "List of supported values of frame structure"; + "List of supported values of frame structure. For semantic and allowed values see CUS-Plane Specification, clause '7.5.2.13 frameStructure (frame structure)'"; } leaf managed-delay-support { @@ -1266,6 +2973,7 @@ module o-ran-uplane-conf { uses endpoint-section-capacity; uses endpoint-beam-capacity; uses endpoint-prb-capacity; + uses endpoint-section-extension-limits; leaf-list prb-capacity-allocation-granularity { type uint16; @@ -1277,6 +2985,608 @@ module o-ran-uplane-conf { } uses endpoint-numerology-capacity; + + leaf static-transmission-window-control-supported { + if-feature feat:STATIC-TRANSMISSION-WINDOW-CONTROL; + type boolean; + description + "Endpoint supports transmission-window-control = STATIC"; + } + + leaf uniformly-distributed-transmission-supported { + if-feature "feat:STATIC-TRANSMISSION-WINDOW-CONTROL and feat:UNIFORMLY-DISTRIBUTED-TRANSMISSION"; + type boolean; + description + "Endpoint supports transmission-type = UNIFORMLY-DISTRIBUTED"; + } + + leaf ordered-transmission-supported { + if-feature feat:ORDERED-TRANSMISSION; + type boolean; + description + "Endpoint supports ordered transmission of U-plane messages + and can be configured with ordered-transmission = TRUE"; + } + + leaf dynamic-transmission-window-control-supported { + if-feature feat:DYNAMIC-TRANSMISSION-WINDOW-CONTROL; + type boolean; + description + "Endpoint supports U-plane transmission window control via C-plane + (supports transmission-window-control = DYNAMIC) with independent window offset and size per symbol"; + } + + leaf dynamic-transmission-window-control-per-section-supported { + when "../dynamic-transmission-window-control-supported = 'true'"; + if-feature feat:DYNAMIC-TRANSMISSION-WINDOW-CONTROL; + type boolean; + description + "Endpoint supports U-plane transmission window control via C-plane + (supports transmission-window-control = DYNAMIC) with independent window offset and size per section"; + } + + leaf dynamic-uniformly-distributed-transmission-supported { + if-feature "feat:DYNAMIC-TRANSMISSION-WINDOW-CONTROL and feat:UNIFORMLY-DISTRIBUTED-TRANSMISSION"; + type boolean; + description + "Endpoint supports U-plane transmission window control via C-plane + (supports transmission-window-control = DYNAMIC) with independent transmission type per symbol"; + } + + leaf dynamic-uniformly-distributed-transmission-per-section-supported { + when "../dynamic-uniformly-distributed-transmission-supported = 'true'"; + type boolean; + description + "Endpoint supports U-plane transmission window control via C-plane + (supports transmission-window-control = DYNAMIC) with independent transmission type per section"; + } + + uses transmission-buffering-capacity { + when "static-transmission-window-control-supported = 'true' or dynamic-transmission-window-control-supported = 'true'"; + if-feature "feat:STATIC-TRANSMISSION-WINDOW-CONTROL or feat:DYNAMIC-TRANSMISSION-WINDOW-CONTROL"; + } + + leaf cplane-message-processing-limits-required { + if-feature feat:CPLANE-MESSAGE-PROCESSING-LIMITS; + type boolean; + config false; + description + "Endpoint requires applying C-Plane message processing limits defined in 'per-cplane-message-limits'. + and can be configured with cplane-message-processing-limits-enabled = TRUE"; + } + + uses per-cplane-message-limits { + when "cplane-message-processing-limits-required = 'true'"; + if-feature feat:CPLANE-MESSAGE-PROCESSING-LIMITS; + } + + leaf uplane-message-processing-limits-required { + if-feature feat:UPLANE-MESSAGE-PROCESSING-LIMITS; + type boolean; + config false; + description + "Endpoint has processing limits regarding U-Plane message. Detailed types of limits are defined in 'per-uplane-message-limits'."; + } + + uses per-uplane-message-limits { + when "uplane-message-processing-limits-required = 'true'"; + if-feature feat:UPLANE-MESSAGE-PROCESSING-LIMITS; + } + + leaf beam-update-contention-control-limits-required { + if-feature feat:BEAM-UPDATE-CONTENTION-CONTROL; + type boolean; + config false; + description + "Endpoint requires applying beam update contention control limits defined in 'beam-update-contention-control-limits'. + and can be configured with beam-update-contention-control-enabled = TRUE"; + } + + uses beam-update-contention-control-limits { + when "beam-update-contention-control-limits-required = 'true'"; + if-feature feat:BEAM-UPDATE-CONTENTION-CONTROL; + } + + leaf max-ack-nack-per-symbol { + type uint16; + description + "This value indicates the max number of ACK/NACK feedbacks supported by the endpoint in a symbol when + section extension 22 (ACK/NACK request) and section type 8 (ACK/NACK feedback) are supported by the endpoint. + The number of ACK/NACK feedbacks in a symbol is defined as the sum of 'numberofACKs' + 'numberofNACKs' in all C-Plane + messages sent by the endpoints in a symbol"; + } + + leaf non-scheduled-ueid-supported { + if-feature feat:NON-SCHEDULED-UEID; + type boolean; + default false; + description + "The parameter informs that the endpoint supports the capability of interpreting that those PRBs in the specified port are not allocated. + Please refer to CUS specification clause 7.9.13 for more details."; + } + + leaf se-11-continuity-flag-supported { + if-feature feat:SE11-WITH-CONTINUITY-BIT-SUPPORT; + type boolean; + config false; + description + "This flag is applicable for 'static-low-level-tx-endpoints' which support Section Extension 11 (SE 11). The + O-RU may choose to indicate its support for handling continuity flag as defined in CUS-Plane Clause 7.7.11.9 + by advertising this flag to TRUE/FALSE. + - Value of the flag advertised as 'TRUE' implies O-RU supports handling of 'continuity' flag in SE 11; + - Value of the flag advertised to 'FALSE' implies the O-RU does not support handling of 'continuity' flag in SE 11."; + } + + leaf se-23-prb-block-mode-supported { + if-feature feat:SE23-PRB-BLOCK-MODE-SUPPORT; + type boolean; + config false; + description + "This flag is applicable for 'static-low-level-tx-endpoints' which support Section Extension 23 (SE 23). The + O-RU may choose to indicate its support for prbMode = PRB-BLOCK mode flag as defined in CUS-Plane Clause 7.7.23.1 + by advertising this flag as TRUE/FALSE. + - Value of the flag advertised as 'TRUE' implies O-RU supports both prbMode = PRB-BLOCK mode of SE 23 + and prbMode = PRB-MASK which is the default mode when SE-23 is used. + - Value of the flag advertised as 'FALSE' implies O-RU supports prbMode = PRB-MASK which is the + default mode when SE-23 is used and the O-RU does not support prbMode = PRB-BLOCK mode."; + } + + leaf user-group-optimization-supported { + if-feature feat:USER-GROUP-OPTIMIZATION; + type boolean; + default false; + description + "The parameter indicates that if O-RU sets this feature flag to 'TRUE' for a given endpoint, and the O-DU chooses to + support this feature by setting 'user-group-optimization-enabled-tx' to 'TRUE' for static-low-level-tx-endpoints, + 'user-group-optimization-enabled-rx' to 'TRUE' for static-low-level-rx-endpoints,then the O-DU shall be required + to send all layers for a given user group UEs i.e., UEs with same time-frequency allocation using single C-Plane + section description. refer to CUS-Plane specification clause 7.9.14."; + } + + leaf se-20-multi-sd-punc-pattern-suported { + if-feature feat:SE20-MULTI-SD-PUNC-PATTERN-SUPPORT; + type boolean; + config false; + description + "This flag is applicable for 'static-low-level-[tr]x-endpoints' which support Section Estension 20 (SE-20). + The flag associated with each puncturing pattern in SE-20. The details of are defined in CUS-Plane Clause + 7.7.20.1. The O-RU indicates support for this feature by advertising this flag as TRUE/FALSE. + - Value of the flag advertised as 'TRUE' indicates O-RU supports handling of 'multiSDScope' field in SE-20. + - Value of the flag advertised as 'FALSE' indicates O-RU does not supports handling of 'multiSDScope' field in SE-20."; + } + + uses supported-configuration-combinations-grp; + + leaf-list supported-filter-indices { + type uint32; + description + "The list of supported values of filterIndex. + An empty list means that the set of supported values of filterIndex is not constrained."; + } + + leaf-list bf-profile-group { + if-feature feat:BF-DELAY-PROFILE; + type leafref { + path "/user-plane-configuration/endpoint-bf-profile-group/bf-profile-id"; + require-instance false; + } + description + "List of beamforming method groups supported by the endpoint, and the related delay profile values."; + } + + list supported-pass-band-for-filterindex09-per-scs { + key "scs"; + config false; + + description + "When filterIndex 0x9 is used, O-RU shall use minimum pass band filter among the reported passband filter sizes + that can accommodate the numPrbc and startPrbc of all the section descriptions associated with same frameStructure. + Please refer to CUS specification clause 7.5.2.3 for more details."; + + leaf scs { + type mcap:scs-config-type; + description + "Value corresponds to SCS values defined for frameStructure in C-plane."; + } + + leaf supported-max-num-msg-for-filterindex0x9-per-scs { + type uint16; + description + "Max number of filters can be actived at a time, + and this parameter limits the maximum number of ST3 mesaages with filterIndex set to 9 that O-DU can send so that the total number of filters active is below the maximum limit"; + } + + leaf-list filter-bandwidth { + type uint64; + units Hz; + description + "Bandwidth of a filter given in Hz. + If the list for the given SCS indicated via frameStructure is not empty, + O-DU should set filterIndex as 1001b for mixed numerology and other channels except PRACH and NB-IoT as specified in Table 7.5.2.3-1 when ST 3 C-plane message is used."; + + } + } + + container se24-dmrs-capabilities { + if-feature "feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ"; + description + "Container collecting SE24 DMRS BF capabilties. + Please refer to CUS specification clause 7.7.24 for more details."; + + leaf-list supported-entry-types { + type uint8; + description + "Supported values of entryType."; + } + leaf ue-time-partial-overlap-supported { + type boolean; + description + "Indicates if UE time partial overlap is supported. + See CUS-plane clause 12.6.1.2.1."; + } + leaf ue-freq-partial-overlap-supported { + type boolean; + description + "Indicates if UE frequency partial overlap is supported. + See CUS-plane clause 12.6.1.2.1."; + } + leaf max-user-groups-per-ue-in-time { + type uint16; + description + "The maximum supported number of user groups in time-domain per UE. + See CUS-plane clause 12.6.1.2.1"; + } + leaf different-transform-precoding-in-user-group-supported { + type boolean; + description + "Indicates if different transform precoding in user group is supported."; + } + leaf different-cdm-without-data-in-user-group-supported { + type boolean; + description + "Indicates if different cdm without data in user group is supported."; + } + leaf max-dmrs-configs-per-user-group-incl-first-last-prb { + type uint32; + description + "Maximum number of different DMRS configurations (excluding differences in dmrsPortNumber) per user group, + including first and last PRB."; + } + + leaf max-dmrs-configs-per-user-group-excl-first-last-prb { + type uint32; + description + "Maximum number of different DMRS configurations (excluding differences in dmrsPortNumber) per user group, + excluding first and last PRB."; + } + uses common-se24-dmrs-capabilities-grp; + grouping dmr-mask-capability-grp { + description + "Grouping of transform-precoding capabilities"; + + list dmrs-mask-capability { + key id; + description + "Parameters for DMRS mask capabilities"; + leaf id { + type uint16; + description + "An identifier of an entry in the list."; + } + leaf-list dmrs-symbol-mask { + type uint16; + description + "Supported DMRS symbol mask. + Empty list means all the possible symbol masks are supported."; + } + leaf max-dmrs-ant-port-number { + type uint32; + description + "Maximum DMRS antenna port number."; + } + leaf max-user-data-layers { + type uint32; + description + "Maximum number of user data layers"; + } + } + } + container transform-precoding-enabled { + description + "Parameters for SE24 DMRS BF capabilities with transform precoding enabled"; + uses dmr-mask-capability-grp; + list low-papr-config { + key id; + description + "Supported Low-PAPR configs"; + leaf id { + type uint16; + description + "An identifier of an entry in the list."; + } + leaf low-papr-type { + type uint16 { + range "0 .. 3"; + } + description + "Supported values of lowPaprType"; + } + leaf hopping-mode { + type uint16 { + range "0 .. 3"; + } + description + "Supported values of hoppingMode"; + } + } + } + container transform-precoding-disabled { + description + "Parameters for SE24 DMRS BF capabilities with transform precoding disabled"; + uses dmr-mask-capability-grp; + list dmrs-config { + key id; + description + "Supported DMRS configs"; + leaf id { + type uint16; + description + "An identifier of an entry in the list."; + } + leaf d-type { + type uint16 { + range "0 .. 1"; + } + description + "Supported values of dType."; + } + leaf pusch-dmrs-muxing-supported { + type boolean; + description + "Indicates if PUSCH DMRS muxing is supported."; + } + } + } + } + + leaf sinr-reporting-supported { + if-feature feat:DMRS-BF-EQ; + type boolean; + default false; + description + "Indicates if SINR reporting is supported."; + } + container sinr-reporting-capabilities { + when "../sinr-reporting-supported = 'true'"; + if-feature feat:DMRS-BF-EQ; + description + "Container collecting parameters related to capabilities of SINR reporting"; + leaf simultaneous-sinr-and-dmrs-sending-supported { + type boolean; + description + "Indicates if simultaneous SINR and DMRS sending is supported."; + } + list supported-sinr-resolutions { + key "id"; + description + "The list of supported SINR reporting resolutions. + This entry is applicable if maximum number of data layers in any user group in any slot does not exceed value of max-data-layers. + + Please refer to CUS specification clause 7.2.10 for more details."; + leaf id { + type uint16; + description + "Identifies a supported SINR reporting resolution."; + } + leaf sinr-max-data-layers { + type uint8; + description + "The maximum number of data layers scheduled in any user group in a slot."; + } + leaf-list sinr-per-prb { + type uint8; + description + "List of supported values. Indicates number of SINR values per PRB."; + } + leaf-list sinr-slot-mask { + type uint16; + description + "List of bitmasks representing supported patterns of SINR reporting in time domain. An emplty list means that the set of supported SINR reporting is unrestricted."; + } + } + container supported-sinr-reference-level { + description + "Supported range of SINR reference levels values. + + See CUS specification clause 7.2.10 for more details"; + leaf sinr-reference-level-min { + type decimal64 { + fraction-digits 4; + } + units dB; + description + "Minimum supported SINR reference level."; + } + leaf sinr-reference-level-max { + type decimal64 { + fraction-digits 4; + } + units dB; + description + "Maximum supported SINR reference level."; + } + } + list supported-sinr-compression-methods { + key "id"; + description + "The list of supported SINR compression methods."; + leaf id { + type uint16; + description + "Identifies a supported SINR compression method."; + } + uses cf:sinr-compression-details; + } + } + container supported-symb-reorder-capabilities { + if-feature "feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ"; + description + "List of capabilities related to symbol reordering."; + uses supported-symb-reorder-capability; + } + leaf-list supported-user-group-self-assembly-modes { + if-feature feat:USER-GROUP-SELF-ASSEMBLY; + type user-group-self-assembly-mode ; + description + "List of user group self assembly mode(s) supported by an endpoint. The O-RU may support SELF-ASSEMBLY-WITH-GROUP-ID and/or SELF-ASSEMBLY-WITHOUT-GROUP-ID."; + } + leaf-list continuity-block-sizes-supported { + if-feature "(feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ) and feat:CONTINUITY-BLOCK-SIZE"; + type uint16; + description + "List of continuity bock sizes supported by the O-RU."; + } + leaf eq-scale-offset-min { + if-feature feat:DMRS-BF-EQ; + type decimal64 { + fraction-digits 4; + } + units dB; + description + "Refer to cus specification 8.3.1.4, max value 0 dB"; + } + leaf eq-scale-offset-max { + if-feature feat:DMRS-BF-EQ; + type decimal64 { + fraction-digits 4; + } + units dB; + description + "Refer to cus specification 8.3.1.4, max value 0 dB"; + } + leaf-list rrm-meas-supported { + if-feature feat:RRM-MEAS-REPORTING; + type rrm-meas-types; + description + "List of rrm types supported by the endpoint type"; + } + leaf max-ipn-unalloc-reports-supported { + when "../rrm-meas-supported = 'MEAS-IPN-UNALLOC'"; + if-feature feat:RRM-MEAS-REPORTING; + type uint16; + description + "This value indicates the maximum number of ipn unallocated measurement reports per PRB (PRB range) and slot"; + } + leaf max-ipn-unalloc-symbols-supported { + when "../rrm-meas-supported = 'MEAS-IPN-UNALLOC'"; + if-feature feat:RRM-MEAS-REPORTING; + type uint16; + description + "This parameter indicates maximum number of measured symbols of all measurement reports for a PRB (PRB range) in the slot "; + } + leaf max-ipn-alloc-reports-supported { + when "../rrm-meas-supported = 'MEAS-IPN-ALLOC'"; + if-feature feat:RRM-MEAS-REPORTING; + type uint16; + description + "This value indicates the maximum number of ipn alloc measurement reports per PRB per slot. Relationship between this value and alloc-ipn-per-sym-supported can be found in CUS plan specification clause 9.2.2.4"; + } + leaf-list alloc-ipn-per-dmrs-sym-grp-supported { + when "../rrm-meas-supported = 'MEAS-IPN-ALLOC'"; + if-feature feat:RRM-MEAS-REPORTING; + type uint8 { + range "0 .. 1"; + } + description + "This parameter indicates alloc-ipn measurement type(s) supported by the O-RU. + Refer to CUS specification clause 9.2.2.4 for details"; + } + leaf se-10-bgt-11b-supported { + type boolean; + default false; + description + "The parameter is applicable for static-low-level-[tr]x-endpoints supporting Section Extension 10. This flag + if set to TRUE indicates that the O-RU advertised endpoint, supporting Section Extension 10 supports beamGroupType = 11b. + It is mandatory for endpoints supporting DMRS-BF-EQ/DMRS-BF-NEQ beamforming methods to support beamGroupType = 11b. + refer to CUS-Plane specification clause 7.7.10.1"; + } + + leaf-list se-27-odu-controlled-dimensionality-reduction-supported { + if-feature feat:SE27-ODU-CONTROLLED-DIMENSIONALITY-REDUCTION; + type enumeration { + enum STATIC { + description + "Static O-DU controlled dimnesionality reduction enabled."; + } + enum DYNAMIC { + description + "Dynamic O-DU controlled dimnesionality reduction enabled."; + } + } + description + "Supported type O-DU controlled dimensionality reduction using SE27. + Please refer to CUS specification clause 7.7.27 for more details."; + } + leaf se-27-omission-when-enabled-supported { + when "(../se-27-odu-controlled-dimensionality-reduction-supported = 'STATIC') + or (../se-27-odu-controlled-dimensionality-reduction-supported = 'DYNAMIC')"; + if-feature feat:SE27-ODU-CONTROLLED-DIMENSIONALITY-REDUCTION; + type boolean; + description + "Indicates if O-RU supports omission of SE27 when O-DU controlled dimensionality reduction using SE27 is enabled. + Please refer to CUS specification clause 7.7.27 for more details."; + } + list supported-se-27-configurations { + when "(../se-27-odu-controlled-dimensionality-reduction-supported = 'STATIC') + or (../se-27-odu-controlled-dimensionality-reduction-supported = 'DYNAMIC')"; + if-feature feat:SE27-ODU-CONTROLLED-DIMENSIONALITY-REDUCTION; + key number-of-ue-data-layers; + description + "List of supported values of numElements parameter per number of UE + data layers scheduled in user group. + Please refer to CUS specification clause 7.7.27 for more details."; + leaf number-of-ue-data-layers { + type uint16; + description + "Number of UE data layers scheduled in user group."; + } + leaf-list supported-se-27-num-elements { + type uint16; + description + "Supported values of numElements in SE27 for the provided number of UE data layers."; + } + } + } + + list transmission-window-schedules { + if-feature feat:STATIC-TRANSMISSION-WINDOW-CONTROL; + key id; + description + "Parameters for scheduled UL U-plane message transmission (static transmission window control)"; + leaf id { + type uint16; + description + "Identifies a UL U-plane message transmission schedule"; + } + list schedule { + key symbol; + description + "Defines transmission window offset for given symbol. + If no entry is present for a symbol then O-RU assumes offset=0 for that symbol. + Entries with offset=0 shall be omitted."; + leaf symbol { + type uint16; + description + "Number of a symbol within a frame for which transmission offset is given."; + } + leaf offset { + type uint16; + description + "Transmission window offset; expressed as number of symbols the transmission window start is delayed by. + This value is added to u-plane-transmission-control/transmission-window-offset. + For restrictions on value of offset see description of transmission-window-offset."; + } + } } list endpoint-capacity-sharing-groups { @@ -1286,11 +3596,18 @@ module o-ran-uplane-conf { "Represents groups of endpoints that share capacity. Depending on O-RU implementation, processing resources that handle CU-plane (e.g. memory to keep sections and beams) could be allocated per endpoint or shared between several endpoints. - To address this O-RU shall reports own capability per endpoint (see endpoint-types) + To address this O-RU shall report own capability per endpoint (see endpoint-types) and per group of endpoints sharing capacity. If endpoint is in multiple groups then resulting constraint is minimum over all groups. Note: values of parameters representing capacity that is not shared between endpoints in a group - shall be set to max value of specific parameter; this effectively removes related constraint."; + shall be set to max value of specific parameter; this effectively removes related constraint. + Note: For any endpoint supporting mixed numerology within slot/symbol (multiple-numerology-supported=TRUE) + * Interval specific (per-slot and per-symbol) capacity constraints instantaneous capacity usage + (i.e. capacity is shared/distributed between all numerologies used at an instant of time). + * Instantaneous capacity usage is the sum of capacity usages of all intervals of a specific type (slot/symbol) + that share the instant of time at which instantaneous capacity usage is evaluated regardless of numerology. + * Capacity used in an interval is allocated at the start of the interval and is released at the end of the interval + (e.g. capacity used for symbol #N of numerology #M is unavailable during symbol #N and available for reuse after symbol #N ends)."; leaf id { type uint16; @@ -1302,6 +3619,7 @@ module o-ran-uplane-conf { uses endpoint-beam-capacity; uses endpoint-prb-capacity; uses endpoint-numerology-capacity; + uses endpoint-section-extension-limits; leaf max-endpoints { type uint16; @@ -1318,6 +3636,31 @@ module o-ran-uplane-conf { description "Number of endpoints supporting non-managed delay that can be used (configured for use) at a time"; } + uses transmission-buffering-capacity { + if-feature "feat:STATIC-TRANSMISSION-WINDOW-CONTROL or feat:DYNAMIC-TRANSMISSION-WINDOW-CONTROL"; + } + + uses per-cplane-message-limits { + if-feature feat:CPLANE-MESSAGE-PROCESSING-LIMITS; + } + leaf max-ack-nack-per-symbol { + type uint16; + description + "This value indicates the max number of ACK/NACK feedbacks supported by the endpoint sharing group in a symbol when + section extension 22 (ACK/NACK request) and section type 8 (ACK/NACK feedback) are supported by the endpoint sharing group. + The number of ACK/NACK feedbacks in a symbol is defined as the sum of 'numberofACKs' + 'numberofNACKs' in all C-Plane + messages sent by the endpoints in group in a symbol"; + } + uses supported-configuration-combinations-grp; + + container se24-dmrs-capabilities { + if-feature "feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ"; + description + "Container collecting SE24 DMRS BF capabilties. + Please refer to CUS specification clause 7.7.24 for more details."; + + uses common-se24-dmrs-capabilities-grp; + } } list endpoint-prach-group { @@ -1355,7 +3698,10 @@ module o-ran-uplane-conf { } list compression-method-supported { - uses cf:compression-parameters; + uses cf:compression-method-grouping; + uses cf:compresion-format-grp { + status deprecated; + } leaf-list fs-offset { if-feature cf:CONFIGURABLE-FS-OFFSET; @@ -1370,7 +3716,153 @@ module o-ran-uplane-conf { "List of supported compression methods by O-RU Note: if O-RU supports different compression methods per endpoint then please refer to endpoints to have information what - exactly is supported on paticular endpoint"; + exactly is supported on particular endpoint"; + } + } + + grouping supported-configuration-combinations-grp { + description + "Grouping of supported freqOffset & PRB range combinations."; + + list supported-configuration-combinations { + key "combination-id"; + config false; + + leaf combination-id { + type uint32; + description + "Identification number for a combination."; + } + + list set { + key "set-id"; + + leaf set-id { + type uint32; + description + "Identification number for a set."; + } + + leaf max-overlapping-instances { + type uint32; + description + "Max number of configs of the set that can be used at the same time."; + } + + list config { + key "config-id"; + + leaf config-id { + type uint32; + description + "Identification number for a config."; + } + + leaf-list scs { + type mcap:scs-config-type; + description + "Value corresponds to SCS values defined for frameStructure in C-plane."; + } + + leaf-list carrier-types { + type enumeration { + enum NR { + description + "5G technology"; + } + enum LTE { + description + "LTE technology"; + } + enum DSS_LTE_NR { + if-feature mcap:DSS_LTE_NR; + description + "NR and LTE technologies in Dynamic Spectrum Sharing mode"; + } + } + description + "Type of carrier. Indicates array-carrier technology."; + } + + leaf filter-pass-bandwidth { + type uint64; + units Hz; + + description + "Width of a filter given in Hz. + The filter center frequency is given in center-of-channel-bandwidth of an array carrier. + When filterIndex 0x9 is used, O-RU shall report all the passband filter bandwidth per scs using the list supported-pass-band-for-filterindex09-per-scs."; + } + + leaf max-prb-range { + type uint32; + + description + "Maximum frequency range of PRBs that may be requested per frequency offset. Either contiguously or non-contiguously. + Total number of PRBs requested per config shall not exceed this value."; + } + + leaf center-from-freqoffset { + type boolean; + description + "This node allows to distinguish between combinations valid when + center-from-freqoffset-enabled is set to TRUE and combinations + valid when center-from-freqoffset-enabled is set to FALSE"; + } + + leaf-list supported-filter-indices { + type uint32; + description + "The list of supported values of filterIndex. + An empty list means that the set of supported values of filterIndex is constrained by the supported-filter-indices + provided in the endpoint type."; + } + + description + "Supported freqOffset & PRB range configuration. + Configuration is an instance of processing output equivalent to single FFT operation."; + } + description + "Set of freqOffset & PRB range configurations that require same resource allocation."; + } + description + "List of supported combinations of freqOffset & PRB range configurations. + If a leaf is not present in a list element it implies there is no constraint on that particular + parameter for the configuration in question."; + } + leaf center-from-freqoffset-supported { + type boolean; + description + "Endpoint's support for autonomous center frequency (k0) calculation based on frequency offset. + This capability applies only to RX endpoints."; + } + } + + grouping supported-symb-reorder-capability { + description + "List of capabilities related to symbol reordering."; + leaf-list supported-symb-reorder-capability { + type symb-reorder-capability; + description + "List of supported symbol reordering methods."; + } + leaf max-num-symbol-reordering-pattern-per-slot { + when "../supported-symb-reorder-capability = 'PER-SECTION-TX-WINDOW-REASSIGNMENT'"; + type uint16; + description + "This parameter defines the maximum number of unique symbol reassignment patterns supported + per slot per rx-array-carrier, where a 'symbol reassignment pattern' comprises 14 symbol + numbers specifying an altered symbol order (using txWinForOnAirSymbol0~13). The maximum + value applies over all SE25 invocations, including when an SE25 invocation includes + multiple symbol reassignment patterns. Repeated invocations of a single symbol reassignment + pattern shall count as a single unique instance. When endpoints of different endpoint-types + with different values of this parameter are associated with an rx-array-carrier, then the + smallest of the values shall apply."; + } + leaf-list up-symbolId-type-supported { + type up-SymbolId-type; + description + "List of supported symbol reordering symbolId interpretation capability."; } } @@ -1472,7 +3964,7 @@ module o-ran-uplane-conf { type boolean; description - "Informs if endpoint supports realtime variable bit with"; + "Informs if endpoint supports real-time variable bit with"; } leaf supported-compression-set-id { @@ -1487,6 +3979,22 @@ module o-ran-uplane-conf { uses endpoint-tdd-pattern-support; + leaf-list energy-sharing-group-id { + if-feature feat:MPLANE-DATA-LAYER-CONTROL; + type uint8; + description + "This value indicates a group of common underlying HW that can be used for energy savings."; + } + leaf se10-member-candidate-list { + if-feature feat:SE10-MEMBER-CANDIDATE-LIST; + type leafref { + path "/user-plane-configuration/se10-member-candidate-tx-lists/id"; + require-instance false; + } + description + "This parameter is a pointer to a given member-candidate list entry in 'se10-member-candidate-tx-lists'. + This parameter shall be applicable for endpoints supporting Section Extension 10"; + } } list static-low-level-rx-endpoints { @@ -1564,7 +4072,7 @@ module o-ran-uplane-conf { type boolean; description - "Informs if endpoint supports realtime variable bit with"; + "Informs if endpoint supports real-time variable bit with"; } leaf supported-compression-set-id { @@ -1581,6 +4089,42 @@ module o-ran-uplane-conf { uses endpoint-tdd-pattern-support; + leaf transmission-order { + when "(/user-plane-configuration/endpoint-types[id=current()/../endpoint-type]/ordered-transmission-supported = 'true')"; + if-feature feat:ORDERED-TRANSMISSION; + type uint32; + description + "The value indicates relative order of sending U-plane messages specific to same symbol + and transmission window by two endpoints with ordered-transmission = TRUE + belonging to the same transmission-order-group; + multiple endpoints may report the same value if their relative sending order is not guaranteed"; + } + + leaf transmission-order-group { + when "(/user-plane-configuration/endpoint-types[id=current()/../endpoint-type]/ordered-transmission-supported = 'true')"; + if-feature feat:ORDERED-TRANSMISSION; + type uint32; + description + "The value indicates a group of endpoints that preserve relative ordering of message sending; + message sending between endpoints in different groups is not guaranteed"; + } + + leaf-list energy-sharing-group-id { + if-feature feat:MPLANE-DATA-LAYER-CONTROL; + type uint8; + description + "This value indicates a group of common underlying HW that can be used for energy savings."; + } + leaf se10-member-candidate-list { + if-feature feat:SE10-MEMBER-CANDIDATE-LIST; + type leafref { + path "/user-plane-configuration/se10-member-candidate-rx-lists/id"; + require-instance false; + } + description + "This parameter is a pointer to a given member-candidate list entry in 'se10-member-candidate-rx-lists'. + This parameter shall be applicable for endpoints supporting Section Extension 10"; + } } list low-level-tx-endpoints { @@ -1588,7 +4132,7 @@ module o-ran-uplane-conf { description "Object model for low-level-tx-endpoints configuration - augmented static-low-level-tx-endpoints by local-address - which cannot be added to static low-level-tx-endpoints as we cannot have modificable element in static object"; + which cannot be added to static low-level-tx-endpoints as we cannot have modifiable element in static object"; leaf name { type leafref { @@ -1601,71 +4145,250 @@ module o-ran-uplane-conf { "Unique name of low-level-tx-endpoint object. Reference to static object"; } - container compression { - presence - "This container shall exists to avoid missaligned compression - methods between devices"; - + leaf sro-id { + if-feature feat:SHARED-ORU-MULTI-OPERATOR; + type leafref { + path "/or-user:users/or-user:user/or-user:sro-id"; + } description - "Container which consists of global configurable parameters for compression"; - - uses cf:compression-details; - - leaf fs-offset { - if-feature cf:CONFIGURABLE-FS-OFFSET; - type uint8; - default 0; - description - "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. - Please refer to CU-Plane specification for details"; - } - - list dynamic-compression-configuration { - when "../compression-type = 'DYNAMIC'"; - key "id"; - unique "compression-method iq-bitwidth fs-offset"; - description - "List of possible configuration in case dynamic configuration is used - Note: In case of empty list all available compressions can be choosen dynamically - and default fs-offset is taken (0)."; - - leaf id { - type uint16; - description - "Identification number for particular compression"; - } - - uses cf:compression-method-grouping; - - leaf fs-offset { - if-feature cf:CONFIGURABLE-FS-OFFSET; - type uint8; - default 0; - description - "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. - Please refer to CU-Plane specification for details"; - } - } + "An optional shared resource operator associated with this list entry. + When present, indicates that the list entry corresponds to a low-level-tx-endpoint + associated with a shared resource operator where the sro-id identifies + a specific shared resource operator. + This schema-node is used to refine NACM privileges for shared + resource operators"; } + + uses tx-endpoint-compression-grouping; uses scs-config; container e-axcid { uses eaxc; description - "Contains local address of low level TX endpoint offered by Netconf server."; + "Contains local address of low level TX endpoint offered by NETCONF server."; } uses coupling-methods; leaf configurable-tdd-pattern-supported { + if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; type leafref { - path "/user-plane-configuration/static-low-level-rx-endpoints[name=current()/../name]/configurable-tdd-pattern-supported"; + path "/user-plane-configuration/static-low-level-tx-endpoints[name=current()/../name]/configurable-tdd-pattern-supported"; require-instance false; } description "RO to RW parameter mapping - needed for conditional under tx-array-carrier"; } + + leaf cplane-message-processing-limits-enabled { + if-feature feat:CPLANE-MESSAGE-PROCESSING-LIMITS; + type boolean; + default false; + description + "TRUE: O-DU shall support the C-Plane message processing limits and has selected to adhere to the C-Plane limits defined in 'per-cplane-message-limits'. + FALSE: O-DU shall not support C-Plane message processing limits and endpoint limits defined in 'per-cplane-message-limits' shall not apply"; + } + + leaf uplane-message-section-header-limit-enabled { + if-feature feat:UPLANE-MESSAGE-PROCESSING-LIMITS; + type boolean; + default false; + description + "O-DU declares to obey the limit exposed via the leaf max-section-headers-per-uplane-message by setting this parameter to 'true'. + For details of this parameter's usage, please refer to M-plane spec clause 15.10"; + } + + leaf beam-update-contention-control-enabled { + if-feature feat:BEAM-UPDATE-CONTENTION-CONTROL; + type boolean; + default false; + description + "TRUE: O-DU shall support beam update contention control feature of O-RU.Thus requiring O-DU to comply with beam + updates restrictions defined in CUS-Plane Spec Section 'Weight-based dynamic beamforming'. In this case applicable + beam limits defined in 'beam-update-contention-control-limits' shall apply. + FALSE: O-DU shall not support beam update contention control feature of O-RU. Applicable beam limits defined in + 'endpoint-beam-capacity' shall apply"; + } + + container channel-information-prb-group-configuration { + if-feature feat:CHANNEL-INFORMATION-PRB-GROUP; + description + "Container for configurable parameters for channel information prb group"; + + leaf enable-ci-prb-group { + type boolean; + description + "Informs whether or not to enable channel information PRB group in the O-RU, + if its value is set to true, the O-RU shall receive and process channel + information (e.g., ST6) with PRB group size of configured ci-prb-group-size."; + } + + leaf ci-prb-group-size { + type uint8 { + range "2..254"; + } + description + "The configured channel information PRB group size. + If enable-ci-prb-group is configured as TRUE, and the IE ciPrbGroupSize doesn't exist in a section description for channel information, + the parameter ci-prb-group-size shall be used for this section description. + If the IE ciPrbGroupSize exists in a section description for channel information, + no matter whether enable-ci-prb-group is configured as TRUE, the IE ciPrbGroupSize shall be used for this section description."; + } + } + + leaf non-scheduled-ueid-enabled{ + if-feature feat:NON-SCHEDULED-UEID; + type boolean; + default false; + description + "If O-DU configures 'non-scheduled-ueid-enabled' = TRUE, + and Section Extension 10 is applied to Section Types 5 and beamGroupType = 10b, + and the O-DU set ueId of a port in Section Extension 10 to 0x7FFF, + the endpoint shall interpret that the PRBs in the section description are not scheduled for this port. + The endpoint only interprets this leaf if non-scheduled-ueid-supported = true is reported in the related static endpoint, in other cases this leaf is ignored. + Please refer to CUS specification clause 7.9.13 for more details."; + } + + leaf se-11-continuity-flag-enabled { + if-feature feat:SE11-WITH-CONTINUITY-BIT-SUPPORT; + type boolean; + default false; + description + "By setting the value of this leaf node to TRUE, the O-DU declares it will provide 'continuity' flag information in SE 11. + In this case the O-DU shall provide PRB region 'continuity' information in every SE 11 sent to the applicable low-level-tx-endpoint(s) + (static-low-level-tx-endpoit(s) which indicated support of this feature by setting 'se-11-continuity-flag-supported' flag to TRUE). + In case + - O-DU is running SW conformant to older O_RAN release and does not interpret the flag 'se11-continuity-bit-enabled' or + - the O-DU sets 'se11-continuity-flag-enabled' = FALSE, + no information regarding PRB region continuity is sent to the O-RU. In such case the O-RU shall process the PRB bundles as + it would have in the absence of the 'continuity' flag in SE11. + This behavior shall be same as when O-RU receives message with 'reserved' field value set to '0b'."; + } + + leaf prg-size-supp-se-21-with-st6-enabled { + if-feature feat:PRG-SIZE-SUPP-SE-21-WITH-ST6; + type boolean; + default false; + description + "TRUE: O-DU shall send prgSize information from the O-DU to the O-RU as described in Clause 7.7.2.3.1 of the CUS-Plane spec. + FALSE:prgSize information cannot be sent from the O-DU to the O-RU using Section Type 6."; + } + + leaf prg-size-supp-se-21-with-st5-enabled { + if-feature feat:PRG-SIZE-SUPP-SE-21-WITH-ST5; + type boolean; + default false; + description + "TRUE: O-DU shall send prgSize information from the O-DU to the O-RU as described in Clause 7.7.2.3.2 of the CUS-Plane spec. + FALSE:prgSize information cannot be sent from the O-DU to the O-RU using Section Type 5."; + } + + leaf user-group-optimization-enabled-tx { + if-feature feat:USER-GROUP-OPTIMIZATION; + type boolean; + default false; + description + "The parameter indicates that if the O-RU advertises the feature flag to 'user-group-optimization-supported' set to + TRUE for associated static-level-tx-endpoint, the O-DU may choose to set this flag to 'TRUE' or 'FALSE'. + - If set to 'TRUE', the O-DU shall be required to send all layers for a given user group UEs i.e., UEs with same + time-frequency allocation using single C-Plane section description. + - If set to 'FALSE', the O-DU restriction to send all layers for a given user group UEs shall not apply."; + } + + leaf se-20-multi-sd-punc-pattern-enabled-tx { + if-feature feat:SE20-MULTI-SD-PUNC-PATTERN-SUPPORT; + if-feature feat:USER-GROUP-OPTIMIZATION; + type boolean; + default false; + description + "This flag is applicable for O-RU adevertised static-level-tx-endpoint advertises for which + 'se-20-multi-sd-punc-pattern-suported' = TRUE. The flag is configured by the O-DU to TRUE/FALSE. + - Value of the flag set to 'TRUE' indicates O-DU shall set the value 'multiSDScope' in SE-20 to TRUE/FALSE. + - Value of the flag set to 'FALSE' indicates O-DU shall not set the value 'multiSDScope' in SE-20. The corresponding + fields shall be interpretted as reserved field by the O-RU."; + } + + container combination-configuration { + leaf endpoint-type { + type leafref { + path "/user-plane-configuration/static-low-level-tx-endpoints[name=current()/../../name]/endpoint-type"; + require-instance false; + } + description + "Leafref to the endpoint-type of the endpoint."; + } + + leaf combination-id { + type leafref { + path "/user-plane-configuration/endpoint-types[id = current()/../endpoint-type]/supported-configuration-combinations/combination-id"; + require-instance false; + } + description + "A parameter describing which configuration combination will be used by the endpoint."; + } + + list configurations { + key id; + + leaf id { + type uint32; + description + "Identifier of an entry in the list"; + } + + leaf set-id { + type leafref { + path "/user-plane-configuration/endpoint-types[id = current()/../../endpoint-type]/supported-configuration-combinations[combination-id = current()/../../combination-id]/set/set-id"; + require-instance false; + } + description + "A parameter describing which set will be used by the endpoint."; + } + + leaf config-id { + type leafref { + path "/user-plane-configuration/endpoint-types[id = current()/../../endpoint-type]/supported-configuration-combinations[combination-id = current()/../../combination-id]/set[set-id = current()/../set-id]/config/config-id"; + require-instance false; + } + description + "A parameter describing which config will be used by the endpoint."; + } + + description + "An optional list describing which configurations will be used by the endpoint. + The list can be provided by an O-DU, so that an O-RU can optimize the processing in the endpoint. + If the list is empty, then O-DU intends to use every capability within combination identified by combination-id."; + } + + description + "An optional container describing which configuration combination will be used by the endpoint. + The container can be provided by an O-DU, so that an O-RU can optimize the processing in the endpoint."; + } + + leaf configured-bf-profile-id { + if-feature feat:BF-DELAY-PROFILE; + type leafref { + path "/user-plane-configuration/endpoint-types/bf-profile-group"; + require-instance false; + } + description + "Configure the beamforming method list and related delay profiles will be used by the endpoint. + The configured-bf-profile-id must be one of the supported bf-profile-id(s) reported by the endpiont-type related to the endpoint. + If O-DU does not set configured-bf-profile-id, the O-RU shall not support the feature."; + } + + leaf-list bf-methods { + if-feature "feat:SELECTED-BF-METHOD-CONFIGURATION and feat:BF-DELAY-PROFILE"; + type beamforming-method-type; + description + "Beamforming method(s) configured on the endpoint. + + If the value of configured-bf-profile-id is set, then beamforming method(s) configured on the endpoint shall + be selected from the set of supported beamforming methods of the selected endpoint-bf-profile-group + Otherwise, the beamforming method(s) configured on the endpoint shall be selected from the set of supported + beamforming methods reported in the related endpoint-bf-profile-group(s)."; + } } list low-level-rx-endpoints { @@ -1673,7 +4396,7 @@ module o-ran-uplane-conf { description "Object model for low-level-rx-endpoint configuration - augmented static-low-level-rx-endpoints by local-address - which cannot be added to static low-level-rx-endpoints as we cannot have modificable element in static object"; + which cannot be added to static low-level-rx-endpoints as we cannot have modifiable element in static object"; leaf name { type leafref { @@ -1686,49 +4409,21 @@ module o-ran-uplane-conf { "Unique name of low-level-rx-endpoint object. Reference to static object"; } - container compression { + leaf sro-id { + if-feature feat:SHARED-ORU-MULTI-OPERATOR; + type leafref { + path "/or-user:users/or-user:user/or-user:sro-id"; + } description - "Container which consists of global configurable parameters for compression"; - - uses cf:compression-details; - - leaf fs-offset { - if-feature cf:CONFIGURABLE-FS-OFFSET; - type uint8; - default 0; - description - "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. - Please refer to CU-Plane specification for details"; - } - - list dynamic-compression-configuration { - when "../compression-type = 'DYNAMIC'"; - key "id"; - unique "compression-method iq-bitwidth fs-offset"; - description - "List of possible configuration in case dynamic configuration is used - Note: In case of empty list all available compressions can be choosen dynamically - and default fs-offset is taken (0)."; - - leaf id { - type uint16; - description - "Identification number for particular compression"; - } - - uses cf:compression-method-grouping; - - leaf fs-offset { - if-feature cf:CONFIGURABLE-FS-OFFSET; - type uint8; - default 0; - description - "Adjusts FS (full scale) value of IQ format relative to FS derived from unmodified IQ format. - Please refer to CU-Plane specification for details"; - } - } + "An optional shared resource operator associated with this list entry. + When present, indicates that the list entry corresponds to a low-level-rx-endpoint + associated with a shared resource operator where the sro-id identifies + a specific shared resource operator. + This schema-node is used to refine NACM privileges for shared + resource operators"; } + uses rx-endpoint-compression-grouping; uses scs-config; list ul-fft-sampling-offsets { @@ -1751,8 +4446,11 @@ module o-ran-uplane-conf { description "Determines time advance of capture window for FFT. Value represents time advance of capture window start in relation to the end of CP. Unit is Ts. + The value of this parameter shall not be larger than the duration of the cyclic prefix; in case of + variability of the cyclic prefix duration, the limit is the shortest duration of the cyclic prefix in use. Note: value of this parameter is usually set to '0' (zero) for PRACH channels. - Any phase offset resulting from the non-zero value of this parameter is handled in O-DU."; + Any phase offset resulting from the non-zero value of this parameter is handled in O-DU. + Please refer to the O-RAN CUS-Plane, clause 4.4.3 for more details on the intended usage and value restrictions."; } } @@ -1760,7 +4458,7 @@ module o-ran-uplane-conf { uses eaxc; description - "Contains local address of low level RX endpoint offered by Netconf server."; + "Contains local address of low level RX endpoint offered by NETCONF server."; } leaf eaxc-gain-correction { @@ -1771,7 +4469,7 @@ module o-ran-uplane-conf { units dB; default 0; description - "eAxC specifc part of overall gain_correction. + "eAxC specific part of overall gain_correction. gain_correction = common array-carrier gain-correction + eAxC-gain-correction."; } @@ -1810,7 +4508,7 @@ module o-ran-uplane-conf { } description "This parameter creates reference to static SRS configuration applicable for particular endpoint"; - } + } leaf configurable-tdd-pattern-supported { if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; @@ -1820,6 +4518,285 @@ module o-ran-uplane-conf { } description "RO to RW parameter mapping - needed for conditional under rx-array-carrier"; } + + uses u-plane-transmission-control; + + leaf ordered-transmission { + if-feature feat:ORDERED-TRANSMISSION; + type boolean; + default false; + description + "Commands O-RU to order UL U-plane message transmission between endpoints + Meaningless when ordered transmission is not supported for particular endpoint."; + } + + leaf cplane-message-processing-limits-enabled { + if-feature feat:CPLANE-MESSAGE-PROCESSING-LIMITS; + type boolean; + default false; + description + "TRUE: O-DU shall support C-Plane message processing limits and has selected to adhere + to the C-Plane limits defined in 'per-cplane-message-limits'. + FALSE: O-DU shall not support C-Plane message processing limits and hence C-Plane and + endpoint limits defined in 'per-cplane-message-limits' shall not apply"; + } + + leaf beam-update-contention-control-enabled { + if-feature feat:BEAM-UPDATE-CONTENTION-CONTROL; + type boolean; + default false; + description + "TRUE: O-DU shall support beam update contention control feature of O-RU.Thus requiring O-DU to comply with beam + updates restrictions defined in CUS-Plane Spec Section 'Weight-based dynamic beamforming'. In this case applicable + beam limits defined in 'beam-update-contention-control-limits' shall apply. + FALSE: O-DU shall not support beam update contention control feature of O-RU. Applicable beam limits defined in + 'endpoint-beam-capacity' shall apply"; + } + + leaf non-scheduled-ueid-enabled{ + if-feature feat:NON-SCHEDULED-UEID; + type boolean; + default false; + description + "If O-DU configures 'non-scheduled-ueid-enabled' = TRUE, + and Section Extension 10 is applied to Section Types 5 and beamGroupType = 10b, + and the O-DU set ueId of a port in Section Extension 10 to 0x7FFF, + the endpoint shall interpret that the PRBs in the section description are not scheduled for this port. + The endpoint only interprets this leaf if non-scheduled-ueid-supported = true is reported in the related static endpoint, in other cases this leaf is ignored. + Please refer to CUS specification clause 7.9.13 for more details."; + } + + leaf center-from-freqoffset-enabled { + type boolean; + default false; + description + "Endpoint is enabled / prohibited to autonomously calculate center frequency based on frequency offset."; + } + + leaf user-group-optimization-enabled-rx{ + if-feature feat:USER-GROUP-OPTIMIZATION; + type boolean; + default false; + description + "The parameter indicates that if the O-RU advertises the feature flag to 'user-group-optimization-supported' set to + TRUE for associated static-level-rx-endpoint, the O-DU may choose to set this flag to 'TRUE' or 'FALSE'. + - If set to 'TRUE', the O-DU shall be required to send all layers for a given user group UEs i.e., + UEs with same time-frequency allocation using single C-Plane section description. + - If set to 'FALSE', the O-DU restriction to send all layers for a given user group UEs shall not apply."; + } + + leaf se-20-multi-sd-punc-pattern-enabled-rx { + if-feature feat:SE20-MULTI-SD-PUNC-PATTERN-SUPPORT; + if-feature feat:USER-GROUP-OPTIMIZATION; + type boolean; + default false; + description + "This flag is applicable for O-RU adevertised static-level-rx-endpoint advertises for which + 'se-20-multi-sd-punc-pattern-suported' = TRUE. The flag is configured by the O-DU to TRUE/FALSE. + - Value of the flag set to 'TRUE' indicates O-DU shall set the value 'multiSDScope' in SE-20 to TRUE/FALSE. + - Value of the flag set to 'FALSE' indicates O-DU shall not set the value 'multiSDScope' in SE-20. The corresponding + fields shall be interpretted as reserved field by the O-RU."; + } + + container combination-configuration { + leaf endpoint-type { + type leafref { + path "/user-plane-configuration/static-low-level-rx-endpoints[name=current()/../../name]/endpoint-type"; + require-instance false; + } + description + "Leafref to the endpoint-type of the endpoint."; + } + + leaf combination-id { + type leafref { + path "/user-plane-configuration/endpoint-types[id = current()/../endpoint-type]/supported-configuration-combinations/combination-id"; + require-instance false; + } + description + "A parameter describing which configuration combination will be used by the endpoint."; + } + + list configurations { + key id; + + leaf id { + type uint32; + description + "Identifier of an entry in the list"; + } + + leaf set-id { + type leafref { + path "/user-plane-configuration/endpoint-types[id = current()/../../endpoint-type]/supported-configuration-combinations[combination-id = current()/../../combination-id]/set/set-id"; + require-instance false; + } + description + "A parameter describing which set will be used by the endpoint."; + } + + leaf config-id { + type leafref { + path "/user-plane-configuration/endpoint-types[id = current()/../../endpoint-type]/supported-configuration-combinations[combination-id = current()/../../combination-id]/set[set-id = current()/../set-id]/config/config-id"; + require-instance false; + } + description + "A parameter describing which config will be used by the endpoint."; + } + + description + "An optional list describing which configurations will be used by the endpoint. + The list can be provided by an O-DU, so that an O-RU can optimize the processing in the endpoint."; + + } + + description + "An optional container describing which configuration combination will be used by the endpoint. + The container can be provided by an O-DU, so that an O-RU can optimize the processing in the endpoint."; + } + + leaf configured-bf-profile-id { + if-feature feat:BF-DELAY-PROFILE; + type leafref { + path "/user-plane-configuration/endpoint-types/bf-profile-group"; + require-instance false; + } + description + "Configure which beamforming method list and related delay profile will be used by the endpoint. + The configured-bf-profile-id must be one of the supported bf-profile-id(s) reported by the endpiont-type related to the endpoint. + If O-DU does not set configured-bf-profile-id, the O-RU shall not support the feature."; + } + + leaf sinr-reporting-enabled { + if-feature feat:DMRS-BF-EQ; + type boolean; + default false; + description + "Enables SINR reporting for the endpoint."; + } + + container sinr-reporting-configuration { + when "../sinr-reporting-enabled = 'true'"; + if-feature feat:DMRS-BF-EQ; + description + "Container collecting parameters related to configuration of SINR reporting"; + + container sinr-resolution { + description + "Container collecting parameters related to configuration of SINR reporting + resolution. + Supported values are constrained by the values reported in endpoint-types/supported-sinr-resolutions. + + Please refer to CUS specification clause 7.2.10 for more details."; + leaf sinr-per-prb { + type uint8; + description + "Number of SINR values per PRB."; + } + leaf sinr-slot-mask { + type uint16; + description + "Pattern of SINR reports represented as a bitmask."; + } + } + container sinr-compression { + description + "Configuration of SINR compression."; + uses cf:sinr-compression-details; + leaf sinr-reference-level-config { + type decimal64 { + fraction-digits 4; + } + units dB; + description + "SINR reference level."; + } + + leaf sinr-reference-level-used { + type decimal64 { + fraction-digits 4; + } + units dB; + config false; + description + "SINR reference level used. This parameter shall be the O-RU's best approximation of the sinr-reference-level-config."; + } + } + } + leaf se26-usage-enabled { + type boolean; + default false; + description + "When se26-usage-enabled = FALSE, O-DU shall not use SE 26 and shall not convey UE frequency offset information. + When se26-usage-enabled = TRUE, O-DU may convey UE frequency offset information via SE 26."; + } + + leaf-list bf-methods { + if-feature "feat:SELECTED-BF-METHOD-CONFIGURATION and feat:BF-DELAY-PROFILE"; + type beamforming-method-type; + description + "Beamforming method(s) configured on the endpoint. + + If the value of configured-bf-profile-id is set, then beamforming method(s) configured on the endpoint shall + be selected from the set of supported beamforming methods of the selected endpoint-bf-profile-group + Otherwise, the beamforming method(s) configured on the endpoint shall be selected from the set of supported + beamforming methods reported in the related endpoint-bf-profile-group(s)."; + } + leaf eq-scale-offset-config { + if-feature "feat:DMRS-BF-EQ"; + type decimal64 { + fraction-digits 4; + } + units dB; + description + "scale offset is configured by the O-DU to avoid overflow when encoding data for the fronthaul interface.Refer to cus specification clause 8.1.3.4 for details."; + } + leaf eq-scale-offset-used { + if-feature "feat:DMRS-BF-EQ"; + type decimal64 { + fraction-digits 4; + } + units dB; + config false; + description + "scale offset is used by the O-RU to avoid overflow when encoding data for the fronthaul interface.Refer to cus specification clause 8.1.3.4 for details."; + } + leaf-list rrm-meas-enabled { + if-feature feat:RRM-MEAS-REPORTING; + type rrm-meas-types; + description + "This parameter indicates which rrm measurements are enabled for this low level endpoint"; + } + + leaf se-27-odu-controlled-dimensionality-reduction-enabled { + if-feature feat:SE27-ODU-CONTROLLED-DIMENSIONALITY-REDUCTION; + type enumeration { + enum DISABLED { + description + "O-DU controlled dimnesionality reduction disabled."; + } + enum STATIC { + description + "Static O-DU controlled dimnesionality reduction enabled."; + } + enum DYNAMIC { + description + "Dynamic O-DU controlled dimnesionality reduction enabled."; + } + } + default DISABLED; + description + "Parameter indicating if O-DU controlled dimnesionality reduction is enabled. + Please refer to CUS specification clause 7.7.27 for more details."; + } + leaf se-27-num-elements { + when "../se-27-odu-controlled-dimensionality-reduction-enabled = 'STATIC'"; + if-feature feat:SE27-ODU-CONTROLLED-DIMENSIONALITY-REDUCTION; + type uint16; + description + "Configured value of numElements in SE27. + Please refer to CUS specification clause 7.7.27 for more details."; + } } list tx-array-carriers { @@ -1829,10 +4806,49 @@ module o-ran-uplane-conf { leaf name { type string; - description "Unique name of tx-array-carriers object."; } + list odu-ids { + if-feature feat:SHARED-ORU-MULTI-ODU; + key odu-id; + description + "An optional list of o-du identities associated with this list entry. + When present, indicates that the list entry corresponds to a tx-array-carrier + associated with one or more particular odu-id(s). + + This list is used to enable enhanced watchdog operation when operating + in a single operator environment, where watchdog supervision is performed + on a per odu-id basis and supervision failure only results in a sub-set + of carriers being de-activated."; + + leaf odu-id { + type string; + description "an o-du identity "; + } + } + + list sro-ids-and-odu-ids { + if-feature "feat:SHARED-ORU-MULTI-ODU and feat:SHARED-ORU-MULTI-OPERATOR"; + key "odu-id sro-id"; + description + "An optional list of sro and o-du identities associated with this list entry. + When present, indicates that the list entry corresponds to a tx-array-carrier + associated with one or more particular odu-id(s) operated by a particular sro-id. + + This list is used to enable enhanced watchdog operation when operating + in a multi operator environment, where watchdog supervision is performed on + a per odu-id basis and supervision failure only results in a sub-set of + carriers being de-activated."; + leaf odu-id { + type string; + description "an o-du identity "; + } + leaf sro-id { + type string; + description "an sro identity "; + } + } uses tx-common-array-carrier-elements; @@ -1845,7 +4861,7 @@ module o-ran-uplane-conf { description "This parameter informing which frequency band particular antenna array is serving for. - Intended use is to deal with multiband solutions."; + Intended use is to deal with multi-band solutions."; } container lte-tdd-frame { @@ -1943,7 +4959,9 @@ module o-ran-uplane-conf { mandatory true; description - "Transmission gain in dB. Value applicable to each array element carrier belonging to array carrier."; + "Transmission gain in dB. Value applicable to each array element carrier belonging to array carrier. + + The value of transmission gain shall meet the constraints defined in CUS-Plane, clause 8.1.3.3."; } leaf downlink-radio-frame-offset { @@ -1954,8 +4972,8 @@ module o-ran-uplane-conf { description "This parameter is used for offsetting the starting position of 10ms radio frame. - Note: The value should have same value within DU to all tx-array-carrierss that have same frequency and bandwidth. - Note2: Unit is 1/1.2288e9 Hz and accuracy is 1/4 Tc. Then, its range is calculated 0..12288000."; + Note: The value should have same value within DU to all tx-array-carriers that have same frequency and bandwidth. + Note2: Unit is 1/1.2288e9 s. Then, its range is calculated 0..12288000."; } leaf downlink-sfn-offset { @@ -1967,7 +4985,22 @@ module o-ran-uplane-conf { description "This parameter is used for offsetting SFN value. Unit is in 10ms. - Note: The value should have same value within DU to all tx-array-carrierss that have same frequency and bandwidth."; + Note: The value should have same value within DU to all tx-array-carriers that have same frequency and bandwidth."; + } + + leaf t-da-offset { + if-feature "feat:EXT-ANT-DELAY-CONTROL"; + type uint32; + units Tc; + default 0; + description + "the time difference between the output of DL signal at the + antenna connector of O-RU and the transmission over the air. + units are Tc=~0.5ns=1/1.96608GHz. + An O-RU with 'ext-ant-delay-capability' = 'PER-O-RU' shall reject any configuration + where different values of t-da-offset are configured on tx-array-carriers; + An O-RU with 'ext-ant-delay-capability' = 'PER-ARRAY' shall reject any configuration + where different values of t-da-offset are configured on tx-array-carriers associated with the same tx-array."; } leaf reference-level { @@ -1992,6 +5025,22 @@ module o-ran-uplane-conf { The leaf may exist under tx-array-carrier only in case O-RU supports feature 'CONFIGURABLE-TDD-PATTERN-SUPPORTED' AND all low-level-tx-endpoints linked to this tx-array-carrier have configurable-tdd-pattern-supported = 'true'"; } + + leaf crb-to-prb-grid-offset { + if-feature "feat:PRG-SIZE-SUPP-SE-21-WITH-ST6 or feat:PRG-SIZE-SUPP-SE-21-WITH-ST5"; + type uint16 { + range 0..2199; + } + default 0; + description + "This parameter specifies the value of 'offsetToCarier' parameter as specified in the 3GPP Specification TS 38.331. + This value is the offset in frequency domain, between lowest subcarrier of common RB 0, which is the start of + carrier resource Block(CRB grid) and the lowest usable subcarrier on this array-carrier, which is (RE0 of PRB0), + in units of number of PRBs (using the SCS defined for associated array-carrier). This parameter shall be used with + 'prgSize' in Section Extension 21 by the O-RU to correctly derive Channel Information Based Beamforming weights. + Value of this parameter is not interpretted by the O-RU, if either 'prg-size-supp-se-21-with-st6-enabled' + or 'prg-size-supp-se-21-with-st5-enabled' parameter is not set to TRUE by the O-DU."; + } } list rx-array-carriers { @@ -2005,6 +5054,47 @@ module o-ran-uplane-conf { "Unique name of rx-array-carriers object."; } + list odu-ids { + if-feature feat:SHARED-ORU-MULTI-ODU; + key odu-id; + description + "An optional list of o-du identities associated with this list entry. + When present, indicates that the list entry corresponds to a rx-array-carrier + associated with one or more particular odu-id(s). + + This list is used to enable enhanced watchdog operation when operating + in a single operator environment, where watchdog supervision is performed + on a per odu-id basis and supervision failure only results in a sub-set + of carriers beign de-activated."; + + leaf odu-id { + type string; + description "an o-du identity "; + } + } + + list sro-ids-and-odu-ids { + if-feature "feat:SHARED-ORU-MULTI-ODU and feat:SHARED-ORU-MULTI-OPERATOR"; + key "odu-id sro-id"; + description + "An optional list of sro and o-du identities associated with this list entry. + When present, indicates that the list entry corresponds to a rx-array-carrier + associated with one or more particular odu-id(s) operated by a particular sro-id. + + This list is used to enable enhanced watchdog operation when operating + in a multi operator environment, where watchdog supervision is performed on + a per odu-id basis and supervision failure only results in a sub-set of + carriers beign de-activated."; + leaf odu-id { + type string; + description "an o-du identity "; + } + leaf sro-id { + type string; + description "an sro identity "; + } + } + uses rx-common-array-carrier-elements; leaf downlink-radio-frame-offset { @@ -2015,8 +5105,8 @@ module o-ran-uplane-conf { description "This parameter is used for offsetting the starting position of 10ms radio frame. - Note: The value should have same value within DU to all tx-array-carrierss that have same frequency and bandwidth. - Note2: Unit is 1/1.2288e9 Hz and accuracy is 1/4 Tc. Then, its range is calculated 0..12288000."; + Note: The value should have same value within DU to all tx-array-carriers that have same frequency and bandwidth. + Note2: Unit is 1/1.2288e9 s. Then, its range is calculated 0..12288000."; } leaf downlink-sfn-offset { @@ -2028,7 +5118,7 @@ module o-ran-uplane-conf { description "This parameter is used for offsetting SFN value. Unit is in 10ms. - Note: The value should have same value within DU to all tx-array-carrierss that have same frequency and bandwidth."; + Note: The value should have same value within DU to all tx-array-carriers that have same frequency and bandwidth."; } leaf gain-correction { @@ -2053,6 +5143,21 @@ module o-ran-uplane-conf { units are Tc=~0.5ns=1/1.96608GHz"; } + leaf t-au-offset { + if-feature "feat:EXT-ANT-DELAY-CONTROL"; + type uint32; + units Tc; + default 0; + description + "the time difference between the reception over the air and + the input of UL signal at the antenna connector of O-RU. + units are Tc=~0.5ns=1/1.96608GHz. + An O-RU with 'ext-ant-delay-capability' = 'PER-O-RU' shall reject any configuration + where different values of t-au-offset are configured on rx-array-carriers; + An O-RU with 'ext-ant-delay-capability' = 'PER-ARRAY' shall reject any configuration + where different values of t-au-offset are configured on rx-array-carriers associated with the same rx-array."; + } + leaf configurable-tdd-pattern { when "not(/user-plane-configuration/low-level-rx-endpoints[name = string(/user-plane-configuration/low-level-rx-links[rx-array-carrier = current()/../name]/rx-array-carrier)]/configurable-tdd-pattern-supported = 'false')"; if-feature mcap:CONFIGURABLE-TDD-PATTERN-SUPPORTED; @@ -2064,6 +5169,53 @@ module o-ran-uplane-conf { The leaf may exist under rx-array-carrier only in case O-RU supports feature 'CONFIGURABLE-TDD-PATTERN-SUPPORTED' AND all low-level-rx-endpoints linked to this rx-array-carrier have configurable-tdd-pattern-supported = 'true'"; } + + leaf user-group-mode { + if-feature "feat:USER-GROUP-SELF-ASSEMBLY"; + type enumeration { + enum NO-SELF-ASSEMBLY { + description "No user group self assembly"; + } + enum SELF-ASSEMBLY-WITH-GROUP-ID { + description "User group self assembly with group id."; + } + enum SELF-ASSEMBLY-WITHOUT-GROUP-ID { + description "User group self assembly without group id."; + } + } + default NO-SELF-ASSEMBLY; + description + "Configuration of user group self assembly."; + } + + leaf point-a-offset-to-absolute-frequency-center { + if-feature "(feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ) and feat:POINT-A-OFFSET-TO-ABSOLUTE-FREQUENCY-CENTER"; + type int32; + description + "An offset between center-of-channel-bandwidth and Point A. + If the value is not provided, then Point A coincides with RE#0 of PRB#0 indicated by offset-to-absolute-frequency-center. + The unit of this parameter is 1/2 of reference SCS, where reference SCS is 15 kHz for FR1 and 60 kHz for FR2. + + Please refer to CUS specification clause 7.7.24 for more details."; + } + + leaf continuity-block-size-configured { + if-feature "(feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ) and feat:CONTINUITY-BLOCK-SIZE"; + type uint8; + description + "This parameter specified the O-DU configured value of continuity block size per rx-array-carrier. + The O-DU shall pick one of the values advertised by the O-RU in 'continuity-block-size-list'"; + } + + leaf port-reduced-dmrs-data-sending-enabled { + if-feature "feat:DMRS-BF-EQ or feat:DMRS-BF-NEQ"; + type boolean; + description + "This parameter value if set to TRUE indicates O-DU request to O-RU for sending port reduced DMRS + sending from O-RU. If the flag is set to FALSE indicates O-RU shall not send port reduced DMRS + from O-RU to O-DU."; + } + } list tx-arrays { @@ -2074,6 +5226,16 @@ module o-ran-uplane-conf { uses parameters; + leaf min-gain { + type decimal64 { + fraction-digits 4; + + } + units dB; + description + "Min gain of RF path linked with array element (maximum over elements of array) or array layers"; + } + leaf max-gain { type decimal64 { fraction-digits 4; @@ -2090,13 +5252,38 @@ module o-ran-uplane-conf { mandatory true; description "If true then every element of array has own, power budget independent from power budget of other elements. - Else all elements of array that are at same row and column and have same polarization share power budget"; + Else all elements of array that are at same row and column and have same polarisation share power budget"; } list capabilities { description "List of capabilities related to this tx-array"; uses mcap:support-for-dl; + + container supported-energy-saving-capabilities-dl { + description + "Network energy saving capabilities supported in DL path"; + + container trx-control-capability-info { + if-feature feat:TRX-CONTROL; + description + "A container with parameters for TRX-CONTROL capabilities supported by the O-RU."; + uses mcap:trx-control-capability-info; + } + + container asm-capability-info { + if-feature feat:ADVANCED-SLEEP-MODE; + description + "A container with parameters for advanced sleep mode capabilities supported by the O-RU."; + uses mcap:asm-capability-info; + } + } + } + container mplane-trx-control-txarr-capability-info { + if-feature feat:MPLANE-TRX-CONTROL; + description + "A container with parameters for MPLANE-TRX-CONTROL feature supported by the O-RU."; + uses mplane-trx-control-supp-antenna-masks; } } @@ -2132,6 +5319,32 @@ module o-ran-uplane-conf { description "List of capabilities related to this rx-array"; uses mcap:support-for-ul; + + container supported-energy-saving-capabilities-ul { + description + "Network energy saving capabilities supported in UL path"; + + container trx-control-capability-info { + if-feature feat:TRX-CONTROL; + description + "A container with parameters for TRX-CONTROL capabilities supported by the O-RU"; + uses mcap:trx-control-capability-info; + } + + container asm-capability-info { + if-feature feat:ADVANCED-SLEEP-MODE; + description + "A container with parameters for advanced sleep mode capabilities supported by the O-RU"; + uses mcap:asm-capability-info; + } + } + } + container mplane-trx-control-rxarr-capability-info { + if-feature feat:MPLANE-TRX-CONTROL; + description + "A container with parameters for MPLANE-TRX-CONTROL feature supported by the O-RU."; + + uses mplane-trx-control-supp-antenna-masks; } } @@ -2151,13 +5364,13 @@ module o-ran-uplane-conf { uses array-choice; description - "Defnes name for first array"; + "Defines name for first array"; } container array2 { uses array-choice; description - "Defnes name for second array"; + "Defines name for second array"; } list types { key "relation-type"; @@ -2248,7 +5461,7 @@ module o-ran-uplane-conf { type uint16; description "This parameter contains eAxC_ID that populates content of C-Plane section - extension 11 to eAxC_IDs configured in the group as 'member-tx-eaxc-id'(s)."; + extension 10 to eAxC_IDs configured in the group as 'member-tx-eaxc-id'(s)."; } leaf-list member-tx-eaxc-id { type uint16; @@ -2258,9 +5471,13 @@ module o-ran-uplane-conf { must "current()!=../representative-tx-eaxc-id" { error-message "the representative eaxcid does not need to be a list member"; } + ordered-by user; description "This is a list of member eAxC IDs, which together with the representative-tx-eaxc-id, - are assigned to low-level-tx-endpoints in the group."; + are assigned to low-level-tx-endpoints in the group. + This list is defined as 'ordered-by user', because the order of the eaxc-id list should be maintained, + and the parameters in the SE10 are applied to the eaxc-ids based on the order of eaxc-ids in the list + when the section extension conveys unique parameters (beamId/ueId) per eaxc-id."; } } @@ -2282,7 +5499,7 @@ module o-ran-uplane-conf { type uint16; description "This parameter contains eAxC_ID that populates content of C-Plane section - extension 11 to eAxC_IDs configured in the group as 'member-rx-eaxc-id'(s)."; + extension 10 to eAxC_IDs configured in the group as 'member-rx-eaxc-id'(s)."; } leaf-list member-rx-eaxc-id { @@ -2291,10 +5508,14 @@ module o-ran-uplane-conf { error-message "too many rx-eaxcid-id members"; } must "current()!=../representative-rx-eaxc-id" { - error-message "the representative eaxcid does not need to be a list member"; + error-message "the representative eaxc-id does not need to be a list member"; } + ordered-by user; description - "This is a list of member eAxC IDs assigned to low-level-rx-endpoints in the group."; + "This is a list of member eAxC IDs assigned to low-level-rx-endpoints in the group. + This list is defined as 'ordered-by user', because the order of the eaxc-id list should be maintained, + and the parameters in the SE10 are applied to the eaxc-ids based on the order of eaxc-ids in the list + when the section extension conveys unique parameters (beamId/ueId) per eaxc-id."; } } } @@ -2320,6 +5541,17 @@ module o-ran-uplane-conf { description "Set of parameters related to static PRACH configuration"; + leaf sfn-offset { + type uint32; + + description + "This parameter is used for offsetting SFN value. + The SFN that results from the offset is used as the reference for the start of pattern periods. + If the value is not set, then pattern periods follow the reference set in a related rx-array-carrier. + The value is primarily used for cases in which pattern-period is not a power of 2. + Unit is in 10ms."; + } + leaf pattern-period { type uint16 { range 1..1024; @@ -2357,20 +5589,23 @@ module o-ran-uplane-conf { units Ts; mandatory true; description - "Duration of single sequence of the PRACH. Sequence may be considered as 'single PRACH symbol'"; + "Duration of single PRACH Symbol. Refer to definition of PRACH Symbol in CUS specification clause 3.1."; } list prach-patterns { key prach-pattern-id; min-elements 1; description - "Provides a PRACH pattern. Each record in the list represents a single PRACH occasion. Number of list entries cannot exceed max-prach-patterns"; + "Provides a PRACH pattern. Each record in the list represents a single PRACH occasion. Number of list entries cannot + exceed max-prach-patterns or extended-max-prach-patterns if EXTENDED-PRACH-CONFIGURATION is supported."; leaf prach-pattern-id { - type uint16; + type uint32; mandatory true; description - "Supplementary parameter acting as key for prach-pattern list."; + "Supplementary parameter acting as key for prach-pattern list. + NETCONF client shall limit its maximum value to 65535 when configuring + any O-RU that does not support the EXTENDED-PRACH-CONFIGURATION feature."; } leaf number-of-repetitions { @@ -2379,15 +5614,17 @@ module o-ran-uplane-conf { } mandatory true; description - "This parameter defines number of PRACH repetitions in PRACH occasion, - to which the section control is applicable."; + "This parameter defines number of PRACH PRACH Symbol repetitions in PRACH occasion, + to which the section control is applicable. Refer to definition of PRACH Symbol in CUS specification clause 3.1."; } leaf number-of-occasions { - type uint8; + type uint32; mandatory true; description - "This parameter informs how many consecutive PRACH occasions is described by the PRACH pattern."; + "This parameter informs how many consecutive PRACH occasions is described by the PRACH pattern. + NETCONF client shall limit its maximum value to 255 when configuring any O-RU that does not + support the EXTENDED-PRACH-CONFIGURATION feature."; } leaf re-offset { @@ -2409,10 +5646,11 @@ module o-ran-uplane-conf { to value of parameter number-of-occasions."; leaf occasion-id { - type uint8; + type uint32; mandatory true; description - "Supplementary parameter acting as key in 'occasion-parameters' list"; + "Supplementary parameter acting as key in 'occasion-parameters' list. + The value is limited to 255 if EXTENDED-PRACH-CONFIGURATION is unsupported."; } leaf cp-length { @@ -2431,7 +5669,9 @@ module o-ran-uplane-conf { } leaf beam-id { - type uint16; + type uint16 { + range "min .. 32767"; + } mandatory true; description "This parameter defines the beam pattern to be applied to the U-Plane data. @@ -2520,7 +5760,9 @@ module o-ran-uplane-conf { } leaf beam-id { - type uint16; + type uint16 { + range "min .. 32767"; + } mandatory true; description "This parameter defines the beam pattern to be applied to the U-Plane data. @@ -2531,8 +5773,8 @@ module o-ran-uplane-conf { type uint16; mandatory true; description - "This parameter defines number of consecutive symbols covered by specific srs-pattern. - Single srs-pattern may address at least one symbol. However, possible optimizations + "This parameter defines number of consecutive symbols covered by specific srs-pattern. + Single srs-pattern may address at least one symbol. However, possible optimisations could allow for several (up to 14) symbols."; } @@ -2596,7 +5838,7 @@ module o-ran-uplane-conf { type uint32; mandatory true; description - "Offset from DL air frame boundary transmitted at RF connector to the point in time that is characteristic to the operation on RF switches. Unit is 1/1.2288e9 Hz and accuracy is 1/4 Tc."; + "Offset from DL air frame boundary transmitted at RF connector to the point in time that is characteristic to the operation on RF switches. Unit is 1/1.2288e9 s."; } } } @@ -2630,6 +5872,79 @@ module o-ran-uplane-conf { uses configurable-tdd-pattern; } + + list endpoint-bf-profile-group { + if-feature feat:BF-DELAY-PROFILE; + key "bf-profile-id"; + config false; + description + "An optional list of list(s) containing beamforming methods supported by the O-RU with the associated delay-profile-id + per each beamforming method list"; + leaf bf-profile-id { + type uint16; + description + "Identifies the beamforming method list."; + } + leaf-list supported-bf-methods { + type beamforming-method-type; + min-elements 1; + description + "Beamforming methods can be supported simultaneously."; + } + leaf supported-delay-profile { + type leafref { + path "/or-dm:delay-management/or-dm:non-default-ru-delay-profile/or-dm:delay-profile-id"; + require-instance false; + } + description + "The delay-profile-id associated with the supported beamforming method list. + If not configured or the value is set to 0, all delay parameters shall be equivalent to the default value."; + } + } + list se10-member-candidate-tx-lists { + if-feature feat:SE10-MEMBER-CANDIDATE-LIST; + key "id"; + config false; + description + "List of leaf-lists, where each leaf-list is a member-candidate list comprising of endpoints + which can be associated to one or more static-low-level-tx-endpoint(s)."; + leaf id { + type uint8; + description + "Index into the list se10-member-candidate-tx-lists."; + } + leaf-list member-candidates { + type leafref { + path "/user-plane-configuration/static-low-level-tx-endpoints/name"; + require-instance false; + } + description + "Each leaf-list comprises one or more static-low-elevel-tx-endpoint(s). Endpoints in this list can + be representative endpoint or member endpoint."; + } + } + list se10-member-candidate-rx-lists { + if-feature feat:SE10-MEMBER-CANDIDATE-LIST; + key "id"; + config false; + description + "List of leaf-lists, where each leaf-list is a member-candidate list comprising of endpoints + which can be associated to one or more static-low-level-rx-endpoint(s)."; + leaf id { + type uint8; + description + "Index into the list se10-member-candidate-rx-lists."; + } + leaf-list member-candidates { + type leafref { + path "/user-plane-configuration/static-low-level-rx-endpoints/name"; + require-instance false; + } + description + "Each leaf-list comprises one or more static-low-elevel-rx-endpoint(s). Endpoints in this list can + be representative endpoint or member endpoint."; + } + } } grouping tx-array-notification-group { @@ -2651,8 +5966,15 @@ module o-ran-uplane-conf { type leafref{ path "/user-plane-configuration/tx-array-carriers/state"; } - description - "state of tx-array-carriers is notified at state change"; + description + "state of tx-array-carriers is notified at state change"; + } + leaf availability-status{ + type leafref{ + path "/user-plane-configuration/tx-array-carriers/availability-status"; + } + description + "availability-status of tx-array-carriers is notified at availability-status change"; } } } @@ -2679,16 +6001,23 @@ module o-ran-uplane-conf { description "state of rx-array-carriers is notified at state change"; } + leaf availability-status{ + type leafref{ + path "/user-plane-configuration/rx-array-carriers/availability-status"; + } + description + "availability-status of rx-array-carriers is notified at availability-status change"; + } } } -// top level container - + // top level container container user-plane-configuration { description "top level container for user plane configuration"; uses uplane-conf-group; uses general-config; + uses array-config-group; } //notification statement @@ -2703,4 +6032,68 @@ module o-ran-uplane-conf { uses rx-array-notification-group; } + + notification data-layer-control-wakeup-notification { + if-feature feat:MPLANE-DATA-LAYER-CONTROL; + description + "Notification used to inform about wake-up completion after M-Plane based data layer control sleep is terminated"; + leaf-list energy-sharing-group { + type uint8; + description + "Notification for wake-up completion of underlying HW components corresponding to energy sharing group. + This value shall be specific values from the list of 'energy-sharing-group-id' inside static-low-level-[tr]x-endpoints."; + } + } + notification mplane-trx-control-ant-mask-update { + if-feature feat:MPLANE-TRX-CONTROL; + + leaf array-name { + type union { + type leafref { + path "/user-plane-configuration/rx-arrays/name"; + } + type leafref { + path "/user-plane-configuration/tx-arrays/name"; + } + } + description + "The array name for which antenna mask has been updated using + MPLANE-TRX-CONTROL feature."; + } + leaf array-type { + type enumeration { + enum TX-ARRAY { + description + "this array is of type TX array"; + } + enum RX-ARRAY { + description + "this array is of type RX array"; + } + } + description + "The type of array for which antenna mask has been updated using + MPLANE-TRX-CONTROL feature."; + } + leaf updated-antenna-mask { + type binary; + description + "The updated antenna mask value after processing M-Plane based TRX control command at the O-RU. + If mplane-supported-trx-control-masks list is not advertised as part of capability for the referred [tr]x-array, + the parameter antenna-bitmask shall be used for notification. + The parameter antenna-bitmask-index shall not be used for notification."; + } + leaf updated-antenna-mask-index { + type uint8; + description + "The parameter indicates updated antenna mask index value after processing M-Plane based TRX control command at the O-RU. + If mplane-supported-trx-control-masks list is advertised as part of capability for the referred [tr]x-array, + the parameter antenna-bitmask-index shall be used for notification to refer to the index of advertised mplane-supported-trx-control-masks. + The parameter antenna-bitmask shall not be used for notification."; + } + description + "M-Plane notification event to notify that the commanded mask has been activated via M-plane. This notification + is required to be sent for either tx-array or rx-array for which the antenna mask was + commanded to be changed by the O-DU."; + } } diff --git a/radio/fhi_72/mplane/yang/models/o-ran-usermgmt.yang b/radio/fhi_72/mplane/yang/models/o-ran-usermgmt.yang new file mode 100644 index 0000000000..e8ac1fdeff --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/o-ran-usermgmt.yang @@ -0,0 +1,331 @@ +module o-ran-usermgmt { + yang-version 1.1; + namespace "urn:o-ran:user-mgmt:1.0"; + prefix "o-ran-usermgmt"; + + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + import o-ran-wg4-features { + prefix "feat"; + } + + import ietf-crypto-types { + prefix ct; + } + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the user management model for the O-RAN Equipment. + + Copyright 2024 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2024-08-12" { + description + "version 16.0.0 + + 1) add SSH Public Key."; + + reference "ORAN-WG4.M.0-v16.00"; + } + + revision "2023-12-11" { + description + "version 10.1.0 + + 1) clarify handling of User-Names."; + + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2022-08-15" { + description + "version 10.0.0 + + 1) introduced SHARED-ORU-MULTI-OPERATOR feature."; + + reference "ORAN-WG4.M.0-v10.00"; + } + + + revision "2021-12-01" { + description + "version 1.3.0 + + 1) typographical corrections in descriptions"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2020-12-10" { + description + "version 1.2.0 + + 1) updated description for enabled leaf"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-07-03" { + description + "version 1.1.0 + + 1) change name leaf to type nacm:user-name-type + 2) added account-type to qualify when password is required "; + + reference "ORAN-WG4.M.0-v01.00"; + } + + revision "2019-02-04" { + description + "version 1.0.0 + + 1) imported model from xRAN + 2) changed namespace and reference from xran to o-ran"; + + reference "ORAN-WG4.M.0-v01.00"; + } + + typedef password-type { + type string { + length "8..128"; + pattern "[a-zA-Z0-9!$%\\^()\\[\\]_\\-~{}.+]*" { + error-message "Password content does not meet the requirements"; + } + } + description + "The password for this entry. + The Password must contain at least 2 characters from + each of the following groups: + a) Lower case alphabetic (a-z) + b) Upper case alphabetic (A-Z) + c) Numeric 0-9 + d) Special characters Allowed !$%^()[]_-~{}.+ + Password must not contain Username. + + When a password is received by a NETCONF server, + it should be securely stored in the O-RU's configuration datastore. + How to securely store the password in the datastore is implementation-specific + and out of scope of WG4 M-Plane specification."; + } + + grouping user-list { + description "a user list grouping"; + list user { + key "name"; + description + "The list of local users configured on this device."; + leaf name { + type nacm:user-name-type; + description + "The user name string identifying this entry. + + NOTE: o-ran-usermgmt:user-profile/user/name is + identical to nacm:nacm/groups/group/user-name + but the current schema is preserved for backwards + compatibility."; + } + leaf account-type { + type enumeration { + enum PASSWORD { + description "the user-name is for password based authentication"; + } + enum CERTIFICATE { + description "the user-name is for certificate based authentication"; + } + enum SSHPUBLICKEY { + if-feature feat:CLIENT-AUTH-SSH-PUBLIC-KEY; + description "the user-name is for public key based authentication"; + } + } + default "PASSWORD"; + description "the account type"; + } + + leaf password { + nacm:default-deny-all; + type password-type; + description + "The password for this entry. + + This field is only valid when account-type is PASSWORD, + i.e., when account-type is NOT present or present and set to + PASSWORD."; + } + + container ssh-public-key { + nacm:default-deny-all; + when "../account-type='SSHPUBLICKEY'"; + if-feature feat:CLIENT-AUTH-SSH-PUBLIC-KEY; + uses ct:public-key-grouping; + description + "The SSH pubic key for this entry. + + This field is valid only when account-type is SSHPUBLICKEY."; + } + + leaf enabled { + type boolean; + description + "Indicates whether an account is enabled or disabled. + + A NETCONF Server shall reject a configuration that attempts to + enable a Password account for an account where the password leaf + is not configured. + + This validation statement is included in the YANG description and + not in a MUST statement to preserve backwards compatibility."; + } + leaf-list sro-id { + if-feature feat:SHARED-ORU-MULTI-OPERATOR; + type string; + description + "An optional list if Shared Resource Operator identities associated with the + user-account. Used to realize enhanced access privileges in a shared O-RU. + When an sro-id is configured in the O-RU, the O-RU shall + implement additional sro-id based NETCONF access control + as specified in O-RAN.WG4.MP.0-v10.00. + The O-RU does not further interpret the specific value of sro-id."; + } + } + } + + container users { + must "user/enabled='true'" { + error-message "At least one account needs to be enabled."; + } + //TAKE NOTE - any configuration with zero enabled users is invalid. + //This will typically be the case when using a simulated NETCONF Server + //and so this constraint should be removed when operating in those scenarios + + //The config data base of the O-RAN equipment should ensure that the user + //default account is enabled on factory restart + + description "list of user accounts"; + uses user-list; + } + + rpc chg-password { + description "the RPC used to change a password"; + nacm:default-deny-all; + input { + leaf currentPassword { + type password-type; + mandatory true; + description + "provide the current password"; + } + leaf newPassword { + type password-type; + mandatory true; + description + "provide a new password"; + } + leaf newPasswordConfirm { + type password-type; + mandatory true; + description + "re-enter the new password "; + } + } + output { + leaf status { + type enumeration { + enum "Successful" { + value 1; + description "change password operation is successful"; + } + enum "Failed" { + value 2; + description "change password operation failed"; + } + } + mandatory true; + description + "Successful or Failed"; + } + leaf status-message { + type string; + description + "Gives a more detailed reason for success / failure"; + } + } + } + + rpc chg-ssh-public-key { + if-feature feat:CLIENT-AUTH-SSH-PUBLIC-KEY; + description "the RPC used to change SSH public key"; + nacm:default-deny-all; + input { + container current-ssh-public-key { + uses ct:public-key-grouping; + description + "provide the current SSH public algorithm and key"; + } + container new-ssh-public-key { + uses ct:public-key-grouping; + description + "provide a new SSH public algorithm and key"; + } + container new-ssh-public-key-confirm { + uses ct:public-key-grouping; + description + "re-enter the new SSH public algorithm and key"; + } + } + output { + leaf status { + type enumeration { + enum "Successful" { + value 1; + description "change SSH public key operation is successful"; + } + enum "Failed" { + value 2; + description "change SSH public key operation failed"; + } + } + mandatory true; + description + "Successful or Failed"; + } + leaf status-message { + type string; + description + "Gives a more detailed reason for success / failure"; + } + } + } + +} diff --git a/radio/fhi_72/mplane/yang/models/o-ran-wg4-features.yang b/radio/fhi_72/mplane/yang/models/o-ran-wg4-features.yang new file mode 100644 index 0000000000..1f186ea7d6 --- /dev/null +++ b/radio/fhi_72/mplane/yang/models/o-ran-wg4-features.yang @@ -0,0 +1,532 @@ +module o-ran-wg4-features { + yang-version 1.1; + namespace "urn:o-ran:wg4feat:1.0"; + prefix "o-ran-feat"; + + + organization "O-RAN Alliance"; + + contact + "www.o-ran.org"; + + description + "This module defines the set of re-usable type definitions for WG4 specific + features. + + Copyright 2024 the O-RAN Alliance. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the above disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the above disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the Members of the O-RAN Alliance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission."; + + revision "2024-08-12" { + description + "version 16.0.0 + new features: + + 1) PRG-SIZE-SUPP-SE-21-WITH-ST6 + 2) PRG-SIZE-SUPP-SE-21-WITH-ST5 + 3) USER-GROUP-OPTIMIZATION + 4) BF-DELAY-PROFILE + 5) DMRS-BF-EQ + 6) DMRS-BF-NEQ + 7) RRM-MEAS-REPORTING + 8) USER-GROUP-SELF-ASSEMBLY + 9) UEID-PERSISTENCE + 10) CONTINUITY-BLOCK-SIZE + 11) SELECTED-BF-METHOD-CONFIGURATION + 12) DMRS-BF-NEQ-UNALTERED-FREQ-OFFSET + 13) DMRS-BF-NEQ-UNALTERED-TAE + 14) SE10-MEMBER-CANDIDATE-LIST + 15) MACSEC-BYPASS-POLICY + 16) SE27-ODU-CONTROLLED-DIMENSIONALITY-REDUCTION + 17) SE20-MULTI-SD-PUNC-PATTERN-SUPPORT + 18) CONFIGURABLE-VSWR-THRESHOLDS + 19) CLIENT-AUTH-SSH-PUBLIC-KEY + 20) POINT-A-OFFSET-TO-ABSOLUTE-FREQUENCY-CENTER"; + + reference "ORAN-WG4.M.0-v16.00"; + } + + revision "2024-04-15" { + description + "version 15.0.0 + new features: + + 1) PRG-SIZE-SUPP-SE-21-WITH-ST6 + 2) PRG-SIZE-SUPP-SE-21-WITH-ST5 + 3) BF-DELAY-PROFILE + 4) USER-GROUP-OPTIMIZATION + 5) MULTIPLE-BEAMID-TABLES-SUPPORTED + 6) PER-PORT-PTP-CONFIG + 7) PER-PORT-SYNCE-CONFIG + 8) MPLANE-TRX-CONTROL + 9) PER-INT-TCP-MSS + 10) DEEP-HIBERNATE"; + + reference "ORAN-WG4.M.0-v15.00"; + } + + revision "2023-12-11" { + description + "version 14.0.0 + new features: + + 1) SE23-PRB-BLOCK-MODE-SUPPORT + 2) MPLANE-DATA-LAYER-CONTROL + 3) SHARED-CELL-STATS"; + + reference "ORAN-WG4.M.0-v14.00"; + } + + revision "2023-08-14" { + description + "version 13.0.0 + new features: + + 1) CALL-HOME-REACTIVATION-SUPPORTED + 2) SEQ-ID-CHECKING-CONFIGURABLE + 3) TRX-CONTROL + 4) ADVANCED-SLEEP-MODE"; + + reference "ORAN-WG4.M.0-v13.00"; + } + + revision "2023-04-10" { + description + "version 12.0.0 + new features: + + 1) EXTENDED-PRACH-CONFIGURATION + 2) NON-SCHEDULED-UEID + 3) SE11-WITH-CONTINUITY-BIT-SUPPORT + 4) UPLANE-MESSAGE-PROCESSING-LIMITS"; + + reference "ORAN-WG4.M.0-v12.00"; + } + + revision "2022-12-05" { + description + "version 11.0.0 + new features: + + 1) UPLANE-ONLY-DL-MODE + 2) SUPERVISION-WITH-SESSION-ID + 3) INTEGRITY-CHECK-AT-SW-DOWNLOAD + 4) ST4-SLOT-CONFIG-MSG-SUPPORT"; + + reference "ORAN-WG4.M.0-v11.00"; + } + + + revision "2022-08-15" { + description + "version 10.0.0 + new features: + 1) SHARED-ORU-MULTI-ODU + 2) SHARED-ORU-MULTI-OPERATOR"; + reference "ORAN-WG4.M.0-v10.00"; + } + + revision "2021-12-01" { + description + "version 8.0.0 + new features: + 1) Typographical corrections in descriptions + 2) Add new features: + BEAM-UPDATE-CONTENTION-CONTROL + MULTIPLE-SCS-IN-EAXC + ENHANCED-T-COMBINE + CHANNEL-INFORMATION-COMPRESSION + CHANNEL-INFORMATION-PRB-GROUP + MULTIPLE-TRANSPORT-SESSION-TYPE"; + reference "ORAN-WG4.M.0-v08.00"; + } + + revision "2021-07-26" { + description + "version 7.0.0 + + new features: + 1) EXT-ANT-DELAY-CONTRO + 2) CPLANE-MESSAGE-PROCESSING-LIMITS"; + + reference "ORAN-WG4.M.0-v07.00"; + } + + revision "2021-03-22" { + description + "version 6.0.0 + + 1) Features added to handle updated transmission window control: + STATIC-TRANSMISSION-WINDOW-CONTROL + DYNAMIC-TRANSMISSION-WINDOW-CONTROL + UNIFORMLY-DISTRIBUTED-TRANSMISSION + ORDERED-TRANSMISSION + INDEPENDENT-TRANSMISSION-WINDOW-CONTROL + "; + + reference "ORAN-WG4.M.0-v06.00"; + } + + revision "2020-12-10" { + description + "version 5.0.0 + + 1) initial version."; + + reference "ORAN-WG4.M.0-v05.00"; + } + + feature NON-PERSISTENT-MPLANE { + description + "Indicates that the Radio Unit supports the optional + capability to improve the operation with a SMO using a non- + persistent NETCONF session."; + } + + feature STATIC-TRANSMISSION-WINDOW-CONTROL { + description + "O-RU supports U-plane transmission window control (scheduled transmission + and optionally uniformly distributed transmission) configuration over M-plane"; + } + + feature DYNAMIC-TRANSMISSION-WINDOW-CONTROL { + description + "O-RU supports U-plane transmission window control (scheduled transmission + and optionally uniformly distributed transmission) configuration over C-plane"; + } + + feature UNIFORMLY-DISTRIBUTED-TRANSMISSION { + if-feature "STATIC-TRANSMISSION-WINDOW-CONTROL or DYNAMIC-TRANSMISSION-WINDOW-CONTROL"; + description + "O-RU supports transmission of UL U-plane messages distributed uniformly over transmission window."; + } + + feature ORDERED-TRANSMISSION { + description + "O-RU supports ordered transmission"; + } + + feature INDEPENDENT-TRANSMISSION-WINDOW-CONTROL { + if-feature "STATIC-TRANSMISSION-WINDOW-CONTROL or DYNAMIC-TRANSMISSION-WINDOW-CONTROL"; + description + "O-RU supports independent U-plane transmission window per endpoint. + + If this feature is not supported then for all endpoints with transmission control enabled + (see u-plane-transmission-control/transmission-window-control) must be configured for transmission + window offsets and window sizes that coincide for each symbol. + + If INDEPENDENT-TRANSMISSION-WINDOW-CONTROL feature is not supported then all endpoints with + transmission control enabled that handle the same carrier type and SCS must be configured + (via M-plane or C-plane) with parameter values resulting in transmission windows that coincide + between the endpoints. That is, for every symbol N, the effective transmission window for symbol N + must be shared (start at the same time and end at the same time) by all the endpoints handling + same carrier type and SCS. This restriction applies only to endpoints that have transmission + control enabled. + + If INDEPENDENT-TRANSMISSION-WINDOW-CONTROL feature is supported then restriction described + above does not apply and a different transmission window (window offset and window size) + can be used for every endpoint capable of transmission window control."; + } + + feature EXT-ANT-DELAY-CONTROL { + description + "This feature indicates that the O-RU supports external antenna delay control"; + } + + feature CPLANE-MESSAGE-PROCESSING-LIMITS { + description + "Feature to indicate O-RU limitation of C-Plane message processing. Refer CUS-Plane specification + section 'O-RU C-Plane message limits' for more details on this feature."; + } + + feature CHANNEL-INFORMATION-COMPRESSION { + description + "This feature indicates that the O-RU supports channel information compression."; + } + + feature CHANNEL-INFORMATION-PRB-GROUP { + description + "Feature to indicate O-RU supports receiving and processing channel + information (e.g., ST6) with PRB group size greater than one PRB"; + } + + feature BEAM-UPDATE-CONTENTION-CONTROL { + description + "Feature to indicate O-RU requirements for beam weight update for a given beamId, to avoid beam update contentions. + Refer CUS-Plane specification section 'Weight-based dynamic beamforming' for more details on this feature."; + } + + feature MULTIPLE-SCS-IN-EAXC { + description + "Presence of feature indicates that FHM supports combining for multiple SCS + or multiple c-plane-types/frameStructure in a single eAxC-id in UL direction."; + } + + feature MULTIPLE-TRANSPORT-SESSION-TYPE { + description + "Feature to indicate O-RU supports to be configured with multiple transport-session-type + (Ethernet, ALIASMAC, UDP/IP)"; + } + + feature ENHANCED-T-COMBINE { + description + "Presence of feature indicates that FHM/Cascade O-RU can support t-combine-net and tx-duration"; + } + + feature SHARED-ORU-MULTI-OPERATOR { + description + "Feature to indicate the O-RU supports shared operation with one or more shared + resource operators (i.e., multiple MNOs) and implements enhanced NACM privileges per shared + resource operator. + + Note, there is no linkage or dependency between the SHARED-CELL feature and the SHARED-ORU feature."; + } + + feature SHARED-ORU-MULTI-ODU { + description + "Feature to indicate the O-RU supports independent supervision qualified based on odu-id, where + loss of supervision triggers selective carrier deactivation of carriers associated with odu-id."; + } + + feature INTEGRITY-CHECK-AT-SW-DOWNLOAD { + description "Feature indicates that radio unit support performing integrity check at software download"; + } + + feature SUPERVISION-WITH-SESSION-ID { + description + "O-RUs supporting this feature reuse the session-id generated for each NETCONF + session in supervision-notification. The session-id is defined in RFC 6241. + For these O-RUs, the O-RU controller participating in the NETCONF supervision + procedure can subscribe to supervision-notification notification events, + filtering for the supervision-notification/session-id matching + session-id in the Hello Message received from NETCONF Server earlier."; + } + + feature UPLANE-ONLY-DL-MODE { + description + "Presence of feature indicates that O-RU supports U-Plane-only DL mode."; + } + + feature ST4-SLOT-CONFIG-MSG-SUPPORT { + description + "Feature to indicate O-RU support for Section Type 4 slot configuration message"; + } + feature NON-SCHEDULED-UEID { + description + "Feature to indicate that O-RU supports 'non-scheduled-ueid' to indicate the ports in the section which are not scheduled for a given eAxcid"; + } + + feature EXTENDED-PRACH-CONFIGURATION { + description + "Presence of the feature indicates that O-RU supports extended number of PRACH patterns and occasions + provided by means of static PRACH."; + } + + feature SE11-WITH-CONTINUITY-BIT-SUPPORT { + description + "Feature to indicate O-RU support for handling 'continuity' bit information in Section Extension 11"; + } + + feature UPLANE-MESSAGE-PROCESSING-LIMITS { + description + "Feature to indicate O-RU limitation of U-Plane message processing. Refer M-Plane specification + clause 15.10 for more details on this feature."; + } + + feature CALL-HOME-REACTIVATION-SUPPORTED { + description + "Presence of the feature indicates that O-RU supports re-activation of timed out call home flows."; + } + + feature SEQ-ID-CHECKING-CONFIGURABLE { + description + "Feature to indicate O-RU supports configuration of sequence number checking functionality."; + } + + feature TRX-CONTROL { + description + "Feature to indicate O-RU support for handling RF channel reconfiguration by TRX Control."; + } + + feature ADVANCED-SLEEP-MODE { + description + "Feature to indicate O-RU support for handling Advanced Sleep Modes."; + } + + feature SE23-PRB-BLOCK-MODE-SUPPORT { + description + "Presence of the feature indicates that O-RU supports PRB-BLOCK mode of SE-23 as defined in CUS-Plane + specification Clause 7.7.23.1."; + } + + feature MPLANE-DATA-LAYER-CONTROL { + description + "Feature to indicate O-RU support for M-Plane based data layer control energy saving feature."; + } + + feature SHARED-CELL-STATS { + description + "Feature to indicate FHM/Cascade O-RU support for shared-cell-stats."; + } + + feature PER-PORT-PTP-CONFIG { + description + "This feature indicates that the equipment supports per-port PTP configuration functionality"; + } + + feature PER-PORT-SYNCE-CONFIG { + description + "This feature indicates that the equipment supports per-port SYNCE configuration functionality"; + } + + feature PER-INT-TCP-MSS { + description + "This feature indicates that the RU supports a per-interfacece MSS + configuration for TCP."; + } + + feature MULTIPLE-BEAMID-TABLES-SUPPORTED { + description + "Feature to indicate O-RU support for multiple beamId tables."; + } + + feature MPLANE-TRX-CONTROL { + description + "Feature to indicate O-RU support for M-plane based TRX control for Network Energy Saving."; + } + + feature DEEP-HIBERNATE { + description + "Feature to indicate O-RU support for M-Plane based deep-hibernate energy saving feature."; + } + + feature PRG-SIZE-SUPP-SE-21-WITH-ST6 { + description + "Feature to indicate O-RU support for receiving prgSize information when Section Extension 21 is + sent with Section Type 6."; + } + + feature PRG-SIZE-SUPP-SE-21-WITH-ST5 { + description + "Feature to indicate O-RU support for receiving prgSize information when Section Extension 21 is + sent with Section Type 5."; + } + + feature USER-GROUP-OPTIMIZATION { + description + "Feature to indicate O-DU requirement to send all layers for a given user group i.e., UEs with same + time-frequency allocation using single C-Plane section description."; + } + + feature BF-DELAY-PROFILE { + description + "Feature to indicate O-RU support for beamforming list and delay profiles(s) per endpoint."; + } + + feature DMRS-BF-EQ { + description + "DMRS beamforming with equalization supported. See CUS-plane clause 12.6"; + } + + feature DMRS-BF-NEQ { + description + "DMRS beamforming without equalization supported. See CUS-plane clause 12.6"; + } + + feature RRM-MEAS-REPORTING { + description + "Reporting of RRM measurmenets supported. See CUS-plane clause 12.6.1.6"; + } + + feature USER-GROUP-SELF-ASSEMBLY { + description + "Feature to indicate user group self assembly. See CUS-Plane clause 7.7.24.7."; + } + + feature UEID-PERSISTENCE { + description + "Feature to indicate if ueId persistance over multiple slots is supported. See CUS-Plane clause 7.7.24.10."; + } + + feature CONTINUITY-BLOCK-SIZE { + description + "The O-RUs capability for reporting one or more values of continuity block sizes. See CUS-plane clause 12.6.1.2.1"; + } + + feature SELECTED-BF-METHOD-CONFIGURATION { + description + "Feature to indicate O-RU support for configuration of a subset of beamforming methods from an + endpoint-bf-profile-group that shall be used by a specific endpoint."; + } + + feature DMRS-BF-NEQ-UNALTERED-FREQ-OFFSET { + description + "Feature to indicate that DMRS-BF-NEQ beamforming performed by the O-RU does not change frequency offset, + hence it can be measured by the O-DU."; + } + + feature DMRS-BF-NEQ-UNALTERED-TAE { + description + "Feature to indicate that DMRS-BF-NEQ beamforming performed by the O-RU does not change TAE, + hence TAE can be measured by the O-DU. Refer CUS specification clause 9.2.2.1 for details."; + } + + feature SE10-MEMBER-CANDIDATE-LIST { + description + "Reporting of member-list of endpoints for SE-10 supporting endpoint. See CUS-plane clause 7.7.10.1"; + } + + feature MACSEC-BYPASS-POLICY { + description + "O-RU supports MACsec bypass policy"; + } + + feature SE27-ODU-CONTROLLED-DIMENSIONALITY-REDUCTION { + description + "Presence of the feature indicates that O-RU supports O-DU controlled dimensionality reduction using SE27 as defined in CUS-Plane + specification Clause 7.7.27."; + } + + feature SE20-MULTI-SD-PUNC-PATTERN-SUPPORT { + description + "Feature to indicate O-RU support for handling multiple section description puncturing pattern in + Section Extension 20 per endpoint."; + } + + feature CONFIGURABLE-VSWR-THRESHOLDS { + description + "Feature to indicate O-RU support for configurable VSWR thresholds."; + } + + feature CLIENT-AUTH-SSH-PUBLIC-KEY { + description + "O-RU supports an optional feature to authenticate SSH client via SSHPUBLICKEY method."; + } + + feature POINT-A-OFFSET-TO-ABSOLUTE-FREQUENCY-CENTER { + description + "Feature to indicate if leaf rx-array-carriers/point-a-offset-to-absolute-frequency-center is supported. See CUS-Plane clause 7.7.24.1."; + } +} diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index fc9f58a492..31c754738d 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -172,24 +172,31 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) struct xran_fh_init *fh_init = get_xran_fh_init(); struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int prach_sym = get_prach_conf_duration(0); + nr_prach_info_t prach_info = get_prach_info(0); struct xran_ru_config *ru_conf = &fh_cfg->ru_conf; int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; int tti = slots_per_frame * (frame) + (slot); uint32_t subframe = slot / slots_per_subframe; - uint32_t is_prach_slot = xran_is_prach_slot(0, subframe, (slot % slots_per_subframe)); + // PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4 + uint32_t is_prach_frame = (frame % prach_info.x == prach_info.y); + uint32_t is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (slot % slots_per_subframe)); int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; /* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */ if (is_prach_slot) { - for (sym_idx = 0; sym_idx < prach_sym; sym_idx++) { + if (!ru->prach_buf) { + 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 (int aa = 0; aa < ru->nb_rx; aa++) { int16_t *dst, *src; int idx = 0; oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru); - dst = ru->prach_buf[aa]; // + (sym_idx*576)); + // hardcoded to use only first prach occasion + dst = (int16_t *)ru->prach_buf[0][aa]; 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) { @@ -259,7 +266,14 @@ static bool is_tdd_ul_symbol(const struct xran_frame_config *frame_conf, int slo * slot is not UL). */ static bool is_tdd_dl_guard_slot(const struct xran_frame_config *frame_conf, int slot) { - return !is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1); + return !is_tdd_ul_symbol(frame_conf, slot, 0); +} + +/** @brief Check if current slot is UL or guard/mixed without UL (i.e., current + * slot is not UL). */ +static bool is_tdd_ul_guard_slot(const struct xran_frame_config *frame_conf, int slot) +{ + return is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1); } /** @details Read PRACH and PUSCH data from xran buffers. If @@ -337,7 +351,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) start_ptr = rx_data + (slot_size * slot_offset_rxdata); const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; // skip processing this slot is TX (no RX in this slot) - if (is_tdd_dl_guard_slot(frame_conf, *slot)) + if (!is_tdd_ul_guard_slot(frame_conf, *slot)) continue; // This loop would better be more inner to avoid confusion and maybe also errors. for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { @@ -484,12 +498,70 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) int nPRBs = fh_cfg->nDLRBs; int fftsize = 1 << fh_cfg->ru_conf.fftSize; int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports; + int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; + + // Handle CP UL packet here instead of at xran_fh_rx_read_slot() as oran_fh_if4p5_south_in() lags behind + // oran_fh_if4p5_south_out() (which is invoked at the right time slot) by 4 slots. + // Need to use --continuous-tx so that this routine will be triggered in RX slot. + for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. + for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) { + int first = 1; // The first UL symbol + const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; + // skip processing this slot is TX (no RX in this slot) + if (!is_tdd_ul_guard_slot(frame_conf, slot)) { + continue; + } + // This loop would better be more inner to avoid confusion and maybe also errors. + for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { + /* the callback is for mixed and UL slots. In mixed, we have to + * skip DL and guard symbols. */ + if (!is_tdd_ul_symbol(frame_conf, slot, sym_idx)) { + continue; + } + oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru); + uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; + struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; + + struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[0]; + + struct xran_prb_map *pRbMap = pPrbMap; + uint32_t idxElm = 0; + + LOG_D(HW, "pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); + for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { + LOG_D(HW, "prbMap[%d] : PRBstart %d nPRBs %d\n", idxElm, pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].nRBSize); + pRbElm = &pRbMap->prbMap[idxElm]; + if (first) { + // ant_id / no of antenna per beam gives the beam_nb + pRbElm->nBeamIndex = + ru->beam_id[ant_id / (ru->nb_rx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; + // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. + if (pRbElm->nBeamIndex == -1) { + pRbElm->nBeamIndex = 0; + } else { + first = 0; + } + } + } + } + } + } for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. for (uint8_t ant_id = 0; ant_id < ru->nb_tx; ant_id++) { oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_tx_per_ru); + const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_tx_per_ru)->frame_conf; + // skip processing this slot is TX (no TX in this slot) + if (!is_tdd_dl_guard_slot(frame_conf, slot)) { + continue; + } // This loop would better be more inner to avoid confusion and maybe also errors. for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { + /* the callback is for mixed and UL slots. In mixed, we have to + * skip UL and guard symbols. */ + if (is_tdd_ul_symbol(frame_conf, slot, sym_idx)) { + continue; + } uint8_t *pData = bufs->src[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT].pData; uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; @@ -512,6 +584,14 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { struct xran_section_desc *p_sec_desc = NULL; p_prbMapElm = &pRbMap->prbMap[idxElm]; + if (sym_idx == 0) { + // ant_id / no of antenna per beam gives the beam_nb + p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT]; + // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. + if (p_prbMapElm->nBeamIndex == -1) + p_prbMapElm->nBeamIndex = 0; + } + // assumes one fragment per symbol #ifdef E_RELEASE p_sec_desc = p_prbMapElm->p_sec_desc[sym_id][0]; diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 89c1838fa3..684d44e7cf 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -918,7 +918,7 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c fh_config->dpdk_port = ru_idx; // DPDK port number used for FH fh_config->sector_id = 0; // Band sector ID for FH; not used in xran fh_config->nCC = 1; // number of Component carriers supported on FH; M-plane info - fh_config->neAxc = RTE_MAX(oai0->num_distributed_ru * oai0->tx_num_channels / num_rus, oai0->num_distributed_ru * oai0->rx_num_channels / num_rus); // number of eAxc supported on one CC = max(PDSCH, PUSCH) + fh_config->neAxc = RTE_MAX(oai0->tx_num_channels / num_rus, oai0->rx_num_channels / num_rus); // number of eAxc supported on one CC = max(PDSCH, PUSCH) fh_config->neAxcUl = 0; // number of eAxc supported on one CC for UL direction = PUSCH; used only if XRAN_CATEGORY_B fh_config->nAntElmTRx = 0; // number of antenna elements for TX and RX = SRS; used only if XRAN_CATEGORY_B fh_config->nDLFftSize = 0; // DL FFT size; not used in xran diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index 07517dcf18..516c2795fe 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -30,9 +30,7 @@ #include "common/utils/assertions.h" #include "common/utils/LOG/log.h" -#include "common/utils/nr/nr_common.h" #include "common_lib.h" -#include "openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h" /* PRACH data samples are 32 bits wide (16bits for I/Q). Each packet contains * 840 samples for long sequence or 144 for short sequence. The payload length @@ -50,7 +48,7 @@ void *gxran_handle; static struct xran_fh_init g_fh_init = {0}; static struct xran_fh_config g_fh_config[XRAN_PORTS_NUM] = {0}; -static uint32_t g_prach_conf_duration[XRAN_PORTS_NUM] = {0}; +static nr_prach_info_t g_prach_info[XRAN_PORTS_NUM] = {0}; static uint32_t get_nSW_ToFpga_FTH_TxBufferLen(int mu, int sections) { @@ -470,11 +468,9 @@ int *oai_oran_initialize(struct xran_fh_init *xran_fh_init, struct xran_fh_confi // retrieve and store prach duration uint8_t idx = xran_fh_config[o_xu_id].prach_conf.nPrachConfIdx; const struct xran_frame_config *fc = &xran_fh_config[o_xu_id].frame_conf; - g_prach_conf_duration[o_xu_id] = - get_nr_prach_occasion_info_from_index(idx, - fc->nNumerology > 2 ? FR2 : FR1, - fc->nFrameDuplexType == XRAN_FDD ? duplex_mode_FDD : duplex_mode_TDD) - .N_dur; + g_prach_info[o_xu_id] = get_nr_prach_occasion_info_from_index(idx, + fc->nNumerology > 2 ? FR2 : FR1, + fc->nFrameDuplexType == XRAN_FDD ? duplex_mode_FDD : duplex_mode_TDD); } // store config after xran initialization -- xran makes modifications to @@ -504,9 +500,9 @@ struct xran_fh_config *get_xran_fh_config(uint32_t port_id) return &g_fh_config[port_id]; } -uint32_t get_prach_conf_duration(uint32_t port_id) +nr_prach_info_t get_prach_info(uint32_t port_id) { struct xran_fh_init *fh_init = get_xran_fh_init(); DevAssert(port_id < fh_init->xran_ports); - return g_prach_conf_duration[port_id]; + return g_prach_info[port_id]; } diff --git a/radio/fhi_72/oran-init.h b/radio/fhi_72/oran-init.h index e56b683a9f..419cbccce4 100644 --- a/radio/fhi_72/oran-init.h +++ b/radio/fhi_72/oran-init.h @@ -22,6 +22,9 @@ #ifndef ORAN_INIT_H #define ORAN_INIT_H +#include "common/utils/nr/nr_common.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_prach_config.h" + typedef struct oran_bufs { struct xran_flat_buffer tx[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN][XRAN_NUM_OF_SYMBOL_PER_SLOT]; struct xran_flat_buffer tx_prbmap[XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN]; @@ -62,6 +65,16 @@ int *oai_oran_initialize(struct xran_fh_init *fh_init, struct xran_fh_config *fh oran_buf_list_t *get_xran_buffers(uint32_t port_id); struct xran_fh_init *get_xran_fh_init(void); struct xran_fh_config *get_xran_fh_config(uint32_t port_id); -uint32_t get_prach_conf_duration(uint32_t port_id); + +/** + * @brief queries PRACH information necessary for the FHI + * + * @arg port_id XRAN port id + * @return PRACH information holding among other information: + * - N_dur PRACH duration from TS 38.211 Table 6.3.3.2-2/3/4 + * - x from TS 38.211 Table 6.3.3.2-2/3/4 + * - y from TS 38.211 Table 6.3.3.2-2/3/4 + */ +nr_prach_info_t get_prach_info(uint32_t port_id); #endif /* ORAN_INIT_H */ diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 3bdbe1df12..679936d9c9 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -31,6 +31,7 @@ #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "openair1/PHY/defs_gNB.h" +#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h" #include "oaioran.h" #include "oran-config.h" @@ -85,6 +86,7 @@ int trx_oran_stop(openair0_device *device) #ifdef OAI_MPLANE printf("[MPLANE] Stopping M-plane.\n"); disconnect_mplane(s->mplane_priv); + free(s->mplane_priv); #endif return (0); } @@ -212,10 +214,15 @@ int trx_oran_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len) void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) { - ru_info_t ru_info; - ru_info.nb_rx = ru->nb_rx * ru->num_beams_period; - ru_info.rxdataF = ru->common.rxdataF; - ru_info.prach_buf = ru->prach_rxsigF[0]; // index: [prach_oca][ant_id] + prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, SEARCH_EXIST); + ru_info_t ru_info = { + .nb_rx = ru->nb_rx * ru->num_beams_period, + .nb_tx = ru->nb_tx * ru->num_beams_period, + .rxdataF = ru->common.rxdataF, + .beam_id = ru->common.beam_id, + .num_beams_period = ru->num_beams_period, + .prach_buf = prach_id ? prach_id->rxsigF : NULL, + }; RU_proc_t *proc = &ru->proc; int f, sl; @@ -266,9 +273,14 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) void oran_fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) { start_meas(&ru->tx_fhaul); - ru_info_t ru_info; - ru_info.nb_tx = ru->nb_tx * ru->num_beams_period; - ru_info.txdataF_BF = ru->common.txdataF_BF; + ru_info_t ru_info = { + .nb_rx = ru->nb_rx * ru->num_beams_period, + .nb_tx = ru->nb_tx * ru->num_beams_period, + .txdataF_BF = ru->common.txdataF_BF, + .beam_id = ru->common.beam_id, + .num_beams_period = ru->num_beams_period, + }; + // printf("south_out:\tframe=%d\tslot=%d\ttimestamp=%ld\n",frame,slot,timestamp); int ret = xran_fh_tx_send_slot(&ru_info, frame, slot, timestamp); @@ -301,41 +313,42 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d bool success = false; #ifdef OAI_MPLANE - ru_session_list_t ru_session_list = {0}; - success = init_mplane(&ru_session_list); + ru_session_list_t *ru_session_list = calloc(1, sizeof(*ru_session_list)); + assert(ru_session_list != NULL && "Memory exhausted"); + success = init_mplane(ru_session_list); AssertFatal(success, "[MPLANE] Cannot initialize M-plane.\n"); - bool ru_configured[ru_session_list.num_rus]; - for (size_t i = 0; i < ru_session_list.num_rus; i++) { - ru_session_t *ru_session = &ru_session_list.ru_session[i]; + bool ru_configured[ru_session_list->num_rus]; + for (size_t i = 0; i < ru_session_list->num_rus; i++) { + ru_session_t *ru_session = &ru_session_list->ru_session[i]; ru_configured[i] = connect_mplane(ru_session); if (!ru_configured[i]) { continue; } - ru_configured[i] = manage_ru(ru_session, openair0_cfg, ru_session_list.num_rus); + ru_configured[i] = manage_ru(ru_session, openair0_cfg, ru_session_list->num_rus); } bool all_ok = true; - bool ru_ready[ru_session_list.num_rus]; - for (size_t i = 0; i < ru_session_list.num_rus; i++) { + bool ru_ready[ru_session_list->num_rus]; + for (size_t i = 0; i < ru_session_list->num_rus; i++) { if (!ru_configured[i]) { - MP_LOG_I("RU with IP %s couldn't be configured.\n", ru_session_list.ru_session[i].ru_ip_add); + MP_LOG_I("RU with IP %s couldn't be configured.\n", ru_session_list->ru_session[i].ru_ip_add); all_ok = false; } ru_ready[i] = false; } if (!all_ok) { - disconnect_mplane((void *)&ru_session_list); + disconnect_mplane(ru_session_list); AssertFatal(false, "[MPLANE] Stopping M-plane.\n"); } while (true) { sleep(1); bool all_rus_ready = true; - for (int i = 0; i < ru_session_list.num_rus; i++) { - ru_session_t *ru_session = &ru_session_list.ru_session[i]; - if (!ru_ready[i] && ru_session->ru_notif.config_change && ru_session->ru_notif.rx_carrier_state && ru_session->ru_notif.tx_carrier_state) { + for (int i = 0; i < ru_session_list->num_rus; i++) { + ru_session_t *ru_session = &ru_session_list->ru_session[i]; + if (!ru_ready[i] && ru_session->ru_notif.config_change && !ru_session->ru_notif.rx_carrier_state && !ru_session->ru_notif.tx_carrier_state) { MP_LOG_I("RU \"%s\" is now ready.\n", ru_session->ru_ip_add); ru_ready[i] = true; if (!ru_session->pm_stats.start_up_timing) { @@ -353,9 +366,9 @@ __attribute__((__visibility__("default"))) int transport_init(openair0_device *d } } - eth->mplane_priv = (void *)&ru_session_list; + eth->mplane_priv = ru_session_list; - success = get_xran_config((void *)&ru_session_list, openair0_cfg, &fh_init, fh_config); + success = get_xran_config(ru_session_list, openair0_cfg, &fh_init, fh_config); AssertFatal(success, "[MPLANE] Cannot configure xran with M-plane info.\n"); #else success = get_xran_config(NULL, openair0_cfg, &fh_init, fh_config); diff --git a/radio/fhi_72/oran_isolate.h b/radio/fhi_72/oran_isolate.h index 174c1399a6..6ec011a24b 100644 --- a/radio/fhi_72/oran_isolate.h +++ b/radio/fhi_72/oran_isolate.h @@ -28,7 +28,8 @@ #include #include "xran_fh_o_du.h" - +#include "openair1/PHY/impl_defs_nr.h" +#include "openair1/PHY/TOOLS/tools_defs.h" /* * Structure added to bear the information needed from OAI RU */ @@ -41,8 +42,16 @@ typedef struct ru_info_s { int nb_tx; int32_t **txdataF_BF; + /// \brief Anaglogue beam ID for each OFDM symbol (used when beamforming not done in RU) + /// - first index: concurrent beam + /// - second index: beam_id [0.. symbols_per_frame] + int32_t **beam_id; + + /// number of concurrent analog beams in period + int num_beams_period; + // Needed for Prach - int16_t **prach_buf; + c16_t (*prach_buf)[NB_ANTENNAS_RX][NR_PRACH_SEQ_LEN_L]; } ru_info_t; /** @brief Reads RX data (PRACH/PUSCH) of next slot. diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index 13a414fed6..94234a755f 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -688,6 +688,8 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, if (b->conn_sock >= 0) { samplesBlockHeader_t header = {nsamps, nbAnt, timestamp}; + if (!nbAnt) + LOG_E(HW, "rfsimulator sending 0 tx antennas\n"); fullwrite(b->conn_sock, &header, sizeof(header), t); if (nbAnt == 1) { fullwrite(b->conn_sock, samplesVoid[0], sampleToByte(nsamps, nbAnt), t); @@ -796,6 +798,8 @@ static void process_recv_header(rfsimulator_state_t *t, buffer_t *b, bool first_ // We have a transmission hole to fill, like TDD // we create no signal samples up to the beginning of this reception int nbAnt = b->th.nbAnt; + if (!nbAnt) + LOG_E(HW, "rfsimulator receive 0 rx antennas\n"); if (b->th.timestamp - b->lastReceivedTS < CirSize) { // case we wrap at circular buffer end for (uint64_t index = b->lastReceivedTS; index < b->th.timestamp; index++) { @@ -822,6 +826,8 @@ static void process_recv_header(rfsimulator_state_t *t, buffer_t *b, bool first_ b->transferPtr = (char *)&b->circularBuf[(b->lastReceivedTS * b->th.nbAnt) % CirSize]; // we now need to read the samples b->remainToTransfer = sampleToByte(b->th.size, b->th.nbAnt); + if (!b->remainToTransfer) + b->headerMode = true; // We got a header with 0 antennas, no I/Q to read return; } diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf index 887ff6eced..08691c3b62 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf @@ -22,6 +22,7 @@ RUs = ({ att_tx = 0 att_rx = 0; bands = [78]; + sl_ahead = 2; max_pdschReferenceSignalPower = -27; max_rxgain = 125; }); diff --git a/tests/nr-cuup/CMakeLists.txt b/tests/nr-cuup/CMakeLists.txt index 02becb2496..9d48fd89e2 100644 --- a/tests/nr-cuup/CMakeLists.txt +++ b/tests/nr-cuup/CMakeLists.txt @@ -1,4 +1,14 @@ add_executable(nr-cuup-load-test nr-cuup-load-test.c) +add_dependencies(nr-cuup-load-test params_libconfig) target_link_libraries(nr-cuup-load-test PRIVATE GTPV1U ${T_LIB} utils ITTI e1ap SCTP_CLIENT) target_link_libraries(nr-cuup-load-test PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) # ITTI + +if(ENABLE_TESTS) + # we add also nr-cuup as it is required for the test + add_dependencies(tests nr-cuup-load-test nr-cuup) + add_test(NAME nr_cuup_functional_test + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/nr-cuup-functional-test.sh ${CMAKE_CURRENT_SOURCE_DIR}/load-test.conf + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) +endif() diff --git a/tests/nr-cuup/nr-cuup-functional-test.sh b/tests/nr-cuup/nr-cuup-functional-test.sh new file mode 100755 index 0000000000..28a9b3779a --- /dev/null +++ b/tests/nr-cuup/nr-cuup-functional-test.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# this script takes one argument, which is the path to the CU-UP configuration +if [ $# -ne 1 ]; then + echo "usage: $0 " + exit 1 +fi + +CONFIG=$1 + +set -x + +# current dir should be CMAKE_BINARY_DIR +./nr-cuup -O ${CONFIG} & +CUUP_PID=$! + +timeout 5s ./tests/nr-cuup/nr-cuup-load-test -t 3 -d 10 -u 10 +RET=$? + +kill ${CUUP_PID} +exit ${RET} diff --git a/tests/nr-cuup/nr-cuup-load-test.c b/tests/nr-cuup/nr-cuup-load-test.c index 0c417ca5aa..0774b26b1b 100644 --- a/tests/nr-cuup/nr-cuup-load-test.c +++ b/tests/nr-cuup/nr-cuup-load-test.c @@ -28,6 +28,7 @@ #include "openair3/SCTP/sctp_eNB_task.h" #include "openair2/E1AP/e1ap.h" #include "openair3/ocp-gtpu/gtp_itf.h" +#include "openair2/E1AP/lib/e1ap_interface_management.h" configmodule_interface_t *uniqCfg; @@ -90,6 +91,7 @@ static void setup_cuup(sctp_assoc_t *assoc_id, e1ap_nssai_t *nssai) DevAssert(req->plmn[0].slice != NULL); *nssai = *req->plmn[0].slice; DevAssert(assoc_id != 0); + free_e1ap_cuup_setup_request(req); itti_free(TASK_GNB_APP, itti_req); // acknowledge the E1 setup request with a response @@ -165,7 +167,6 @@ static struct ue_stat { static bool recv_ng(protocol_ctxt_t *ctxt, const ue_id_t ue_id, const srb_flag_t flag, - const rb_id_t rb, const mui_t mui, const confirm_t confirm, const sdu_size_t size, @@ -665,6 +666,9 @@ int main(int argc, char *argv[]) success = false; } + free(ng_ip); + free(f1_ip); + if (success) LOG_A(GNB_APP, "test succeeded\n"); else diff --git a/tools/scripts/traffic_runner.sh b/tools/scripts/traffic_runner.sh index b7178bc820..30ba7f4a90 100755 --- a/tools/scripts/traffic_runner.sh +++ b/tools/scripts/traffic_runner.sh @@ -41,7 +41,7 @@ iperf_udp_ul_forever() { ( iperf -u -c "$IPERF_HOST_UDP" -B "$OAITUN_IP" -p "$IP # ---------------- profiles ---------------- do_boring() { - iperf_udp_ul_forever 3M + iperf_udp_dl_forever 500K wait # iperf -c "$IPERF_HOST" -p "$IPERF_PORT" -B "$OAITUN_IP" -u -b 25M -t "$LONG_T" }